5.4 KiB
AGENTS.md
Guide for AI coding agents working in this repository.
Project Overview
This is a pure Nix flake project that exposes custom Nix packages, a development
shell, checks, and a nixpkgs overlay. All source files are written in the Nix
expression language (.nix files). There is no traditional programming language
involved -- this is purely Nix infrastructure/packaging code.
Repository Structure
flake.nix # Main flake entry point (inputs, outputs, nixConfig)
flake.lock # Pinned flake dependency versions
.envrc # direnv integration ("use flake")
.gitignore # Ignores result, result-*, .direnv
pkgs/
default.nix # Package set aggregator (barrel file)
example-a/default.nix
example-b/default.nix
checks/
default.nix # Flake checks (formatting enforcement)
devshells/
default.nix # Development shell with tooling
overlays/
default.nix # Nixpkgs overlay re-exporting packages
Every directory uses default.nix as its entry point -- this is the Nix equivalent
of index/barrel files. The top-level flake.nix imports each module via
import ./pkgs, import ./checks, etc.
Build / Check / Format Commands
# Build the default package
nix build
# Build a specific package
nix build .#example-a
nix build .#example-b
# Run all flake checks (currently: formatting validation)
nix flake check
# Format all Nix files (MUST pass before committing)
nixfmt flake.nix pkgs checks devshells overlays
# Check formatting without modifying files
nixfmt --check flake.nix pkgs checks devshells overlays
# Enter the development shell (provides nixfmt, nil, nix-tree)
nix develop
# View the dependency tree of a package
nix-tree .#example-a
# Update flake inputs
nix flake update
Testing
There are no unit/integration tests. The only check is formatting validation
via nix flake check, which runs nixfmt --check against all .nix files.
Always run nix flake check before committing to ensure formatting is correct.
Code Style Guidelines
Formatter
nixfmt-rfc-style is enforced via nix flake check. Always format files with
nixfmt before committing. The formatter is available in the dev shell.
Indentation and Whitespace
- 2 spaces for indentation (no tabs)
- Opening brace on the same line as context
- Trailing semicolons on all attribute definitions
Naming Conventions
| Entity | Convention | Examples |
|---|---|---|
| Files / directories | kebab-case |
example-a, example-b |
| Entry point files | default.nix |
Always default.nix per directory |
| Attributes/variables | camelCase |
installPhase, buildInputs |
| Package names | kebab-case |
example-a, nixfmt-rfc-style |
Function Parameters
Always list parameters one per line with a trailing comma, enclosed in braces:
{
lib,
stdenv,
}:
Imports and Dependency Injection
- Use relative path imports:
import ./pkgs { inherit pkgs; } - Pass dependencies via function arguments (dependency injection), never globals
- Use
inheritto concisely forward bindings:{ inherit pkgs system; } - Use
pkgs.callPackageto auto-inject dependencies into package definitions
Package Definition Template
Every package follows this pattern:
{
lib,
stdenv,
}:
stdenv.mkDerivation {
pname = "package-name";
version = "0.1.0";
src = ./.;
installPhase = ''
# build/install commands
'';
meta = {
description = "Short description of the package";
license = lib.licenses.mit;
platforms = lib.platforms.all;
};
}
Module / Barrel File Pattern
Aggregator files (pkgs/default.nix) collect sub-packages and define a default:
{ pkgs }:
let
self = {
example-a = pkgs.callPackage ./example-a { };
example-b = pkgs.callPackage ./example-b { };
};
in
self // { default = self.example-a; }
Overlay Pattern
Overlays use inherit to selectively re-export packages:
final: prev:
let
customPkgs = import ../pkgs { pkgs = final; };
in
{
inherit (customPkgs) example-a example-b;
}
Comments
- Prefer self-documenting code via
descriptionattributes inmetablocks - Inline comments are used sparingly and only when the intent is non-obvious
- No JSDoc or similar documentation patterns -- Nix is declarative
Error Handling
- Nix is a purely functional language; errors are build-time evaluation failures
- Use
assertfor preconditions when needed - Use
lib.warnorlib.infofor non-fatal diagnostics - Use
builtins.throwfor fatal errors with descriptive messages
Flake Outputs
Follow the standard flake output schema:
packages.<system>.<name>-- built packagespackages.<system>.default-- the default packagedevShells.<system>.default-- development shellchecks.<system>.<name>-- CI checksoverlays.default-- nixpkgs overlay
The flake uses flake-utils.lib.eachDefaultSystem for multi-platform support.
Dev Environment
- direnv auto-activates the dev shell (
.envrccontainsuse flake) - nil (Nix LSP) is available in the dev shell for editor integration
- nix-tree is available for inspecting dependency trees
- Binary cache:
nix-community.cachix.orgis configured as an extra substituter