Claude Code hooks: stop asking your agent to remember the rules
Your CLAUDE.md says "always run the formatter after editing," and for three weeks the agent did. Then a long session compacted, that line fell out of the summary, and this morning CI is red over trailing whitespace in a file you never touched by hand.
Nobody disobeyed you. You wrote a law and enforced it with a request. In an agent workflow, anything that must happen every single time cannot depend on a model remembering to do it. That gap, between "please always" and "always," is exactly what Claude Code hooks close.
What Claude Code hooks actually are
A hook is a shell command that Claude Code runs automatically at a fixed point
in its loop: before a tool call (PreToolUse), after one succeeds (PostToolUse),
when the agent finishes a turn (Stop), when it wants your attention
(Notification), and a few other lifecycle events. You declare them in
.claude/settings.json, scope them to the tools they should watch, and they
fire whether or not the model thinks of it.
The key property: hooks are deterministic in a workflow that is not. Everything else you tell an agent is a suggestion, filtered through sampling, context limits and compaction. A hook is code. A PreToolUse hook that exits with a blocking status stops the tool call before it runs, and its message goes back to the model as feedback. A PostToolUse hook receives the tool's input as JSON on stdin, so it knows exactly which file just changed. There is no "mostly" involved.
Hooks pull your shell commands into the agent's loop. The mirror image, putting the whole agent inside one of your shell scripts, is headless mode, and the two compose well.
Prompt for judgment, hook for law
The rule of thumb: if you would reject the work every time the rule is broken, it belongs in a hook. If breaking it is sometimes fine, it belongs in an instruction.
Your instructions file is the right home for judgment calls: prefer this pattern, avoid that dependency, ask before writing migrations. An agent weighing trade-offs is the point of having one. But formatting, protected paths and forbidden commands are not trade-offs, and putting them in prose does two bad things at once: the model can drop them under pressure, and every reminder permanently occupies context that real work needs.
Moving each invariant into a hook makes it unbreakable and makes your instructions file shorter. Both halves are wins.
Four Claude Code hooks that pay for themselves on day one
- Format after every edit. A PostToolUse hook on Edit and Write that runs Prettier, Pint or gofmt on the touched file. Every diff you read is about the change, never about style, which quietly speeds up reviewing agent work too.
- Block the commands you never want run. A PreToolUse hook on Bash that refuses force pushes, hard resets, or anything that reads secrets. This is guardrails as executable policy instead of hope. The agent gets told what was blocked and why, and routes around it.
- Protect files no agent should edit. Lockfiles, generated code, prod config. A small script that checks the target path and blocks with a one-line explanation ends a whole category of bad diffs.
- Get pinged when a session actually needs you. Notification and Stop hooks that trigger a sound or desktop alert. Trivial with one agent, and the whole ballgame once you run several sessions: the most expensive state in a parallel workflow is "the agent finished twenty minutes ago and nobody noticed."
Where hooks go wrong
The honest section, because hooks fail in ways prompts never do:
- Latency lands on every matching call. A two-second formatter sounds free until a refactor touches forty files and you have bought eighty seconds of dead air. Keep per-edit hooks fast, and push heavy checks (test suites, builds) to a Stop hook that runs once per turn.
- Failures are quiet. A hook with a broken jq expression or a missing binary does not crash your session; it just stops protecting you. You believe the rule is enforced, and it is not. After writing a blocking hook, ask the agent to do the forbidden thing once and watch it get refused.
- Overblocking makes agents flail. A bare "blocked" with no reason sends the model into retry loops, burning tokens on variants of the same denied command. Every block should say why, and what to do instead.
- Hooks are code you now maintain. They run with your shell permissions, automatically, on events you do not watch. Review a new hook the way you would review anything with that kind of access, especially one copied from a stranger's config.
Hooks run one session honestly; SanuDesk runs the fleet
A hook's jurisdiction ends at the session it runs in. The moment you have several agents working in parallel, the problems move up a level: which session owns which task, what came back, and whether a human has looked at it. No PostToolUse matcher reaches that layer.
That layer is what SanuDesk is built for. It is a desktop app that puts your Claude Code, Codex and Gemini sessions in one tiled grid, next to a Kanban board that does the dispatching: write the task as a card, deploy it to a fresh session with one click, and when the agent stops, the card parks itself in a review lane with a "what changed, how to test it" note. It is the same guarantee as a Stop hook, promoted from a beep to a queue you can trust. Loops handle recurring jobs on a schedule, it is bring-your-own-model so your existing agent subscriptions do the work, and the grid and board are in the free plan (details on pricing).
Hooks keep every individual session within the law. The board keeps the fleet honest. They compose.
Try this today
Add exactly one hook, the formatter, to .claude/settings.json in a project
you work in daily:
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "jq -r '.tool_input.file_path' | xargs npx prettier --write"
}
]
}
]
}
}
Then delete the "always run the formatter" line from your instructions file. You have just moved one rule from memory to law, and every diff this week will arrive already clean. Once that feels normal, promote your next most-repeated reminder the same way.
Download SanuDesk free to give the sessions those hooks protect a grid and a board, or see how the pieces fit together on the features page.