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", "additionalContext": "Context injected back to model", "decision": "approve" | "block" } ``` **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 - `additionalContext` - Text injected into model context (event-specific) - `decision` - "approve" or "block" for PreToolUse hooks ### 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" }] }] } } ``` WŸ