Files
lux/AGENTS.md
T

4.8 KiB

AGENTS.md

Purpose

This repo uses the Dendritic Pattern with flake-parts.

Design and change the configuration as a composition of features, not as a host-first tree.

For deeper design rationale and pattern descriptions, refer to .agents/dendritic-design-with-flake-parts.wiki.

Core Terms

  • Feature: a flake-parts module under modules/ that defines one coherent concern.
  • Aspect: a reusable module published at flake.modules.<module class>.<aspect name>.
  • Module class: the configuration context of an aspect. This repo primarily uses nixos and homeManager.
  • Feature module: the flake-parts module that defines aspects, flake outputs, options, or shared helpers.

In this repo, flake.nix imports ./modules recursively via inputs.import-tree. Any non-private .nix file under modules/ is therefore treated as a feature module.

Design Principles

  • Work bottom-up. Define features first; assemble hosts from features.
  • Keep semantic ownership local. A feature should contain the configuration for that concern across all relevant module classes.
  • Name aspects semantically. The aspect name should usually match the file or directory name that defines it.
  • Prefer small, composable aspects. Build larger configurations with imports.
  • Import aspects unconditionally and only within the same module class.
  • Put conditions inside module content with lib.mkIf or lib.mkMerge, never around imports.
  • Avoid importing the same aspect multiple times along one import path.
  • Keep private helper files next to the feature that uses them and prefix them with _ so import-tree does not import them as feature modules.
  • Put shared schemas and constructors in dedicated shared modules, not ad hoc host files.

Repo Structure

  • modules/features/: reusable features and most aspect definitions.
  • modules/hosts/<name>/default.nix: host features that assemble NixOS aspects into flake.modules.nixos.<name>.
  • modules/secrets/: secret-related features shared by hosts.
  • modules/flake-parts.nix: flake-parts entrypoint; defines systems, formatter, and flake.nixosConfigurations.
  • modules/lib.nix: shared constructors and helpers in config.meta.lib, especially mkHost and mkCaddyReverseProxy.
  • modules/data.nix: canonical shared repo data and account attrsets exposed through meta.lib.repo and meta.lib.accounts.
  • modules/features/meta.nix: shared metadata schema for meta.host and meta.user.

How Features Are Applied Here

  • Reusable NixOS concerns are published as flake.modules.nixos.<name>.
  • Reusable Home Manager concerns are published as flake.modules.homeManager.<name>.
  • Hosts are aspects too. orion, polaris, and zenith are nixos aspects assembled from smaller aspects.
  • Host modules should use config.meta.lib.mkHost to define meta.host, base imports, hostname, and state version.
  • Per-host user declarations should stay inline under users.<name> using canonical accounts from meta.lib.accounts, so host-local defaults stay close to the host and mkHost can wire meta.host and meta.user into Home Manager consistently.
  • Features may rely on the meta contract. Existing modules already read config.meta.host, config.meta.user, and config.meta.lib.

Preferred Aspect Patterns

  • Simple Aspect: use for one self-contained concern in one or more module classes.
  • Multi Context Aspect: use when one concern must configure both nixos and homeManager.
  • Inheritance Aspect: use by importing a parent aspect and extending it.
  • Conditional Aspect: use lib.mkMerge plus lib.mkIf for conditional content.

Use Collector Aspect only when composition through imports or shared library helpers is insufficient.

Change Rules

  • When adding a feature, add or extend aspects under modules/features/ and let hosts opt into them explicitly.
  • When adding a host, create modules/hosts/<name>/default.nix and keep host-local generated files private as _hardware.nix, _disk.nix, or similar.
  • When a feature needs local data or helper code, keep it inside that feature directory and prefix non-feature files with _ when they live under modules/.
  • Do not place arbitrary non-feature .nix files under modules/ unless they are intentionally private and excluded from recursive import.
  • If a concern is shared across hosts, it belongs in a reusable feature, not inline in one host unless it is truly host-specific.

Practical Heuristics

  • If you are about to edit a host because of a reusable concern, that concern probably wants its own feature.
  • If a Home Manager module needs host or user facts, prefer reading config.meta.host or config.meta.user instead of duplicating literals.
  • If a concern spans system and user space, keep both aspects in one feature so the behavior stays coherent.
  • If imports would need to be conditional, redesign the aspect boundary instead.