DEV Community

solemness
solemness

Posted on

Claude Code hooks are the seatbelt nobody buckles — here's the 10-hook setup that makes agent disasters impossible

Every Claude Code power user has a story: the force-pushed main, the "helpfully" rewritten .env, the API key committed at 2am. The fix has been sitting in the docs the whole time — hooks: shell scripts that run on every tool call, outside the model, so they hold even when the model has a bad day.

Almost nobody sets them up. Writing defensive hook scripts is genuinely fiddly. Here's what I learned building a full 10-hook guard-rail set, including the parts the docs make you discover the hard way.

The three mechanics that matter

1. Exit code 2 is the magic word. A PreToolUse hook that exits 2 blocks the tool call, and everything you wrote to stderr is fed back to Claude as the reason. Claude then adapts — tell it "force-push to main refused, use a feature branch" and it does exactly that. Exit 0 allows; other codes just log.

2. JSON decisions beat exit codes for nuance. Printing {"decision":"block","reason":"..."} on stdout does the same job and works for PostToolUse feedback loops too — that's how you pipe lint errors straight back to the model so it fixes its own warnings.

3. Stop hooks can refuse "done". A Stop hook that runs your test suite and blocks on red means the agent literally cannot declare victory with failing tests. Guard against infinite loops by checking stop_hook_active in the payload.

Design rules for hooks you'll trust

  • Fail open. If jq is missing or your script errors, allow the action. A guard rail that bricks your session gets uninstalled by lunchtime.
  • Block with instructions, not just "no". The stderr message is a prompt — tell the model what to do instead.
  • Make every hook a no-op switch away. REPO_ARMOR_DANGER_OFF=1 beats editing settings.json mid-incident.
  • Match narrowly. A Bash matcher that blocks rm -rf / must still allow rm -f build/tmp.txt, or you'll drown in false positives and turn it all off.

The full set worth having

Secret-leak blocker, dangerous-command guard, protected-file guard, main-branch commit guard, test-on-stop, format-on-edit, lint feedback loop, desktop notifications, JSONL audit log, and a context guard that injects a warning when your prompt mentions "production".

I packaged all 10 (bash + jq, zero network, fail-open, 52 self-tests) with a one-command installer as repo-armor — it's $5 on Gumroad: https://solemness.gumroad.com/l/repo-armor. Or build your own from the mechanics above; either way, buckle the seatbelt before the next long unattended session.

Top comments (0)