Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

nix-skills

nix-skills is a collection of portable skills that give AI coding agents (Claude Code, Codex, OpenCode, Antigravity and others) current, source-backed knowledge of Nix, NixOS, Home Manager, nix-darwin, devenv, Nixpkgs, and running coding agents on NixOS.

Agents often give Nix advice that is out of date, meant for another distribution, or imperative: nix-env -i, editing generated files, curl | sh. A skill is a folder of instructions and references that the agent loads when a request matches. With these skills installed, the agent proposes declarative, reversible changes based on the versions you actually run.

The collection installs skills, not agents. To install an agent itself on NixOS, see the nixos-coding-agents skill.

Where to start

You want toGo to
Install the skills and try themGetting started
Install for a specific agent, or without Home ManagerInstall the skills
See which skills exist and where their content comes fromSkill catalog
Understand how the references stay currentHow updates work
Add or improve a skillContribute a skill

The source is on GitHub. The catalog, the update schedule and the module options on this site are generated from the repository when the site is built, so they match the published commit.

Getting started

This tutorial installs the skills for one agent on NixOS, checks that the agent sees them, and gives you the first prompt to use. It assumes Home Manager is used as a NixOS module in a flake-based system configuration. For other setups, see Install the skills.

1. Add the input and enable the module

Add the input to your system flake, and commit the lock file:

inputs.nix-skills.url = "github:olafkfreund/nix-skills";

Enable the module for your user (replace alice; inputs must be in scope), and pick your agents:

home-manager.users.alice = {
  imports = [ inputs.nix-skills.homeManagerModules.default ];
  programs.nix-skills = {
    enable = true;
    agents = [ "claude" ];
  };
};

Rebuild through NixOS with nixos-rebuild, never home-manager switch. The agents values are listed in Install the skills.

2. Check that the agent sees them

ls ~/.claude/skills   # or your agent's directory

Then, in the agent, run /skills (Claude Code, Codex) or ask “Which skills do you have available?” (OpenCode, Antigravity). If a skill is missing, see Fix skill discovery.

3. Start with this prompt

Open your agent in your system configuration repository and paste:

Use the nix-skills skills. I'm on NixOS and want to set up this machine for
agentic coding. Read my system configuration first, tell me what you found,
and propose changes as a diff. Do not rebuild, install or run containers
until I approve.

4. Try more requests

You askSkill it should use
“My rebuild fails with ‘The option … does not exist’. What changed?”nixos-operations, nixos-wiki
“Add a devenv shell with Python 3.12 and Postgres to this repo.”devenv-project
“Which package provides libssl.so, and how do I reference it?”nix-workflow
“Move my shell and git config into Home Manager.”home-manager
“Package this Go CLI with buildGoModule.”nixpkgs-development
“Run Claude Code on this repo so it cannot read ~/.ssh.”nixos-coding-agents

The full list is in the skill catalog.

Next: agentic coding on NixOS

As a NixOS user with no AI agent yet, I want a coding agent set up declaratively, and optionally sandboxed, so that I can start agentic coding without breaking my system or exposing my secrets.

  1. Run an agent once, without installing it.

    nix run github:numtide/llm-agents.nix#claude-code   # or #codex, #opencode, #antigravity-cli
    

    Check: it starts, and nothing is installed.

  2. Install the skills for that agent, as in step 1 above, and rebuild. Check: as in step 2 above.

  3. Give the start prompt from your system configuration repository. Check: the agent reads your configuration and proposes a diff without applying it. Typically the diff adds the llm-agents.nix input and your agent, the Numtide binary cache, and optionally virtualisation.podman.enable for sandboxing.

  4. Review the diff, then build and switch yourself: nixos-rebuild build, then nixos-rebuild switch. Check: the agent is on your PATH without nix run. Undo: roll back to the previous generation.

  5. Per project. In a code repository, ask for a devenv shell (devenv-project). For repositories you do not trust, ask to run the agent in a container or an agent-box worktree (nixos-coding-agents). Check: the devenv shell activates, and the sandbox check from nixos-coding-agents stories 3 and 4 passes.

SkillPurposeInitial reference
devenv-projectConfigure and troubleshoot devenv project environmentsdevenv v2.3.1
home-managerConfigure Home Manager user environments and NixOS integrationHome Manager master snapshot
microvm-nixConfigure declarative microVMs with microvm.nixmicrovm.nix main snapshot
nix-darwinConfigure nix-darwin macOS systems and darwin-rebuild generationsnix-darwin master snapshot
nix-languageWrite, explain, debug, and review Nix expressionsNix 2.35.2
nix-workflowChoose Nix commands, find packages and files, use dev shells, debug builds, and navigate the ecosystemAuthored guidance; ecosystem status checked 2026-09-23
nixos-coding-agentsChoose, install and sandbox AI coding agents with llm-agents.nix, agent-images and agent-boxAuthored guidance linking upstream; checked 2026-09-23
nixos-operationsOperate NixOS: rebuild modes, generations and rollback, upgrades, store cleaning, boot and servicesNixOS manual chapters from the Nixpkgs master snapshot
nixpkgs-developmentPackage software and use Nixpkgs helpers, overlays, and library APIsmaster snapshot; development series 26.11
nixos-wikiFind retained NixOS configuration and troubleshooting guidance17 curated topics from the 2026-09-22 dump

Each package records its upstream snapshot identity, curated selection, and input/output hashes in its own sources.json. References cover selected topics, not every upstream feature. Agents must check the project’s actual versions. The Nix skill does not supply NixOS options or replace Nixpkgs API documentation. The portable devenv-project skill is distinct from a machine-specific devenv policy skill and upstream’s devenv-setup; their behavior is not interchangeable. Each skill can be installed independently.

The demo VM and Set up your own machine now cover steps 1 to 4 in a single command or import.

Try it in a demo VM

The demo is a disposable NixOS virtual machine with coding agents and these skills already installed. It changes nothing on your own system, and deleting one file resets it.

What is inside

  • Agents from llm-agents.nix: Claude Code (claude, unfree), Codex (codex) and OpenCode (opencode).
  • The skills, installed for Claude Code (~/.claude/skills) and Codex (~/.agents/skills). OpenCode reads both directories, so it sees them too without a duplicate copy.
  • Podman for the sandbox examples in the nixos-coding-agents skill, and devenv.
  • A sample project in ~/example, with the start prompt and a small Python devenv setup.

There are no API keys or accounts in the image. You sign in or add your own key inside the VM.

Requirements

  • Linux with KVM (/dev/kvm), on x86_64 or aarch64.
  • Nix 2.26 or newer with flakes enabled. The demo uses a relative flake input, which older versions do not support.
  • About 3.8 GiB to download: the VM’s closure. The agents are 245 to 555 MiB each. Accepting the flake’s nixConfig adds the Numtide binary cache.
  • 4 GiB of RAM and 4 CPU cores for the VM. Its disk file grows to at most 16 GiB.

1. Start it

mkdir nix-skills-demo && cd nix-skills-demo
nix run github:olafkfreund/nix-skills?dir=demo

The VM starts in your terminal and logs in automatically as demo on the console. The disk file nix-skills-demo.qcow2 is created in the current directory.

To use a second terminal, connect over SSH. It is forwarded only to your own machine’s loopback address:

ssh -p 2222 demo@127.0.0.1   # password: demo

The fixed password is safe only because of that loopback forward. Never forward the port more widely.

2. Sign in to an agent

Start the agent you want and follow its sign-in, or export your own key in the VM, for example export ANTHROPIC_API_KEY=… for Claude Code or export OPENAI_API_KEY=… for Codex.

3. Check the skills and try the prompt

cd ~/example
claude          # or codex, or opencode

In the agent, run /skills (Claude Code, Codex) to see the collection, then paste the start prompt from ~/example/README.md. Inside the demo, the “system configuration” the agent reads is the VM itself.

4. Stop and reset

Shut down with sudo poweroff inside the VM, or press Ctrl-a then x in the console. To start from scratch, delete nix-skills-demo.qcow2.

Change the agents

Clone the repository, edit nix-skills.agentic.agents in demo/demo.nix (choose from claude-code, codex, opencode and gemini-cli), and run nix run ./demo. Gemini CLI has no skill directory in the Home Manager module yet, so it does not get the skills installed.

Limits

  • The demo is a convenience, not a hardened sandbox. It protects your own files from the agent, but anything you type or copy into the VM is readable inside it.
  • It is built only as a VM. nixos-rebuild cannot build nixosConfigurations.demo for real hardware, because it defines no disks or bootloader. To set up your own machine with the same module, follow Set up your own machine.
  • A test in CI boots this VM and checks the agents and skills on every change to the demo, the module or the skills.

Install the skills

Every skill is a complete, self-contained folder. Install whole folders: SKILL.md needs its references/, sources.json and licence file.

Add inputs.nix-skills.url = "github:olafkfreund/nix-skills"; to your flake, import inputs.nix-skills.homeManagerModules.default for your user, and set programs.nix-skills:

programs.nix-skills = {
  enable = true;
  agents = [ "claude" "codex" ];
  # skills = [ "nix-language" "nixos-operations" ];  # omit for all skills
};

The module links each selected skill directory, read-only from the Nix store, into each agent’s skill directory. Existing files keep Home Manager’s normal collision protection. All options are listed in Home Manager module options.

When Home Manager is a NixOS module, rebuild with nixos-rebuild. Never run home-manager switch in that setup.

Agents and directories

Agentagents valueSkill directoryCall a skill
Claude Code"claude"~/.claude/skills/nixos-coding-agents
Codex"codex"~/.agents/skills$nixos-coding-agents
OpenCode"opencode"~/.config/opencode/skillsName the skill in your prompt
Antigravity"antigravity"~/.gemini/config/skills/nixos-coding-agents

List the installed skills with /skills in Claude Code and Codex; in OpenCode and Antigravity, ask the agent which skills it has.

All four also pick a skill automatically when a request matches its description. Directories and syntax were checked against each agent’s documentation on 2026-09-23. OpenCode also reads ~/.claude/skills and ~/.agents/skills and needs unique skill names: if you already selected "claude" or "codex", do not add "opencode".

For one shared or custom location, set directory instead of agents, for example directory = ".agents/skills";. Do not combine the two.

Without Home Manager

The collection is also a data package. It exposes share/nix-skills/<name> but creates no links:

environment.systemPackages = [
  inputs.nix-skills.packages.${pkgs.stdenv.hostPlatform.system}.nix-skills
];

Or clone a reviewed commit and link folders by hand:

git clone https://github.com/olafkfreund/nix-skills.git
cd nix-skills
git checkout --detach <reviewed-commit-sha>
mkdir -p ~/.agents/skills
ln -s "$PWD/skills/nix-workflow" ~/.agents/skills/nix-workflow

Repeat the link for each skill you want, using your agent’s directory from the table. For an agent without native skill discovery, ask it to read the chosen SKILL.md and its linked references before the task.

Module and package details

Copy or link the whole desired skill directory into your agent’s supported skill directory. Keep references/, sources.json, and its license (COPYING for Nix/Nixpkgs/wiki, LICENSE for devenv/Home Manager/microvm.nix) with SKILL.md. If your configuration manages agent files declaratively, declare that link or copy in your configuration instead. No installation is performed by this repository’s checks or update workflow.

For an agent without native skill discovery, explicitly ask it to read the chosen SKILL.md and the relevant linked references before the task. Portability of the files does not imply native discovery has been tested in every agent.

This links complete immutable skill directories, including resources and licenses, under the user’s home. Existing files retain Home Manager’s normal collision protection; links are never forced. Disabling the module adds no installation effects. Unknown or duplicate names and absolute/traversing destinations are rejected. The module builds data with your existing pkgs; it does not replace your host’s Nixpkgs input or install an agent.

To install the complete collection for all supported agents, select their native user skill directories:

programs.nix-skills = {
  enable = true;
  agents = [ "claude" "codex" "opencode" "antigravity" ];
};

The agent destinations are .claude/skills, .agents/skills, .config/opencode/skills, and .gemini/config/skills, respectively. Set skills alongside agents to install only a subset. The existing directory option remains the compatibility path for one shared or custom destination; do not combine a custom directory with agents. This installs skill bundles, not the agents themselves or their plugin configuration.

Validate and rebuild through your existing NixOS workflow. Do not run home-manager switch when Home Manager is a NixOS module. The default path and symlink support follow Codex’s documented discovery locations. For another agent, select its documented relative directory; native discovery in other agents is not claimed by package/module checks.

Without Home Manager, the collection is also a data package:

environment.systemPackages = [
  inputs.nix-skills.packages.${pkgs.stdenv.hostPlatform.system}.nix-skills
];

This exposes share/nix-skills/<name> in the package; it does not create user discovery links. Declare those separately in your own configuration. Individual outputs, for example packages.x86_64-linux.nix-language, contain the same complete directory. default contains all registered skills. Packages are exported for x86_64-linux and aarch64-linux; our validation distinguishes native x86_64 builds from aarch64 evaluation.

Codex also reads a project’s .agents/skills/, and symlinked skill directories are supported (Codex skill discovery documentation). Repository builds and checks never activate a home or host.

Set up your own machine

Put coding agents and the skills on your own NixOS machine with one module, nixosModules.agentic. Try everything first in the demo VM; the demo is built on this same module.

The module only adds what its options ask for: agent packages, the skills for one user’s agents, and optionally the Numtide binary cache, Podman and devenv. It never adds users, passwords, logins, SSH, firewall or boot settings, and it does not touch your nixpkgs config.

Route A: an existing flake configuration

Add the input. It is the repository’s demo/ flake, which pins llm-agents.nix:

inputs.agentic.url = "github:olafkfreund/nix-skills?dir=demo";

Import the module next to Home Manager’s NixOS module, and set the options:

nixosConfigurations.my-machine = nixpkgs.lib.nixosSystem {
  modules = [
    home-manager.nixosModules.home-manager
    inputs.agentic.nixosModules.agentic
    ./configuration.nix
  ];
};
# configuration.nix
nix-skills.agentic = {
  enable = true;
  agents = [ "claude-code" "codex" ];
  user = "alice";
};

Build with nixos-rebuild build --flake .#my-machine, then switch. When Home Manager is a NixOS module, never use home-manager switch.

If you already install the skills through homeManagerModules.default yourself, set user = null so that the module installs only the agents.

Route B: a new configuration from the template

mkdir my-nixos && cd my-nixos
nix flake init -t github:olafkfreund/nix-skills#agentic-nixos
nixos-generate-config --show-hardware-config > hardware-configuration.nix

Edit the parts of configuration.nix marked CHANGE ME: the boot loader, your user (the template sets no password) and the agents. Then build and switch as in route A. The template is a starting point: it does not boot until your hardware configuration is in place.

Options

OptionDefaultEffect
nix-skills.agentic.enablefalseTurns the module on
nix-skills.agentic.agents[ "claude-code" ]Agents from llm-agents.nix: claude-code, codex, opencode, gemini-cli
nix-skills.agentic.usernullThe Home Manager user whose agents get the skills; null installs none
nix-skills.agentic.cache.enabletrueAdds https://cache.numtide.com and its key to nix.settings
nix-skills.agentic.podman.enablefalseEnables rootless Podman for sandboxed agents
nix-skills.agentic.devenv.enablefalseAdds devenv

Notes

  • Skill directories. With Claude Code or Codex selected, the skills go into ~/.claude/skills and ~/.agents/skills. OpenCode reads those too, so it only gets its own directory when neither is selected. Gemini CLI has no skill directory in the Home Manager module yet.
  • Licences. claude-code is labelled unfree upstream; codex, opencode and gemini-cli are free. llm-agents.nix marks its unfree licence as allowed, so no allowUnfree setting is needed or effective.
  • Cache. Adding a binary cache means trusting its key. Set cache.enable = false to build everything yourself.
  • Updates. nix flake update agentic moves the agents and the module to the demo flake’s latest pins. Review the lock change, then rebuild.
  • Missing Home Manager. Setting user without importing home-manager.nixosModules.home-manager fails with an assertion that says so.

Add agents and skills to a project

Give one repository its own skills, pinned with the project, so every contributor’s agent gets the same skills there. Nothing is installed outside the project directory, and no Home Manager or NixOS is needed: only Nix and devenv.

The project imports the nix-skills/devenv module. On devenv shell it links whole skill folders (with their references and licences) into the project’s agent skill directories:

DirectoryRead by
.claude/skillsClaude Code, OpenCode
.agents/skillsCodex, Antigravity, OpenCode

A new project

mkdir my-project && cd my-project
nix flake init -t github:olafkfreund/nix-skills#project
devenv shell

The template adds devenv.yaml, devenv.nix, a .gitignore for the links and a README. Start your agent in the project and check the skills with /skills.

An existing devenv project

Add the input and the import to devenv.yaml:

inputs:
  nix-skills:
    url: github:olafkfreund/nix-skills
    flake: false
imports:
  - nix-skills/devenv

Choose skills in devenv.nix:

{
  nix-skills.skills = [ "nix-workflow" "nix-language" "devenv-project" ];
}

Add one .gitignore line per skill and directory, for example .claude/skills/nix-workflow and .agents/skills/nix-workflow. The links point into /nix/store; the shell prints a reminder for any link that is not ignored.

Options

OptionDefaultEffect
nix-skills.enabletrueLink the skills
nix-skills.skillsnix-workflow, nix-language, devenv-projectSkills to link, by catalog name
nix-skills.directories.claude/skills, .agents/skillsWhere to link them

Skill names are checked against the skill catalog; a typo fails with the list of valid names.

Pin an agent in the project

Add the llm-agents.nix input to devenv.yaml:

inputs:
  llm-agents:
    url: github:numtide/llm-agents.nix

and the agent to devenv.nix:

{ pkgs, inputs, ... }:
{
  packages = [ inputs.llm-agents.packages.${pkgs.stdenv.hostPlatform.system}.claude-code ];
}

Agent support

Claude Code and Codex document support for linked skill directories. OpenCode and Antigravity do not; check that the agent lists the skills. If one does not follow the links, copy that skill instead:

{
  files.".agents/skills/nix-workflow".copyMode = "copy";
}

Update

devenv update nix-skills

Review the devenv.lock change, then enter the shell again. Removed skills’ links are cleaned up automatically.

What the module never does

  • It writes nothing outside the listed project directories and devenv’s own state.
  • It never replaces an existing file or directory at a link’s path: devenv only warns, so a project’s own skills are left alone.
  • It installs no agent unless you add one as above.

Update and roll back

The skills you use are whatever commit your flake lock (or checkout) pins. Nothing updates on its own.

With a flake input

Update only this input, review the change, then rebuild:

nix flake update nix-skills
git diff flake.lock

What changed between two commits is visible on GitHub: https://github.com/olafkfreund/nix-skills/compare/<old>...<new>.

To roll back, restore the previous flake.lock (for example git checkout HEAD~1 -- flake.lock) and rebuild, or boot the previous NixOS generation.

With a clone

Check out a newer reviewed commit (git checkout --detach <sha>). Linked folders follow the checkout; copied folders must be replaced as complete directories. To roll back, check out the previous commit.

What changes between versions

Generated references change when upstream sources change; see the update schedule. Hand-written guidance changes only through reviewed pull requests; see How updates work.

Fix skill discovery

Check the files first

ls -l ~/.claude/skills           # or your agent's directory
ls ~/.claude/skills/nix-workflow  # SKILL.md must be present

If the directory is empty, the module is not enabled for this user, or the system was not rebuilt. With Home Manager as a NixOS module, rebuild with nixos-rebuild, not home-manager switch.

Then check the agent

  • Claude Code, Codex: run /skills. Both document support for symlinked skill directories.
  • OpenCode, Antigravity: ask “Which skills do you have available?”. Neither documents whether it follows symlinked skill directories, and the module installs each skill as a link into /nix/store. If a skill is missing here, please open an issue with the agent version.

Common causes

SymptomCauseFix
OpenCode shows each skill twiceOpenCode also reads ~/.claude/skills and ~/.agents/skillsRemove "opencode" from agents when "claude" or "codex" is selected
Home Manager refuses to create a linkA file or folder already exists at the destinationMove the existing item away; links are never forced
A skill is present but never usedIts description did not match the requestCall it explicitly, see Install the skills
Old guidance after an updateThe agent session started before the rebuildStart a new agent session

Contribute a skill

Contributions follow the repository’s CONTRIBUTING.md and AGENTS.md. In short:

  1. Open an issue and work on a task branch (feat/<issue>-<slug>), with Conventional Commits.

  2. Write the design first. Tasks that are tracked as issues or touch several files need three reviewed documents, each approved before the next: intent/ (why), spec/ (what) and plan/ (how). Nobody approves their own.

  3. Add the package: skills/<name>/SKILL.md with exactly name and description frontmatter, detail in linked references/, and the name in the sorted skills.json.

  4. Keep provenance. Copied upstream material needs sources.json and the upstream licence. Hand-written skills need neither.

  5. Follow the Nix style rules.

  6. Run the checks before opening the pull request:

    devenv shell check-fast
    nix flake check
    nix build .#nix-skills --no-link
    nix build .#docs
    

main is protected: a pull request and a passing collection-check are required. Registering a skill never enrols it in automatic updates; a new upstream updater needs its own design review.

Documentation pages

Site pages live in docs/src/ and must be listed in docs/src/SUMMARY.md. The skill catalog, the update schedule and the module options are generated when the site is built; never edit them by hand.

Narrow the update token

Update pull requests are pushed and opened with the repository secret UPDATE_PR_TOKEN, so they get normal pull request checks. It currently holds a classic token with account-wide scopes, an accepted risk recorded in the design history. This guide replaces it with a token that can only touch this repository.

1. Create a fine-grained token

On GitHub, go to Settings → Developer settings → Personal access tokens → Fine-grained tokens → Generate new token, and choose:

  • Repository access: only olafkfreund/nix-skills;
  • Permissions: Contents read and write, Pull requests read and write (Metadata read is added automatically);
  • Expiration: a date you will notice, for example 90 days.

2. Replace the secret

gh secret set UPDATE_PR_TOKEN --repo olafkfreund/nix-skills

Paste the new token when prompted. No workflow change is needed.

3. Verify

Run Update references (gh workflow run update.yml). For any skill with upstream changes, the update pull request should be opened by your account and show normal checks. If the secret is missing or lacks permission, the publication step fails with an error naming UPDATE_PR_TOKEN.

Replacing the secret removes the old token from this repository. Revoke the old token on GitHub only if nothing else uses it; a token kept in a secrets store such as agenix is often shared with other tools.

Skill catalog

Generated from skills.json, each skill’s SKILL.md and sources.json when this site was built.

devenv-project

Create, explain, review, and debug devenv project environments, including devenv.nix, devenv.yaml, lockfiles, languages, tasks, services, and shell activation.

home-manager

Configure and troubleshoot Home Manager user environments on NixOS, nix-darwin or standalone Linux and macOS installations.

microvm-nix

Configure and troubleshoot declarative microVMs with microvm.nix when working in a NixOS flake.

nix-darwin

Configure, build and troubleshoot nix-darwin macOS system configurations and darwin-rebuild generations.

nix-language

Write, explain, debug, and review Nix expressions using versioned upstream language references. Use for syntax, scope, lazy evaluation, functions, strings, paths, derivations, and built-ins; NixOS service options and Nixpkgs APIs need their own references.

nix-workflow

Choose Nix commands, locate store paths and libraries, use development shells, debug builds, configure Nix and navigate ecosystem tools.

  • Licence: Repository licence (MIT)
  • Instructions: SKILL.md

nixos-coding-agents

Choose, install and sandbox AI coding agents on NixOS with llm-agents.nix packages, agent-images containers and agent-box disposable workspaces.

  • Licence: Repository licence (MIT)
  • Instructions: SKILL.md

nixos-operations

Operate NixOS systems by choosing rebuild modes, managing generations and rollback, upgrading, cleaning the store, and diagnosing boot and service problems.

nixos-wiki

Find and interpret retained NixOS Wiki guidance for system configuration, modules, rebuilds, boot, networking, storage and systemd; check applicability against the consumer’s actual NixOS pin.

nixpkgs-development

Write, explain, review, and debug Nixpkgs package expressions, build helpers, overrides, overlays, and library APIs against the project’s pinned package set.

Home Manager module options

Generated from homeManagerModules.default when this site was built.

programs.nix-skills.enable

Whether to enable the selected portable Nix skills.

Type: boolean

Default:

false

Example:

true

Declared by:

programs.nix-skills.agents

Agents to install into their native user skill directories.

Type: list of (one of “antigravity”, “claude”, “codex”, “opencode”)

Default:

[ ]

Declared by:

programs.nix-skills.directory

Destination relative to the home directory, without dot or parent components.

Type: string

Default:

".agents/skills"

Declared by:

programs.nix-skills.skills

Skill directories to link; defaults to the complete collection.

Type: list of (one of “devenv-project”, “home-manager”, “microvm-nix”, “nix-darwin”, “nix-language”, “nix-workflow”, “nixos-coding-agents”, “nixos-operations”, “nixos-wiki”, “nixpkgs-development”)

Default:

[
  "devenv-project"
  "home-manager"
  "microvm-nix"
  "nix-darwin"
  "nix-language"
  "nix-workflow"
  "nixos-coding-agents"
  "nixos-operations"
  "nixos-wiki"
  "nixpkgs-development"
]

Declared by:

Update schedule

Generated from .github/workflows/update.yml when this site was built.

Update references runs on the schedule 17 6 * * 1 (cron, UTC) and on manual dispatch.

Refreshed automatically

  • nix-language
  • devenv-project
  • home-manager
  • microvm-nix
  • nix-darwin
  • nixos-operations
  • nixpkgs-development
  • nixos-wiki

Changed only through reviewed pull requests

  • nix-workflow
  • nixos-coding-agents

How a refresh becomes a merged change is described in How updates work.

Nix style rules

Every SKILL.md in the collection carries these two rules, and scripts/check_collection.py enforces them in hand-written Markdown.

Never search or hard-code the store

Searching /nix/store only finds what happens to be on this machine, cannot tell which path belongs to your pin, and a copied store path breaks on the next update. Instead:

  • find the package that provides a file with nix-locate;
  • refer to it through Nix: ${pkgs.foo}/lib, or lib.makeLibraryPath [ pkgs.foo ].

Do not quote names that need no quotes

An attribute name can be written without quotes when it is a valid identifier (Nix manual): it matches [A-Za-z_][A-Za-z0-9_'-]* and is not a keyword. Dashes are allowed, so pkgs.foo-bar and packages.x86_64-linux need no quotes.

Quotes are needed only for:

  • names outside that grammar: ".config/foo", "2.0", "a.b";
  • the keywords assert else if in inherit let or rec then with;
  • interpolation: "${name}".

What the check does

FindingWhereExample that fails
quoted-namenix code blockspkgs."foo-bar", "foo-bar" = 1;
store-searchany code blockfind or ls of the store, a store glob
store-pathany code blocka hard-coded hashed store path
  • Hand-written files fail the check; generated upstream references are only reported, because they are verbatim copies.
  • A deliberate counterexample needs the line <!-- nix-style: counterexample --> directly before its code fence.
  • This site’s pages are checked the same way when the site is built.

Why skills

The problem

General-purpose AI models learn Nix from a mix of old blog posts, other distributions and imperative habits. Typical results are:

  • nix-env -i or curl | sh instead of a declarative change;
  • editing files that NixOS or Home Manager generate;
  • options that no longer exist, or advice for a different release;
  • searching /nix/store by hand and copying store paths.

What a skill changes

A skill is a folder with a short SKILL.md and linked references. The agent always sees the skill’s one-line description; it loads the full text only when a request matches. That keeps context small while giving the agent, at the moment it needs it:

  • authoritative text, for example the NixOS manual’s rebuild chapters or the Nix language reference, at a recorded upstream revision;
  • rules such as “check the user’s release first” or “propose the rebuild command, do not run it”;
  • routing to the right neighbouring skill.

Why many small skills

Each skill covers one area: the language, NixOS operations, Home Manager, nix-darwin, devenv, Nixpkgs packaging, microVMs, the wiki, everyday Nix workflow, and coding agents on NixOS. Users install only what they need, and each skill can be updated and reviewed on its own. See the skill catalog.

Why pinned and versioned

Advice is only correct for a version. Generated references record exactly which upstream revision they come from, and skills tell the agent to check the user’s actual versions before relying on them. See Hand-written and generated references.

Hand-written and generated references

Each skill has two kinds of content.

Hand-written

Every SKILL.md is written and reviewed by hand: when to use the skill, rules, routing, and the Nix style rules. Two skills are hand-written throughout, nix-workflow and nixos-coding-agents; they link to upstream documentation instead of copying it, because their sources change too often to copy.

Hand-written text changes only through reviewed pull requests, and automated updates never replace it.

Generated from upstream

The other skills also carry references/ generated from upstream sources: the Nix manual, the NixOS manual, Nixpkgs documentation, the Home Manager and nix-darwin repositories, microvm.nix, devenv, and a retained NixOS Wiki dump.

Each such skill has a sources.json that records:

  • the upstream repository or dump, and the branch, release or snapshot;
  • the exact revision or snapshot hash the text was generated from;
  • which upstream files were selected, with their hashes;
  • the hash of every generated output file.

scripts/check.py recomputes these hashes offline, so any hand edit to a generated file, or any mismatch with its recorded source, fails the check. The skill catalog shows each skill’s upstream and pin.

Licences

Generated text is a copy of upstream material and keeps its upstream licence, which ships with the skill as LICENSE or COPYING: for example LGPL-2.1 for the Nix manual, MIT for Nixpkgs, NixOS and Home Manager text, and Apache-2.0 for devenv. The repository does not relicense copied material. Hand-written skills are covered by the repository licence.

Per-skill sources and licences

Each package records its upstream snapshot identity, curated selection, and input/output hashes in its own sources.json. References cover selected topics, not every upstream feature. Agents must check the project’s actual versions. The Nix skill does not supply NixOS options or replace Nixpkgs API documentation. The portable devenv-project skill is distinct from a machine-specific devenv policy skill and upstream’s devenv-setup; their behavior is not interchangeable. Each skill can be installed independently.

Home Manager references originate in nix-community/home-manager and retain its accompanying LICENSE. microvm.nix references originate in microvm-nix/microvm.nix and retain its accompanying LICENSE. nix-darwin references originate in nix-darwin/nix-darwin and retain its accompanying LICENSE. These packages record the selected branch revision, source-file hashes, and generated-output hashes in sources.json; the repository does not relicense copied upstream material.

Design history: intent, spec, implementation plan.

The copied references originate in Nix, whose upstream README identifies LGPL v2.1; the upstream licence accompanies the skill as COPYING. Generated references identify the Nix contributors and link to original files at the recorded revision. The repository does not relicense that material under MIT or another permissive licence. The manifest tracks source files, generator helpers, the full language dump, and generated hashes for reproduction.

Design history: intent, spec, implementation plan.

Devenv references originate in cachix/devenv, under its accompanying Apache-2.0 LICENSE. The manifest hashes selected narrative pages, committed generated data, generators/templates, the upstream setup skill, and the documentation coverage. Modified excerpts retain source attribution. The repository does not relicense Nix material under devenv’s license.

Devenv design history: intent, spec, implementation plan.

Nixpkgs references originate in NixOS/nixpkgs, under its accompanying MIT COPYING. The license of the nixdoc generator does not replace the upstream source license. Nixpkgs design history: intent, spec, implementation plan.

Wiki text is from the official NixOS Wiki, under the retained MIT COPYING from copyright-policy revision 22887. Media can have other terms and is excluded. Wiki design history: intent, spec, plan.

How updates work

Generated references are refreshed by the Update references workflow. Which skills it covers, and when it runs, is on the update schedule. It never merges or installs anything: every refresh becomes a pull request that must pass the same checks as a human change.

The pipeline

  1. Generate (one job per skill, read-only). The updater fetches the latest upstream source, regenerates the skill’s references and sources.json, and runs that skill’s checks and the unit tests. The result is packed into an artifact.

  2. Accept (publication job). A separate job, starting from the current default branch, accepts the artifact only if it is safe. It rejects:

    • a stale base, symlinks, or paths that escape the skill;
    • invalid hashes;
    • changes to hand-written instructions or to the selection of upstream files;
    • Nixpkgs evaluator or branch-policy changes, and changes to any other skill.

    An artifact with no changes is verified and produces nothing.

  3. Publish. For a changed skill, the job pushes that skill’s fixed update branch (for example automation/home-manager-reference-update) and opens or updates at most one pull request for it, with a report of changed inputs, coverage and option or built-in metadata.

  4. Check. The pull request runs the full Check workflow like any other: collection and style checks, every provider’s regeneration check, the flake checks and the distribution builds.

  5. Merge by a person. main is protected: a pull request and a passing collection-check are required, for administrators too. A maintainer reviews the report and merges.

Why it is built this way

  • Least privilege. Generation runs with read-only permissions and never sees a publishing credential. Only the single publication step that pushes and opens the pull request receives UPDATE_PR_TOKEN; see the security model.
  • No silent changes to guidance. The accept step rejects changes to hand-written text, so an upstream change can only ever update generated references.
  • Reviewable. One pull request per skill, with a report, keeps each upstream change small and easy to judge or revert.

Maintainer detail (branches, reports, the token and failure behaviour) is in Automatic updates.

Design history for this pipeline is in the repository’s intent/, spec/ and plan/ folders, for example issues #43 and #48.

Security model

What installing a skill does

A skill is text: instructions and references. Installing it links read-only folders from the Nix store into your agent’s skill directory. The Home Manager module installs no agent, starts no service and never forces over existing files. Some skills describe commands; agents are told to propose rebuilds, secret changes or destructive commands and wait for your approval.

Repository automation

  • Read-only by default. Every workflow’s default token permission is read-only. Pull request checks run with no secrets and cannot publish.
  • No privileged pull request triggers. The repository does not use pull_request_target.
  • Publication is narrow. Only one step, in the job that pushes an update branch and opens its pull request, receives the UPDATE_PR_TOKEN secret. Generation, artifact acceptance and checks never see it, and it is not stored in the job’s git configuration.
  • The token is an accepted risk. UPDATE_PR_TOKEN currently holds a classic token with account-wide scopes. Narrowing it to this repository only needs a new secret value; see Narrow the update token.
  • Protected main branch. Changes need a pull request and a passing collection-check; administrators are included, and force-pushes and branch deletion are blocked.
  • Pinned actions. Every GitHub Action is pinned to a commit hash.
  • The documentation site is deployed by a job that alone holds the Pages permissions; pull requests only build it.

Running coding agents

An agent running directly on your machine can read what you can read, including ~/.ssh, cloud credentials and .env files. The nixos-coding-agents skill explains what containers and disposable worktrees protect, and what they do not: anything you mount or pass into them remains readable.

Maintain the collection

For a new skill, bug fix or development setup, start with CONTRIBUTING.md and AGENTS.md. skills.json registers portable packages; it does not enroll source updaters. Read-only PR checks validate the collection, package/module builds and explicit maintained providers. A reviewed merge makes a contribution available to users who choose to update their pin.

Development environment

The root Devenv environment supplies Python, Git, GitHub CLI, Zstandard, actionlint and Nix, plus two commands:

devenv info
devenv shell check-fast
devenv shell check-providers
nix flake check

check-fast runs offline collection validation, unit tests and workflow lint; check-providers also runs all six explicit maintained-source checks, including network-dependent regeneration. Entering the environment does not run either command, regenerate sources, install skills or start services. The environment was validated with Devenv 2.3.1 and the committed module/input pins.

devenv.lock owns project tooling; flake.lock owns distribution/test inputs. Update them deliberately and separately. The provider fixture under tests/devenv/ has its own lock and remains independent.

Reading the skill needs only a Markdown-capable agent. Offline validation needs Python 3.10 or newer; regeneration additionally needs Git, Nix with nix-command and flakes, and network access to upstream Git tags, source/build caches, and the versioned manual. Nix may build the pinned executable if a substitute is unavailable; no global package installation is required.

Run from the repository root:

python3 scripts/check.py
python3 -m unittest discover -s tests -p 'test_*.py'
python3 scripts/update.py --check

--check obtains Nix from the manifest’s exact upstream revision, regenerates in temporary storage, checks published manual pages/anchors, evaluates tests/language.nix with that executable, and compares bytes without modifying the package. The host Nix is only the bootstrap tool; it is not the documentation generator. Network failures are failures, not skipped checks.

Explicitly update on a task branch with either:

python3 scripts/update.py --release 2.35.2
python3 scripts/update.py --latest

--latest selects the highest numeric stable upstream tag and verifies that the source declares officialRelease = true before generating a changed version. Upstream currently publishes tags rather than GitHub Release objects, so the updater does not rely on /releases/latest. A moved/deleted pinned tag fails for investigation. An unchanged latest revision is a no-op; use --check to force regeneration of the current pin. Generation validates links before replacing files and restores previous bytes if replacement fails. Normal process failures are covered; filesystem/power-loss durability is not a database transaction.

Curated paths, headings, built-in names, and any missing upstream link definitions live under selection in sources.json. Selection edits require review; the bot cannot change them. The initial derivation selection supplies the upstream page’s missing system configuration-option link definition. Upstream source sections retain their wording; reference links, anchors, and incidental prose whitespace are adapted, while fenced code examples are preserved. Only the selected subset is bundled; linked manual pages follow the upstream major/minor documentation series, which may receive later patch-level updates. Exact copied-source provenance remains pinned to a full commit SHA.

Automatic updates

After the workflows reach the default branch, Update references runs each Monday at 06:17 UTC and on manual dispatch. Each skill generates and validates with read-only permissions, then passes an allowlisted artifact to a separate publication job. That job rejects stale bases, symlinks, traversal, invalid hashes, instruction/selection changes, Nixpkgs evaluator/branch-policy changes, and changes to the sibling skill. It updates automation/nix-reference-update, automation/devenv-reference-update, automation/home-manager-reference-update, automation/microvm-nix-reference-update, automation/nix-darwin-reference-update, automation/nixos-operations-reference-update, automation/nixpkgs-reference-update, or automation/nixos-wiki-reference-update, with at most one open PR per skill. Artifacts, branches, and job concurrency are separate for each skill. No-op artifacts are verified but produce no branch or PR. It never merges or installs the result. Reports identify changed selected inputs, coverage changes, and option/built-in metadata changes. Changes to upstream’s devenv setup skill are review signals; authored instructions are never automatically replaced.

Update branches are pushed, and update PRs opened, with the repository secret UPDATE_PR_TOKEN, so they get the same push and pull_request Check runs as any other branch, with no approval step. main is protected: a PR is required, collection-check from GitHub Actions must pass, and the rules include admins, so an update can only merge after Check passes. GITHUB_TOKEN stays read-only everywhere; the publication job only reads the repository with it.

UPDATE_PR_TOKEN currently holds a classic token with account-wide scopes, an accepted risk. It is exposed only to the single publication step that pushes the branch and opens the PR, never to generation, artifact acceptance or Check, and it is not stored in the job’s git configuration. To narrow it, replace the secret’s value with a fine-grained token limited to this repository (Contents and Pull requests: read and write, with an expiry); no workflow change is needed:

gh secret set UPDATE_PR_TOKEN --repo olafkfreund/nix-skills

If the secret is missing or invalid, publication fails with an error naming it.

Failed generation publishes no package. Failed PR creation leaves a validated update branch and an actionable workflow error. The initial Nix live updater passed as a no-op. After merging the devenv addition, validate the first live run too; a no-op does not prove changed-source PR publication.

devenv maintenance

The same commands accept --skill devenv-project; omitting --skill retains all existing Nix behavior:

python3 scripts/check.py --skill devenv-project
python3 scripts/update.py --skill devenv-project --check
python3 scripts/update.py --skill devenv-project --release v2.3.1
python3 scripts/update.py --skill devenv-project --latest

Devenv updates use stable GitHub Releases, not unreleased main. The updater converts selected Markdown/MDX sections, preserving tab labels, version notices, warning meaning, and fenced executable text. Unsupported forms or renamed paths fail for review. It reads the committed options JSON at the same revision and records generator/template provenance; it does not rebuild the full website or option catalogue. Declaration links into devenv are checked and pinned; foreign links retain their distinct origin. Public devenv.sh links are checked but follow the moving site, while exact source citations and hashes remain revision-pinned.

--check obtains the matching CLI from the pinned upstream flake and evaluates matching modules in a disposable project using the reviewed auxiliary pins in tests/devenv/devenv.lock. It compares representative defaults against upstream option data and runs harmless shell/script/task/enterTest assertions. Language and service enablement is evaluated without starting services. The test does not run devenv allow or modify user trust. A candidate update changes only the module pin in its temporary fixture; unrelated input changes fail for review. Local builds can use configured substitutes; CI explicitly uses upstream’s published devenv/Cachix cache keys. There is no fallback to the host CLI.

Home Manager maintenance

python3 scripts/check.py --skill home-manager
python3 scripts/update.py --skill home-manager --check
python3 scripts/update.py --skill home-manager --revision <full-commit-sha>
python3 scripts/update.py --skill home-manager --latest

Home Manager tracks the master branch by full commit revision. The package contains selected manual pages for NixOS-module integration, configuration, dotfiles, modular services, and writing modules. It does not mirror the full option catalogue. Relative source links are pinned to the selected commit, fenced examples are preserved, and the authored SKILL.md is never replaced. An upstream path or license change fails for review rather than changing the curated selection automatically.

microvm.nix maintenance

python3 scripts/check.py --skill microvm-nix
python3 scripts/update.py --skill microvm-nix --check
python3 scripts/update.py --skill microvm-nix --revision <full-commit-sha>
python3 scripts/update.py --skill microvm-nix --latest

microvm.nix tracks the main branch by full commit revision. The package contains selected documentation for VM declarations, declarative deployment, host integration, options, networking, and shares. Generated references pin relative source links and preserve fenced examples; authored instructions and the reviewed selection remain immutable to automation.

nix-darwin maintenance

python3 scripts/check.py --skill nix-darwin
python3 scripts/update.py --skill nix-darwin --check
python3 scripts/update.py --skill nix-darwin --revision <full-commit-sha>
python3 scripts/update.py --skill nix-darwin --latest

nix-darwin tracks the master branch by full commit revision. The package contains nix-darwin’s README, its only prose documentation; options are generated upstream and are not bundled. darwin-rebuild guidance in the authored SKILL.md was checked against pkgs/nix-tools/darwin-rebuild.sh at the initial revision and should be re-checked when that script changes.

NixOS operations maintenance

python3 scripts/check.py --skill nixos-operations
python3 scripts/update.py --skill nixos-operations --check
python3 scripts/update.py --skill nixos-operations --revision <full-commit-sha>
python3 scripts/update.py --skill nixos-operations --latest

NixOS operations follows Nixpkgs master by full commit revision, with its own manifest and the same pinned Nix toolchain and master-ancestry check as nixpkgs-development. It bundles selected NixOS manual chapters (changing the configuration, upgrading, rollback, store cleaning, boot problems and service management). Links to NixOS options come from a reviewed map of option names, and resolve to each option’s declaring file, found by evaluating the NixOS options at the pinned revision. An unmapped, missing or unused option link fails the update for review. The provider reuses the nixpkgs-development manual converter unchanged. Its excerpts are covered by the Nixpkgs COPYING.

NixOS Wiki maintenance and lookup

The wiki skill bundles 17 reviewed English topic pages, the copyright policy and latest template source, with one retained revision per page. It preserves raw wikitext, examples and notices; it does not render MediaWiki templates or mirror the whole wiki. Search excerpts can omit caveats, so read page notices and complete examples before use. Advice still needs checking against the consumer’s actual pin.

python3 skills/nixos-wiki/scripts/wiki.py search 'rebuild'
python3 skills/nixos-wiki/scripts/wiki.py show 'Nixos-rebuild'
python3 skills/nixos-wiki/scripts/wiki.py show 'Garbage Collection' --follow
python3 skills/nixos-wiki/scripts/wiki.py show 'Template:Warning'
python3 scripts/check.py --skill nixos-wiki
python3 scripts/update.py --skill nixos-wiki --check

Lookup and --check need only Python 3.10+, work offline, and never execute wiki examples. show limits each original-text window to 200 lines / 16 KiB and gives continuation arguments (--start, --offset); --lines can request a smaller window. Template search requires --templates. Missing redirect targets are labeled as live, unpinned links; revision citations do not pin templates used by the live website’s renderer. Other agents may read individual JSON records instead.

Ingestion additionally requires zstd; CI supplies it from a fixed Nixpkgs commit. No global installation is needed. On a task branch or disposable copy:

python3 scripts/update.py --skill nixos-wiki --latest
python3 scripts/update.py --skill nixos-wiki --dump /path/to/wikidump.xml.zst --sha256 <expected-sha256>

The updater bounds download/decompression/XML processing, rejects DTD/entities, and verifies the compressed hash and decoder success. It rejects regressions, mutated revision identities, missing primary titles, broken primary redirects and copyright-policy changes. Same-dump and irrelevant-history/recompression changes are no-ops; advanced retained revisions with identical text are reported as provenance-only updates. Changes require review, including template changes.

Retained JSON contains the exact consumed text and metadata, allowing offline reproduction after the moving dump URL changes. The compressed checksum identifies the original acquisition; the subset cannot reconstruct the full historical XML. No full dump, contributor identities/history or media are distributed. Source origin, selection, namespace/size/schema policy and copyright-policy identity are immutable to automation, as are SKILL.md and the package’s lookup helper. Restore the complete package from a reviewed repository commit to roll back.

Nixpkgs maintenance

python3 scripts/check.py --skill nixpkgs-development
python3 scripts/update.py --skill nixpkgs-development --check
python3 scripts/update.py --skill nixpkgs-development --revision 7561e7e3e12a06677b1525a12bcccb0b4e4c601d
python3 scripts/update.py --skill nixpkgs-development --latest

Nixpkgs tracks master snapshots, not releases or channel promotions. The .version value is development-series metadata. --latest resolves master once, requires descendant ancestry from the previous snapshot, and regenerates/tests any advanced SHA, even when only provenance changed. An identical SHA is a no-op. Rewinds, divergence, unavailable inputs and unverifiable ancestry fail for review. Explicit full-SHA repinning is reviewed work; --release is rejected for Nixpkgs.

The updater copies selected doc/ sections and builds the pinned source’s nixpkgs-manual.lib-docs derivation for twelve curated library APIs. It does not rebuild the whole website. Its independently pinned Nix 2.35.2 evaluator cannot change through automated updates. If substitutes are unavailable, Nix may build that evaluator, nixdoc and their dependencies; network/cache access and disk space are needed. Authored instructions, selection, branch and evaluator policy remain reviewed files. The snapshot records consumed inputs, coverage, generated API records and outputs, including the upstream MIT license.

--check verifies deterministic generation and runs a small pinned fixture for argument/attribute overrides, overlays, library/fileset results and generic module composition. It builds a local-source package to check phase hooks and installed output, and executes a small shell helper. Language helpers are evaluated for availability; their full ecosystems are not built. Checks have been exercised on x86_64-linux; this is not a claim of cross-platform or native-agent discovery tests. No services, host configuration, user trust or installed skills are changed.

Custom manual anchors are resolved to bundled sections or pinned source files with named sections. Unsupported documentation syntax fails before replacement. Fenced code is preserved, including illustrative or historical upstream examples; the Python excerpt identifies an upstream duplicate argument needing adaptation. Consumers must use their own project’s pin rather than assume master APIs exist in older Nixpkgs. Roll back by restoring the entire skill from a reviewed commit.