Guide to Claude Code hooks — lifecycle events, handler types, decision control, and common patterns. Use when creating, debugging, or planning hooks for guardrails, context injection, quality gates, notifications, or automation.
Creates deterministic lifecycle handlers for guardrails, context injection, and automation that Claude cannot ignore.
npx claudepluginhub captaincrouton89/crouton-kitThis skill inherits all available tools. When active, it can use any tool Claude has access to.
patterns.mdHooks are deterministic handlers that fire at lifecycle events. Unlike instructions, hooks cannot be ignored — they block, inject, or modify at the system level.
| Event | Fires When | Can Block? | Can Inject Context? |
|---|---|---|---|
SessionStart | Session begins/resumes/compacts | No | Yes |
UserPromptSubmit | User submits prompt | Yes | Yes |
PreToolUse | Before tool executes | Yes | Yes |
PostToolUse | After tool succeeds | No | Yes |
PostToolUseFailure | After tool fails | No | Yes |
Stop | Claude finishes responding | Yes (continue) | Yes |
SubagentStart | Subagent spawns | No | Yes |
SubagentStop | Subagent finishes | Yes (continue) | Yes |
TeammateIdle | Teammate about to idle | Yes (continue) | Yes |
TaskCompleted | Task marked complete | Yes (reject) | Yes |
PreCompact | Before context compaction | No | No |
Notification | Notification sent | No | No |
SessionEnd | Session terminates | No | No |
PermissionRequest | Permission dialog appears | Yes (auto-allow) | No |
command — Shell script. Receives JSON on stdin, returns via exit code + stdout/stderr.
prompt — Single-turn LLM evaluation. Fast, no tool access. Good for nuanced decisions.
agent — Multi-turn subagent with tool access. Can read files, run commands, investigate. Most powerful but slowest.
PreToolUse handlers can return:
permissionDecision: "allow" | "deny" | "ask" — override permission systemupdatedInput: {...} — transparently modify tool parametersadditionalContext: "..." — inject text into Claude's contextStop/SubagentStop/TeammateIdle/TaskCompleted handlers can return:
decision: "block" with reason: "..." — force continuationPermissionRequest handlers can return:
behavior: "allow" | "deny" | "ask" — auto-approve or rejectupdatedPermissions: [...] — apply persistent permission rules{
"event": "PreToolUse",
"matcher": "Bash|Edit|Write",
"command": "node ${CLAUDE_PLUGIN_ROOT}/hooks/guard.mjs"
}
| separates multiple tool names: Write|Edit|MultiEditmcp__servername__toolname or mcp__servername__*resume, clear, compactSee patterns.md for comprehensive examples organized by category:
"async": true for hooks that shouldn't block (tests, notifications)stop_hook_active to prevent infinite continuation loops.