Claude Code Hooks Explained: The Deterministic Layer Around Your Agent
. Claude Code Hooks Explained: The Deterministic Layer Around Your Agent Why it matters for engineering teams What shipped and who is affected.
By Dillip Chowdary • Sep 24, 2026 • Source: HN Claude/Codex/Fable
I now have enough detail from the source. The article is a deep technical reference about Claude Code hooks — published by Blake Crosley, verified against Anthropic's official docs as of August 8, 2026 (with the Agent SDK section verified September 6, 2026). Key facts: 33 hook events, 5 handler types, exit codes 0/1/2, bypassPermissions enforcement, Agent SDK parity, CLAUDE_CODE_STOP_HOOK_BLOCK_CAP defaults to 8, v2.1.214 matcher semantics change, v2.1.219+ for register_repo_root, output cap of 10,000 characters, timeout values (600s/30s/10s), and 5 core patterns. The article is a reference/explainer, not an announcement of a new feature — no before/after benchmark table exists in the source. The prompt asks for one in the improvements section; I'll note what the source explicitly documents about capability evolution across versions.
Anthropic's Claude Code shipped a hooks system that turns an otherwise probabilistic coding agent into one with a deterministic enforcement layer developers control. Blake Crosley, a design engineer and former VP of Product Design at ZipRecruiter, published a 4,152-word technical reference in July 2026 that maps every documented facet of the system — verified against Anthropic's official hooks reference and guide as of August 8, 2026, with Agent SDK details re-verified September 6, 2026.
This piece covers what Claude Code hooks are, how the 33-event lifecycle is structured, how the input/output contract works, how to register hooks in settings.json, and five concrete patterns any builder can adapt. It is written for developers already running Claude Code who want to move beyond CLAUDE.md guidance into enforceable, scriptable automation.
What shipped in Claude Code Hooks Explained
Anthropic's Claude Code hooks system lets developers register user-defined handlers — shell scripts, HTTP endpoints, MCP tools, or model prompts — that the agent executes automatically at named lifecycle points. The core guarantee, stated directly in Anthropic's official guide, is "deterministic control: certain actions always happen rather than relying on the LLM to choose to run them." Unlike CLAUDE.md instructions, which the model follows probabilistically, hooks fire every time the matching event occurs regardless of model behavior or context length.
The reference documents 33 hook events organized across three cadences: once per session (SessionStart, SessionEnd), once per turn (UserPromptSubmit, Stop, StopFailure), and on every tool call inside the agentic loop (PreToolUse, PostToolUse). The remainder fire on specific conditions — config changes, context compaction, subagent lifecycle, MCP elicitation, model switches, worktree creation, file watches, and directory registration. The guide notes that nearly every production setup is built from five: PreToolUse, PostToolUse, UserPromptSubmit, SessionStart, and Stop.
What improved in Claude Code Hooks Explained
The hooks API has changed materially across Claude Code v2.1.x releases. Two versioned changes carry practical weight. First, since v2.1.214, a SessionStart hook receives a fifth source value — fork — alongside startup, resume, clear, and compact; any hook copied from an older four-value list will silently miss forked sessions. Second, since v2.1.214, a single-segment path pattern in the per-handler if field (e.g., Edit(src/)) matches only a top-level src under the working directory; patterns written before that release that relied on any-depth matching must be rewritten as Edit(/src/). The DirectoryAdded event, which fires when a repo root is registered mid-session via /add-dir or the Agent SDK's register_repo_root, requires v2.1.219 or later.

| Aspect | Before | After (current) |
|---|---|---|
| SessionStart source values | 4 (startup, resume, clear, compact) | 5 (adds fork in v2.1.214+) |
| Single-segment if path depth | Any depth (e.g., packages/app/src/) | Top-level only; use /src/ for old behavior |
| register_repo_root in SDK | Not available | Available in v2.1.219+ |
| PreToolUse decision fields | Top-level decision/reason (deprecated) | hookSpecificOutput.permissionDecision |
| Handler types | command, http | command, http, mcp_tool, prompt, agent (experimental) |
What you gain from Claude Code Hooks Explained
Advertisement
Tech Pulse Daily
Get tomorrow's pulse first
Join engineers who read Tech Pulse before stand-up. Free, weekday mornings.
A hook that returns permissionDecision: "deny" on PreToolUse blocks the tool call even when the session is running in bypassPermissions mode or under --dangerously-skip-permissions. The enforcement is asymmetric: hooks can tighten policy past what permissions allow, but a hook returning "allow" cannot loosen a deny rule already present in settings. This makes hooks the correct layer for safety-critical enforcement — blocking rm -rf, git push --force, or DROP TABLE — because no permission mode can route around a hook denial.
The Stop event extends this pattern to completion gating. Returning decision: "block" from a Stop hook prevents the agent from finishing until the hook exits 0 without a block decision. Anthropic caps consecutive Stop-hook blocks at 8 by default, controllable via CLAUDE_CODE_STOP_HOOK_BLOCK_CAP. A hook that checks stop_hook_active in the event JSON — and exits 0 when it is true — avoids burning through that cap. For softer steering, hookSpecificOutput.additionalContext on Stop or SubagentStop re-enters the conversation as non-error feedback rather than a hook error, keeping the agent working without triggering the block counter.
How to get Claude Code Hooks Explained
Claude Code hooks require no separate install. Update Claude Code to pick up the latest v2.1.x features:
npm install -g @anthropic-ai/claude-codeHooks are configured in settings.json under an event key. Place the file at ~/.claude/settings.json for user-wide scope, .claude/settings.json for project scope (committable), or .claude/settings.local.json for project scope (gitignored). A minimal PostToolUse formatter registration:
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{ "type": "command", "command": "jq -r '.tool_input.file_path' | xargs npx prettier --write" }
]
}
]
}
}Verify active hooks with the /hooks slash command inside Claude Code — a read-only browser showing every registered event, its handlers, and which settings file each came from. To disable all hooks temporarily, set "disableAllHooks": true in any settings file. Debug hook output with claude --debug-file /tmp/claude.log or the transcript viewer opened with Ctrl+O. One common silent failure: a shell profile that echoes on startup will inject text into a hook's stdout and corrupt any JSON the hook tries to emit.
What to watch after Claude Code Hooks Explained
The Agent SDK surface is the fastest-moving part of the hooks system. As of September 6, 2026, Python SDK callbacks support PreToolUse, PostToolUse, PostToolUseFailure, UserPromptSubmit, Stop, SubagentStart, SubagentStop, PreCompact, PermissionRequest, and Notification — but the full set of 33 events including SessionStart, SessionEnd, PostToolBatch, PermissionDenied, compaction, model-switch, task, worktree, elicitation, and file-watch events are TypeScript-only at time of writing. Developers building SDK applications in Python who need those events today must use shell-command hooks loaded via settingSources rather than SDK callbacks.
The agent handler type — which spawns a subagent with Read, Grep, and Glob tool access to evaluate a hook — is marked experimental. The PermissionRequest event's headless behavior also merits tracking: it fires in -p runs only when an Agent SDK canUseTool callback supplies the permission prompt or when a background subagent triggers it, and not during plain headless runs. Builders automating permission decisions in CI pipelines should use PreToolUse rather than PermissionRequest until that distinction changes. Anthropic's hooks reference at code.claude.com/docs/en/hooks is the canonical source; where the published documentation and any secondary write-up disagree, the reference wins.
Developer Action Items
- ☐ Diff the official changelog for Anthropic / Claude 2.1.214 before you bump — APIs, defaults, and removed flags only.
- ☐ Install through the vendor's documented channel in staging; keep a one-command rollback and time-box the canary.
- ☐ Grep your repo for old flag names, lockfile pins, and plugin versions that the notes mark as breaking.
- ☐ Prefer the first patch cut over the day-zero tag unless you have a reason to be on the leading edge.
- ☐ If HN Claude/Codex/Fable did not name a region, plan, or SKU, screenshot the official availability line before you promise it to users.
Author
Dillip Chowdary
Writes Tech Bytes coverage of AI, engineering, and the tools that actually ship. Editor of Tech Pulse Daily.
Related on Tech Bytes
Claude Opus 5.5, GPT-6 Sol, GPT-6 Luna, and a new price war
Read →
Airbnb widens access to GPT-6 Astra and OpenAI frontier models
Read →
Use open weight models as your AI coding agent with Amazon Bedrock
Read →
OpenAI just upgraded ChatGPT Voice in three ways
Read →
Today's Tech Pulse briefing
Full briefing →
Advertisement