Hooks (Claude Code)

Claude Code

Definition

Shell scripts or commands configured in .claude/settings.json that run at defined lifecycle points: PreToolUse (before tool execution), PostToolUse (after tool execution), Stop (before ending), SubagentStop (when subagent finishes). Used for code quality gates, notifications, logging, and safety checks.

Example Usage

Configure a PostToolUse hook to run 'npm test' automatically after every file edit, giving Claude immediate feedback on whether changes broke tests.

Why It Matters for the CCA-F Exam

Hooks are a Domain 3 focus area. CCA-F questions test your ability to select the right hook event for a given scenario and to explain the difference between hooks (configured in settings.json, run by the harness) and instructions in CLAUDE.md (read by the model). The exam also probes SubagentStop specifically — it only fires for subagent termination, not the main session.

In Depth

Hooks are shell commands or scripts registered in .claude/settings.json that Claude Code executes automatically at defined lifecycle points during a session. They give teams a programmable layer of control around Claude's actions — enforcing quality gates, capturing audit logs, sending notifications, or blocking unsafe operations.

The four hook events:

EventFires whenTypical use
PreToolUseBefore Claude executes any tool callValidate inputs, block dangerous commands, require approval
PostToolUseAfter a tool call completesRun tests, format code, update logs
StopWhen the main agent session endsSend Slack notification, persist artifacts
SubagentStopWhen a subagent finishesCollect subagent output, trigger downstream work

How hooks work in practice:

A PostToolUse hook that runs tests after every file write gives Claude immediate feedback — if the tests fail, Claude knows before moving on and can fix the issue in the same session rather than discovering a broken state later.

A PreToolUse hook can inspect the tool name and arguments. If a Bash tool call looks like rm -rf /, the hook can return a non-zero exit code to block it.

Hooks run as shell processes in the project directory, with the full environment available. They receive context about the triggering event (tool name, arguments, result) via environment variables or stdin, depending on configuration.

Configuration in settings.json:

{
  "hooks": {
    "PostToolUse": ["npm test -- --passWithNoTests"],
    "PreToolUse": ["./.claude/hooks/validate-tool.sh"],
    "Stop": ["node ./.claude/hooks/notify-slack.js"]
  }
}

See also: .claude/settings.json, PreToolUse Hook, PostToolUse Hook.

Related concept: Agent SDK Hooks: PostToolUse & Interception.

Example

All four hook events configured in .claude/settings.json. PreToolUse runs a validation script before any tool fires; PostToolUse runs the test suite after every tool call; Stop and SubagentStop handle session teardown.

json
{
  "hooks": {
    "PreToolUse": ["./.claude/hooks/pre-tool-check.sh"],
    "PostToolUse": ["npm test -- --passWithNoTests --silent"],
    "Stop": ["echo 'Session complete' >> .claude/session.log"],
    "SubagentStop": ["./.claude/hooks/collect-subagent-output.sh"]
  }
}

Frequently Asked Questions

What is the difference between Stop and SubagentStop?

`Stop` fires when the main Claude Code session ends. `SubagentStop` fires when a subagent (spawned via the Task tool) finishes. If you want to process every subagent's output as it completes rather than waiting for the whole session, use SubagentStop.

Can a PreToolUse hook block a tool from executing?

Yes. If a PreToolUse hook exits with a non-zero status code, Claude Code treats the tool call as blocked and will not execute it. This is the mechanism for implementing safety gates — the hook inspects the tool name and arguments and rejects unsafe calls before they run.

Where does the hook run relative to CLAUDE.md instructions?

They are independent layers. CLAUDE.md instructions are read by the model and influence what Claude *decides* to do. Hooks are executed by the harness and run regardless of model decisions — they operate at the infrastructure level, not the prompt level. This makes hooks more reliable for enforcement.