nrempel avatar

add-hook

Add event hooks to a Claude Code plugin. Use when user wants to run code automatically on events lik

提供方 nrempel|开源

Add Hook

You are adding event hooks to a Claude Code plugin. Hooks run automatically in response to Claude Code events. Follow these steps:

1. Gather Information

Ask the user for:

  • Plugin path (which plugin to add to, or current directory)
  • Event type (which event triggers the hook?)
  • Hook type (command, prompt, or agent?)
  • What should happen (script to run or prompt to evaluate)
  • Matcher (optional: filter to specific tools)

2. Available Events

EventTriggered When
PreToolUseBefore Claude uses any tool
PostToolUseAfter successful tool use
PostToolUseFailureAfter a tool fails
UserPromptSubmitUser submits a prompt
SessionStartSession begins
SessionEndSession ends
SubagentStartA subagent is spawned
SubagentStopA subagent completes
PreCompactBefore context compaction
NotificationClaude sends a notification
StopClaude attempts to stop

3. Create or Update hooks.json

Location: <plugin>/hooks/hooks.json

{
  "hooks": {
    "<EventName>": [
      {
        "matcher": "<ToolName|Pattern>",
        "hooks": [
          {
            "type": "command",
            "command": "${CLAUDE_PLUGIN_ROOT}/scripts/<script>.sh"
          }
        ]
      }
    ]
  }
}

4. Hook Types

Command Hook

Runs a shell command:

{
  "type": "command",
  "command": "${CLAUDE_PLUGIN_ROOT}/scripts/lint.sh"
}

Prompt Hook

Evaluates with an LLM:

{
  "type": "prompt",
  "prompt": "Check if this action is safe",
  "timeout": 5000
}

Agent Hook

Runs agentic verification:

{
  "type": "agent",
  "prompt": "Analyze this change for issues"
}

5. Matcher Patterns

  • "Write|Edit" - Matches Write or Edit tools
  • "Read" - Matches Read tool only
  • "" - Matches all (empty string)
  • Tool names are case-sensitive

6. Exit Codes (for command hooks)

  • 0 - Success, continue
  • 1 - Failure, block the action
  • 2 - Intervention, ask user

7. Environment Variables

Always use ${CLAUDE_PLUGIN_ROOT} for paths in hooks - it resolves to the plugin's absolute path.

8. Example: Lint on Write

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "command",
            "command": "${CLAUDE_PLUGIN_ROOT}/scripts/lint.sh"
          }
        ]
      }
    ]
  }
}

After creating hooks.json, remind the user to:

  1. Create any referenced scripts
  2. Make scripts executable: chmod +x scripts/*.sh
  3. Test the hook by triggering the event