关于 hooks-builder
用于创建 Claude Code 钩子的指南技能,可响应工具调用、提示词和会话生命周期事件。内容涵盖事件选择、匹配器、实现方式、安全加固与测试。
主要功能
- 01十种钩子事件参考
- 02事件与匹配器选择指南
- 03命令、脚本和提示词模式
- 04安全与输入验证检查
- 05手动及集成测试步骤
适用场景
- 01阻止高风险工具操作
- 02编辑后格式化或验证代码
- 03审计工具活动
- 04配置会话环境
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ mike-coulbourn/ claude-vibes --skill hooks-builder安装后在 Claude Code 中输入/hooks-builder确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
examples/quality-hooks.mdsecurity-hooks.mdworkflow-hooks.mdreference/best-practices.mdsyntax-guide.mdtroubleshooting.mdtemplates/basic-hook.mdproduction-hooks.mdwith-decisions.mdwith-prompts.mdwith-scripts.md详细介绍
Hooks 构建器
创建 Claude Code hooks 的综合指南——一种用于监控和控制 Claude 操作的事件驱动自动化机制。
快速参考
10 个 Hook 事件
| 事件 | 触发时机 | 可以阻止? | 支持匹配器? |
|---|---|---|---|
| PreToolUse | 工具执行前 | 是 | 是(工具名称) |
| PermissionRequest | 显示权限对话框时 | 是 | 是(工具名称) |
| PostToolUse | 工具成功执行后 | 否 | 是(工具名称) |
| Notification | Claude 发送通知时 | 否 | 是 |
| UserPromptSubmit | 用户提交提示词时 | 是 | 否 |
| Stop | Claude 完成响应时 | 可强制继续 | 否 |
| SubagentStop | 子 Agent 完成时 | 可强制继续 | 否 |
| PreCompact | 上下文压缩前 | 否 | 是(手动/自动) |
| SessionStart | 会话开始时 | 否 | 是(启动/恢复/清除/压缩) |
| SessionEnd | 会话结束时 | 否 | 否 |
退出代码语义
| 退出代码 | 含义 | 效果 |
|---|---|---|
| 0 | 成功 | 将 stdout 解析为 JSON 以进行控制 |
| 2 | 阻止性错误 | 否决——将 stderr 显示给 Claude |
| 其他 | 非阻止性错误 | 在调试模式下记录 stderr |
配置位置
~/.claude/settings.json → Personal hooks (all projects)
.claude/settings.json → Project hooks (team, committed)
.claude/settings.local.json → Local overrides (not committed)
必备环境变量
| 变量 | 说明 |
|---|---|
$CLAUDE_PROJECT_DIR | 项目根目录 |
$CLAUDE_CODE_REMOTE | 远程/本地标识 |
$CLAUDE_ENV_FILE | 环境持久化路径(SessionStart) |
$CLAUDE_PLUGIN_ROOT | 插件目录(插件 hooks) |
关键命令
/hooks # View active hooks
claude --debug # Enable debug logging
chmod +x script.sh # Make script executable
6 阶段工作流
阶段 1:收集需求
使用 AskUserQuestion 进行澄清:
-
应该由哪个事件触发此 hook?
- 工具执行(Pre/Post/Permission)→ PreToolUse、PostToolUse、PermissionRequest
- 用户输入 → UserPromptSubmit
- 响应完成 → Stop、SubagentStop
- 会话生命周期 → SessionStart、SessionEnd
- 上下文管理 → PreCompact
- 通知 → Notification
-
触发后应该执行什么操作?
- 仅观察(日志记录、指标)
- 根据条件阻止/允许
- 执行前修改输入
- 向提示词添加上下文
- 强制继续
-
它应该阻止、修改,还是只进行观察?
- 观察者:PostToolUse、Notification、SessionEnd(无法阻止)
- 守卫者:PreToolUse、PermissionRequest、UserPromptSubmit(可以阻止)
- 转换器:带有 updatedInput 的 PreToolUse(可以修改)
- 控制器:Stop、SubagentStop(可以强制继续)
-
有哪些安全影响?
- 是否会处理不可信输入?
- 是否可能泄露敏感数据?
- 是否需要访问外部系统?
阶段 2:选择事件
根据用例匹配事件:
| 用例 | 最佳事件 |
|---|---|
| 阻止危险操作 | PreToolUse |
| 写入后自动格式化代码 | PostToolUse |
| 验证用户提示词 | UserPromptSubmit |
| 设置环境 | SessionStart |
| 确保任务完成 | Stop |
| 记录所有工具使用情况 | 带有 "*" 匹配器的 PostToolUse |
| 保护敏感文件 | 针对 Write/Edit 的 PreToolUse |
| 添加项目上下文 | UserPromptSubmit |
确定是否需要匹配器:
- 指定工具?→ 使用匹配器:
"Write|Edit" - 所有工具?→ 使用
"*"或省略匹配器 - MCP 工具?→ 使用
mcp__server__tool模式 - Bash 命令?→ 使用
Bash(git:*)模式
阶段 3:设计匹配器
匹配器模式语法:
// Exact match (case-sensitive!)
"matcher": "Write"
// OR pattern
"matcher": "Write|Edit"
// Prefix match
"matcher": "Notebook.*"
// Contains match
"matcher": ".*Read.*"
// All tools
"matcher": "*"
// MCP tools
"matcher": "mcp__memory__.*"
// Bash sub-patterns
"matcher": "Bash(git:*)"
常见匹配器模式:
| 模式 | 匹配对象 |
|---|---|
"Write" | 仅 Write 工具 |
"Write|Edit" | Write 或 Edit |
"Bash" | 所有 Bash 命令 |
"Bash(git:*)" | 仅 git 命令 |
"Bash(npm:*)" | 仅 npm 命令 |
"mcp__.*__.*" | 所有 MCP 工具 |
".*" 或 "*" | 所有内容 |
阶段 4:实施
选择实施方式:
-
内联命令(简单,无需外部文件):
{ "type": "command", "command": "echo \"$(date) | $tool_name\" >> ~/.claude/audit.log" } -
外部脚本(逻辑复杂,可重复使用):
{ "type": "command", "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/validate.sh" } -
基于提示词(大模型评估,智能决策):
{ "type": "prompt", "prompt": "Analyze if all tasks are complete: $ARGUMENTS", "timeout": 30 }
脚本模板(Bash):
#!/bin/bash
set -euo pipefail
# Read JSON input from stdin
input=$(cat)
# Parse fields with jq
tool_name=$(echo "$input" | jq -r '.tool_name // empty')
file_path=$(echo "$input" | jq -r '.tool_input.file_path // empty')
# Your logic here
if [[ "$file_path" == *".env"* ]]; then
echo "BLOCKED: Cannot modify .env files" >&2
exit 2
fi
# Success - output decision
echo '{"decision": "approve"}'
exit 0
脚本模板(Python):
#!/usr/bin/env python3
import sys
import json
# Read JSON input from stdin
data = json.load(sys.stdin)
# Extract fields
tool_name = data.get('tool_name', '')
tool_input = data.get('tool_input', {})
file_path = tool_input.get('file_path', '')
# Your logic here
if '.env' in file_path:
print("BLOCKED: Cannot modify .env files", file=sys.stderr)
sys.exit(2)
# Success - output decision
output = {"decision": "approve"}
print(json.dumps(output))
sys.exit(0)
阶段 5:强化安全性
重要:钩子会以你的权限执行 shell 命令。
安全检查清单:
- 为所有变量加引号:
"$VAR",而不是$VAR - 使用 jq 或 json.load 解析 JSON(而不是 grep/sed)
- 验证路径(不含
..,并进行规范化) - 日志/输出中不包含敏感数据
- 不使用 sudo 或提升权限
- 先手动测试脚本
- 运行项目前审查钩子
- 设置适当的超时时间
- 为所有故障模式处理错误
安全模式:
# UNSAFE - injection risk
rm $file_path
# SAFE - quoted, prevents flag injection
rm -- "$file_path"
# UNSAFE - parsing risk
cat "$input" | grep "field"
# SAFE - proper JSON parsing
echo "$input" | jq -r '.field'
纵深防御:
- 输入验证(正确解析 JSON)
- 路径净化(规范化并检查边界)
- 输出净化(不包含敏感数据)
- 故障安全默认值(出错时阻止,而非允许)
- 超时保护(防止无限循环)
阶段 6:测试
步骤 1:手动测试脚本
# Create mock input
cat > /tmp/mock-input.json << 'EOF'
{
"session_id": "test-123",
"hook_event_name": "PreToolUse",
"tool_name": "Write",
"tool_input": {
"file_path": "/path/to/file.txt",
"content": "test content"
}
}
EOF
# Test script
cat /tmp/mock-input.json | ./my-hook.sh
echo "Exit code: $?"
步骤 2:边缘情况测试
- 空输入:
{} - 缺少字段:
{"tool_name": "Write"} - 恶意输入:
{"tool_input": {"file_path": "; rm -rf /"}} - 大型输入:10KB 以上的内容
- Unicode:包含特殊字符的路径
步骤 3:集成测试
# Start Claude with debug mode
claude --debug
# Trigger the tool your hook targets
# Watch debug output for hook execution
步骤 4:验证
# Check hooks are registered
/hooks
# Watch hook execution
claude --debug 2>&1 | grep -i hook
钩子模式
观察者模式
记录但不阻止——使用 PostToolUse 或 Notification。
{
"hooks": {
"PostToolUse": [{
"matcher": "*",
"hooks": [{
"type": "command",
"command": "echo \"$(date) | $tool_name\" >> ~/.claude/audit.log"
}]
}]
}
}
守门员模式
阻止危险操作——使用 PreToolUse 或 PermissionRequest。
{
"hooks": {
"PreToolUse": [{
"matcher": "Write|Edit",
"hooks": [{
"type": "command",
"command": "python3 ~/.claude/hooks/file-protector.py"
}]
}]
}
}
转换器模式
在执行前修改输入——使用带 updatedInput 的 PreToolUse。
# In script, output:
output = {
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"permissionDecision": "allow",
"updatedInput": {
"content": add_license_header(original_content)
}
}
}
print(json.dumps(output))
编排器模式
协调多个事件——组合使用 SessionStart、PreToolUse 和 PostToolUse。
{
"hooks": {
"SessionStart": [{
"matcher": "startup",
"hooks": [{"type": "command", "command": "~/.claude/hooks/setup-env.sh"}]
}],
"PreToolUse": [{
"matcher": "Write|Edit",
"hooks": [{"type": "command", "command": "~/.claude/hooks/validate.sh"}]
}],
"PostToolUse": [{
"matcher": "Write|Edit",
"hooks": [{"type": "command", "command": "~/.claude/hooks/format.sh"}]
}]
}
}
常见问题
1. 忘记使用退出代码 2 来阻止操作
# WRONG - exit 1 doesn't block
echo "Error" >&2
exit 1
# RIGHT - exit 2 blocks Claude
echo "BLOCKED: reason" >&2
exit 2
2. 匹配器区分大小写
// WRONG - won't match "Write" tool
"matcher": "write"
// RIGHT - case-sensitive match
"matcher": "Write"
3. 变量未加引号(存在注入风险)
# WRONG - command injection vulnerability
rm $file_path
# RIGHT - properly quoted
rm -- "$file_path"
4. 脚本缺少 Shebang
# WRONG - no shebang, may fail
set -euo pipefail
# RIGHT - explicit interpreter
#!/bin/bash
set -euo pipefail
5. 未将脚本设为可执行
# Don't forget!
chmod +x ~/.claude/hooks/my-hook.sh
6. 忘记在 JSON 中为路径加引号
// WRONG - spaces in path will break
"command": "$CLAUDE_PROJECT_DIR/.claude/hooks/script.sh"
// RIGHT - quoted path
"command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/script.sh"
7. 没有错误处理
# WRONG - silent failures
input=$(cat)
tool=$(echo "$input" | jq -r '.tool_name')
# RIGHT - handle errors
input=$(cat) || { echo "Failed to read input" >&2; exit 1; }
tool=$(echo "$input" | jq -r '.tool_name') || { echo "Failed to parse JSON" >&2; exit 1; }
8. 记录敏感数据
# WRONG - may log secrets
echo "Processing: $input" >> /tmp/debug.log
# RIGHT - sanitize before logging
echo "Processing tool: $tool_name" >> /tmp/debug.log
何时使用钩子
适合使用钩子的场景:
- 安全强制执行(阻止危险操作)
- 代码质量自动化(保存时格式化、运行 lint)
- 合规与审计(记录所有操作)
- 环境设置(保持配置一致)
- 工作流自动化(通知、集成)
- 输入验证(检查提示词)
- 任务完成验证
不适合使用钩子的场景:
- 添加新功能(使用 Skills)
- 委派复杂工作(使用 Agents)
- 由用户调用的提示词(使用 Commands)
- 简单的一次性任务(直接询问 Claude)
此技能中的文件
模板(由简到繁)
templates/basic-hook.md— 单个事件,内联命令templates/with-scripts.md— 外部 shell 脚本templates/with-decisions.md— 权限控制、输入修改templates/with-prompts.md— 基于大模型的评估templates/production-hooks.md— 完整的多事件系统
示例(18 个完整钩子)
examples/security-hooks.md— 保护、验证、审计examples/quality-hooks.md— 格式化、lint、测试examples/workflow-hooks.md— 设置、上下文、通知
参考资料
reference/syntax-guide.md— 完整的 JSON 架构、所有事件reference/best-practices.md— 安全、设计、团队部署reference/troubleshooting.md— 10 个常见问题、测试方法
评论
支持 Markdown