Claude Codehigh

Hooks (PreToolUse, PostToolUse, Stop)

Hooks are shell commands that fire on agent lifecycle events. Configured in settings.json. The most-used events: PreToolUse (before any tool runs), PostToolUse (after), Stop (when the model tries to end its turn), UserPromptSubmit (when user sends a message). Additional events include SubagentStop, PreCompact, SessionStart, SessionEnd, and Notification — see the Claude Code docs for the full list.

Memory anchor

Hooks are airport security checkpoints — PreToolUse is the metal detector (block before action), PostToolUse is the customs declaration (observe after), Stop is the gate agent (can't leave the gate until boarding pass scans).

Expected depth

Each hook has an event, an optional matcher (e.g., 'Bash' for tool name), and a command that runs in the project root. Hooks can block actions: returning non-zero exit + a message in stderr cancels the tool call (PreToolUse) or forces the agent to keep working (Stop). Hooks see structured JSON about the event on stdin. Common uses: auto-format on PostToolUse Edit, run typecheck on Stop, log every Bash call to a security audit, snapshot session state on PreCompact before context compression.

Deep — senior internals

Hook commands inherit the user's environment — same shell, same PATH, same secrets. Stop hooks are the most powerful: they can prevent the agent from ending its turn until conditions are met (tests pass, build succeeds). SubagentStop fires when a spawned subagent finishes — useful for verifying delegated work. PreCompact fires before auto-compaction so you can persist important state. The model sees hook stderr messages as user feedback and is expected to address them. Hooks bypass approval gates — they ALWAYS run, so a misconfigured hook (e.g., infinite loop) can deadlock the agent. disableAllHooks: true in settings.local.json is the kill switch. Multi-hook chains: multiple hooks for the same event run sequentially; first failure usually short-circuits.

🎤Interview-ready answer

Hooks let me run shell commands at agent lifecycle points — before/after tool calls, on stop, on user prompt submission. They're configured in settings.json with an event type, an optional matcher, and a command. The most powerful is Stop hooks because they can block the model from ending its turn — I use them to enforce 'tests must pass' or 'no uncommitted changes.' The model sees hook stderr as feedback and is expected to fix the issue. Hooks always run, so a buggy hook can deadlock the agent — I keep a kill switch in settings.local.json.

Common trap

Stop hooks that fire after every turn become noise — the model gets the same complaint repeatedly even if it's not actionable. Make Stop hooks specific: 'fail if tests are failing AND tests were touched in this session,' not 'fail if tests are failing.'

Related concepts