4.6 KiB
AGENTS.md
On this configuration, rules exist to keep it from turning into an unmanageable mess as it grows across multiple machines.
Development rules
- For version control: try not to use
gitdirectly. Instead ofgit add, usejj file track. The repo is colocated with git (jj on top,.git/still present) so it stays compatible with repository. - Never commit or push on your own (neither
jj commit/jj git pushnorgit commit/git push). Leave changes tracked/staged and stop there — the human reviews and commits/pushes themselves. - Always use the Dendritic Pattern: every module file ends in
*.ulu.nixand is auto-discovered byflake.nix. There is no centralimports = [ ... ]list anywhere in the repo. flake.nixitself only does discovery (listFilesRecursive+hasSuffix ".ulu.nix"). Never add a manual import list back intoflake.nix, no matter how tempting it seems for "just this one file".- Where you place a
*.ulu.nixfile in the directory tree is for human organization only. It has no effect on whether the file is loaded. Directory names should describe the topic (modules/nixos/,hosts/,services/), not the loading mechanism. - Never use old-style
nix-*commands. Always prefer the newnix3commands (nix buildovernix-build,nix flake checkovernix-instantiate, and so on).
File arrangement
- A module file should do ONE thing. If you can't describe what a file does in one sentence without using "and", split it into two files.
- There is no fixed line-count limit — a genuinely complex, single concern (e.g. a from-scratch service definition) is allowed to be long. What's not allowed is a grab-bag file that bundles unrelated concerns together because it was convenient at the time (this repo has explicitly rejected the "one giant catch-all file" pattern).
- If you're adding to an existing file and the addition isn't the
same concern as the rest of the file, create a new
*.ulu.nixfile instead of appending.
The module pool is not an active list
-
flake.nixosModules.*andflake.homeModules.*are a registry, not a set of things that are automatically active. A module existing in the pool has zero effect on any host until a host explicitly imports it by name. -
Host files (
hosts/<hostname>.ulu.nix) must NEVER pull the whole pool in automatically. Do not writebuiltins.attrValues config.flake.nixosModules(orattrNames, or any other "grab everything" construct) in a host file. Every host lists the exact modules it wants, by name:modules = [ config.flake.nixosModules.common config.flake.nixosModules.gaming config.flake.nixosModules.niri ]; -
If the same group of modules is reused across multiple hosts, create a profile file (e.g.
gaming-profile.ulu.nix) whose only job is to list other module names under one name. A profile file must not contain new logic of its own, only composition.
Naming
- Custom option namespace:
elars.*(e.g.elars.hardware.graphics.driver,elars.desktop.compositor). Don't invent a second namespace. - Module names in the pool are prefixed by domain so the pool stays
browsable as it grows:
common-*— shared across every host regardless of rolehw-*— hardware-specific modules (graphics, bluetooth, etc.)net-*— networkingservice-*— systemd services / daemonsgaming-*— Steam and anything gaming-relateddesktop-*— window managers / compositors (niri, hyprland) and other desktop-session-level nixos moduleshome-*— home-manager modules that are not a window manager (git, shell programs, dotfile-level config)
- Host file name must exactly match the hostname it defines
(
hosts/canavar.ulu.nixdefinesnetworking.hostName = "canavar", not something else). Prefer adding a sanity assertion that checks this rather than relying on discipline alone.
Toolchain notes
- Version control: jj, colocated with git (see Development rules).
- Formatter: nixfmt.
- User-level config: home-manager. (hjem was considered but rejected — home-manager stays.)
What NOT to do
- Don't reintroduce a central
default.nixthat manually listsimports = [ ./a.nix ./b.nix ]. That's the pattern we're moving away from. - Don't create a file just because "it needs to live somewhere for
now" — if it doesn't have a clear single concern yet, it's not
ready to be a
*.ulu.nixfile. - Don't use
builtins.attrValues/attrNamesto wire a host's module list. Every host's module list must be explicit and readable at a glance.