Hook Development for Claude Code Plugins
Overview
Hooks are event-driven automation scripts that execute in response to Claude Code events. Use hooks to validate operations, enforce policies, add context, and integrate external tools into workflows.
**Key capabilities:**
- Validate tool calls before execution (PreToolUse)
- React to tool results (PostToolUse)
- Enforce completion standards (Stop, SubagentStop)
- Load project context (SessionStart)
- Automate workflows across the development lifecycle
Hook Types
Prompt-Based Hooks (Recommended)
Use LLM-driven decision making for context-aware validation:
{
"type": "prompt",
"prompt": "Evaluate if this tool use is appropriate: $TOOL_INPUT",
"timeout": 30
}**Supported events:** Stop, SubagentStop, UserPromptSubmit, PreToolUse
**Benefits:**
- Context-aware decisions based on natural language reasoning
- Flexible evaluation logic without bash scripting
- Better edge case handling
- Easier to maintain and extend
Command Hooks
Execute bash commands for deterministic checks:
{
"type": "command",
"command": "bash ${CLAUDE_PLUGIN_ROOT}/scripts/validate.sh",
"timeout": 60
}**Use for:**
- Fast deterministic validations
- File system operations
- External tool integrations
- Performance-critical checks
Hook Configuration Formats
Plugin hooks.json Format
**For plugin hooks** in `hooks/hooks.json`, use wrapper format:
{
"description": "Brief explanation of hooks (optional)",
"hooks": {
"PreToolUse": [...],
"Stop": [...],
"SessionStart": [...]
}
}**Key points:**
- `description` field is optional
- `hooks` field is required wrapper containing actual hook events
- This is the **plugin-specific format**
**Example:**
{
"description": "Validation hooks for code quality",
"hooks": {
"PreToolUse": [
{
"matcher": "Write",
"hooks": [
{
"type": "command",
"command": "${CLAUDE_PLUGIN_ROOT}/hooks/validate.sh"
}
]
}
]
}
}Settings Format (Direct)
**For user settings** in `.claude/settings.json`, use direct format:
{
"PreToolUse": [...],
"Stop": [...],
"SessionStart": [...]
}**Key points:**
- No wrapper - events directly at top level
- No description field
- This is the **settings format**
**Important:** The examples below show the hook event structure that goes inside either format. For plugin hooks.json, wrap these in `{"hooks": {...}}`.
Hook Events
PreToolUse
Execute before any tool runs. Use to approve, deny, or modify tool calls.
**Example (prompt-based):**
{
"PreToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "prompt",
"prompt": "Validate file write safety. Check: system paths, credentials, path traversal, sensitive content. Return 'approve' or 'deny'."
}
]
}
]
}**Output for PreToolUse:**
{
"hookSpecificOutput": {
"permissionDecision": "allow|deny|ask",
"updatedInput": {"field": "modified_value"}
},
"systemMessage": "Explanation for Claude"
}PostToolUse
Execute after tool completes. Use to react to results, provide feedback, or log.
**Example:**
{
"PostToolUse": [
{
"matcher": "Edit",
"hooks": [
{
"type": "p
<!-- truncated -->