钩子开发Skill HookDevelopment

这个技能用于创建和实现Claude Code插件的钩子,支持事件驱动自动化脚本,以验证操作、执行策略、添加上下文和集成外部工具。关键词:钩子开发、事件驱动自动化、Claude Code插件、提示基础钩子、安全验证、DevOps自动化、插件集成、工具验证。

DevOps 0 次安装 0 次浏览 更新于 3/13/2026

名称: 钩子开发 描述: 此技能应在用户要求“创建钩子”、“添加预工具使用/后工具使用/停止钩子”、“验证工具使用”、“实现提示基础钩子”、“使用${CLAUDE_PLUGIN_ROOT}”、“设置事件驱动自动化”、“阻止危险命令”或提及钩子事件(预工具使用、后工具使用、停止、子代理停止、会话开始、会话结束、用户提示提交、预压缩、通知)时使用。为创建和实现Claude Code插件钩子提供全面指导,重点介绍高级提示基础钩子API。 版本: 0.1.0

Claude Code插件钩子开发

概述

钩子是事件驱动的自动化脚本,响应Claude Code事件执行。使用钩子来验证操作、执行策略、添加上下文,并将外部工具集成到工作流中。

关键能力:

  • 在执行前验证工具调用(预工具使用)
  • 对工具结果做出反应(后工具使用)
  • 强制执行完成标准(停止、子代理停止)
  • 加载项目上下文(会话开始)
  • 在开发生命周期中自动化工作流

钩子类型

提示基础钩子(推荐)

使用LLM驱动的决策进行上下文感知验证:

{
  "type": "prompt",
  "prompt": "评估此工具使用是否合适:$TOOL_INPUT",
  "timeout": 30
}

支持的事件: 停止、子代理停止、用户提示提交、预工具使用

好处:

  • 基于自然语言推理的上下文感知决策
  • 无需bash脚本的灵活评估逻辑
  • 更好的边缘情况处理
  • 更容易维护和扩展

命令钩子

执行bash命令进行确定性检查:

{
  "type": "command",
  "command": "bash ${CLAUDE_PLUGIN_ROOT}/scripts/validate.sh",
  "timeout": 60
}

用于:

  • 快速确定性验证
  • 文件系统操作
  • 外部工具集成
  • 性能关键检查

钩子配置格式

插件hooks.json格式

对于插件钩子hooks/hooks.json中,使用包装器格式:

{
  "description": "钩子简要说明(可选)",
  "hooks": {
    "PreToolUse": [...],
    "Stop": [...],
    "SessionStart": [...]
  }
}

关键点:

  • description字段可选
  • hooks字段是必需包装器,包含实际钩子事件
  • 这是插件特定格式

示例:

{
  "description": "代码质量验证钩子",
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Write",
        "hooks": [
          {
            "type": "command",
            "command": "${CLAUDE_PLUGIN_ROOT}/hooks/validate.sh"
          }
        ]
      }
    ]
  }
}

设置格式(直接)

对于用户设置.claude/settings.json中,使用直接格式:

{
  "PreToolUse": [...],
  "Stop": [...],
  "SessionStart": [...]
}

关键点:

  • 无包装器 - 事件直接位于顶层
  • 无描述字段
  • 这是设置格式

重要: 以下示例显示钩子事件结构,用于任一格式。对于插件hooks.json,将其包装在{"hooks": {...}}中。

钩子事件

预工具使用

在任何工具运行前执行。用于批准、拒绝或修改工具调用。

示例(提示基础):

{
  "PreToolUse": [
    {
      "matcher": "Write|Edit",
      "hooks": [
        {
          "type": "prompt",
          "prompt": "验证文件写入安全性。检查:系统路径、凭据、路径遍历、敏感内容。返回'approve'或'deny'。"
        }
      ]
    }
  ]
}

预工具使用输出:

{
  "hookSpecificOutput": {
    "permissionDecision": "allow|deny|ask",
    "updatedInput": {"field": "modified_value"}
  },
  "systemMessage": "Claude解释"
}

后工具使用

在工具完成后执行。用于对结果做出反应、提供反馈或记录。

示例:

{
  "PostToolUse": [
    {
      "matcher": "Edit",
      "hooks": [
        {
          "type": "prompt",
          "prompt": "分析编辑结果的潜在问题:语法错误、安全漏洞、破坏性更改。提供反馈。"
        }
      ]
    }
  ]
}

输出行为:

  • 退出0: stdout显示在记录中
  • 退出2: stderr反馈给Claude
  • systemMessage包含在上下文中

停止

在主代理考虑停止时执行。用于验证完整性。

示例:

{
  "Stop": [
    {
      "matcher": "*",
      "hooks": [
        {
          "type": "prompt",
          "prompt": "验证任务完成:测试运行、构建成功、问题已回答。返回'approve'停止或'block'带原因继续。"
        }
      ]
    }
  ]
}

决策输出:

{
  "decision": "approve|block",
  "reason": "解释",
  "systemMessage": "额外上下文"
}

子代理停止

在子代理考虑停止时执行。用于确保子代理完成任务。

类似于停止钩子,但用于子代理。

用户提示提交

在用户提交提示时执行。用于添加上下文、验证或阻止提示。

示例:

{
  "UserPromptSubmit": [
    {
      "matcher": "*",
      "hooks": [
        {
          "type": "prompt",
          "prompt": "检查提示是否需要安全指导。如果讨论认证、权限或API安全,返回相关警告。"
        }
      ]
    }
  ]
}

会话开始

在Claude Code会话开始时执行。用于加载上下文和设置环境。

示例:

{
  "SessionStart": [
    {
      "matcher": "*",
      "hooks": [
        {
          "type": "command",
          "command": "bash ${CLAUDE_PLUGIN_ROOT}/scripts/load-context.sh"
        }
      ]
    }
  ]
}

特殊能力: 使用$CLAUDE_ENV_FILE持久化环境变量:

echo "export PROJECT_TYPE=nodejs" >> "$CLAUDE_ENV_FILE"

参见examples/load-context.sh获取完整示例。

会话结束

在会话结束时执行。用于清理、记录和状态保存。

预压缩

在上下文压缩前执行。用于添加强制信息以保存。

通知

在Claude发送通知时执行。用于对用户通知做出反应。

钩子输出格式

标准输出(所有钩子)

{
  "continue": true,
  "suppressOutput": false,
  "systemMessage": "给Claude的消息"
}
  • continue: 如果false,停止处理(默认true)
  • suppressOutput: 隐藏记录中的输出(默认false)
  • systemMessage: 显示给Claude的消息

退出码

  • 0 - 成功(stdout显示在记录中)
  • 2 - 阻塞错误(stderr反馈给Claude)
  • 其他 - 非阻塞错误

钩子输入格式

所有钩子通过stdin接收JSON,具有公共字段:

{
  "session_id": "abc123",
  "transcript_path": "/path/to/transcript.txt",
  "cwd": "/current/working/dir",
  "permission_mode": "ask|allow",
  "hook_event_name": "PreToolUse"
}

事件特定字段:

  • 预工具使用/后工具使用: tool_name, tool_input, tool_result
  • 用户提示提交: user_prompt
  • 停止/子代理停止: reason

在提示中使用$TOOL_INPUT$TOOL_RESULT$USER_PROMPT等访问字段。

环境变量

在所有命令钩子中可用:

  • $CLAUDE_PROJECT_DIR - 项目根路径
  • $CLAUDE_PLUGIN_ROOT - 插件目录(用于可移植路径)
  • $CLAUDE_ENV_FILE - 仅会话开始:在此持久化环境变量
  • $CLAUDE_CODE_REMOTE - 如果在远程上下文中运行则设置

始终在钩子命令中使用${CLAUDE_PLUGIN_ROOT}以确保可移植性:

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

插件钩子配置

在插件中,在hooks/hooks.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
        }
      ]
    }
  ]
}

插件钩子与用户钩子合并并并行运行。

匹配器

工具名称匹配

精确匹配:

"matcher": "Write"

多个工具:

"matcher": "Read|Write|Edit"

通配符(所有工具):

"matcher": "*"

正则表达式模式:

"matcher": "mcp__.*__delete.*"  // 所有MCP删除工具

注意: 匹配器区分大小写。

常见模式

// 所有MCP工具
"matcher": "mcp__.*"

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

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

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

安全最佳实践

输入验证

始终在命令钩子中验证输入:

#!/bin/bash
set -euo pipefail

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

# 验证工具名称格式
if [[ ! "$tool_name" =~ ^[a-zA-Z0-9_]+$ ]]; then
  echo '{"decision": "deny", "reason": "无效工具名称"}' >&2
  exit 2
fi

路径安全

检查路径遍历和敏感文件:

file_path=$(echo "$input" | jq -r '.tool_input.file_path')

# 拒绝路径遍历
if [[ "$file_path" == *".."* ]]; then
  echo '{"decision": "deny", "reason": "检测到路径遍历"}' >&2
  exit 2
fi

# 拒绝敏感文件
if [[ "$file_path" == *".env"* ]]; then
  echo '{"decision": "deny", "reason": "敏感文件"}' >&2
  exit 2
fi

参见examples/validate-write.shexamples/validate-bash.sh获取完整示例。

引用所有变量

# 好:引用
echo "$file_path"
cd "$CLAUDE_PROJECT_DIR"

# 坏:未引用(注入风险)
echo $file_path
cd $CLAUDE_PROJECT_DIR

设置适当超时

{
  "type": "command",
  "command": "bash script.sh",
  "timeout": 10
}

默认值: 命令钩子(60秒),提示钩子(30秒)

性能考虑

并行执行

所有匹配钩子并行运行

{
  "PreToolUse": [
    {
      "matcher": "Write",
      "hooks": [
        {"type": "command", "command": "check1.sh"},  // 并行
        {"type": "command", "command": "check2.sh"},  // 并行
        {"type": "prompt", "prompt": "验证..."}   // 并行
      ]
    }
  ]
}

设计影响:

  • 钩子看不到彼此的输入
  • 非确定性排序
  • 设计为独立

优化

  1. 使用命令钩子进行快速确定性检查
  2. 使用提示钩子进行复杂推理
  3. 在临时文件中缓存验证结果
  4. 在热路径中最小化I/O

临时活动钩子

通过检查标志文件或配置创建条件激活的钩子:

模式:标志文件激活

#!/bin/bash
# 仅当标志文件存在时激活
FLAG_FILE="$CLAUDE_PROJECT_DIR/.enable-strict-validation"

if [ ! -f "$FLAG_FILE" ]; then
  # 标志不存在,跳过验证
  exit 0
fi

# 标志存在,运行验证
input=$(cat)
# ... 验证逻辑 ...

模式:基于配置的激活

#!/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中记录激活机制,以便用户知道如何启用/禁用临时钩子。

钩子生命周期和限制

钩子在会话开始时加载

重要: 钩子在Claude Code会话开始时加载。更改钩子配置需要重启Claude Code。

无法热交换钩子:

  • 编辑hooks/hooks.json不会影响当前会话
  • 添加新钩子脚本不会被识别
  • 更改钩子命令/提示不会更新
  • 必须重启Claude Code:退出并再次运行claude

测试钩子更改:

  1. 编辑钩子配置或脚本
  2. 退出Claude Code会话
  3. 重启:claudecc
  4. 新钩子配置加载
  5. 使用claude --debug测试钩子

启动时的钩子验证

钩子在Claude Code启动时验证:

  • hooks.json中的无效JSON导致加载失败
  • 缺少脚本导致警告
  • 调试模式中报告语法错误

使用/hooks命令查看当前会话中加载的钩子。

调试钩子

启用调试模式

claude --debug

查看钩子注册、执行日志、输入/输出JSON和计时信息。

测试钩子脚本

直接测试命令钩子:

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

echo "退出码:$?"

验证JSON输出

确保钩子输出有效JSON:

output=$(./your-hook.sh < test-input.json)
echo "$output" | jq .

快速参考

钩子事件摘要

事件 何时 用途
预工具使用 工具前 验证、修改
后工具使用 工具后 反馈、记录
用户提示提交 用户输入 上下文、验证
停止 代理停止 完整性检查
子代理停止 子代理完成 任务验证
会话开始 会话开始 上下文加载
会话结束 会话结束 清理、记录
预压缩 压缩前 保存上下文
通知 用户通知 记录、反应

最佳实践

做:

  • ✅ 使用提示基础钩子进行复杂逻辑
  • ✅ 使用${CLAUDE_PLUGIN_ROOT}确保可移植性
  • ✅ 在命令钩子中验证所有输入
  • ✅ 引用所有bash变量
  • ✅ 设置适当超时
  • ✅ 返回结构化JSON输出
  • ✅ 彻底测试钩子

不做:

  • ❌ 使用硬编码路径
  • ❌ 未经验证信任用户输入
  • ❌ 创建长时间运行钩子
  • ❌ 依赖钩子执行顺序
  • ❌ 不可预测地修改全局状态
  • ❌ 记录敏感信息

额外资源

参考文件

有关详细模式和高级技术,请参阅:

  • references/patterns.md - 常见钩子模式(8+已验证模式)
  • references/migration.md - 从基础钩子迁移到高级钩子
  • references/advanced.md - 高级用例和技术

示例钩子脚本

examples/中的工作示例:

  • validate-write.sh - 文件写入验证示例
  • validate-bash.sh - Bash命令验证示例
  • load-context.sh - 会话开始上下文加载示例

实用脚本

scripts/中的开发工具:

  • validate-hook-schema.sh - 验证hooks.json结构和语法
  • test-hook.sh - 部署前使用样本输入测试钩子
  • hook-linter.sh - 检查钩子脚本的常见问题和最佳实践

外部资源

实施工作流

在插件中实施钩子:

  1. 识别要挂钩的事件(预工具使用、停止、会话开始等)
  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中记录钩子

关注提示基础钩子用于大多数用例。保留命令钩子用于性能关键或确定性检查。