Skip to content

Latest commit

 

History

History
161 lines (141 loc) · 4.33 KB

File metadata and controls

161 lines (141 loc) · 4.33 KB

Hooks Configuration

Hooks run commands at specific points in Claude Code's lifecycle.

Hook Structure

```json { "hooks": { "EVENT_NAME": [ { "matcher": "ToolName|OtherTool", "hooks": [ { "type": "command", "command": "your-command-here", "timeout": 60, "statusMessage": "Running..." } ] } ] } } ```

Hook Events

Event Matcher Purpose
PermissionRequest Tool name Run before permission prompt
PreToolUse Tool name Run before tool, can block
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" }] }] } } ```