docs(nix): clarify convention examples

This commit is contained in:
2026-08-28 09:43:52 -04:00
parent 4c40aa12a7
commit 3c3d9d80f2

View File

@@ -5,31 +5,232 @@ Prefer these conventions when changing this flake.
## Names
### Reserve `lib` for `nixpkgs.lib`
Use `lib` only for the base `nixpkgs.lib` value.
Do not use `lib` for project helper functions.
Use `dotfiles.lib` for pure project helpers passed through module arguments.
Use `dotfiles.<name>` for project assembly helpers passed through module arguments.
Avoid:
```nix
{
lib = dotfilesHelpers;
}
```
Use:
```nix
{
lib = nixpkgs.lib;
dotfiles.lib = dotfilesHelpers;
}
```
## Imports
Prefer explicit import arguments.
Use exact function argument patterns without `...` when the imported file has a closed interface.
Use `...` only when the file intentionally accepts extra arguments.
### Use closed interfaces for helper imports
## `let` bindings
Use exact function argument patterns when an imported helper file has a closed interface.
A helper file has a closed interface when the importer owns the argument set.
The imported file must name each accepted attribute.
This rejects stale or accidental extra attributes.
Minimize `let` bindings.
Use a `let` binding when it names an important intermediate value or avoids repeated complex expressions.
Avoid:
```nix
{
inputs,
lib,
self,
...
}:
```
Use:
```nix
{
inputs,
lib,
self,
}:
```
### Pass import arguments explicitly
Pass only the values an imported helper file needs.
Bind `lib` to the base `nixpkgs.lib` value at the call site.
Use `inherit` for values that keep the same name.
Avoid:
```nix
import ./flake inputs
```
Use:
```nix
import ./flake {
inherit inputs self;
lib = nixpkgs.lib;
}
```
### Keep NixOS module interfaces open
NixOS modules must accept extra arguments because the module system owns their argument shape.
Name the arguments the module uses.
Keep `...` so the module accepts standard module arguments and special arguments.
Avoid:
```nix
{
config,
lib,
pkgs,
registry,
}:
```
Use:
```nix
{
config,
lib,
pkgs,
registry,
...
}:
```
### Use `@` for forwarding wrappers
Use `@` when a wrapper must pass the complete argument set to another module function.
Name the arguments the wrapper uses before `...`.
Forward the bound argument set unchanged.
Avoid:
```nix
{ dotfiles, ... }:
dotfiles.guest { name = "sample"; } { inherit dotfiles; }
```
Use:
```nix
args@{ dotfiles, ... }:
dotfiles.guest { name = "sample"; } args
```
## `let` Bindings
### Use `let` for important intermediate values
Use a `let` binding when it names an important intermediate value.
Use a `let` binding when it avoids repeating a complex expression.
Do not use a `let` binding only to shorten a standard library call.
## Standard library calls
Avoid:
```nix
let
inherit (lib) mapAttrs;
in
mapAttrs f attrs
```
Use:
```nix
lib.mapAttrs f attrs
```
## Standard Library Calls
### Qualify standard library calls in flake assembly
Prefer qualified standard library calls inside flake assembly code.
Use `lib.mapAttrs` instead of inheriting `mapAttrs` from `lib`.
This keeps the source of helper functions visible.
## Flake assembly
Avoid:
```nix
let
inherit (lib) mapAttrs;
in
mapAttrs f attrs
```
Use:
```nix
lib.mapAttrs f attrs
```
## Flake Assembly
### Keep assembly code under `flake/`
Keep flake assembly code under `flake/`.
Do not expose assembly helpers as public flake outputs unless an external consumer needs them.
Keep `flake.nix` focused on inputs and public outputs.
A public output is any attribute returned by the flake `outputs` function.
Another flake can reference a public output through `inputs.<name>.<output>`.
Tools such as `nix flake show` also display public outputs.
Avoid:
```nix
# flake.nix
let
mkHosts = hostsDir: ...;
in
{
nixosConfigurations = mkHosts (self + "/hosts");
}
```
Use:
```nix
# flake.nix
let
flakeAssembly = import ./flake {
inherit inputs self;
lib = nixpkgs.lib;
};
in
{
nixosConfigurations = flakeAssembly.mkHosts (self + "/hosts");
}
```
### Expose only supported flake outputs
Use public outputs for the supported interface of this flake.
Do not expose assembly helpers as public outputs unless an external consumer needs them.
Keep internal helpers in `flake/` or `dotfiles` special arguments.
Avoid:
```nix
{
lib = flakeAssembly;
nixosConfigurations = flakeAssembly.mkHosts (self + "/hosts");
}
```
Use:
```nix
{
nixosConfigurations = flakeAssembly.mkHosts (self + "/hosts");
}
```