Claude Code hooks are user-defined rules that run automatically at specific points in a session. Rather than the AI "remembering" to do something, a shell command runs every time conditions match — so you can deterministically enforce guardrails like auto-format on save, blocking dangerous commands, or no commit until tests pass. (As of June 2026 · Official: code.claude.com/hooks)
What hooks are
Hooks are user-defined event handlers (usually shell scripts) that run at specific moments in the Claude Code lifecycle. The key is that they're deterministic: they don't depend on the model remembering to format or run tests — they execute every time their conditions match. That makes them ideal for enforcing a team's non-negotiables.
Three parts: event · matcher · action
Every hook has three components:
- Event — the lifecycle moment it fires (e.g., PreToolUse, PostToolUse, Stop, SessionStart).
- Matcher — an optional filter to narrow when it runs (e.g., only the "Bash" tool, only "Edit|Write" operations).
- Action — what actually happens, usually a shell command.
Common events
The two most used are PreToolUse and PostToolUse.
- PreToolUse — "before" a tool runs. Good for validation or blocking dangerous operations.
- PostToolUse — "after" a tool completes. Good for cleanup like formatting or tests (it can't undo an already-run action, only give feedback).
- Stop — when Claude is about to finish responding. Use for final checks or notifications.
- SessionStart / SessionEnd — at session start/end (setup/cleanup).
There are more events, and the full list and count vary by version — check /hooks or the official docs.
Configuration and communication
There are two ways to set up. The interactive /hooks command walks you through picking an event, matcher, and command, or you edit ~/.claude/settings.json (global) / .claude/settings.json (project) as JSON directly. When an event fires, Claude Code passes JSON context — session ID, working directory, tool name, input — to your handler (via stdin for command hooks). The handler inspects it, acts, and returns a result via exit code. If a PreToolUse hook exits with code 2, that tool call is blocked.
Practical examples
- Auto-format — PostToolUse + matcher "Edit|Write" +
prettier --write. Formatting is applied every time a file is saved. - Block risky commands — PreToolUse + matcher "Bash" exits 2 when it sees a dangerous pattern.
- Test gate — a Stop hook that checks tests pass before wrapping up.
Things to know
- Four handler types — command (shell), prompt, agent, http. command covers most everyday use.
- Fires for subagents too — when Claude uses tools via a subagent, PreToolUse/PostToolUse hooks run for those tools as well, so safety gates aren't bypassed.
- Synchronous = performance — each hook runs synchronously and adds time to matched tool calls. Heavy hooks can slow a session, so keep them fast.
- Team sharing — put hooks in the project
.claude/settings.jsonso the whole team shares the same guardrails.
Related
- Subagents — delegate work (hooks fire there too)
- Slash commands — configured via
/hooks - How-to-use guide — using it in the terminal
- CLAUDE.md guide — passing project rules
Disclaimer: This article is based on Anthropic's official Claude Code docs (code.claude.com·docs.anthropic.com). The number, names, input schemas, and exit-code behavior of hook events may change by policy and version — check /hooks and the official docs. Security hooks like blocking risky commands are an aid, not a complete defense. This site is not affiliated with Anthropic.