构建钩子 building-hooks

构建钩子技能是专家级的能力,专注于创建和修改Claude Code事件钩子,以实现自动化和策略执行。这项技能能够在用户需要创建、更新、修改、增强、验证或标准化钩子时自动调用,特别适用于事件驱动的自动化、策略自动执行、工具使用验证、操作记录和审计,以及工具调用的预处理和后处理。

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

以下是对“building-hooks”技能的中文翻译:


name: building-hooks description: 擅长创建和修改Claude Code事件钩子,用于自动化和策略执行。当用户想要创建、更新、修改、增强、验证或标准化钩子,或在修改hooks.json配置时,需要帮助进行事件驱动的自动化,或想要了解钩子模式时,会自动调用。此外,当Claude即将写入hooks.json文件,或执行涉及创建事件钩子配置的任务时,也会主动调用。 version: 2.0.0 allowed-tools: 读取,写入,编辑,搜索,全局搜索,Bash

构建钩子技能

你是创建Claude Code事件钩子的专家。钩子是事件驱动的自动化,它们在响应特定事件时执行,如工具调用、用户提示或会话生命周期事件。

何时创建钩子

使用HOOKS的情况:

  • 需要事件驱动的自动化
  • 想要验证或阻止工具使用
  • 需要自动执行策略
  • 想要记录或审计Claude的行动
  • 需要工具调用的预/后处理

使用COMMANDS的情况:

  • 用户显式触发一个动作
  • 需要手动调用

使用AGENTS/SKILLS的情况:

  • 需要Claude的推理和生成
  • 任务需要LLM能力

钩子模式和结构

文件位置

  • 项目级别.claude/hooks.json
  • 项目设置.claude/settings.json(钩子部分)
  • 目录特定.claude-hooks.json(任何目录中)
  • 插件级别plugin-dir/hooks/hooks.json

文件格式

JSON配置文件。

模式结构

{
  "hooks": {
    "EventName": [
      {
        "matcher": "ToolPattern",
        "hooks": [
          {
            "type": "command",
            "command": "bash command to execute"
          }
        ]
      }
    ]
  }
}

事件类型

带匹配器的事件(工具特定)

PreToolUse: 工具运行前

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [{"type": "command", "command": "bash validate.sh"}]
      }
    ]
  }
}

PostToolUse: 工具成功完成后

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [{"type": "command", "command": "bash format.sh"}]
      }
    ]
  }
}

无匹配器的事件(生命周期事件)

UserPromptSubmit: 用户提交提示时

{
  "hooks": {
    "UserPromptSubmit": [
      {
        "hooks": [{"type": "command", "command": "bash log-prompt.sh"}]
      }
    ]
  }
}

Stop: Claude完成响应时

{
  "hooks": {
    "Stop": [
      {
        "hooks": [{"type": "command", "command": "bash cleanup.sh"}]
      }
    ]
  }
}

SessionStart: 会话开始时

{
  "hooks": {
    "SessionStart": [
      {
        "hooks": [{"type": "command", "command": "bash setup.sh"}]
      }
    ]
  }
}

其他事件

  • Notification: Claude发送警报时
  • SubagentStop: 子代理完成时
  • PreCompact: 转录压缩前

匹配器模式

对于PreToolUsePostToolUse事件:

模式 匹配 示例
"Write" 确切的工具名称 仅匹配Write工具
"Edit|Write" 正则OR 匹配Edit或Write
"Bash" 单个工具 匹配Bash工具
"*" 通配符 匹配所有工具
"Notebook.*" 正则模式 匹配NotebookEdit等
"" 空(非工具事件) 生命周期事件

钩子类型

类型1:命令钩子

执行bash命令:

{
  "type": "command",
  "command": "bash /path/to/script.sh"
}

用途:

  • 验证脚本
  • 格式化工具
  • 日志和审计
  • 文件系统操作

类型2:提示钩子(基于LLM)

使用LLM进行评估:

{
  "type": "prompt",
  "prompt": "Analyze the tool usage and determine if it's safe"
}

用途:

  • 复杂策略评估
  • 上下文感知决策
  • 自然语言分析

钩子返回值

钩子可以返回结构化的JSON来控制行为:

{
  "continue": true,
  "decision": "approve",
  "reason": "Explanation for the decision",
  "suppressOutput": false,
  "systemMessage": "Optional message shown to user",
  "hookSpecificOutput": {
    "permissionDecision": "approve",
    "permissionDecisionReason": "Safe operation",
    "additionalContext": "Extra context for Claude"
  }
}

键字段

  • continue: true继续,false停止
  • decision: "approve", "block", 或 "warn"
  • reason: 解释决策
  • suppressOutput: 从转录中隐藏钩子输出
  • systemMessage: 显示给用户的消息
  • permissionDecision: 用于工具权限钩子
  • additionalContext: 添加到Claude知识的上下文

退出代码

  • 0: 成功(stdout显示在转录模式中)
  • 2: 阻止错误(stderr提供给Claude)
  • 其他: 非阻止错误

常见钩子模式

模式1:验证钩子(PreToolUse)

在执行前验证工具使用:

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "command",
            "command": "bash /path/to/validate-write.sh"
          }
        ]
      }
    ]
  }
}

示例validate-write.sh

#!/bin/bash
# 检查是否写入受保护的目录

FILE_PATH="$1"

if [[ "$FILE_PATH" == /protected/* ]]; then
  echo '{"decision": "block", "reason": "Cannot write to protected directory"}'
  exit 2
fi

echo '{"decision": "approve", "reason": "Path is valid"}'
exit 0

模式2:格式化钩子(PostToolUse)

写入后自动格式化文件:

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "command",
            "command": "bash /path/to/format-file.sh"
          }
        ]
      }
    ]
  }
}

示例format-file.sh

#!/bin/bash
FILE_PATH="$1"

if [[ "$FILE_PATH" == *.py ]]; then
  black "$FILE_PATH"
elif [[ "$FILE_PATH" == *.js ]]; then
  prettier --write "$FILE_PATH"
fi

exit 0

模式3:日志钩子(所有工具)

记录所有工具使用情况:

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "*",
        "hooks": [
          {
            "type": "command",
            "command": "bash /path/to/log-tool.sh"
          }
        ]
      }
    ]
  }
}

模式4:安全钩子(Bash命令)

验证bash命令的安全性:

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "bash /path/to/validate-bash.sh"
          }
        ]
      }
    ]
  }
}

示例validate-bash.sh

#!/bin/bash
COMMAND="$1"

# 阻止危险命令
if echo "$COMMAND" | grep -qE "rm -rf /|dd if="; then
  echo '{"decision": "block", "reason": "Dangerous command detected"}'
  exit 2
fi

echo '{"decision": "approve"}'
exit 0

模式5:会话设置钩子

在会话开始时初始化环境:

{
  "hooks": {
    "SessionStart": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "bash /path/to/setup-session.sh"
          }
        ]
      }
    ]
  }
}

示例setup-session.sh

#!/bin/bash
# 加载环境,启动服务等。
export PROJECT_ROOT=$(pwd)
echo "Session initialized for project: $PROJECT_ROOT"
exit 0

创建钩子

第1步:确定需求

询问用户:

  1. 什么事件应该触发钩子?
  2. 需要什么验证或操作?
  3. 应该阻止、警告还是仅记录?
  4. 需要监控哪些工具或操作?

第2步:选择事件和匹配器

  • PreToolUse:执行前验证
  • PostToolUse:执行后处理
  • UserPromptSubmit:分析提示
  • SessionStart:初始化环境
  • Stop:清理或总结

第3步:设计钩子逻辑

  • 编写钩子的bash脚本
  • 定义输入参数
  • 计划返回JSON结构
  • 处理错误情况
  • 测试安全性

第4步:创建hooks.json

{
  "hooks": {
    "EventName": [
      {
        "matcher": "ToolPattern",
        "hooks": [
          {
            "type": "command",
            "command": "bash /path/to/script.sh"
          }
        ]
      }
    ]
  }
}

第5步:实现钩子脚本

  • 接受适当的输入参数
  • 验证输入
  • 执行检查或操作
  • 返回带有决策的JSON
  • 使用适当的退出代码

第6步:测试钩子

  • 将hooks.json放在.claude/
  • 触发事件
  • 验证钩子正确执行
  • 检查阻止/批准的工作
  • 测试错误处理

验证脚本

这项技能包括一个验证脚本:

validate-hooks.py - 架构验证器

用于验证hooks.json文件的Python脚本。

用法:

python3 {baseDir}/scripts/validate-hooks.py <hooks.json>

它检查的内容:

  • JSON语法有效性
  • 事件名称有效性(PreToolUse,PostToolUse等)
  • 匹配器要求(工具事件需要匹配器)
  • 钩子类型有效性(命令,提示)
  • 脚本存在(引用的脚本存在)
  • 安全模式(危险命令,注入风险)

返回值:

  • 如果有效则退出代码0
  • 如果无效则退出代码1并显示错误消息

示例:

python3 validate-hooks.py .claude/hooks.json

✅ Hooks验证通过
   配置的事件:PreToolUse,PostToolUse
   总钩子数:3
   验证的脚本数:2

钩子脚本最佳实践

输入参数

钩子接收上下文作为参数:

PreToolUse / PostToolUse

  • $1:工具名称
  • $2:工具参数(JSON)
  • 带有工具详细信息的环境变量

UserPromptSubmit

  • $1:用户提示文本

其他事件

  • 事件特定的参数

返回JSON格式

始终返回格式良好的JSON:

#!/bin/bash

# 成功
echo '{"decision": "approve", "reason": "Validation passed"}'
exit 0

# 阻止
echo '{"decision": "block", "reason": "Security violation detected"}'
exit 2

# 警告
echo '{"decision": "warn", "reason": "Unusual pattern detected"}'
exit 0

错误处理

#!/bin/bash

if [ $# -lt 1 ]; then
  echo '{"decision": "block", "reason": "Missing required arguments"}' >&2
  exit 2
fi

# 验证输入
if ! validate_input "$1"; then
  echo '{"decision": "block", "reason": "Invalid input"}' >&2
  exit 2
fi

# 正常处理
echo '{"decision": "approve"}'
exit 0

安全考虑

创建钩子时:

  1. 验证所有输入:不要信任来自工具参数的数据
  2. 避免命令注入:在使用shell命令时清理字符串
  3. 检查退出代码:使用适当的代码(0,2)
  4. 限制权限:以最小必要权限运行
  5. 记录安全事件:审计敏感操作
  6. 彻底测试:尝试绕过你自己的钩子

安全反模式

(命令注入):

eval "$1"  # 永远不要这样做

(安全验证):

if [[ "$1" =~ ^[a-zA-Z0-9_/-]+$ ]]; then
  # 处理清理后的输入
fi

验证清单

部署钩子前,请验证:

  • [ ] hooks.json具有有效的JSON语法
  • [ ] 事件名称正确
  • [ ] 匹配器正确转义(使用|用于正则OR)
  • [ ] 钩子脚本存在且可执行
  • [ ] 脚本接受正确的输入参数
  • [ ] 脚本返回有效的JSON
  • [ ] 退出代码适当(0或2)
  • [ ] 安全验证彻底
  • [ ] 错误情况已处理
  • [ ] 钩子不创建无限循环

参考模板

完整的模板和示例可在以下位置获得:

  • {baseDir}/templates/hooks-template.json - 基本钩子配置
  • {baseDir}/templates/validation-script.sh - 验证钩子脚本
  • {baseDir}/templates/formatting-script.sh - 格式化钩子脚本
  • {baseDir}/references/hook-examples.md - 现实世界的例子

完整示例:受保护的目录

hooks.json

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "command",
            "command": "bash ~/.claude/hooks/protect-dirs.sh"
          }
        ]
      }
    ],
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "command",
            "command": "bash ~/.claude/hooks/auto-format.sh"
          }
        ]
      }
    ]
  }
}

protect-dirs.sh

#!/bin/bash
TOOL_NAME="$1"
FILE_PATH="$2"

PROTECTED_DIRS=("/etc" "/usr" "/sys" "/protected")

for dir in "${PROTECTED_DIRS[@]}"; do
  if [[ "$FILE_PATH" == $dir/* ]]; then
    echo "{\"decision\": \"block\", \"reason\": \"Cannot modify protected directory: $dir\"}"
    exit 2
  fi
done

echo '{"decision": "approve"}'
exit 0

auto-format.sh

#!/bin/bash
FILE_PATH="$2"

if [[ "$FILE_PATH" == *.py ]]; then
  black --quiet "$FILE_PATH" 2>/dev/null
elif [[ "$FILE_PATH" == *.js ]] || [[ "$FILE_PATH" == *.ts ]]; then
  prettier --write "$FILE_PATH" > /dev/null 2>&1
fi

echo '{"decision": "approve", "reason": "File formatted"}'
exit 0

你的角色

当用户要求创建钩子时:

  1. 了解需要自动化或验证的行为
  2. 推荐适当的事件和匹配器
  3. 以安全为考虑设计钩子逻辑
  4. 生成hooks.json配置
  5. 创建结构正确的钩子脚本
  6. 验证JSON语法和脚本逻辑
  7. 使脚本可执行
  8. 提供测试说明

主动进行:

  • 识别安全风险
  • 推荐适当的事件
  • 创建健壮的验证逻辑
  • 编写防御性钩子脚本
  • 测试边缘情况和错误条件

你的目标是帮助用户创建安全、可靠的事件钩子,以有效自动化工作流程和执行策略。

维护和更新钩子

钩子是安全关键的基础设施,需要持续维护。

安全第一原则

  1. 从不信任输入:所有参数都可能是恶意的
    # 错误
    eval "$1"
    
    # 正确
    if [[ "$1" =~ ^[a-zA-Z0-9_/-]+$ ]]; then
        # 安全使用
    fi
    
  2. 验证一切:检查参数、路径、命令
    set -euo pipefail  # 严格错误处理
    [[ ! "$PATH" =~ \.\. ]]  # 无目录遍历
    
  3. 使用安全默认值:默认阻止,明确批准
    echo '{"decision": "block", "reason": "Validation failed"}' >&2
    exit 2
    
  4. 阻止危险模式
    • eval, 未经验证的命令替换
    • rm -rf /, dd if=, mkfs
    • 将wget/curl管道到bash
    • 过于宽松的权限(chmod 777)

维护清单

在审查钩子更新时:

  • [ ] JSON语法有效:有效的JSON结构
  • [ ] 事件名称正确:PreToolUse,PostToolUse等
  • [ ] 匹配器适当:特定工具,不是通配符
  • [ ] 脚本存在:引用的脚本存在
  • [ ] 脚本可执行:chmod +x脚本文件
  • [ ] 输入验证:脚本验证参数
  • [ ] 没有危险模式:没有eval,rm -rf等

常见维护场景

场景1:钩子脚本未执行

问题:预期时钩子脚本未运行 解决方案

  • 验证脚本是否存在于指定路径
  • 使脚本可执行:chmod +x script.sh
  • 检查钩子事件名称是否与预期触发器匹配
  • 验证匹配器模式是否与工具匹配

场景2:安全硬化

问题:钩子缺乏输入验证 解决方案:在脚本开始处添加参数验证:

#!/bin/bash
set -euo pipefail

# 验证输入
if [[ ! "$1" =~ ^[a-zA-Z0-9_/-]+$ ]]; then
    echo '{"decision": "block", "reason": "Invalid input"}'
    exit 2
fi

场景3:更改钩子事件

问题:需要从PostToolUse更改为PreToolUse 解决方案:编辑hooks.json以更改事件键:

{
  "hooks": {
    "PreToolUse": [...]  // 从PostToolUse更改
  }
}

最佳实践

  1. 使用特定的匹配器"Write|Edit"而不是"*"
  2. 验证所有输入:永远不要信任参数
  3. 使用绝对路径:脚本引用
  4. 记录安全事件:审计敏感操作
  5. 彻底测试:尝试绕过你自己的钩子
  6. 更改前备份:保留原始hooks.json
  7. 版本控制:提交hooks.json更改