Claude Code hooks are the difference between a chat-driven coding assistant and a coding agent that lives inside your team's workflow. The feature has been in the product since late 2025, but most developers we onboard have never written one. They are using Claude Code the way you would use ChatGPT in a terminal, missing the part of the product that makes it valuable as automation.
A hook is a shell command that runs at a defined event in the agent lifecycle. Before a tool runs. After it. When the agent finishes. When it requests permission. The contract is simple: the hook receives a JSON payload describing what is about to happen, and its exit code decides whether the action proceeds. Six patterns cover almost every production setup we ship.
Pattern 1 - Pre-commit linting that the agent cannot skip
The most basic hook. Configure a PostToolUse hook on Edit and Write tools that runs your linter against the file just changed. If the linter fails, the hook returns a non-zero exit and a JSON payload telling Claude what to fix. The agent reads the failure, understands the lint rule, and tries again.
The win is not that you avoid running the linter manually. The win is that the agent never produces broken code in the first place, because it is corrected inline before the change is committed. We see file-level lint compliance go from 60-70% to 95%+ on agent-driven repos within a week of shipping this hook.
Pattern 2 - Auto-format on every write
Same shape as Pattern 1, but for Prettier, Black, gofmt, or whatever your formatter is. The difference is that a formatter usually rewrites the file rather than failing. The hook runs the formatter against the just-written file and returns success.
This is one of the few hooks where you do not want the agent to know it ran. Set output in the hook response to suppress the message. The agent does not need to know that its formatting was rewritten. It only needs to know the change succeeded.
Pattern 3 - Dangerous command gating
The hook that has prevented the most production accidents in our internal usage. A PreToolUse hook on the Bash tool that inspects the command and blocks it if it matches dangerous patterns: rm -rf outside the project directory, git push --force to main, DROP TABLE against any database, kubectl delete on production namespaces.
The hook does not just block. It returns a structured rejection that explains why the command was blocked, so the agent can ask the user to confirm rather than aborting silently. We pair this with a project-level CLAUDE.md file that documents which patterns are allowed, so the agent knows the boundaries before it tries to cross them.
Pattern 4 - Push notifications when the agent needs you
Long-running agent sessions go off into the weeds and you cannot watch every step. A Notification hook fires when Claude needs your input, whether for permission to run a tool or because it has hit a question it cannot resolve. Wire that hook to your phone via Pushover, ntfy, or a Telegram bot.
The pattern that works best for us: ignore the notification if the agent is just asking permission for a routine command, but send a phone alert if it has been idle for more than 60 seconds waiting on something. The hook script keeps a small state file with the last activity timestamp and decides whether to actually push the notification. Most teams set this up wrong by sending every notification, then disable the channel within a day because of the noise.
Pattern 5 - Audit logging for compliance
If your engineering team has a compliance bar (SOC 2, HIPAA, FedRAMP), an agent making code changes is a new attack surface. A PostToolUse hook that appends every tool call and its result to a structured audit log gives you the trail your auditor will ask for.
- Log the tool name, the parameters, the user identity, and the timestamp. Append-only file or a write to your existing logging service.
- Include a hash of the file contents before and after Edit and Write tool calls. This is what proves the agent did not silently rewrite something it should not have touched.
- Send the audit stream to your SIEM if you have one. The log volume is low. The compliance value is high.
Pattern 6 - CI smoke tests on Stop
The Stop hook fires when Claude finishes its turn and is ready to hand back to the user. This is the right moment to run your test suite. Not every test, just the smoke set: type checks, lint, and the fastest tests that catch regressions.
The hook returns whether the smokes passed and embeds the failure output in the JSON response. Claude then surfaces the failures to the user before saying it is done. The result: fewer "are you sure that worked?" round-trips, because the agent has already verified its own work.
The mental model that helps: hooks are the contract between you and the agent. They are how you encode the parts of your engineering culture that you cannot fit into a system prompt.
Where hooks live and how to share them
Hooks are configured in .claude/settings.json at the project root and in ~/.claude/settings.json for personal preferences. Both are plain JSON. We commit the project-level settings to git so the entire team gets the same agent guardrails. The personal settings stay out of the repo for individual workflow tuning (your push notification provider, your editor preferences).
Three things make hook setups go bad: hooks that block on slow commands (run them async or with a timeout), hooks that produce noisy output the agent has to read every turn, and hooks that depend on environment variables that exist locally but not in CI. Test your hooks the same way you test your code.
Treat hooks as part of the codebase
The teams who get the most out of Claude Code are the ones who treat their hook setup like infrastructure: documented, versioned, and reviewed when it changes. The teams who get the least are the ones who never wrote a hook and are still surprised when the agent makes a formatting choice they did not want.
If you build websites and apps for clients, hooks let you ship a consistent agent-driven workflow that survives developer turnover. We use them on every project we deliver, including 24-hour rapid builds where the consistency a hook setup provides is the only way to hit the deadline without sacrificing quality.