guardrail-hooks

Installation
SKILL.md

Guardrail hooks — rules held by code

A rule whose compliance depends on an agent remembering it at the decisive moment becomes a code path, because prose loses that contest to everything else the agent has read. The principle, its evidence and the test question are in the agent-instructions skill (its prose-vs-code reference). This skill is the practice: which code path to use, how to write a hook that holds a rule without becoming noise, and two hooks to adapt.

The receipt that made the hooks here: on 2026-10-12 an owner answered "up to you" about a wording choice, and the agent stretched it into "my call: delete the live post and repost tomorrow". Nothing was deleted, but only the agent's judgment stood in the way of a one-line delete. The instructions had said since 2026-06-02 that deleting anything public needs the owner. The fix was a hook that makes the owner click.

Pick the smallest code path that holds the rule

The rule is about Hold it with Example
a command the agent may run, recognisable by its prefix a permission rule in settings: permissions.ask: ["Bash(gh repo delete *)"], or permissions.deny checked against every subcommand, inside $() and loop bodies too, and still prompts in auto mode (read 2026-10-24). No script to maintain
what a command does when its text alone can't tell: code in a heredoc, a script it runs, the value of an argument a PreToolUse hook scripts/guard_one_way_doors.py, scripts/block_wrong_identity.py
how your own tool may be used a required argument, or a refusal inside the tool a search-analytics tool, after four silent data errors in one session (2026-08-12: a capped, click-sorted single pull kept 23% of impressions; a cached file read as a 40-day window was a 17-month aggregate): pulls now paginate and write a manifest of the exact window, and the report refuses to run without one
what a commit may contain a git pre-commit hook in the repository, switched on per clone (git config core.hooksPath .githooks, set by a session-start hook) refusing a commit that empties or halves a bookkeeping file (2026-09-07: a ledger committed as 0 bytes while resolving a conflict, 209 rows gone, and the nightly job crashed on it)
what must be true before the agent says it is done a Stop hook returning decision: "block" with the reason tests ran; the release log has every step
what the agent must know when it starts a SessionStart hook returning additionalContext git state checked by code: a shallow clone deepened before any ancestry check (2026-08-05, after three sessions burned time on bogus "unrelated histories"); a warning when the session started on a machine-named branch (2026-07-30, three days of work stranded on one)
a derived file that must track its source a PostToolUse hook that runs the sync a one-way mirror of the skills folder for agents that read another path, re-synced on every write; it always exits 0 so a sync hiccup never blocks a tool

Prefer the higher rows: a permission rule beats a hook, and a refusal inside your own tool beats both, because it holds for every agent and every human that runs it. When the instruction file states such a rule, it says what holds it and where it doesn't ("Bash is held by a hook; MCP tools and browser clicks are not covered, so the rule still binds there").

Installs
9
GitHub Stars
241
First Seen
6 days ago