Skip to main content

Configuration, Hooks, and Customization

The files that make the loop work: settings.json, .mcp.json, AGENTS.md, a local CI command, and an optional pre-commit hook.

settings.json

Controls permissions and hooks. The kit ships a working template in kit/settings.json.

{
"permissions": {
"allow": ["Bash(spec-spine *)", "Bash(make *)", "..."],
"deny": ["Bash(npm publish*)", "Bash(gh repo delete *)", "..."]
},
"hooks": {
"SessionStart": [],
"PostToolUse": [],
"PreToolUse": [],
"Stop": []
}
}

Never commit secrets in this file.

Permissions

allow whitelists tool invocations the agent may run without asking; deny blocks destructive operations (publishing, deleting repos, creating releases). Rewrite both lists for your tool paths.

Hooks

The hooks are the deterministic safety net. They call the spec-spine CLI directly, so they work in any repo that has it on PATH. They read; they do not repair (spec 046). A hook cannot commit, so a hook that regenerated a committed artifact would leave the tree dirty for whoever comes next, and an orchestrator that refuses a dirty tree then never starts the session that would clean it.

HookMatcherWhat it does
SessionStartstartup/resume/clear/compactRuns compile --check and index check, decodes the exit codes, and reports registry + index freshness. Writes nothing.
PostToolUseEdit|WriteAfter a spec.md edit, recompiles the registry (the one sanctioned write: the live session commits the shards with its edit); after any hashed-input edit, runs index check. Acts on the repository that contains the edited file.
PreToolUseBashRefuses git push to main (by refspec or current branch). Intercepts gh pr create: blocks on a stale committed index or uncommitted .derived/, then runs the coupling gate and blocks if it fails with no Spec-Drift-Waiver in the body. Acts on the repository the command targets.
Stop*Runs index check; if stale, prints the command to run and why it was not run here. Writes nothing.

Every hook prints one line when it skips (no spec-spine on PATH, no jq, the target is not a spec-spine corpus) rather than exiting silently.

To adapt: keep all four if you use spec-spine. Adjust the PostToolUse case globs to match your spec-spine.toml [index] extra_hashed_inputs, and the waiver keyword if you changed it. Do not reintroduce a writing subcommand into a hook: crates/spec-spine-core/tests/kit_hooks.rs refuses one in the kit for exactly the reason above.

.mcp.json

Declares Model Context Protocol servers. The kit ships an empty template:

{ "mcpServers": {} }

Add your own servers if you have any.

AGENTS.md

Two jobs: its ## New Sessions section is the protocol /init executes, and its "Available Agents" / "Available Commands" sections document what is on hand. Rewrite the New Sessions section for your repo (see Session init).

A local CI command

/validate-and-fix and /ship expect one command that runs the same gate set as CI. A common convention is three Make targets:

  • make setup: install spec-spine, compile the registry, build the index.
  • make ci: your full local gate (the governance verbs plus build, type-check, lint, tests).
  • make pr-prep: refresh the index, then run spec-spine couple against origin/main.

The names are a contract with the skills; keep them, or rename and update the skill references. Every make ci must include the four spec-spine verbs (compile, lint --fail-on-warn, index check, couple).

Optional pre-commit hook

An opt-in git hook that refuses a commit when spec-spine is missing or the index is stale:

git config core.hooksPath .githooks # enable
git config --unset core.hooksPath # disable
git commit --no-verify # emergency bypass

Keep the staleness gate if you use spec-spine. The hook is read-only: it never mutates the working tree.