Hooks 是 Claude Code 里被低估的强大功能——在特定事件(文件被修改、命令被执行、权限被拒绝)发生时自动触发命令或脚本。配置好 Hooks,可以实现自动 lint、自动测试、自动格式化、变更通知等,无需手动触发。
Hooks 是什么?
Hooks 让你在 Claude Code 操作流程的特定节点插入自定义动作:
- Claude 修改文件后 → 自动运行 lint 和格式化
- Claude 准备执行 Shell 命令前 → 运行安全检查
- Auto Mode 拒绝了某个操作 → 发送通知
- Claude 准备提交 git 前 → 运行完整测试套件
Hooks 是同步阻断的:如果 Hook 返回非零退出码,Claude Code 会中止当前操作并报告错误。这让 Hooks 成为一道安全网。
Hook 事件类型
| 事件 | 触发时机 |
|---|---|
PreToolUse | 工具调用执行前(可以阻断) |
PostToolUse | 工具调用执行后 |
PreCompact | 上下文压缩前(可以阻断) |
PermissionDenied | Auto Mode 拒绝操作时 |
Stop | Claude 结束回复时 |
SubagentStop | Subagent 结束时 |
基础配置格式
// .claude/settings.json
{
"hooks": {
"事件类型": [
{
"matcher": "工具匹配规则(可选)",
"hooks": [
{
"type": "command",
"command": "要执行的命令"
}
]
}
]
}
}实战配置示例
1. 文件修改后自动 Lint 和格式化
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit|MultiEdit",
"hooks": [
{
"type": "command",
"command": "npm run lint --fix 2>/dev/null || true"
},
{
"type": "command",
"command": "npm run prettier --write 2>/dev/null || true"
}
]
}
]
}
}效果:每次 Claude 修改文件后,自动运行 ESLint 修复和 Prettier 格式化。|| true 确保格式化失败不会中止 Claude 的工作流。
2. TypeScript 文件修改后自动类型检查
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write(**/*.ts)|Write(**/*.tsx)|Edit(**/*.ts)|Edit(**/*.tsx)",
"hooks": [
{
"type": "command",
"command": "npx tsc --noEmit 2>&1 | head -20 || true"
}
]
}
]
}
}效果:Claude 修改 TypeScript 文件后立即做类型检查,如果有类型错误,输出前 20 行错误供 Claude 参考。
3. Git Commit 前强制运行测试
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash(git commit *)",
"hooks": [
{
"type": "command",
"command": "./.claude/hooks/pre-commit-guard.sh"
}
]
}
]
}
}# .claude/hooks/pre-commit-guard.sh
#!/bin/bash
echo "Running pre-commit checks..."
# 运行测试
if ! npm test --silent; then
echo "ERROR: Tests failed. Commit blocked."
exit 1 # 非零退出码 → Claude 中止 commit
fi
# 检查是否有 console.log 残留
if git diff --cached | grep -q "console.log"; then
echo "WARNING: Found console.log in staged changes"
echo "Please remove console.log statements before committing"
exit 1
fi
echo "Pre-commit checks passed ✓"
exit 0效果:Claude 每次尝试 git commit 前,必须通过测试和 console.log 检查,否则 commit 被阻断。
4. Python 文件修改后自动运行相关测试
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write(**/*.py)|Edit(**/*.py)",
"hooks": [
{
"type": "command",
"command": "python -m pytest tests/ -x -q 2>&1 | tail -20 || true"
}
]
}
]
}
}5. 危险命令前阻断确认(PreToolUse)
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash(rm *)",
"hooks": [
{
"type": "command",
"command": "./.claude/hooks/rm-guard.sh"
}
]
}
]
}
}# .claude/hooks/rm-guard.sh
#!/bin/bash
# 从环境变量获取要执行的命令(Claude Code 会注入)
CMD="${CLAUDE_TOOL_INPUT}"
# 如果包含 -rf,额外警告
if echo "$CMD" | grep -q "\-rf"; then
echo "BLOCKED: rm -rf command detected"
echo "Command: $CMD"
echo "Use 'trash' instead of 'rm -rf' for recoverable deletion"
exit 1
fi
exit 06. Auto Mode 拒绝时发送通知
{
"hooks": {
"PermissionDenied": [
{
"hooks": [
{
"type": "command",
"command": "osascript -e 'display notification \"Auto Mode 阻断了一个操作\" with title \"Claude Code\"' 2>/dev/null || true"
}
]
}
]
}
}效果:Auto Mode 拦截操作时,macOS 发送系统通知。
7. Hooks 直接调用 MCP 工具(v2.1.114)
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write(**/*.ts)",
"hooks": [
{
"type": "mcp_tool",
"server": "slack",
"tool": "post_message",
"input": {
"channel": "#dev-updates",
"text": "TypeScript 文件已被 Claude Code 更新"
}
}
]
}
]
}
}使用 mcp_tool 类型直接调用 MCP 服务器的工具,比启动新进程更快。
8. 上下文压缩前保存快照(PreCompact)
{
"hooks": {
"PreCompact": [
{
"hooks": [
{
"type": "command",
"command": "mkdir -p .claude/snapshots && git diff > .claude/snapshots/pre-compact-$(date +%Y%m%d-%H%M%S).diff 2>/dev/null || true"
}
]
}
]
}
}效果:每次 /compact 前,保存当前 git diff 到快照文件。
条件 Hooks(if 语法)
{
"hooks": {
"PreToolUse": [
{
"hooks": [
{
"if": "Bash(git push *)",
"type": "command",
"command": "./.claude/hooks/pre-push-checks.sh"
},
{
"if": "Write(**/migrations/**)",
"type": "command",
"command": "echo 'WARNING: Modifying database migrations' && ./.claude/hooks/migration-safety-check.sh"
}
]
}
]
}
}if 语法让你在同一个 hook 块里针对不同情况执行不同命令。
Hook 脚本的环境变量
Claude Code 在执行 Hook 脚本时注入以下环境变量:
| 变量 | 内容 |
|---|---|
CLAUDE_TOOL_NAME | 当前工具名称(如 Bash、Write) |
CLAUDE_TOOL_INPUT | 工具的输入参数(JSON 格式) |
CLAUDE_TOOL_RESULT | 工具执行结果(PostToolUse 里) |
CLAUDE_SESSION_ID | 当前会话 ID |
CLAUDE_PROJECT_DIR | 项目根目录路径 |
#!/bin/bash
# 在 Hook 脚本里解析工具输入
TOOL_NAME="$CLAUDE_TOOL_NAME"
TOOL_INPUT="$CLAUDE_TOOL_INPUT"
# 提取 Bash 命令(如果工具是 Bash)
BASH_CMD=$(echo "$TOOL_INPUT" | python3 -c "import json,sys; print(json.load(sys.stdin).get('command',''))")
echo "Claude wants to run: $BASH_CMD"查看和管理 Hooks
# 在 Claude Code 里查看已配置的 Hooks
/hooks
# 查看 Hook 执行日志
claude --debug 2>&1 | grep -i hook最佳实践
- Hook 脚本加
|| true:对于不应该中止工作流的 Hook(如通知),加|| true防止误报阻断 - 输出要简洁:Hook 的 stdout 会显示在 Claude 的上下文里,不要输出大量内容
- 保持 Hook 脚本快速:PreToolUse Hook 在每个工具调用前执行,慢 Hook 会显著拖慢整体速度
- 用
exit 1明确阻断:只在真正需要阻断时才exit 1,不要滥用 - 把复杂逻辑放到独立脚本:
settings.json只放命令路径,逻辑放在.claude/hooks/目录
来源:Claude Code 官方文档 - Hooks | computingforgeeks.com Hooks 指南 | 整理:ClaudeEagle