hook-development

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Hook Development for Claude Code Plugins

Claude Code插件钩子开发

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
钩子是响应Claude Code事件执行的事件驱动自动化脚本。使用钩子可以验证操作、实施策略、添加上下文,并将外部工具集成到工作流中。
核心功能:
  • 在执行前验证工具调用(PreToolUse)
  • 响应工具执行结果(PostToolUse)
  • 强制执行完成标准(Stop、SubagentStop)
  • 加载项目上下文(SessionStart)
  • 在开发生命周期内实现工作流自动化

Hook Types

钩子类型

Prompt-Based Hooks (Recommended)

基于提示词的钩子(推荐)

Use LLM-driven decision making for context-aware validation:
json
{
  "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
使用LLM驱动的决策实现上下文感知验证:
json
{
  "type": "prompt",
  "prompt": "Evaluate if this tool use is appropriate: $TOOL_INPUT",
  "timeout": 30
}
支持的事件: Stop、SubagentStop、UserPromptSubmit、PreToolUse
优势:
  • 基于自然语言推理的上下文感知决策
  • 无需bash脚本的灵活评估逻辑
  • 更好的边缘情况处理
  • 更易于维护和扩展

Command Hooks

命令式钩子

Execute bash commands for deterministic checks:
json
{
  "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
执行bash命令以进行确定性检查:
json
{
  "type": "command",
  "command": "bash ${CLAUDE_PLUGIN_ROOT}/scripts/validate.sh",
  "timeout": 60
}
适用场景:
  • 快速确定性验证
  • 文件系统操作
  • 外部工具集成
  • 性能关键型检查

Hook Configuration Formats

钩子配置格式

Plugin hooks.json Format

插件hooks.json格式

For plugin hooks in
hooks/hooks.json
, use wrapper format:
json
{
  "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:
json
{
  "description": "Validation hooks for code quality",
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Write",
        "hooks": [
          {
            "type": "command",
            "command": "${CLAUDE_PLUGIN_ROOT}/hooks/validate.sh"
          }
        ]
      }
    ]
  }
}
插件的钩子定义在
hooks/hooks.json
中,使用包装格式:
json
{
  "description": "钩子的简要说明(可选)",
  "hooks": {
    "PreToolUse": [...],
    "Stop": [...],
    "SessionStart": [...]
  }
}
关键点:
  • description
    字段可选
  • hooks
    字段是必填的包装器,包含实际的钩子事件
  • 这是插件专用格式
示例:
json
{
  "description": "代码质量验证钩子",
  "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:
json
{
  "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": {...}}
.
用户设置中的钩子定义在
.claude/settings.json
中,使用直接格式:
json
{
  "PreToolUse": [...],
  "Stop": [...],
  "SessionStart": [...]
}
关键点:
  • 无包装器 - 事件直接位于顶层
  • 无description字段
  • 这是设置格式
重要提示: 以下示例展示了可用于上述两种格式的钩子事件结构。对于插件hooks.json,需要将这些结构包装在
{"hooks": {...}}
中。

Hook Events

钩子事件

PreToolUse

PreToolUse

Execute before any tool runs. Use to approve, deny, or modify tool calls.
Example (prompt-based):
json
{
  "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:
json
{
  "hookSpecificOutput": {
    "permissionDecision": "allow|deny|ask",
    "updatedInput": {"field": "modified_value"}
  },
  "systemMessage": "Explanation for Claude"
}
在任何工具运行前执行。用于批准、拒绝或修改工具调用。
示例(基于提示词):
json
{
  "PreToolUse": [
    {
      "matcher": "Write|Edit",
      "hooks": [
        {
          "type": "prompt",
          "prompt": "验证文件写入安全性。检查:系统路径、凭据、路径遍历、敏感内容。返回'approve'或'deny'。"
        }
      ]
    }
  ]
}
PreToolUse输出:
json
{
  "hookSpecificOutput": {
    "permissionDecision": "allow|deny|ask",
    "updatedInput": {"field": "modified_value"}
  },
  "systemMessage": "给Claude的说明"
}

PostToolUse

PostToolUse

Execute after tool completes. Use to react to results, provide feedback, or log.
Example:
json
{
  "PostToolUse": [
    {
      "matcher": "Edit",
      "hooks": [
        {
          "type": "prompt",
          "prompt": "Analyze edit result for potential issues: syntax errors, security vulnerabilities, breaking changes. Provide feedback."
        }
      ]
    }
  ]
}
Output behavior:
  • Exit 0: stdout shown in transcript
  • Exit 2: stderr fed back to Claude
  • systemMessage included in context
工具完成后执行。用于响应结果、提供反馈或记录日志。
示例:
json
{
  "PostToolUse": [
    {
      "matcher": "Edit",
      "hooks": [
        {
          "type": "prompt",
          "prompt": "分析编辑结果是否存在潜在问题:语法错误、安全漏洞、破坏性变更。提供反馈。"
        }
      ]
    }
  ]
}
输出行为:
  • 退出码0:标准输出显示在对话记录中
  • 退出码2:标准错误反馈给Claude
  • systemMessage会被包含在上下文中

Stop

Stop

Execute when main agent considers stopping. Use to validate completeness.
Example:
json
{
  "Stop": [
    {
      "matcher": "*",
      "hooks": [
        {
          "type": "prompt",
          "prompt": "Verify task completion: tests run, build succeeded, questions answered. Return 'approve' to stop or 'block' with reason to continue."
        }
      ]
    }
  ]
}
Decision output:
json
{
  "decision": "approve|block",
  "reason": "Explanation",
  "systemMessage": "Additional context"
}
当主Agent考虑停止时执行。用于验证任务完成情况。
示例:
json
{
  "Stop": [
    {
      "matcher": "*",
      "hooks": [
        {
          "type": "prompt",
          "prompt": "验证任务完成情况:测试已运行、构建成功、问题已解答。返回'approve'以停止,或返回'block'并说明原因以继续。"
        }
      ]
    }
  ]
}
决策输出:
json
{
  "decision": "approve|block",
  "reason": "说明",
  "systemMessage": "额外上下文"
}

SubagentStop

SubagentStop

Execute when subagent considers stopping. Use to ensure subagent completed its task.
Similar to Stop hook, but for subagents.
当子Agent考虑停止时执行。用于确保子Agent已完成其任务。
与Stop钩子类似,但针对子Agent。

UserPromptSubmit

UserPromptSubmit

Execute when user submits a prompt. Use to add context, validate, or block prompts.
Example:
json
{
  "UserPromptSubmit": [
    {
      "matcher": "*",
      "hooks": [
        {
          "type": "prompt",
          "prompt": "Check if prompt requires security guidance. If discussing auth, permissions, or API security, return relevant warnings."
        }
      ]
    }
  ]
}
当用户提交提示词时执行。用于添加上下文、验证或阻止提示词。
示例:
json
{
  "UserPromptSubmit": [
    {
      "matcher": "*",
      "hooks": [
        {
          "type": "prompt",
          "prompt": "检查提示词是否需要安全指导。如果讨论身份验证、权限或API安全,返回相关警告。"
        }
      ]
    }
  ]
}

SessionStart

SessionStart

Execute when Claude Code session begins. Use to load context and set environment.
Example:
json
{
  "SessionStart": [
    {
      "matcher": "*",
      "hooks": [
        {
          "type": "command",
          "command": "bash ${CLAUDE_PLUGIN_ROOT}/scripts/load-context.sh"
        }
      ]
    }
  ]
}
Special capability: Persist environment variables using
$CLAUDE_ENV_FILE
:
bash
echo "export PROJECT_TYPE=nodejs" >> "$CLAUDE_ENV_FILE"
See
examples/load-context.sh
for complete example.
当Claude Code会话开始时执行。用于加载上下文和设置环境。
示例:
json
{
  "SessionStart": [
    {
      "matcher": "*",
      "hooks": [
        {
          "type": "command",
          "command": "bash ${CLAUDE_PLUGIN_ROOT}/scripts/load-context.sh"
        }
      ]
    }
  ]
}
特殊功能: 使用
$CLAUDE_ENV_FILE
持久化环境变量:
bash
echo "export PROJECT_TYPE=nodejs" >> "$CLAUDE_ENV_FILE"
完整示例请参见
examples/load-context.sh

SessionEnd

SessionEnd

Execute when session ends. Use for cleanup, logging, and state preservation.
会话结束时执行。用于清理、日志记录和状态保存。

PreCompact

PreCompact

Execute before context compaction. Use to add critical information to preserve.
上下文压缩前执行。用于添加需要保留的关键信息。

Notification

Notification

Execute when Claude sends notifications. Use to react to user notifications.
当Claude发送通知时执行。用于响应用户通知。

Hook Output Format

钩子输出格式

Standard Output (All Hooks)

标准输出(所有钩子)

json
{
  "continue": true,
  "suppressOutput": false,
  "systemMessage": "Message for Claude"
}
  • continue
    : If false, halt processing (default true)
  • suppressOutput
    : Hide output from transcript (default false)
  • systemMessage
    : Message shown to Claude
json
{
  "continue": true,
  "suppressOutput": false,
  "systemMessage": "给Claude的消息"
}
  • continue
    :如果为false,终止处理(默认true)
  • suppressOutput
    :隐藏对话记录中的输出(默认false)
  • systemMessage
    :显示给Claude的消息

Exit Codes

退出码

  • 0
    - Success (stdout shown in transcript)
  • 2
    - Blocking error (stderr fed back to Claude)
  • Other - Non-blocking error
  • 0
    - 成功(标准输出显示在对话记录中)
  • 2
    - 阻塞错误(标准错误反馈给Claude)
  • 其他 - 非阻塞错误

Hook Input Format

钩子输入格式

All hooks receive JSON via stdin with common fields:
json
{
  "session_id": "abc123",
  "transcript_path": "/path/to/transcript.txt",
  "cwd": "/current/working/dir",
  "permission_mode": "ask|allow",
  "hook_event_name": "PreToolUse"
}
Event-specific fields:
  • PreToolUse/PostToolUse:
    tool_name
    ,
    tool_input
    ,
    tool_result
  • UserPromptSubmit:
    user_prompt
  • Stop/SubagentStop:
    reason
Access fields in prompts using
$TOOL_INPUT
,
$TOOL_RESULT
,
$USER_PROMPT
, etc.
所有钩子通过标准输入接收包含通用字段的JSON:
json
{
  "session_id": "abc123",
  "transcript_path": "/path/to/transcript.txt",
  "cwd": "/current/working/dir",
  "permission_mode": "ask|allow",
  "hook_event_name": "PreToolUse"
}
事件特定字段:
  • PreToolUse/PostToolUse:
    tool_name
    ,
    tool_input
    ,
    tool_result
  • UserPromptSubmit:
    user_prompt
  • Stop/SubagentStop:
    reason
在提示词中使用
$TOOL_INPUT
$TOOL_RESULT
$USER_PROMPT
等访问字段。

Environment Variables

环境变量

Available in all command hooks:
  • $CLAUDE_PROJECT_DIR
    - Project root path
  • $CLAUDE_PLUGIN_ROOT
    - Plugin directory (use for portable paths)
  • $CLAUDE_ENV_FILE
    - SessionStart only: persist env vars here
  • $CLAUDE_CODE_REMOTE
    - Set if running in remote context
Always use ${CLAUDE_PLUGIN_ROOT} in hook commands for portability:
json
{
  "type": "command",
  "command": "bash ${CLAUDE_PLUGIN_ROOT}/scripts/validate.sh"
}
所有命令式钩子中可用的环境变量:
  • $CLAUDE_PROJECT_DIR
    - 项目根路径
  • $CLAUDE_PLUGIN_ROOT
    - 插件目录(用于可移植路径)
  • $CLAUDE_ENV_FILE
    - 仅SessionStart可用:在此处持久化环境变量
  • $CLAUDE_CODE_REMOTE
    - 在远程环境中运行时设置
为了可移植性,在钩子命令中始终使用${CLAUDE_PLUGIN_ROOT}:
json
{
  "type": "command",
  "command": "bash ${CLAUDE_PLUGIN_ROOT}/scripts/validate.sh"
}

Plugin Hook Configuration

插件钩子配置

In plugins, define hooks in
hooks/hooks.json
:
json
{
  "PreToolUse": [
    {
      "matcher": "Write|Edit",
      "hooks": [
        {
          "type": "prompt",
          "prompt": "Validate file write safety"
        }
      ]
    }
  ],
  "Stop": [
    {
      "matcher": "*",
      "hooks": [
        {
          "type": "prompt",
          "prompt": "Verify task completion"
        }
      ]
    }
  ],
  "SessionStart": [
    {
      "matcher": "*",
      "hooks": [
        {
          "type": "command",
          "command": "bash ${CLAUDE_PLUGIN_ROOT}/scripts/load-context.sh",
          "timeout": 10
        }
      ]
    }
  ]
}
Plugin hooks merge with user's hooks and run in parallel.
在插件中,钩子定义在
hooks/hooks.json
中:
json
{
  "PreToolUse": [
    {
      "matcher": "Write|Edit",
      "hooks": [
        {
          "type": "prompt",
          "prompt": "验证文件写入安全性"
        }
      ]
    }
  ],
  "Stop": [
    {
      "matcher": "*",
      "hooks": [
        {
          "type": "prompt",
          "prompt": "验证任务完成情况"
        }
      ]
    }
  ],
  "SessionStart": [
    {
      "matcher": "*",
      "hooks": [
        {
          "type": "command",
          "command": "bash ${CLAUDE_PLUGIN_ROOT}/scripts/load-context.sh",
          "timeout": 10
        }
      ]
    }
  ]
}
插件钩子会与用户的钩子合并并并行运行。

Matchers

匹配器

Tool Name Matching

工具名称匹配

Exact match:
json
"matcher": "Write"
Multiple tools:
json
"matcher": "Read|Write|Edit"
Wildcard (all tools):
json
"matcher": "*"
Regex patterns:
json
"matcher": "mcp__.*__delete.*"  // All MCP delete tools
Note: Matchers are case-sensitive.
精确匹配:
json
"matcher": "Write"
多个工具:
json
"matcher": "Read|Write|Edit"
通配符(所有工具):
json
"matcher": "*"
正则表达式模式:
json
"matcher": "mcp__.*__delete.*"  // 所有MCP删除工具
注意: 匹配器区分大小写。

Common Patterns

常见模式

json
// All MCP tools
"matcher": "mcp__.*"

// Specific plugin's MCP tools
"matcher": "mcp__plugin_asana_.*"

// All file operations
"matcher": "Read|Write|Edit"

// Bash commands only
"matcher": "Bash"
json
// 所有MCP工具
"matcher": "mcp__.*"

// 特定插件的MCP工具
"matcher": "mcp__plugin_asana_.*"

// 所有文件操作
"matcher": "Read|Write|Edit"

// 仅Bash命令
"matcher": "Bash"

Security Best Practices

安全最佳实践

Input Validation

输入验证

Always validate inputs in command hooks:
bash
#!/bin/bash
set -euo pipefail

input=$(cat)
tool_name=$(echo "$input" | jq -r '.tool_name')
在命令式钩子中始终验证输入:
bash
#!/bin/bash
set -euo pipefail

input=$(cat)
tool_name=$(echo "$input" | jq -r '.tool_name')

Validate tool name format

验证工具名称格式

if [[ ! "$tool_name" =~ ^[a-zA-Z0-9_]+$ ]]; then echo '{"decision": "deny", "reason": "Invalid tool name"}' >&2 exit 2 fi
undefined
if [[ ! "$tool_name" =~ ^[a-zA-Z0-9_]+$ ]]; then echo '{"decision": "deny", "reason": "Invalid tool name"}' >&2 exit 2 fi
undefined

Path Safety

路径安全

Check for path traversal and sensitive files:
bash
file_path=$(echo "$input" | jq -r '.tool_input.file_path')
检查路径遍历和敏感文件:
bash
file_path=$(echo "$input" | jq -r '.tool_input.file_path')

// 拒绝路径遍历
if [[ "$file_path" == *".."* ]]; then
  echo '{"decision": "deny", "reason": "Path traversal detected"}' >&2
  exit 2
fi

// 拒绝敏感文件
if [[ "$file_path" == *".env"* ]]; then
  echo '{"decision": "deny", "reason": "Sensitive file"}' >&2
  exit 2
fi
完整示例请参见
examples/validate-write.sh
examples/validate-bash.sh

Deny path traversal

引用所有变量

if [[ "$file_path" == ".." ]]; then echo '{"decision": "deny", "reason": "Path traversal detected"}' >&2 exit 2 fi
bash
undefined

Deny sensitive files

正确:已引用

if [[ "$file_path" == ".env" ]]; then echo '{"decision": "deny", "reason": "Sensitive file"}' >&2 exit 2 fi

See `examples/validate-write.sh` and `examples/validate-bash.sh` for complete examples.
echo "$file_path" cd "$CLAUDE_PROJECT_DIR"

Quote All Variables

错误:未引用(存在注入风险)

bash
undefined
echo $file_path cd $CLAUDE_PROJECT_DIR
undefined

GOOD: Quoted

设置适当的超时时间

echo "$file_path" cd "$CLAUDE_PROJECT_DIR"
json
{
  "type": "command",
  "command": "bash script.sh",
  "timeout": 10
}
默认值: 命令式钩子(60秒),提示词钩子(30秒)

BAD: Unquoted (injection risk)

性能考虑

并行执行

echo $file_path cd $CLAUDE_PROJECT_DIR
undefined
所有匹配的钩子并行运行
json
{
  "PreToolUse": [
    {
      "matcher": "Write",
      "hooks": [
        {"type": "command", "command": "check1.sh"},  // 并行
        {"type": "command", "command": "check2.sh"},  // 并行
        {"type": "prompt", "prompt": "Validate..."}   // 并行
      ]
    }
  ]
}
设计影响:
  • 钩子无法看到彼此的输出
  • 执行顺序非确定性
  • 设计时需考虑独立性

Set Appropriate Timeouts

优化

json
{
  "type": "command",
  "command": "bash script.sh",
  "timeout": 10
}
Defaults: Command hooks (60s), Prompt hooks (30s)
  1. 使用命令式钩子进行快速确定性检查
  2. 使用提示词钩子进行复杂推理
  3. 在临时文件中缓存验证结果
  4. 减少热点路径中的I/O操作

Performance Considerations

临时激活钩子

Parallel Execution

All matching hooks run in parallel:
json
{
  "PreToolUse": [
    {
      "matcher": "Write",
      "hooks": [
        {"type": "command", "command": "check1.sh"},  // Parallel
        {"type": "command", "command": "check2.sh"},  // Parallel
        {"type": "prompt", "prompt": "Validate..."}   // Parallel
      ]
    }
  ]
}
Design implications:
  • Hooks don't see each other's output
  • Non-deterministic ordering
  • Design for independence
通过检查标志文件或配置来创建条件激活的钩子:
模式:标志文件激活
bash
#!/bin/bash

Optimization

仅当标志文件存在时激活

  1. Use command hooks for quick deterministic checks
  2. Use prompt hooks for complex reasoning
  3. Cache validation results in temp files
  4. Minimize I/O in hot paths
FLAG_FILE="$CLAUDE_PROJECT_DIR/.enable-strict-validation"
if [ ! -f "$FLAG_FILE" ]; then // 标志不存在,跳过验证 exit 0 fi
// 标志存在,运行验证 input=$(cat) // ... 验证逻辑 ...

**模式:基于配置的激活**
```bash
#!/bin/bash
// 检查配置以确定是否激活
CONFIG_FILE="$CLAUDE_PROJECT_DIR/.claude/plugin-config.json"

if [ -f "$CONFIG_FILE" ]; then
  enabled=$(jq -r '.strictMode // false' "$CONFIG_FILE")
  if [ "$enabled" != "true" ]; then
    exit 0  // 未启用,跳过
  fi
fi

// 已启用,运行钩子逻辑
input=$(cat)
// ... 钩子逻辑 ...
适用场景:
  • 仅在需要时启用严格验证
  • 临时调试钩子
  • 项目特定的钩子行为
  • 钩子的功能标志
最佳实践: 在插件README中记录激活机制,以便用户知道如何启用/禁用临时钩子。

Temporarily Active Hooks

钩子生命周期和限制

钩子在会话开始时加载

Create hooks that activate conditionally by checking for a flag file or configuration:
Pattern: Flag file activation
bash
#!/bin/bash
重要提示: 钩子在Claude Code会话开始时加载。修改钩子配置需要重启Claude Code。
无法热替换钩子:
  • 编辑
    hooks/hooks.json
    不会影响当前会话
  • 添加新的钩子脚本不会被识别
  • 修改钩子命令/提示词不会更新
  • 必须重启Claude Code:退出后重新运行
    claude
测试钩子更改的步骤:
  1. 编辑钩子配置或脚本
  2. 退出Claude Code会话
  3. 重启:
    claude
    cc
  4. 加载新的钩子配置
  5. 使用
    claude --debug
    测试钩子

Only active when flag file exists

启动时的钩子验证

FLAG_FILE="$CLAUDE_PROJECT_DIR/.enable-strict-validation"
if [ ! -f "$FLAG_FILE" ]; then

Flag not present, skip validation

exit 0 fi
Claude Code启动时会验证钩子:
  • hooks.json中的无效JSON会导致加载失败
  • 缺失的脚本会触发警告
  • 语法错误会在调试模式中报告
使用
/hooks
命令查看当前会话中已加载的钩子。

Flag present, run validation

调试钩子

启用调试模式

input=$(cat)
bash
claude --debug
查看钩子注册、执行日志、输入/输出JSON和计时信息。

... validation logic ...

测试钩子脚本


**Pattern: Configuration-based activation**
```bash
#!/bin/bash
直接测试命令式钩子:
bash
echo '{"tool_name": "Write", "tool_input": {"file_path": "/test"}}' | \
  bash ${CLAUDE_PLUGIN_ROOT}/scripts/validate.sh

echo "Exit code: $?"

Check configuration for activation

验证JSON输出

CONFIG_FILE="$CLAUDE_PROJECT_DIR/.claude/plugin-config.json"
if [ -f "$CONFIG_FILE" ]; then enabled=$(jq -r '.strictMode // false' "$CONFIG_FILE") if [ "$enabled" != "true" ]; then exit 0 # Not enabled, skip fi fi
确保钩子输出有效的JSON:
bash
output=$(./your-hook.sh < test-input.json)
echo "$output" | jq .

Enabled, run hook logic

快速参考

钩子事件摘要

input=$(cat)
事件触发时机用途
PreToolUse工具执行前验证、修改
PostToolUse工具执行后反馈、日志
UserPromptSubmit用户输入时上下文、验证
StopAgent停止前完成度检查
SubagentStop子Agent完成时任务验证
SessionStart会话开始时上下文加载
SessionEnd会话结束时清理、日志
PreCompact上下文压缩前保留关键信息
Notification发送通知时日志、响应

... hook logic ...

最佳实践


**Use cases:**
- Enable strict validation only when needed
- Temporary debugging hooks
- Project-specific hook behavior
- Feature flags for hooks

**Best practice:** Document activation mechanism in plugin README so users know how to enable/disable temporary hooks.
建议:
  • ✅ 使用基于提示词的钩子处理复杂逻辑
  • ✅ 使用${CLAUDE_PLUGIN_ROOT}确保可移植性
  • ✅ 在命令式钩子中验证所有输入
  • ✅ 引用所有bash变量
  • ✅ 设置适当的超时时间
  • ✅ 返回结构化JSON输出
  • ✅ 彻底测试钩子
不建议:
  • ❌ 使用硬编码路径
  • ❌ 未经验证就信任用户输入
  • ❌ 创建长时间运行的钩子
  • ❌ 依赖钩子执行顺序
  • ❌ 不可预测地修改全局状态
  • ❌ 记录敏感信息

Hook Lifecycle and Limitations

其他资源

Hooks Load at Session Start

参考文档

Important: Hooks are loaded when Claude Code session starts. Changes to hook configuration require restarting Claude Code.
Cannot hot-swap hooks:
  • Editing
    hooks/hooks.json
    won't affect current session
  • Adding new hook scripts won't be recognized
  • Changing hook commands/prompts won't update
  • Must restart Claude Code: exit and run
    claude
    again
To test hook changes:
  1. Edit hook configuration or scripts
  2. Exit Claude Code session
  3. Restart:
    claude
    or
    cc
  4. New hook configuration loads
  5. Test hooks with
    claude --debug
有关详细模式和高级技术,请参考:
  • references/patterns.md
    - 常见钩子模式(8+种经过验证的模式)
  • references/migration.md
    - 从基础钩子迁移到高级钩子
  • references/advanced.md
    - 高级用例和技术

Hook Validation at Startup

示例钩子脚本

Hooks are validated when Claude Code starts:
  • Invalid JSON in hooks.json causes loading failure
  • Missing scripts cause warnings
  • Syntax errors reported in debug mode
Use
/hooks
command to review loaded hooks in current session.
examples/
目录中的可用示例:
  • validate-write.sh
    - 文件写入验证示例
  • validate-bash.sh
    - Bash命令验证示例
  • load-context.sh
    - SessionStart上下文加载示例

Debugging Hooks

实用脚本

Enable Debug Mode

bash
claude --debug
Look for hook registration, execution logs, input/output JSON, and timing information.
scripts/
目录中的开发工具:
  • validate-hook-schema.sh
    - 验证hooks.json的结构和语法
  • test-hook.sh
    - 部署前使用示例输入测试钩子
  • hook-linter.sh
    - 检查钩子脚本中的常见问题和最佳实践

Test Hook Scripts

外部资源

Test command hooks directly:
bash
echo '{"tool_name": "Write", "tool_input": {"file_path": "/test"}}' | \
  bash ${CLAUDE_PLUGIN_ROOT}/scripts/validate.sh

echo "Exit code: $?"

Validate JSON Output

实现流程

Ensure hooks output valid JSON:
bash
output=$(./your-hook.sh < test-input.json)
echo "$output" | jq .
在插件中实现钩子的步骤:
  1. 确定要挂钩的事件(PreToolUse、Stop、SessionStart等)
  2. 选择基于提示词(灵活)或命令式(确定性)钩子
  3. hooks/hooks.json
    中编写钩子配置
  4. 对于命令式钩子,创建钩子脚本
  5. 所有文件引用使用${CLAUDE_PLUGIN_ROOT}
  6. 使用
    scripts/validate-hook-schema.sh hooks/hooks.json
    验证配置
  7. 部署前使用
    scripts/test-hook.sh
    测试钩子
  8. 使用
    claude --debug
    在Claude Code中测试
  9. 在插件README中记录钩子
大多数场景优先使用基于提示词的钩子。仅在性能关键型或确定性检查场景中使用命令式钩子。

Quick Reference

Hook Events Summary

EventWhenUse For
PreToolUseBefore toolValidation, modification
PostToolUseAfter toolFeedback, logging
UserPromptSubmitUser inputContext, validation
StopAgent stoppingCompleteness check
SubagentStopSubagent doneTask validation
SessionStartSession beginsContext loading
SessionEndSession endsCleanup, logging
PreCompactBefore compactPreserve context
NotificationUser notifiedLogging, reactions

Best Practices

DO:
  • ✅ Use prompt-based hooks for complex logic
  • ✅ Use ${CLAUDE_PLUGIN_ROOT} for portability
  • ✅ Validate all inputs in command hooks
  • ✅ Quote all bash variables
  • ✅ Set appropriate timeouts
  • ✅ Return structured JSON output
  • ✅ Test hooks thoroughly
DON'T:
  • ❌ Use hardcoded paths
  • ❌ Trust user input without validation
  • ❌ Create long-running hooks
  • ❌ Rely on hook execution order
  • ❌ Modify global state unpredictably
  • ❌ Log sensitive information

Additional Resources

Reference Files

For detailed patterns and advanced techniques, consult:
  • references/patterns.md
    - Common hook patterns (8+ proven patterns)
  • references/migration.md
    - Migrating from basic to advanced hooks
  • references/advanced.md
    - Advanced use cases and techniques

Example Hook Scripts

Working examples in
examples/
:
  • validate-write.sh
    - File write validation example
  • validate-bash.sh
    - Bash command validation example
  • load-context.sh
    - SessionStart context loading example

Utility Scripts

Development tools in
scripts/
:
  • validate-hook-schema.sh
    - Validate hooks.json structure and syntax
  • test-hook.sh
    - Test hooks with sample input before deployment
  • hook-linter.sh
    - Check hook scripts for common issues and best practices

External Resources

Implementation Workflow

To implement hooks in a plugin:
  1. Identify events to hook into (PreToolUse, Stop, SessionStart, etc.)
  2. Decide between prompt-based (flexible) or command (deterministic) hooks
  3. Write hook configuration in
    hooks/hooks.json
  4. For command hooks, create hook scripts
  5. Use ${CLAUDE_PLUGIN_ROOT} for all file references
  6. Validate configuration with
    scripts/validate-hook-schema.sh hooks/hooks.json
  7. Test hooks with
    scripts/test-hook.sh
    before deployment
  8. Test in Claude Code with
    claude --debug
  9. Document hooks in plugin README
Focus on prompt-based hooks for most use cases. Reserve command hooks for performance-critical or deterministic checks.