agentleFS
eisbaweisbaw/mped-skills/skills/nix-scaffold/SKILL.md

nix-scaffold

Skill11 starsChanged 3 months agoMITView on GitHub

Scaffold, fix, or diagnose shell.nix and flake.nix files. Use when creating a new Nix dev shell, fixing broken Nix builds (pinned URL errors, stale hashes, missing buildInputs), or migrating between nixpkgs channels. Enforces project conventions - no verbose shellHook echos, minimal footprint.

The file

Show its rules and text

We split this skill into the rules it gives an agent

13 rules. About 0 are common, 6 are distinctive, and 7 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈6

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 7

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    Never add verbose echos to shellHook: - only what's strictly needed (e.g.

    line 12
  2. Very specific:

    If a shell.nix or flake.nix already exists, use it: - do not replace it without the user's explicit approval.

    line 13
  3. Very specific:

    Prefer shell.nix for simple dev shells.

    line 14
  4. Distinctive:

    Before writing anything, check what exists:

    line 27
  5. Distinctive:

    If files already exist, read them first.

    line 35
  6. Very specific:

    If a Justfile exists in the project, ensure just is in buildInputs (otherwise recipes won't run inside the shell).

    line 60
  7. Very specific:

    If nix-prefetch-url isn't available, fall back to letting Nix fail once and copy the got: hash from the error.

    line 71
  8. Very specific:

    If the project uses .envrc with use nix or use flake, warn the user that changes will take effect on the next direnv allow (or direnv …

    line 73
  9. Distinctive:

    Run the evaluator and capture the real error:

    line 77
  10. Distinctive:

    After any change, confirm the shell actually enters:

    line 105
  11. Distinctive:

    If validation fails, loop back to Step 2b with the new error.

    line 113
  12. Distinctive:

    If you could not fix it, say so plainly and state what would be needed (e.g.

    line 133
  13. Very specific:

    If the existing shell.nix / flake.nix already works, say so and don't touch it.

    line 147

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Nix Scaffold -- shell.nix / flake.nix Authoring and Repair

Scaffolds a clean Nix dev environment or diagnoses failures in an existing one. Respects these hard rules:

  • Never add verbose echos to shellHook - only what's strictly needed (e.g. setting env vars, exporting paths). No "Welcome to..." banners, no status spam.
  • If a shell.nix or flake.nix already exists, use it - do not replace it without the user's explicit approval. Diagnose and patch instead.
  • Prefer shell.nix for simple dev shells. Only reach for flake.nix if the project already uses flakes or the user asks for flake output.

When to use

  • User asks to "make a shell.nix", "add a nix dev shell", "pin nixpkgs"
  • nix-shell / nix develop fails with a cryptic error (hash mismatch, missing attribute, eval error)
  • Migrating channels (e.g. 24.11 -> 25.05 -> unstable)
  • User pastes a Nix error and asks what's wrong

Procedure

Step 1: Survey the project

Before writing anything, check what exists:

ls shell.nix flake.nix flake.lock default.nix .envrc 2>/dev/null

Also look for language hints to choose sensible buildInputs: Cargo.toml, pyproject.toml, package.json, CMakeLists.txt, go.mod, Justfile, .tool-versions.

If files already exist, read them first. Do not overwrite.

Step 2a: Scaffolding a new shell.nix

Minimal, pinned template. Fill in buildInputs based on what you found in Step 1:

{ pkgs ? import (fetchTarball {
    # Pin to a specific nixpkgs revision. Update the URL + sha256 together.
    url = "https://github.com/NixOS/nixpkgs/archive/<REV>.tar.gz";
    sha256 = "<SHA256>";
  }) {} }:

pkgs.mkShell {
  buildInputs = with pkgs; [
    # language toolchain
    # build tools (just, cmake, ...)
    # test/lint tools
  ];

  # Omit shellHook entirely unless strictly required.
  # If needed, add it here - only env exports, no echos/banners.
}

If a Justfile exists in the project, ensure just is in buildInputs (otherwise recipes won't run inside the shell).

To get a current pinned rev + hash, run (once, to fill in the template). Pick the current stable branch - check https://channels.nixos.org/ if unsure which is current:

CHANNEL="nixos-25.05"   # substitute current stable
REV=$(curl -s "https://api.github.com/repos/NixOS/nixpkgs/commits/${CHANNEL}" | jq -r .sha)
SHA=$(nix-prefetch-url --unpack "https://github.com/NixOS/nixpkgs/archive/${REV}.tar.gz")
echo "REV=$REV SHA=$SHA"

If nix-prefetch-url isn't available, fall back to letting Nix fail once and copy the got: hash from the error.

If the project uses .envrc with use nix or use flake, warn the user that changes will take effect on the next direnv allow (or direnv reload).

Step 2b: Diagnosing a broken shell.nix / flake.nix

Run the evaluator and capture the real error:

nix-shell --run true 2>&1 | tail -50
# or for flakes:
nix develop --command true 2>&1 | tail -50

Common failure modes and fixes:

Error fragmentCauseFix
hash mismatch ... got: sha256-XXXXPinned URL changed or sha is wrongReplace the sha256 with the got: value from the error
attribute '...' missingPackage renamed/removed in channelSearch nixpkgs for the new attribute name (use https://search.nixos.org/packages, or nix-env -qaP |grep <name> on non-flake systems), or pin to an older rev
infinite recursion encounteredSelf-referential let/overlay, or with pkgs; at top-level scope leaking into itselfIsolate the offending binding; scope with pkgs; only inside lists like buildInputs = with pkgs; [ ... ];
getting status of '/nix/store/...' / No such fileMissing store pathRebuild / re-realise the path: nix-store --realise <path> or just re-run nix-shell/nix develop to re-download. For flakes, deleting flake.lock and re-locking can refresh references. Do NOT run nix-collect-garbage - that removes paths, making it worse.
error: experimental feature 'flakes' is disabledFlakes not enabledUse nix --extra-experimental-features 'nix-command flakes' develop or enable in config
unable to download '...' / TLS errorsPinned URL 404 or networkVerify URL is reachable; try the channel's current rev

For flakes, also check flake.lock staleness:

nix flake metadata 2>&1 | head -20
nix flake update --commit-lock-file   # only if user wants to bump

Step 3: Validate

After any change, confirm the shell actually enters:

nix-shell --run 'echo OK && which just cargo python3 2>/dev/null'
# or
nix develop --command bash -c 'echo OK'

If validation fails, loop back to Step 2b with the new error. Do not claim success until the shell enters cleanly.

Step 4: Report

Summarize in this format:

## Nix Shell Status

**State:** <NEW | PATCHED | DIAGNOSED-NOT-FIXED>

**Changes:**
- shell.nix: <created | pinned rev updated | added N buildInputs | ...>

**Validation:** `nix-shell --run true` exits 0

**Notes:**
- <anything the user should know: channel chosen, inputs deliberately omitted, etc.>

If you could not fix it, say so plainly and state what would be needed (e.g. "pinned rev is no longer in nixpkgs history; user must choose a replacement channel").

Anti-patterns (do NOT produce these)

  • shellHook that echos a welcome banner, PS1 changes, figlet, environment listings
  • Including an empty shellHook = ''''; block when no hook is needed - just omit it
  • with pkgs; at top-level scope (outside list context) - causes infinite-recursion eval errors
  • Unpinned import <nixpkgs> {} in a project that needs reproducibility
  • Mixing fetchTarball pins with flake.nix (pick one mechanism)
  • Overwriting an existing shell.nix "to clean it up" without being asked
  • Adding packages "just in case" - only what the project actually needs

Tone

If the existing shell.nix / flake.nix already works, say so and don't touch it. Don't rewrite something that isn't broken just because it could be styled differently.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.