# 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 ```