Agent Skills: Claude Code Hook Capabilities

Claude Code Hook system reference for capabilities, possibilities, and limitations. Use when you want to know what hooks can do.

UncategorizedID: chkim-su/forge-editor/hook-capabilities

Install this agent skill to your local

pnpm dlx add-skill https://github.com/chkim-su/forge-editor/tree/HEAD/skills/hook-capabilities

Skill Files

Browse the full folder contents for hook-capabilities.

Download Skill

Loading file tree…

skills/hook-capabilities/SKILL.md

Skill Metadata

Name
hook-capabilities
Description
Claude Code Hook system reference for capabilities, possibilities, and limitations. Use when you want to know what hooks can do.

Claude Code Hook Capabilities

Reference for what hooks can do in Claude Code.

Why Hooks Matter: The Only Guarantee

Hook = 100% execution guarantee (event-based)
Skill/Agent/MCP = ~20-80% (Claude's judgment)

Key insight: Hooks are the ONLY mechanism that executes without Claude's decision. See orchestration-patterns.md for forcing skill/agent activation.

5 Hook Roles

| Role | Description | Examples | |------|-------------|----------| | Gate | Block/allow tool execution | Prevent dangerous commands, workflow precondition checks | | Side Effect | Auto-actions after tool execution | Formatters, linters, auto-commit | | State Manager | Workflow state management | State file creation/deletion, phase tracking | | External Integrator | External system integration | MCP calls, HTTP API, WebSocket, Slack | | Context Injector | Session context injection | Load project settings, activate services |

Event Types and Characteristics

| Event | Block | Special Features | Verification | |-------|-------|------------------|--------------| | SessionStart | No | source (compact/new) | Verified | | UserPromptSubmit | Yes | stdout auto-injects into Claude context | Verified | | PreToolUse | Yes | updatedInput modifies input, tool_use_id | Verified | | PermissionRequest | Yes | allow/deny/ask + input modification | Unverified | | PostToolUse | No | tool_response (access results) | Verified | | Stop | Yes | stop_hook_active (loop prevention) | Verified | | SubagentStop | Yes | parent-child correlation via tool_use_id | Unverified | | Notification | No | includes notification_type | Verified | | PreCompact | No | trigger (auto/manual) | Verified | | SessionEnd | No | On session end | Unverified |

22 Universal Approaches

Control Patterns

| Approach | Description | Event | |----------|-------------|-------| | Iteration Control | Track iteration count + max limit | Stop | | Force Continuation | Use exit 2 to continue Claude work | Stop | | Promise Detection | Detect Claude response patterns, conditional exit | Stop | | Infinite Loop Prevention | Prevent recursion via parent_tool_use_id | UserPromptSubmit | | Threshold Branching | Branch based on error/warning count | Stop |

Input Manipulation

| Approach | Description | Event | |----------|-------------|-------| | Input Modification | Modify tool input via updatedInput | PreToolUse, PermissionRequest | | Path Normalization | Auto-convert relative to absolute paths | PreToolUse | | Environment Injection | Auto-inject environment variables | PreToolUse | | Dry-run Enforcement | Auto-add --dry-run to dangerous commands | PreToolUse |

Context Management

| Approach | Description | Event | |----------|-------------|-------| | Context Injection | stdout auto-injects into Claude context | UserPromptSubmit | | Progressive Loading | Load context/skills on demand | UserPromptSubmit | | Skill Auto-Activation | Keywords trigger skill suggestions | UserPromptSubmit | | Transcript Parsing | Read and analyze previous responses | Stop | | Transcript Backup | Backup session transcript | PreCompact |

State Management

| Approach | Description | Event | |----------|-------------|-------| | Session Cache | Accumulate per-session state + aggregate results | PostToolUse | | Session Lifecycle | Initialize/cleanup state via SessionStart/End | SessionStart/End | | Checkpoint Commit | Checkpoint on every change, then squash | PostToolUse, Stop | | Session Branching | Auto-isolate Git branches per session | Pre/PostToolUse |

External Integration

| Approach | Description | Event | |----------|-------------|-------| | Notification Forwarding | Forward notifications to Slack/Discord/external | Notification | | Desktop/Audio Alert | osascript, notify-send, TTS | Notification | | Subagent Correlation | Track parent-child via tool_use_id | SubagentStop |

Security & Compliance

| Approach | Description | Event | |----------|-------------|-------| | Auto-Approval | Auto-approve specific tools/commands | PermissionRequest | | Secret Scanning | Detect and block API keys/secrets | PreToolUse | | Compliance Audit | Compliance logging + violation detection | PostToolUse |

Implementation Techniques

| Approach | Description | Event | |----------|-------------|-------| | TypeScript Delegation | Delegate complex logic to .ts | Any | | Hook Chaining | Execute multiple hooks sequentially | Any | | Background Execution | Async via run_in_background | Any | | Argument Pattern Matching | Match arguments like Bash(npm test*) | PreToolUse | | MCP Tool Matching | Match MCP like mcp__memory__.* | PreToolUse | | Prompt-Type Hook | LLM evaluation via type: "prompt" | Any |

Capabilities vs Limitations

| Possible | Not Possible | |----------|--------------| | File create/delete/modify | Block in PostToolUse | | MCP/HTTP/WebSocket calls | Direct Claude context modification | | UserPromptSubmit stdout to context | Delete existing context | | PreToolUse/PermissionRequest input modification | Cancel already-executed tools | | Continue work from Stop | Unlimited forcing (infinite loop risk) |

Data Passing Methods (Important)

stdin JSON (Verified)

All session/project info is passed via stdin JSON:

  • session_id - Session UUID
  • cwd - Project directory
  • transcript_path - Session log file path
  • tool_use_id - Tool call ID (PreToolUse/PostToolUse)

stdin JSON Structure by Event

# UserPromptSubmit
{"prompt": "user message", "session_id": "...", "cwd": "/path"}

# PreToolUse / PostToolUse
{"tool_name": "Bash", "tool_input": {"command": "npm test"}, "session_id": "..."}

# PermissionRequest
{"tool_name": "Bash", "tool_input": {...}, "permission_type": "execute"}

# Stop
{"stop_reason": "end_turn", "session_id": "..."}

# SubagentStop
{"agent_name": "backend-dev", "result": "...", "session_id": "..."}

Environment Variables (Verified)

CLAUDE_PROJECT_DIR, CLAUDE_SESSION_ID etc. are NOT environment variables!

Actually set environment variables:

CLAUDE_CODE_ENABLE_CFC="false"
CLAUDE_CODE_ENTRYPOINT="cli"

Settings Reload

  • settings.json changes only apply in new sessions

Exit Code Reference

| Exit Code | Meaning | Behavior | |-----------|---------|----------| | 0 | Success/Allow | Normal proceed | | 1 | Error | Hook failure, show warning | | 2 | Block/Continue | Varies by event |

Exit 2 behavior by event:

| Event | exit 2 Behavior | |-------|-----------------| | PreToolUse | Block tool execution | | PostToolUse | Ignore result (prompt retry) | | PermissionRequest | Deny permission request | | Stop | Force Claude to continue | | UserPromptSubmit | Abort prompt processing |

Hook Execution Order

Multiple hooks on same event → Sequential execution (definition order)
One hook exits 2 → Subsequent hooks don't run

Timeout Setting

{"type": "command", "command": "script.sh", "timeout": 10000}

Default: 60000ms (1 minute)

Common Mistakes

| Mistake | Problem | Solution | |---------|---------|----------| | Not reading stdin | Missing JSON input | INPUT=$(cat) required | | stdout debug output | Context pollution | Use stderr (>&2) | | exit 1 vs exit 2 confusion | Unintended behavior | exit 1=error, exit 2=block | | Parsing without jq | Unstable | Install and use jq |

References