From be4a060e94459aa44979ad05192e238bdf5e9732 Mon Sep 17 00:00:00 2001 From: alexion Date: Sat, 29 Aug 2026 17:05:43 -0400 Subject: [PATCH] docs(nix): record flake conventions --- AGENTS.md | 5 +- docs/dictionary.md | 8 +- docs/nix.md | 270 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 280 insertions(+), 3 deletions(-) create mode 100644 docs/nix.md diff --git a/AGENTS.md b/AGENTS.md index 85f0183..1fc8896 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -4,13 +4,16 @@ One flake builds every machine I own. ## Repository Conventions -- Follow `docs/technical-writing.md` for comments, user-facing descriptions, commit prose, pull-request prose, and Markdown documentation. +- Use `docs/technical-writing.md` and `docs/dictionary.md` while authoring any file. + Apply them to comments, user-facing descriptions, commit prose, pull-request prose, and Markdown documentation. - Comments posted to the forge under the operator's account must end with `— Pi`. The sign-off identifies the agent as the author instead of the operator. - Commit messages follow Conventional Commits, defined in `docs/conventional-commits.md`. Use a scope for the changed module or host, such as `fish`, `nvim`, or `neogaia`. - Keep commit messages about the Git history, not the forge workflow. Do not reference issue or pull-request numbers unless the commit itself requires a stable external reference. +- During pull-request development, add follow-up commits instead of amending existing commits. + Preserve review history until the pull request is ready to merge. - Use `gitea-axi` for Gitea issues, pull requests, labels, reviews, comments, and milestones. It resolves this repository from the `origin` remote inside the checkout. diff --git a/docs/dictionary.md b/docs/dictionary.md index 2037892..fc775e6 100644 --- a/docs/dictionary.md +++ b/docs/dictionary.md @@ -45,11 +45,15 @@ Use the simplest accurate word when a term is not listed. | operator | Agent tooling | The human driving the development process. Use when distinguishing the human from the agent acting on their behalf. | | guest | dotfiles | A systemd-nspawn container managed by this flake. Use for configured containers under `guests/`. | | host | dotfiles | A machine with a NixOS configuration built by this flake. | -| module | dotfiles | In this repository, a self-contained configuration under `modules/`, usually scoped to one program, service, or subsystem. Use `Nix module` for the language-level module-system concept. | +| module | dotfiles | In this repository, a self-contained configuration under `modules/`. Use for one program, service, or subsystem. | | registry | dotfiles | A typed configuration namespace whose entries can be collected across hosts and reused by other configuration. | | Conventional Commits | Git | A commit-message format defined in `docs/conventional-commits.md`. | | forge | Git | A web service that hosts Git repositories, pull requests, issues, and code review comments. Use when the exact provider does not matter. | | flake | Nix | A Nix project with pinned inputs and declared outputs. Use for the repository-level build unit defined by `flake.nix`. | -| Nix module | Nix | A Nix language unit that declares or sets options through the Nix module system. | +| assembly file | Nix | A Nix file under `flake/` that constructs flake outputs or arguments passed to NixOS modules. | +| assembly function | Nix | A project function in `flake/` that creates modules, systems, or output values. | +| library file | Nix | A Nix file that defines reusable project functions instead of a NixOS module or flake output. | +| library function | Nix | A pure project function exposed under `util`. | +| NixOS module | Nix | A Nix file evaluated by `nixosSystem` for a NixOS configuration. | | overlay | Nix | A function that modifies a Nix package set by adding or replacing packages. | | workspace | Window management | A named or numbered group of windows in a graphical session. Some desktop environments call this a virtual desktop. | diff --git a/docs/nix.md b/docs/nix.md new file mode 100644 index 0000000..b1177af --- /dev/null +++ b/docs/nix.md @@ -0,0 +1,270 @@ +# Nix Conventions + +This document records local Nix style and design conventions. +Use these conventions when changing this flake. +Read this document with `docs/dictionary.md`. + +## Names + +### Reserve `lib` for `nixpkgs.lib` + +Use `lib` only for the base `nixpkgs.lib` value. +Do not use `lib` for project functions. +Use `util` for library functions passed through module arguments. +Use `flake.mk` for assembly functions used by flake outputs. + +Avoid: + +```nix +specialArgs = { + lib = util; +}; +``` + +Use: + +```nix +specialArgs = { + inherit util; +}; +``` + +Then call library functions through `util` inside modules: + +```nix +{ + lib, + util, + ... +}: +{ + networking.networkmanager.unmanaged = [ "interface-name:${util.bridgeName 10}" ]; +} +``` + +### Name project function namespaces by role + +Put pure project functions under `util`. +Put functions that create systems or output values under `flake`. +This keeps data-only functions separate from functions that carry flake context. + +Avoid: + +```nix +util.mkHosts { root = self + "/hosts"; } +``` + +Use: + +```nix +flake.mkHosts { root = self + "/hosts"; } +``` + +## File Placement + +### Put files in the directory that owns their role + +Choose the file location before writing a Nix file. +Put assembly files under `flake/`. +Put library files under `lib/`. +Put modules under `modules/`. +Put host configurations under `hosts//`. +Put host-side guest wiring under `guests/`. +Put registry definitions under `registry/`. +Keep `flake.nix` focused on inputs and output wiring. +Do not add root-level Nix files other than `flake.nix`. + +A module is self-contained configuration under `modules/`. +A module configures one program, service, or subsystem. +Files under `hosts/`, `guests/`, and `modules/` return NixOS modules. + +### Use `default.nix` for module directories with support files + +Use `default.nix` as the primary module when a module directory owns support files. +Keep sibling files for data or code read by that primary module. + +Avoid: + +```text +modules/shell/fish/fish.nix +modules/shell/fish/config.fish +``` + +Use: + +```text +modules/shell/fish/default.nix +modules/shell/fish/config.fish +``` + +### Use non-module `default.nix` files only for directory assembly + +Outside `modules/`, use `default.nix` to connect files in its directory. +Do not define primary assembly functions in `default.nix`. +Put primary assembly functions in named files. + +Avoid: + +```text +flake/default.nix # defines mkHost +``` + +Use: + +```text +flake/default.nix # imports ./host.nix +flake/host.nix # defines mkHosts +``` + +### Keep assembly files focused on one concept + +Give each assembly file under `flake/` one top-level concept. +Keep helper functions private to that file when no other file needs them. +Export the constructor for the concept when another assembly file needs it. +Name that constructor `mk`. + +Avoid: + +```nix +{ + inherit collectNixFiles mkHost mkHosts; +} +``` + +Use: + +```nix +{ + inherit mkHosts; +} +``` + +## Function Arguments + +### Use closed interfaces for assembly files and library files + +Use exact function argument patterns for assembly files and library files. +The caller owns the argument set for these files. +The imported file names each accepted attribute. +The imported file rejects stale or accidental extra attributes. + +Avoid: + +```nix +{ + inputs, + lib, + self, + ... +}: +``` + +Use: + +```nix +{ + inputs, + lib, + self, +}: +``` + +### Pass function arguments explicitly + +Pass only the values an assembly file or library file needs. +Bind `lib` to the base `nixpkgs.lib` value at the call site. +Use `inherit` only for values that keep the same name. + +Avoid: + +```nix +import ./flake inputs +``` + +Use: + +```nix +let + inherit (nixpkgs) lib; +in +import ./flake { inherit lib inputs self; } +``` + +### Keep NixOS module interfaces open + +Files under `hosts/`, `guests/`, and `modules/` return NixOS modules. +`nixosSystem` owns their argument shape. +Name each argument the module uses. +Keep `...` so the module accepts standard arguments and special arguments. + +Avoid: + +```nix +{ + config, + lib, + pkgs, + registry, +}: +``` + +Use: + +```nix +{ + config, + lib, + pkgs, + registry, + ... +}: +``` + +## `let` Bindings + +### Use role-specific binding names + +A `let` binding name must explain the value's role in the expression. +Avoid names that describe only the value's type. + +Avoid: + +```nix +let + names = lib.attrNames hosts; +in +lib.genAttrs names mkHost +``` + +Use: + +```nix +let + hostNames = lib.attrNames hosts; +in +lib.genAttrs hostNames mkHost +``` + +## Standard Library Calls + +### Qualify standard library calls in flake assembly + +Use qualified standard library calls inside assembly files. +Use `lib.mapAttrs` instead of inheriting `mapAttrs` from `lib`. +This keeps the source of each function visible. + +Avoid: + +```nix +let + inherit (lib) mapAttrs; +in +mapAttrs f attrs +``` + +Use: + +```nix +lib.mapAttrs f attrs +``` +