Appearance
Claude Code Hooks 是一套事件驱动自动化机制,允许你在 Claude Code 会话中,针对如 PreToolUse、PostToolUse、Stop 等关键事件,自动执行校验、格式化、安全扫描等脚本。支持 command、prompt、HTTP、agent 四种 Hook 类型,结合 matcher 精准匹配工具,实现从 pre-commit 安全扫描到代码格式化的全流程自动化。本文将通过实用示例、JSON 配置和脚本模板,手把手教你用 Hooks 构建高效、可控的 AI 编程环境。
Claude Code Hooks 完全指南:用事件驱动让 AI 自动执行校验和格式化
Claude Code Hooks 是什么?它是一组可以在 Claude Code 会话生命周期内,自动响应事件并执行自定义脚本的自动化机制。通过 Hooks,开发者可以在 AI 生成或修改代码前后,自动进行安全校验、格式化、权限管理、上下文监控等操作,极大提升 AI 编程的安全性和规范性。
如果你已掌握 Claude Code 的基础用法,Hooks 能让你的开发流程从“AI 辅助”跃升到“AI 驱动自动化”。本文将系统讲解 Hooks 的类型、事件、配置方式,并以“pre-commit 自动安全扫描”为核心案例,提供可直接复用的 JSON 配置和脚本模板。
一、Claude Code Hooks 能做什么?
Claude Code Hooks 通过监听会话中的特定事件(如工具调用前后、用户提交提示、会话结束等),自动执行你预设的脚本,实现:
- 代码提交前自动安全扫描(如检测 hardcoded 密钥、敏感操作)
- 文件写入后自动格式化(如 JS/TS 用 Prettier,Python 用 Black)
- 用户输入 prompt 时自动过滤危险请求
- 任务完成后用 LLM 智能判定是否真正完成
- 实时追踪上下文 token 使用量,防止超限
这些自动化动作不仅提升了开发效率,也大幅降低了安全和合规风险。
二、Hook 的四大类型
Claude Code Hooks 支持四种类型,满足不同自动化场景:
Command(命令行脚本)
最常用。执行本地 shell/python 脚本,通过 stdin/stdout 传递 JSON 数据,适合校验、格式化、日志等操作。Prompt(LLM 提示)
直接让 Claude AI 评估某个条件,如智能判断任务是否完成,适合 Stop/SubagentStop 等事件。HTTP(Webhook)
远程 POST JSON 到指定 URL,适合与外部服务、CI/CD、审计系统集成。需显式配置 allowedEnvVars 保证安全。Agent(子代理)
启动专用 subagent 进行多步复杂校验,如自动查阅设计文档、跨文件检查等,适合高阶 AI 审查。
三、五大核心 Hook 事件(及典型用法)
Claude Code 支持 25 种事件,最常用的五个如下:
| 事件名 | 触发时机 | 常见用途 |
|---|---|---|
| PreToolUse | 工具执行前 | 校验命令、阻断危险操作 |
| PostToolUse | 工具执行后 | 格式化、扫描、反馈上下文 |
| UserPromptSubmit | 用户提交 prompt | 过滤敏感/危险请求 |
| Stop | Claude 响应结束 | 智能判定任务是否完成 |
| SubagentStop | 子代理任务结束 | 子代理结果复核 |
事件与 Hook 类型可自由组合,如 PreToolUse 可用 command 校验 Bash 命令,PostToolUse 可用 command 格式化文件,Stop 可用 prompt 让 AI 判断是否完成任务。
四、核心示例:pre-commit 自动安全扫描
以“AI 代码写入前自动安全扫描”为例,完整演示配置与脚本。
1. 配置 JSON(.claude/settings.json)
json
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "python3 \"$CLAUDE_PROJECT_DIR/.claude/hooks/pre-commit.py\"",
"timeout": 30
}
]
}
]
}
}2. 校验脚本(.claude/hooks/pre-commit.py)
python
#!/usr/bin/env python3
import json, sys, re
def main():
data = json.load(sys.stdin)
cmd = data.get("tool_input", {}).get("command", "")
# 检查是否为 git commit
if re.match(r"git\s+commit", cmd):
# 这里可调用 npm test/pytest/go test/cargo test 等
# 简单示例:阻断 commit -m "WIP"
if re.search(r"WIP", cmd):
print("阻止 WIP commit", file=sys.stderr)
sys.exit(2) # exit 2 = 阻断
sys.exit(0)
if __name__ == "__main__":
main()3. 脚本权限
bash
chmod +x .claude/hooks/pre-commit.py4. 工作原理
- 每次 Bash 工具调用前,PreToolUse 事件触发
- matcher 精确匹配 Bash 工具
- 脚本分析命令内容,检测是否为 git commit,并可根据实际需求阻断或放行
- exit 2 阻断操作,stderr 信息会在 Claude Code 中显示
你也可以用 shell 脚本实现更复杂的多语言测试逻辑,详见下方 Bash 版本模板。
Bash 版 pre-commit 示例(支持 Node/Python/Go/Rust)
bash
#!/bin/bash
# .claude/hooks/pre-commit.sh
echo "🧪 Running tests before commit..."
# Node.js
if [ -f "package.json" ]; then
npm test || exit 1
fi
# Python
if [ -f "pytest.ini" ] || [ -f "setup.py" ]; then
pytest || exit 1
fi
# Go
if [ -f "go.mod" ]; then
go test ./... || exit 1
fi
# Rust
if [ -f "Cargo.toml" ]; then
cargo test || exit 1
fi
echo "✅ All tests passed! Proceeding with commit."
exit 0五、自动格式化:PostToolUse + 格式化脚本
自动格式化是 Claude Code Hooks 的高频场景。以下为 PostToolUse 事件结合格式化脚本的配置:
1. 配置 JSON
json
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "command",
"command": "\"$CLAUDE_PROJECT_DIR/.claude/hooks/format-code.sh\"",
"timeout": 30
}
]
}
]
}
}2. 格式化脚本(.claude/hooks/format-code.sh)
bash
#!/bin/bash
FILE=$1
case "$FILE" in
*.js|*.ts) prettier --write "$FILE" ;;
*.py) black "$FILE" ;;
*.go) gofmt -w "$FILE" ;;
*.rs) rustfmt "$FILE" ;;
esac
exit 0结合 Slash Commands 和 Skills 体系,你还可以将格式化能力封装为复用型 AI 技能。
六、上下文监控实用技巧:context-tracker
Claude Code 支持用 Hooks 实时追踪 token 消耗,避免上下文溢出。推荐用法如下:
1. 配置 JSON
json
{
"hooks": {
"UserPromptSubmit": [
{
"hooks": [
{
"type": "command",
"command": "python3 \"$CLAUDE_PROJECT_DIR/.claude/hooks/context-tracker.py\""
}
]
}
],
"Stop": [
{
"hooks": [
{
"type": "command",
"command": "python3 \"$CLAUDE_PROJECT_DIR/.claude/hooks/context-tracker.py\""
}
]
}
]
}
}2. context-tracker.py 脚本
python
#!/usr/bin/env python3
import json, os, sys, tempfile
CONTEXT_LIMIT = 128000 # Claude 的上下文窗口
def get_state_file(session_id):
return os.path.join(tempfile.gettempdir(), f"claude-context-{session_id}.json")
def count_tokens(text):
return len(text) // 4 # 粗略估算
def read_transcript(path):
if not path or not os.path.exists(path): return ""
content = []
with open(path) as f:
for line in f:
try:
entry = json.loads(line.strip())
if "message" in entry:
msg = entry["message"]
if isinstance(msg.get("content"), str):
content.append(msg["content"])
except: continue
return "\n".join(content)
def handle_user_prompt_submit(data):
session_id = data.get("session_id", "unknown")
transcript_path = data.get("transcript_path", "")
tokens = count_tokens(read_transcript(transcript_path))
with open(get_state_file(session_id), "w") as f:
json.dump({"pre_tokens": tokens}, f)
def handle_stop(data):
session_id = data.get("session_id", "unknown")
transcript_path = data.get("transcript_path", "")
tokens = count_tokens(read_transcript(transcript_path))
state_file = get_state_file(session_id)
pre_tokens = 0
if os.path.exists(state_file):
with open(state_file) as f:
pre_tokens = json.load(f).get("pre_tokens", 0)
delta = tokens - pre_tokens
remaining = CONTEXT_LIMIT - tokens
pct = (tokens / CONTEXT_LIMIT) * 100
print(f"Context: ~{tokens} tokens ({pct:.1f}% used, ~{remaining} remaining)", file=sys.stderr)
if delta > 0:
print(f"This request: ~{delta} tokens", file=sys.stderr)
def main():
data = json.load(sys.stdin)
event = data.get("hook_event_name", "")
if event == "UserPromptSubmit":
handle_user_prompt_submit(data)
elif event == "Stop":
handle_stop(data)
sys.exit(0)
if __name__ == "__main__":
main()效果:每次请求和响应后,stderr 输出本轮 token 消耗和剩余量,帮助你实时把控上下文窗口。
七、进阶用法与最佳实践
- 组件级 Hook:可在 skill/agent 的 frontmatter 直接定义,支持 PreToolUse/PostToolUse/Stop 三类事件,便于封装复用。
- 插件级 Hook:插件可在 hooks.json 内集成自定义 Hook,结合 Claude Code Plugins 实现即插即用。
- MCP 工具 Hook:支持 mcp__server__tool 形式 matcher,实现跨服务自动化。
- 安全建议:Hooks 执行任意脚本,务必验证输入、避免路径穿越,生产环境先在本地充分测试。
八、安装与调试
创建 hooks 目录
bashmkdir -p ~/.claude/hooks复制并授权脚本
bashcp your-hooks/*.sh ~/.claude/hooks/ chmod +x ~/.claude/hooks/*.sh编辑配置文件
修改~/.claude/settings.json或.claude/settings.json,粘贴上文 JSON 配置。调试技巧
claude --debug查看详细日志Ctrl+O开启 verbose mode- 独立测试脚本:bash
echo '{"tool_name": "Bash", "tool_input": {"command": "ls"}}' | python3 .claude/hooks/pre-commit.py echo $?
FAQ
Q: Hooks 会影响 Claude Code 的性能吗?
A: 合理配置下影响极小。建议为复杂脚本设置超时时间(如 10-30 秒),避免阻塞主流程。
Q: 如何只让某个 Hook 在每次 session 启动时运行一次?
A: 在 hook 配置中加 "once": true,即可实现只在每次会话首次触发时运行。
Q: Hooks 能否与 Plugins、Skills 等机制结合?
A: 可以。插件可集成 hooks.json,skills/agents 支持 frontmatter 级 hooks,灵活组合自动化能力。
通过灵活配置 Claude Code Hooks,你可以让 AI 自动完成校验、格式化、安全检查等繁琐任务,打造高效、安全、智能的开发工作流。更多进阶用法,参考 Claude Code 高级功能全解 和 六大扩展机制对比。