Formatted SKILL.md (raw)
Copy .md 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
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