# 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 ```sh # 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: ```nix { lib, stdenv, }: ``` ### Imports and Dependency Injection - Use **relative path imports**: `import ./pkgs { inherit pkgs; }` - Pass dependencies via **function arguments** (dependency injection), never globals - Use `inherit` to concisely forward bindings: `{ inherit pkgs system; }` - Use `pkgs.callPackage` to auto-inject dependencies into package definitions ### Package Definition Template Every package follows this pattern: ```nix { 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: ```nix { 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: ```nix final: prev: let customPkgs = import ../pkgs { pkgs = final; }; in { inherit (customPkgs) example-a example-b; } ``` ### Comments - Prefer **self-documenting code** via `description` attributes in `meta` blocks - 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 `assert` for preconditions when needed - Use `lib.warn` or `lib.info` for non-fatal diagnostics - Use `builtins.throw` for fatal errors with descriptive messages ### Flake Outputs Follow the standard flake output schema: - `packages..` -- built packages - `packages..default` -- the default package - `devShells..default` -- development shell - `checks..` -- CI checks - `overlays.default` -- nixpkgs overlay The flake uses `flake-utils.lib.eachDefaultSystem` for multi-platform support. ## Dev Environment - **direnv** auto-activates the dev shell (`.envrc` contains `use 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.org` is configured as an extra substituter