Skip to content

Hooks, part one: events and configuration

Hooks run your own logic on lifecycle events — deterministically, every time the event fires. The main events:

Event When Use for
PreToolUse Before a tool runs Validation, approve/deny/modify
PostToolUse After a tool completes Feedback, formatting, logging
UserPromptSubmit You submit a prompt Add context, validate
Stop / SubagentStop Agent considers stopping Completeness checks
SessionStart / SessionEnd Session boundaries Load context / cleanup
PreCompact Before compaction Preserve critical info
Notification Claude notifies you Logging, reactions
.claude/settings.json — format on save
{
"hooks": {
"PostToolUse": [{
"matcher": "Edit|Write",
"hooks": [{
"type": "command",
"command": "jq -r '.tool_input.file_path' | xargs npx prettier --write",
"timeout": 30
}]
}]
}
}

Matchers select which tools trigger the hook: exact ("Write"), alternation ("Read|Write|Edit"), wildcard ("*"), or regex against MCP tools ("mcp__.*__delete.*"). Hooks receive JSON on stdin (tool_name, tool_input, cwd…) and speak through exit codes: 0 = success, 2 = blocking error whose stderr is fed back to Claude.

Question 1Which exit code makes a hook block the action and feed stderr back to Claude?

Question 2You edited hooks.json mid-session. What must you do?

Question 3Which matcher fires on every MCP tool?