| name | nix-agent-init |
| description | Use when the user wants to make a NixOS/Home Manager config repo agent-ready (AGENT_MAP.md, CLAUDE.md, .mcp.json) and the host exposes the nix-agent MCP server. |
Nix Agent Init
Overview
Make a NixOS/Home Manager config repo agent-ready in one pass. Run
nix-agent inspect-flake once, then generate three artifacts, each derived
from the returned facts and the files you actually read:
AGENT_MAP.md: task-routing table plus search shortcuts.
CLAUDE.md (+ AGENTS.md): a one-screen repo brief.
.mcp.json: wires nix-agent and mcp-nixos.
Everything you write must trace back to an observed fact. A sparse repo
gets a short map; a rich repo gets a longer one. Never pad with generic
NixOS advice, aspirational structure, or rules the facts do not support.
If a fact is null or "unknown", say so or omit the row. Do not invent.
You do not run nix flake show yourself: nix-agent inspect-flake does.
You do read the repo's own files (module dirs, flake.nix) with your native
tools to name real files in the tables.
Step 1: Inspect
Run nix-agent inspect-flake (via Bash); it prints the fact bundle as JSON.
With no argument it auto-resolves the target; if the user named a repo, pass
the path: nix-agent inspect-flake /path/to/repo.
The returned facts drive every decision below:
flake_dir: absolute repo path. Pin .mcp.json to this.
hosts: nixosConfiguration names. null means flake show failed.
home_configurations: standalone HM outputs.
hm_integration: "integrated", "standalone", "none", or
"unknown".
module_dirs: dirs where module files actually live.
auto_import: "import-tree", "none", or "unknown".
formatter: "treefmt", "nixfmt", a passthrough name, or "none".
lint_tools: subset of ["deadnix", "statix"] on PATH.
has_justfile, has_ci: booleans.
mcp_json: "present" or "absent".
If hosts is null (flake show failed), note in CLAUDE.md which facts
are unavailable and read note / first_error, then continue with the
file-level facts only (module_dirs, auto_import, has_justfile,
mcp_json). Do not stall.
Read the module_dirs with your native tools so the routing table names
real files (hosts/laptop.nix, modules/nixos/desktop.nix), not
placeholders. If module_dirs is empty, the table stays generic and
short; that is correct, not a gap to fill.
Step 2: AGENT_MAP.md
A task-routing table plus search shortcuts, both keyed to the layout you
observed. Columns: Task, Inspect first, Usually edit, Validate.
Derive the Validate column from has_justfile:
has_justfile == true: read the justfile and map validation to its real
recipes (just check, just switch). Cite recipes that exist, not ones
you assume.
- otherwise: the nix-agent ladder,
check("lint") then
check("dry-build") then diff() then switch(). Drop check("lint")
from the recommendation if lint_tools is empty.
Derive Usually edit targets from module_dirs and the files you read.
One row per real task the layout supports (add a package, change a host
option, edit an HM program). Do not emit rows for structure the repo does
not have.
Add a Search shortcuts section keyed to the repo's actual directory
names, so an agent greps the right place. Add an Edit rules section
only for rules the facts support, for example:
auto_import == "import-tree": "Drop a new .nix file into
<module_dir>; it is imported automatically, no manual import line."
auto_import == "none": note that new modules need an explicit import.
Skeleton (this is the shape, not the content; every cell must come from
this repo's facts):
<!-- generated by nix-agent /init -->
# Agent Map
<!-- nix-agent:begin routing -->
| Task | Inspect first | Usually edit | Validate |
| --- | --- | --- | --- |
| Add a system package | `eval_config("environment.systemPackages")` | `modules/nixos/packages.nix` | `check("dry-build")` then `diff()` then `switch()` |
<!-- nix-agent:end routing -->
<!-- nix-agent:begin search -->
## Search shortcuts
- Host definitions: `hosts/`
- NixOS modules: `modules/nixos/`
<!-- nix-agent:end search -->
Step 3: CLAUDE.md and AGENTS.md
A one-screen repo brief. Include only what the facts establish: what this
repo is, its hosts, its HM mode, the validation commands (justfile
recipes or the nix-agent ladder), and gotchas the facts support.
When hm_integration == "integrated", state the mode trap plainly: Home
Manager is wired in as a NixOS module, there is no separate
home-manager switch, and nix-agent calls that touch HM options must use
mode="nixos" (the default) with the attr spelled
home-manager.users.<user>.<attr>.
When hm_integration == "standalone", note that HM is its own flake and
its operations use mode="home-manager".
Keep it to one screen. Do not restage generic NixOS tutorials.
Then create AGENTS.md as a symlink to CLAUDE.md:
ln -s CLAUDE.md AGENTS.md
If the platform cannot symlink, write AGENTS.md as a copy carrying the
same markers.
Step 4: .mcp.json
Wire both servers. Pin NIX_AGENT_FLAKE to flake_dir. Append #<host>
only when exactly one host exists; with several hosts, pin the bare dir
and tell the user which host you would otherwise have defaulted to so they
can set it. Never put a secret, token, or password in this file.
{
"mcpServers": {
"nix-agent": {
"command": "nix-agent",
"env": { "NIX_AGENT_FLAKE": "<flake_dir>[#<host>]" }
},
"mcp-nixos": {
"command": "mcp-nixos"
}
}
}
Match the host's actual MCP config schema if it differs from this shape;
the constants are the two server names and the NIX_AGENT_FLAKE pin.
Marker and no-clobber contract
This is exact and testable. Follow it verbatim.
-
Every file you generate starts with the header line, on its own line:
<!-- generated by nix-agent /init -->
-
Each section you own is bounded by a matched pair:
<!-- nix-agent:begin <section> -->
...generated content...
<!-- nix-agent:end <section> -->
-
On a re-run, regenerate ONLY the content between marker pairs. Text
the user added outside any marked section is left byte-for-byte intact.
-
If a target file already exists and does NOT contain the header marker,
it is hand-written. Do NOT write it. Instead show the proposed content
as a diff and let the user decide. This holds for CLAUDE.md,
AGENT_MAP.md, and .mcp.json alike. .mcp.json is JSON and cannot
carry HTML comments, so treat ANY existing .mcp.json as hand-written:
propose the merged content as a diff, never silently replace it.
What not to do
- No validation infrastructure. Do not create justfiles, CI workflows, or
git hooks. Report the ladder; do not build one.
- No editing hand-written docs. Existing unmarked
CLAUDE.md /
AGENT_MAP.md are proposed-as-diff only, never overwritten.
- No secrets in
.mcp.json. Reference them via sops-nix/agenix elsewhere;
this file holds only the flake pin and server names.
- No boilerplate. Every line traces to a fact from
nix-agent inspect-flake
or a file you read. When a fact is missing, omit the line.