PreToolUse
Gatekeeper. Reject before the tool runs.
- Block dangerous commands
- Require auth on risky tools
- Lock paths off-limits
Prevents the tool call.
Canonical — protect-files.sh blocks edits to flagged paths.
Code that runs when the harness fires. Zero context cost — the deterministic edge.
Gatekeeper. Reject before the tool runs.
Prevents the tool call.
Canonical — protect-files.sh blocks edits to flagged paths.
Verifier. Inspect what just happened, surface back to Claude.
Stderr is surfaced to Claude as an actionable error.
Canonical — lint-on-edit.sh runs ruff after every *.py edit.
Final-state check. The agent says "I'm done" — you check first.
Prevents the turn from completing — agent must keep working.
Canonical — tests-on-stop.sh blocks "done" claims if tests fail.
Compaction guard. Catch the surprise auto-compact moment.
/context to audit firstBlocks the compaction. Manual /compact still proceeds.
Canonical — precompact-checkpoint on matcher "auto".
Four common cases, not the full set — Claude Code emits ~28 events across the agent lifecycle (session, turn, agentic loop, file, compaction, worktree, notification). Browse all registered hooks with /hooks · full event list →
Claude Code's interpretation
| Exit | What Claude Code does |
|---|---|
| 0 | Success. Action proceeds. stdout goes to Claude Code's debug log — not surfaced to Claude. |
| 2 | Block. PreToolUse / PreCompact / Stop → action prevented. PostToolUse → stderr is surfaced to Claude as an actionable error in-turn. |
| 1 | Non-blocking error. Action still proceeds — Claude Code treats this as a soft failure. Use 2 if you actually want to block. |
command: prompt (Claude evaluates a rule) · agent (forks a subagent) · http (calls a webhook). Same registration shape, different runner.
Four files. Lower wins — local overrides project overrides user; managed overrides everything.
| File | Scope | Checked in |
|---|---|---|
~/.claude/settings.json |
You · every project | — |
./.claude/settings.json |
Team · everyone on this repo | ✓ |
./.claude/settings.local.json |
You · this repo only | — (gitignored) |
managed-settings.json |
Org · IT-controlled (rare for solo dev) | — (OS policy) |