$npx -y skills add anthropics/claude-code --skill hook-developmentThis skill should be used when the user asks to "create a hook", "add a PreToolUse/PostToolUse/Stop hook", "validate tool use", "implement prompt-based hooks", "use ${CLAUDE_PLUGIN_ROOT}", "set up event-driven automation", "block dangerous commands", or mentions hook events (PreT
| 1 | # Hook Development for Claude Code Plugins |
| 2 | |
| 3 | ## Overview |
| 4 | |
| 5 | 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. |
| 6 | |
| 7 | **Key capabilities:** |
| 8 | - Validate tool calls before execution (PreToolUse) |
| 9 | - React to tool results (PostToolUse) |
| 10 | - Enforce completion standards (Stop, SubagentStop) |
| 11 | - Load project context (SessionStart) |
| 12 | - Automate workflows across the development lifecycle |
| 13 | |
| 14 | ## Hook Types |
| 15 | |
| 16 | ### Prompt-Based Hooks (Recommended) |
| 17 | |
| 18 | Use LLM-driven decision making for context-aware validation: |
| 19 | |
| 20 | ```json |
| 21 | { |
| 22 | "type": "prompt", |
| 23 | "prompt": "Evaluate if this tool use is appropriate: $TOOL_INPUT", |
| 24 | "timeout": 30 |
| 25 | } |
| 26 | ``` |
| 27 | |
| 28 | **Supported events:** Stop, SubagentStop, UserPromptSubmit, PreToolUse |
| 29 | |
| 30 | **Benefits:** |
| 31 | - Context-aware decisions based on natural language reasoning |
| 32 | - Flexible evaluation logic without bash scripting |
| 33 | - Better edge case handling |
| 34 | - Easier to maintain and extend |
| 35 | |
| 36 | ### Command Hooks |
| 37 | |
| 38 | Execute bash commands for deterministic checks: |
| 39 | |
| 40 | ```json |
| 41 | { |
| 42 | "type": "command", |
| 43 | "command": "bash ${CLAUDE_PLUGIN_ROOT}/scripts/validate.sh", |
| 44 | "timeout": 60 |
| 45 | } |
| 46 | ``` |
| 47 | |
| 48 | **Use for:** |
| 49 | - Fast deterministic validations |
| 50 | - File system operations |
| 51 | - External tool integrations |
| 52 | - Performance-critical checks |
| 53 | |
| 54 | ## Hook Configuration Formats |
| 55 | |
| 56 | ### Plugin hooks.json Format |
| 57 | |
| 58 | **For plugin hooks** in `hooks/hooks.json`, use wrapper format: |
| 59 | |
| 60 | ```json |
| 61 | { |
| 62 | "description": "Brief explanation of hooks (optional)", |
| 63 | "hooks": { |
| 64 | "PreToolUse": [...], |
| 65 | "Stop": [...], |
| 66 | "SessionStart": [...] |
| 67 | } |
| 68 | } |
| 69 | ``` |
| 70 | |
| 71 | **Key points:** |
| 72 | - `description` field is optional |
| 73 | - `hooks` field is required wrapper containing actual hook events |
| 74 | - This is the **plugin-specific format** |
| 75 | |
| 76 | **Example:** |
| 77 | ```json |
| 78 | { |
| 79 | "description": "Validation hooks for code quality", |
| 80 | "hooks": { |
| 81 | "PreToolUse": [ |
| 82 | { |
| 83 | "matcher": "Write", |
| 84 | "hooks": [ |
| 85 | { |
| 86 | "type": "command", |
| 87 | "command": "${CLAUDE_PLUGIN_ROOT}/hooks/validate.sh" |
| 88 | } |
| 89 | ] |
| 90 | } |
| 91 | ] |
| 92 | } |
| 93 | } |
| 94 | ``` |
| 95 | |
| 96 | ### Settings Format (Direct) |
| 97 | |
| 98 | **For user settings** in `.claude/settings.json`, use direct format: |
| 99 | |
| 100 | ```json |
| 101 | { |
| 102 | "PreToolUse": [...], |
| 103 | "Stop": [...], |
| 104 | "SessionStart": [...] |
| 105 | } |
| 106 | ``` |
| 107 | |
| 108 | **Key points:** |
| 109 | - No wrapper - events directly at top level |
| 110 | - No description field |
| 111 | - This is the **settings format** |
| 112 | |
| 113 | **Important:** The examples below show the hook event structure that goes inside either format. For plugin hooks.json, wrap these in `{"hooks": {...}}`. |
| 114 | |
| 115 | ## Hook Events |
| 116 | |
| 117 | ### PreToolUse |
| 118 | |
| 119 | Execute before any tool runs. Use to approve, deny, or modify tool calls. |
| 120 | |
| 121 | **Example (prompt-based):** |
| 122 | ```json |
| 123 | { |
| 124 | "PreToolUse": [ |
| 125 | { |
| 126 | "matcher": "Write|Edit", |
| 127 | "hooks": [ |
| 128 | { |
| 129 | "type": "prompt", |
| 130 | "prompt": "Validate file write safety. Check: system paths, credentials, path traversal, sensitive content. Return 'approve' or 'deny'." |
| 131 | } |
| 132 | ] |
| 133 | } |
| 134 | ] |
| 135 | } |
| 136 | ``` |
| 137 | |
| 138 | **Output for PreToolUse:** |
| 139 | ```json |
| 140 | { |
| 141 | "hookSpecificOutput": { |
| 142 | "permissionDecision": "allow|deny|ask", |
| 143 | "updatedInput": {"field": "modified_value"} |
| 144 | }, |
| 145 | "systemMessage": "Explanation for Claude" |
| 146 | } |
| 147 | ``` |
| 148 | |
| 149 | ### PostToolUse |
| 150 | |
| 151 | Execute after tool completes. Use to react to results, provide feedback, or log. |
| 152 | |
| 153 | **Example:** |
| 154 | ```json |
| 155 | { |
| 156 | "PostToolUse": [ |
| 157 | { |
| 158 | "matcher": "Edit", |
| 159 | "hooks": [ |
| 160 | { |
| 161 | "type": "prompt", |
| 162 | "prompt": "Analyze edit result for potential issues: syntax errors, security vulnerabilities, breaking changes. Provide feedback." |
| 163 | } |
| 164 | ] |
| 165 | } |
| 166 | ] |
| 167 | } |
| 168 | ``` |
| 169 | |
| 170 | **Output behavior:** |
| 171 | - Exit 0: stdout shown in transcript |
| 172 | - Exit 2: stderr fed back to Claude |
| 173 | - systemMessage included in context |
| 174 | |
| 175 | ### Stop |
| 176 | |
| 177 | Execute when main agent considers stopping. Use to validate completeness. |
| 178 | |
| 179 | **Example:** |
| 180 | ```json |
| 181 | { |
| 182 | "Stop": [ |
| 183 | { |
| 184 | "matcher": "*", |
| 185 | "hooks": [ |
| 186 | { |
| 187 | "type": "prompt", |
| 188 | "prompt": "Verify task completion: tests run, build succeeded, questions answered. Return 'approve' to stop or 'block' with reason to continue." |
| 189 | } |
| 190 | ] |
| 191 | } |
| 192 | ] |
| 193 | } |
| 194 | ``` |
| 195 | |
| 196 | **Decision output:** |
| 197 | ```json |
| 198 | { |
| 199 | "decision": "approve|block", |
| 200 | "reason": "Explanation", |
| 201 | "systemMessage": "Additional context" |
| 202 | } |
| 203 | ``` |
| 204 | |
| 205 | ### SubagentStop |
| 206 | |
| 207 | Execute when subagent considers stopping. Use to ensure subagent completed its task. |
| 208 | |
| 209 | Similar to Stop hook, but for subagents. |
| 210 | |
| 211 | ### UserPr |