
Claude Code Hooks: The 6 I Actually Run in Production
Claude Code hooks are shell commands that fire automatically at fixed points in the agent's life — before a tool runs, after it runs, when a session starts, when it stops. Because a hook runs on its own and can block an action by exiting non-zero, it enforces a rule instead of hoping the model remembers one. A prompt is a suggestion; a hook is a wall. Here are the six I put on every autonomous agent I ship, with the exact matchers and why each one earns its place.
Why a Hook Beats a Prompt
I run Claude Code unattended — it researches, writes, builds, and pushes on a schedule while I'm asleep. The first time I let it loose, I did what everyone does: I wrote a long system prompt full of “never commit secrets,” “always run the build,” “don't touch the migrations.” It mostly worked. Mostlyis the problem. Over a long enough run, an instruction buried in a 3,000-token prompt is a suggestion the model can quietly drift from, and you find out at 7am when something's in the git history that shouldn't be.
A hook doesn't drift. It's a shell command Claude Code runs itself, at a defined moment, outside the model's judgment. And the ones that fire beforea tool call can veto it — exit non-zero and the action is blocked, with Claude handed a clear error explaining what it hit. That's the mental shift:
The rule I write on the whiteboard:
If something must happen, it belongs in a hook, not a prompt. Prompts are for taste and judgment. Hooks are for the non-negotiables — the walls the agent physically cannot walk through.
Claude Code fires hooks at several lifecycle events. The four I lean on: PreToolUse (before a tool runs, can block it), PostToolUse (after a tool succeeds, can't undo it), SessionStart (when a session begins, its stdout becomes context), and Stop (when the agent finishes). Each entry declares the event, an optional matcher for which tools it applies to, and the command to run. Anthropic's hooks guide documents the full list of events. Below are the six I actually run.
The Two Guards (PreToolUse)
These two are the reason I sleep. Both are PreToolUse hooks matched to the Write and Edit tools, and both work by refusing to let a bad write reach disk.
1. Block secret writes. The hook reads the content Claude is about to write and greps it for secret shapes — private-key headers, long token-shaped strings, common names like SECRET, PASSWORD, or a bare sk- prefix. One match, exit 1, write blocked, Claude told why. This is the single highest-leverage hook you can write. A leaked key in a public repo is a genuinely bad day; a five-line grep makes it structurally impossible.
2. Protect sensitive files. Same idea, keyed on the target path instead of the content. If the file being edited is .env, a lockfile, or a database migration, the hook rejects it. Migrations especially — I never want an autonomous agent rewriting a migration that's already run against production. The hook makes “don't touch these” a fact of the filesystem, not a line the model has to keep in mind 40 turns deep.
Keep these two near-instant. A PreToolUse hook sits in the critical path of everymatching tool call, so a slow one taxes the whole run. A path check or a grep is microseconds — that's the budget.

The Two Reactions (PostToolUse)
A PostToolUse hook fires aftera tool succeeds. It can't undo anything, so it's for reacting, not gating.
3. Auto-format the edited file.After every successful edit, run the formatter on just the touched file. The payoff isn't only clean diffs — it's that formatting stops being something the model has to spend attention on. It writes roughly-right code; the hook makes it exactly-right. Style disappears as a category of thing to get wrong.
4. Run the fast tests. After a code change, run the quick unit tests related to what changed — not the whole suite. This catches the obvious regression the moment it happens, while the context is still fresh, instead of at the very end when the agent has moved on. The discipline here is scope: a hook that runs your entire test matrix after every edit will make the agent crawl. Fast, related tests only. I save the full suite for the end.
If you're wiring hooks into a longer autonomous loop, the same restraint applies to the whole run — I wrote up the budget-and-kill-switch side of that in running AI agents on autopilot without torching your budget.
Context In, Signal Out (SessionStart + Stop)
The last two aren't guardrails — they're quality-of-life, and they're the ones that turned my unattended runs from “works” to “trustworthy.”
5. Inject context on SessionStart. When a session begins, this hook prints the current git branch, the last few commit messages, and any open issues to stdout — and Claude Code injects that stdout straight into the model's context. Instead of starting cold and asking “what am I working on,” the agent opens already knowing the branch, the recent history, and the queue. It's the cheapest way to make a fresh session feel like it never left. This matters even more with subagents, which start cold by design and re-buy their context at the uncached rate.
6. Ping me on Stop.When an unattended job finishes, a Stop hook POSTs a one-line result to Telegram — done, what shipped, or what broke. I don't babysit a terminal for a job that runs at 3am; the hook tells me it's finished and whether I need to look. This is the difference between an automation you trust and one you keep checking on.
A useful contrast: hooks are the deterministic layer, and skills and MCP servers are the model-driven layer. Hooks fire whether or not the model “decides” to; skills and tools are things the model chooses to reach for. You want both, doing their own jobs.
The Six at a Glance
| Hook | Event | What it does |
|---|---|---|
| Block secrets | PreToolUse | Rejects any write containing a key-shaped string |
| Protect files | PreToolUse | Blocks edits to .env, lockfiles, migrations |
| Auto-format | PostToolUse | Formats the file that was just edited |
| Fast tests | PostToolUse | Runs quick related tests after code changes |
| Inject context | SessionStart | Feeds branch, commits, and issues into context |
| Notify | Stop | Messages Telegram when the run finishes |
Put the project-level ones in version control so every agent and every teammate runs the same guardrails. That's the whole game for anything unattended: the rules travel with the repo, not with whoever remembered to paste them into a prompt. If you're building the loop around these, my notes on dynamic Claude Code workflows cover how the pieces fit together.
The Short Version
- A hook is a shell command Claude Code runs at a lifecycle event; PreToolUse hooks can block the action by exiting non-zero.
- If something must happen, it belongs in a hook, not a prompt — prompts drift, hooks don't.
- Guard with PreToolUse: block secret writes and protect .env / migrations. These are the two that let you run unattended.
- React with PostToolUse: auto-format the edited file, run fast related tests. Keep both quick.
- SessionStart injects branch + commits + issues as context; a Stop hook pings you when the job's done.
- Check project hooks into version control so the guardrails travel with the repo.
Want an AI Agent You Can Actually Leave Alone?
I build and audit production AI agents on Claude Code, the Anthropic API, n8n, and Supabase — with the guardrails, budgets, and notifications that make “unattended” mean it. If you want an agent that ships work while you sleep without any 7am surprises, let's talk.
Related Posts
AI Agents
Claude Code vs n8n (2026): The Rule I Use to Pick — and Why I Ship Both
They're not competitors — Claude Code builds software, n8n runs operations. The one-line test: if you can draw the task as fixed boxes before running it, it's n8n; if the path is discovered by reasoning, it's Claude Code. Real cost and reliability trade-offs from production, a full comparison table, and the handoff pattern where n8n owns the plumbing and hands the one ambiguous step to a Claude Code agent.
AI Agents
Claude Skills vs MCP: When I Reach for Each (and the Token Cost That Decides It)
A skill is knowledge, an MCP server is a connection — use a skill to teach the model how, use MCP to let it reach a system it can't otherwise touch. The tiebreaker most people skip is token cost: skills sit idle at ~30–100 tokens each, while five MCP servers can burn ~55k tokens before you type a word. The exact rule I run in production.
AI Agents
Claude Code Dynamic Workflows: How I Actually Run Dozens of Subagents
A dynamic workflow is a script Claude writes to orchestrate subagents in the background, keeping the plan out of your context window. The three primitives (agent, parallel, pipeline), why pipeline beats parallel by default, the caps that stop a runaway, and what a fan-out really costs — from production runs.