ock | | PostToolUse | Tool name | Run after successful tool | | PostToolUseFailure | Tool name | Run after tool fails | | Notification | Notification type | Run on notifications | | Stop | - | Run when Claude stops (including clear, resume, compact) | | PreCompact | "manual"/"auto" | Before compaction | | UserPromptSubmit | - | When user submits | | SessionStart | - | When session starts | **Common tool matchers:** `Bash`, `Write`, `Edit`, `Read`, `Glob`, `Grep` ### Hook Types **1. Command Hook** - Runs a shell command: ```json { "type": "command", "command": "prettier --write $FILE", "timeout": 30 } ``` **2. Prompt Hook** - Evaluates a condition with LLM: ```json { "type": "prompt", "prompt": "Is this safe? $ARGUMENTS" } ``` Only available for tool events: PreToolUse, PostToolUse, PermissionRequest. **3. Agent Hook** - Runs an agent with tools: ```json { "type": "agent", "prompt": "Verify tests pass: $ARGUMENTS" } ``` Only available for tool events: PreToolUse, PostToolUse, PermissionRequest. ### Hook Input (stdin JSON) ```json { "session_id": "abc123", "tool_name": "Write", "tool_input": { "file_path": "/path/to/file.txt", "content": "..." }, "tool_response": { "success": true } // PostToolUse only } ``` ### Hook JSON Output Hooks can return JSON to control behavior: ```json { "systemMessage": "Warning shown to user in UI", "continue": false, "stopReason": "Message shown when blocking", "suppressOutput": false, "decision": "block", "reason": "Explanation for decision", "hookSpecificOutput": { "hookEventName": "PostToolUse", "additionalContext": "Context injected back to model" } } ``` **Fields:** - `systemMessage` - Display a message to the user (all hooks) - `continue` - Set to `false` to block/stop (default: true) - `stopReason` - Message shown when `continue` is false - `suppressOutput` - Hide stdout from transcript (default: false) - `decision` - "block" for PostToolUse/Stop/UserPromptSubmit hooks (deprecated for PreToolUse, use hookSpecificOutput.permissionDecision instead) - `reason` - Explanation for decision - `hookSpecificOutput` - Event-specific output (must include `hookEventName`): - `additionalContext` - Text injected into model context - `permissionDecision` - "allow", "deny", or "ask" (PreToolUse only) - `permissionDecisionReason` - Reason for the permission decision (PreToolUse only) - `updatedInput` - Modified tool input (PreToolUse only) ### Common Patterns **Auto-format after writes:** ```json { "hooks": { "PostToolUse": [{ "matcher": "Write|Edit", "hooks": [{ "type": "command", "command": "jq -r '.tool_response.filePath // .tool_input.file_path' | xargs prettier --write 2>/dev/null || true" }] }] } } ``` **Log all bash commands:** ```json { "hooks": { "PreToolUse": [{ "matcher": "Bash", "hooks": [{ "type": "command", "command": "jq -r '.tool_input.command' >> ~/.claude/bash-log.txt" }] }] } } ``` **Stop hook that displays message to user:** Command must output JSON with `systemMessage` field: ```bash # Example command that outputs: {"systemMessage": "Session complete!"} echo '{"systemMessage": "Session complete!"}' ``` **Run tests after code changes:** ```json { "hooks": { "PostToolUse": [{ "matcher": "Write|Edit", "hooks": [{ "type": "command", "command": "jq -r '.tool_input.file_path // .tool_response.filePath' | grep -E '\\.(ts|js)$' && npm test || true" }] }] } } ```