Hooks: Lifecycle & Control

Deterministic automation at every stage of a Claude session. Hooks are shell commands the harness runs at lifecycle events — they don't go through the model, so behavior is reliable.

SessionStartUserPromptPreToolUsePostToolUseStoptool loop
Walkthrough: blocking rm -rf
1Claude wants to run rm -rf /tmp/build
2PreToolUse fires — JSON sent to hook
3Matcher: "Bash" ✓  If: Bash(rm *)
4Script detects rm -rf in command
✗ DENIED — Tool call blocked
Hook config in .claude/settings.json
// .claude/settings.json{  "hooks": {    "PreToolUse": [      {        "matcher": "Bash",        "hooks": [          {            "type": "command",            "if": "Bash(rm *)",            "command": "./hooks/block-rm.sh"          }        ]      }    ]  }}
Exit codes: 0 = allow · 2 = block · other = warn but continue
Hook types: command, http, prompt, agent

Why use hooks?

Use hooks when you need deterministic safety: blocking destructive commands, running linters/tests after edits, validating commits before push. The model can't talk its way out of an exit code 2.