以下是对“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: 转录压缩前
匹配器模式
对于PreToolUse和PostToolUse事件:
| 模式 | 匹配 | 示例 |
|---|---|---|
"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"
}
]
}
]
}
}
#!/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"
}
]
}
]
}
}
#!/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"
}
]
}
]
}
}
#!/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"
}
]
}
]
}
}
#!/bin/bash
# 加载环境,启动服务等。
export PROJECT_ROOT=$(pwd)
echo "Session initialized for project: $PROJECT_ROOT"
exit 0
创建钩子
第1步:确定需求
询问用户:
- 什么事件应该触发钩子?
- 需要什么验证或操作?
- 应该阻止、警告还是仅记录?
- 需要监控哪些工具或操作?
第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
安全考虑
创建钩子时:
- 验证所有输入:不要信任来自工具参数的数据
- 避免命令注入:在使用shell命令时清理字符串
- 检查退出代码:使用适当的代码(0,2)
- 限制权限:以最小必要权限运行
- 记录安全事件:审计敏感操作
- 彻底测试:尝试绕过你自己的钩子
安全反模式
坏(命令注入):
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"
}
]
}
]
}
}
#!/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
#!/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
你的角色
当用户要求创建钩子时:
- 了解需要自动化或验证的行为
- 推荐适当的事件和匹配器
- 以安全为考虑设计钩子逻辑
- 生成hooks.json配置
- 创建结构正确的钩子脚本
- 验证JSON语法和脚本逻辑
- 使脚本可执行
- 提供测试说明
主动进行:
- 识别安全风险
- 推荐适当的事件
- 创建健壮的验证逻辑
- 编写防御性钩子脚本
- 测试边缘情况和错误条件
你的目标是帮助用户创建安全、可靠的事件钩子,以有效自动化工作流程和执行策略。
维护和更新钩子
钩子是安全关键的基础设施,需要持续维护。
安全第一原则
- 从不信任输入:所有参数都可能是恶意的
# 错误 eval "$1" # 正确 if [[ "$1" =~ ^[a-zA-Z0-9_/-]+$ ]]; then # 安全使用 fi - 验证一切:检查参数、路径、命令
set -euo pipefail # 严格错误处理 [[ ! "$PATH" =~ \.\. ]] # 无目录遍历 - 使用安全默认值:默认阻止,明确批准
echo '{"decision": "block", "reason": "Validation failed"}' >&2 exit 2 - 阻止危险模式:
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更改
}
}
最佳实践
- 使用特定的匹配器:
"Write|Edit"而不是"*" - 验证所有输入:永远不要信任参数
- 使用绝对路径:脚本引用
- 记录安全事件:审计敏感操作
- 彻底测试:尝试绕过你自己的钩子
- 更改前备份:保留原始hooks.json
- 版本控制:提交hooks.json更改