Hooks for coding agents: a reading guide
Twenty-two Tokenise articles on Claude Code and Codex hooks, grouped by what you're trying to do and in the order that makes sense to read them.
A hook is a script the agent runs at a fixed point: before a tool call, when it says it’s finished, when a session starts. That makes hooks the place to enforce things a prompt can only request. The articles below cover the gates, guardrails and bookkeeping people build on them, and they’re written to be tried one at a time.
If you only read three, read the first section. Together they cover the most common use (make the agent prove its work), the most common safety net (refuse a dangerous call) and the most common mistake (a policy hook that quietly stops enforcing anything).
Start here
- Make Claude Code run your tests before it’s allowed to say it’s done : a Stop hook that gates the agent’s “finished” on a passing test run.
- A PreToolUse hook is the guardrail that survives bypass mode : refusing a tool call before it runs.
- Your Claude Code policy hook probably fails open. Here’s how to test it : checking that a broken hook doesn’t let everything through.
Gates: make the agent prove it’s done
- Codex says it’s done. A Stop hook makes it prove it by running your tests first : the same idea for Codex.
- Make the agent pass your checks: Husky, lint-staged and two Claude Code hooks : a commit and push gate the agent can’t skip.
- Let the tests run while the agent keeps typing: a background hook that interrupts only when something breaks : tests in the background, with a wake-up only on failure.
- Make your agent earn the right to fix a flaky test: a shuffle-seed harness and a commit guard : a harness that proves a flake is fixed before the commit is allowed.
- Lint your Claude Code subagent files before commit, because a typo makes them quietly do nothing : a pre-commit check for subagent definitions.
Guardrails and refusals
- onFailure: block, tested. Which hook failures it stops and which it doesn’t
: which hook failures
onFailure: blockstops and which it doesn’t. - Don’t refuse the command, rewrite it: PreToolUse updatedInput in Claude Code : changing a call instead of blocking it.
- A Codex PreToolUse hook that blocks force pushes and –no-verify, and what happens when the hook itself breaks : a git guard for Codex.
- A UserPromptSubmit hook that refuses prompts containing secrets and tells Claude which branch it’s on : screening what goes into the prompt.
- Claude Code now logs every tool call it stops. Build a refusal ledger that shows which rules earn their keep : measuring which rules actually fire.
- Auto mode said no overnight. A PermissionDenied hook tells you what, and why : recording denials from unattended runs.
Context, sessions and cost
- Find out which CLAUDE.md and rules files Claude Code really loads: an InstructionsLoaded audit you can run today : seeing what the agent actually read.
- Make Claude Code re-read your plan after every compaction: a SessionStart brief that also warns before a stale resume : keeping a plan alive across compaction.
- A git snapshot before every prompt: the undo that covers what /rewind skips : an undo built from git refs.
- Give every parallel Claude Code session a worktree that already runs: a WorktreeCreate hook for env files, ports and dependencies : ready-to-run worktrees for parallel sessions.
- A model switch re-reads your whole session uncached. Put a price on it with a PreModelSwitch hook : warning about the cost of switching models mid-session.
Workflows built on hooks
- Hand Claude Code a GitHub issue number and get back a draft PR, with the merge button locked : working from a real ticket.
- Make Claude Code interview you, then keep the editor locked until you approve the spec : a spec gate before any code is written.
- Your overnight Claude Code run died at 2am. A StopFailure hook and a 30-line wrapper decide whether to wait or wake you : handling a dead unattended run.
This page is kept by hand. When a new hooks article is published it’s added to the group it belongs in.