원클릭으로
nix-verification-loop
Use for changes in this NixOS flake to select and run the smallest meaningful validation command before broader checks.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
Use for changes in this NixOS flake to select and run the smallest meaningful validation command before broader checks.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
Use when taking a scoped GitHub issue, review finding, roadmap item, or bug report through implementation, validation, PR/CI, merge, cleanup, and optional learning capture.
Use before broad repository exploration when the relevant files are not already obvious; query a compact generated repo map and open only the top likely files.
Use when reviewing accumulated .agents/learning candidates, deduplicating them, rejecting weak ones, or promoting strong ones into executable checks, hooks, skills, or docs.
Use when converting a rough goal, roadmap item, bug report, or underspecified GitHub issue into an implementation-ready issue with acceptance criteria, non-goals, validation, and user decision questions before code changes.
Use at the end of high-signal work to record one compact reviewed learning candidate, without scanning candidate bodies or editing CLAUDE.md, skills, hooks, or invariants directly.
Use for processing review findings or backlog items in small validated batches while keeping status artifacts accurate.
| name | nix-verification-loop |
| description | Use for changes in this NixOS flake to select and run the smallest meaningful validation command before broader checks. |
Use this workflow whenever editing Nix, shell scripts, host definitions, tests, packages, deploy wiring, secrets boundaries, or generated data in this repo.
bash scripts/validate.sh flake-eval.bash scripts/validate.sh light.bash scripts/validate.sh host <name> when closure risk matters.bash scripts/validate.sh package <name> or package all.bash scripts/validate.sh profile-test <name>.bash scripts/validate.sh smoke-homeserver-gcp when endpoint behavior changes.bash scripts/validate.sh docs.hosts, package all, heavy, cve-reports), consider
running it via a subagent that redirects output to a file and returns only
the exit status and tail — this keeps the noisy build entirely out of the
main session's transcript instead of relying on truncation alone.deploy-rs silence in non-interactive sessions as a known behavior; if
necessary, fall back to closure build/copy/switch instructions from CLAUDE.md.sops.nix develop -c <tool> / nix develop --command <tool> now pass through
<tool>'s stdout and exit status: the default devShell shell hook only
execs zsh for interactive sessions ($- containing i), not for -c
invocations. Prefer tools already available in the current shell directly
when possible, but nix develop -c <cmd> is valid proof a command ran.&&/; (or a single quoted bash -c '...') — never rely on a literal
newline between top-level statements. A backgrounded multi-line command can
collapse onto one pipeline, e.g. turning nix fmt FILE | tail -5 + a
following git add line into tail -5 git add FILE && git commit, which
hangs tail forever on an open pipe with empty output. Avoid piping
nix develop -c <cmd> through tail/head in the background for the same
reason; run such commands in the foreground or redirect to a file instead.When a golden/contract check targets a CLI entrypoint that itself shells out
to networked or build-heavy commands (e.g. nix flake check, nix fmt),
prefer a static source-assertion pkgs.runCommand — grep-based section/keyword
anchors and ordered-list diffs against the script source — over trying to
execute the real script in the Nix sandbox, which has no network/build access.
When such a check encodes a list, especially a negative/denylist, derive it
from its canonical source (e.g. lib/hosts.nix, flake outputs) rather than
hardcoding it, so a new entry is covered automatically instead of silently
rotting the check open.
See tests/lib/doctor.nix (section/keyword/order assertions plus a
host-denylist derived from lib/hosts.nix) and tests/lib/mini-fleet-flake.nix
(derives the expected output list from flake.nix) for worked examples.
nh os switch --hostname main . can build the generation and then fail
activation with sudo: a terminal is required to read the password, leaving
the new services absent from the running generation. Confirm sudo is usable
(sudo -n true) before claiming a host is switched; if it is not, report the
build as done and a user-authenticated switch as the remaining step.deploy-rs runs broad flake checks before any remote activation. A
deploy '.#homeserver-gcp' can fail on an unrelated main-ci invariant or a
repo-wide pre-commit check (checks.x86_64-linux.invariants-main-ci,
checks.x86_64-linux.pre-commit) before the host is ever touched. Treat an
early "Failed to check deployment" as a full-flake validation blocker: fix the
named check first, then retry the host deploy.bash scripts/validate.sh cve-reports (the current flake-built closure) over
vulnix_cve_total from a deployed generation — live counts cause whitelist
churn and false positives. The live homeserver timer intentionally exports
only scanner freshness, not raw counts.VAR= command prefix to silence a linter.
shellcheck SC1007 fires on the bare var= cmd form, but dropping CDPATH=
from script_dir=$(cd -- … && pwd) is a regression: with CDPATH set in the
env, cd <relative> echoes the resolved path into the capture and corrupts
it. Rewrite as CDPATH='' cd -- … — the guard is preserved and SC1007 stops
firing.PATH
($HOME/.nix-profile, /etc/profiles/per-user/<user>/bin) point at the last
built store path, so invoking the wrapper binary for home/files/scripts/*
or packages/*/src/** after editing the source silently runs the old build
with no error. Rebuild (rebuild/nh os switch --hostname main . or
home-manager switch) before testing against the installed command, or run
the interpreter directly against the source file (e.g. python3 path/to/script.py) for quick iteration without a full rebuild.nix build/flake check only proves a transient unit's definition
evaluates, not that systemd accepts it at runtime. Sandbox/namespacing
directives like PrivateNetwork= are service-only — systemd-run --scope
rejects them with "Unknown assignment" at runtime even though the Nix
expression type-checks fine (see hosts/homeserver-gcp/restore-drill.nix's
runIsolated, which uses --pipe --wait service units instead). Transient
units also start with systemd's default PATH and without the env vars a
NixOS module would normally inject, so cat/${pkg}/bin/foo invocations can
fail in ways a build never surfaces. Any drill or check that spawns
systemd-run units must be smoke-tested by actually starting it on a live
host.$'\x60', not an escaped
backtick in a quoted literal. ShellCheck SC2016 flags a literal backtick
inside a single-quoted string as unexpanded command substitution, but
nix fmt (treefmt/shfmt) rewrites an escaped backtick in a double-quoted
string back into that single-quoted form — a formatter-vs-linter loop (see
PR #310). Instead, build the string with local backtick=$'\x60' (or
another ShellCheck-clean construction) and interpolate that variable. Run
nix fmt -- --fail-on-change and ShellCheck together (not just one) before
pushing a shell-script change to confirm both pass.modules/nixos/profiles/observability/backends.nix, PR #335),
nix build the exact package from the flake's nixpkgs input and run the
binary directly against the candidate config
(tempo -config.file=cand.yaml -target=all) before editing the Nix module.
This confirms the new schema's exact keys parse and is cheaper and more
authoritative than docs or a full closure build — it disproved a stale
assumed requirement (Kafka for monolithic target=all) that the upstream
docs/issue text got wrong.