Claude Code Hooks 实战指南

Claude Code Hooks 实战指南

规则靠自觉,Hooks 靠机制。

我之前在 CLAUDE.md 里写了一堆"请确保代码通过 lint"、"不要在根目录创建临时文件",结果 AI 偶尔还是会忘。后来发现 Hooks 能解决这个问题------它是强制执行的,不是写在那等 AI 自觉遵守的。

这篇文章分享我实际在用的 Hooks 配置,以及官方支持的事件和配置方法。


一、Hooks 是什么

Hooks 就是在 Claude Code 工作流程的关键节点,自动执行你预设的脚本。不需要 AI 配合,不靠提示词,系统层面硬性执行。

复制代码
SessionStart ──▶ UserPromptSubmit ──▶ PreToolUse ──▶ [工具执行] ──▶ PostToolUse
                                                                           │
                                              PreCompact ◀── 上下文压缩     │
                                              SessionEnd  ◀── 会话结束      │
                                              Stop        ◀── AI 停止输出

核心区别:

方式 执行保证 适用场景
CLAUDE.md 规则 AI 可能忘 项目约定、编码风格
Hooks 强制执行 安全防护、自动格式化、上下文注入

二、配置位置和优先级

Hooks 写在 JSON 配置文件里,有四个层级:

位置 作用范围 能提交到仓库吗
~/.claude/settings.json 所有项目 不能,本地专属
.claude/settings.json 单个项目
.claude/settings.local.json 单个项目 不能(gitignored)
插件 hooks/hooks.json 插件启用时 跟插件走

我的做法:通用安全防护放全局项目特定规则放项目级


三、配置结构

一个 Hook 由三层嵌套组成:

json 复制代码
{
  "hooks": {
    "事件名": [
      {
        "matcher": "工具匹配器",
        "hooks": [
          {
            "type": "command",
            "command": "你的脚本"
          }
        ]
      }
    ]
  }
}

matcher 匹配规则

写法 匹配方式 示例
"*""" 或不写 匹配所有 所有事件都触发
纯字母+数字+` ` 精确匹配
包含其他字符 正则匹配 "^Notebook""mcp__memory__.*"

退出码含义

退出码 含义 效果
0 成功 正常继续,stdout 会被解析
2 阻断 阻止操作执行,stderr 反馈给 AI
其他 非阻断错误 记录日志,继续执行

脚本能收到的环境变量

变量 说明
$CLAUDE_FILE_PATH 当前操作的文件路径(PostToolUse 时)
$CLAUDE_PROJECT_DIR 项目根目录
$CLAUDE_SESSION_ID 当前会话 ID

脚本通过 stdin 接收 JSON 输入,格式取决于事件类型。


四、我实际在用的 Hooks

1. 危险命令拦截(PreToolUse + Bash)

问题 :AI 偶尔会生成 git push --forcerm -rf / 这种危险命令。

配置

json 复制代码
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "bash /path/to/ocean-dock/hooks/guard_bash.sh"
          }
        ]
      }
    ]
  }
}

脚本做的事

  • 从 stdin 读取 JSON,提取 tool_input.command
  • 先检查安全命令白名单(lspwdgit status 等直接放行)
  • 匹配危险模式:rm -rf /etcgit push --forceDROP TABLEmkfsshutdown
  • 命中则 exit 2 阻断执行

关键代码片段:

bash 复制代码
INPUT=$(cat)
CMD=$(echo "$INPUT" | python3 -c "import sys,json; print(json.load(sys.stdin).get('tool_input',{}).get('command',''))")

# 匹配 force push
echo "$CMD" | grep -qiE 'git\s+push\s+.*(-(-force|-f)\b)' && {
    echo "[GUARD] 危险: 检测到 git push --force 操作" >&2
    exit 2
}

效果 :AI 要执行 git push --force 时,命令直接被拦截,AI 收到错误反馈,会自动换一种方式处理。

2. 垃圾文件拦截(PreToolUse + Write/Edit)

问题 :AI 偶尔会在根目录创建 test.pydebug.py,或者写 .env 文件。

配置

json 复制代码
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "command",
            "command": "bash /path/to/ocean-dock/hooks/guard_write.sh"
          }
        ]
      }
    ]
  }
}

拦截规则

  • __pycache__/.pyc.pyo → 编译缓存
  • .DS_Store → 系统垃圾
  • .git/ 内部文件 → 破坏仓库
  • .egg-info/ → 打包缓存
  • 根目录的 test.pytmp.pydebug.py → 必须放 tests/

3. 自动格式化(PostToolUse + Write/Edit)

问题:AI 写完代码,格式可能不一致。

两个 Hook 叠加使用

json 复制代码
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write|MultiEdit",
        "hooks": [
          {
            "type": "command",
            "command": "bash /path/to/ocean-dock/hooks/auto_check.sh"
          },
          {
            "type": "command",
            "command": "[ \"${CLAUDE_FILE_PATH##*.}\" = \"py\" ] && ruff check --fix \"$CLAUDE_FILE_PATH\" 2>/dev/null && ruff format \"$CLAUDE_FILE_PATH\" 2>/dev/null || true"
          }
        ]
      }
    ]
  }
}

第一个脚本 auto_check.sh 做多语言检查:

  • Python → ruff check
  • JS/TS → eslint
  • Go → go vet
  • Rust → cargo check
  • 所有文件 → 行数超过 1000 行警告

第二个内联命令专门处理 Python 文件的 ruff 格式化。

4. 会话启动注入上下文(SessionStart)

问题:每次新开 session,AI 不知道之前的对话历史。

配置

json 复制代码
{
  "hooks": {
    "SessionStart": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "bash /path/to/ocean-dock/hooks/session_start.sh"
          }
        ]
      }
    ]
  }
}

脚本做的事

  • 查找当前项目的历史 session 列表
  • 展示最近 8 个 session(ID、时间、消息数、首条消息预览)
  • 通过 systemMessage 注入给 Claude
  • 检测项目结构是否变化,如果变了提醒 AI 更新架构概览

效果:AI 开场会说"我看到这些历史 session,需要恢复哪个的上下文吗?"

5. 会话结束自动保存摘要(Stop)

问题:session 结束后,下次无法接续。

配置

json 复制代码
{
  "hooks": {
    "Stop": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "bash /path/to/ocean-dock/hooks/stop.sh"
          }
        ]
      }
    ]
  }
}

脚本做的事

  • 调用 ocean-dock 生成 session 摘要
  • 保存到 .claude/LAST_HANDOFF.md
  • 对比项目目录结构指纹,如果变化了标记"架构记忆需要更新"

6. 上下文压缩保护(PreCompact)

问题:对话太长时 Claude Code 会自动压缩上下文,但压缩可能丢失关键信息。

配置

json 复制代码
{
  "hooks": {
    "PreCompact": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "bash /path/to/ocean-dock/hooks/pre_compact.sh"
          }
        ]
      }
    ]
  }
}

脚本做的事

  • 在压缩前调用 ocean-dock 生成当前 session 摘要
  • 通过 systemMessage 注入回 Claude,让压缩后的对话仍然保留关键信息

7. 桌面通知(Notification)

问题:等 AI 执行长任务时,不知道它什么时候需要权限确认或已经完成。

配置

json 复制代码
{
  "hooks": {
    "Notification": [
      {
        "matcher": "permission_prompt",
        "hooks": [
          {
            "type": "command",
            "command": "bash /path/to/ocean-dock/hooks/notify.sh"
          }
        ]
      },
      {
        "matcher": "idle_prompt",
        "hooks": [
          {
            "type": "command",
            "command": "bash /path/to/ocean-dock/hooks/notify.sh"
          }
        ]
      }
    ]
  }
}

AI 需要权限确认或任务完成空闲时,桌面弹通知。


五、项目级 Hooks 示例

上面是全局配置。对于特定项目,还可以在 .claude/hooks/ 下放项目专用的 hook 文件。

比如 ai-governance-example 项目,我配了文档同步提醒:

PostToolUse 自动化矩阵

文件模式 触发动作
**/*.py ruff format + ruff check --fix
**/*.{ts,tsx} prettier --write
backend/app/api/**/*.py 提醒更新 API 文档
backend/app/models/**/*.py 提醒更新数据模型文档
backend/app/services/**/*.py 提醒更新验收标准
**/Dockerfile 提醒更新部署文档
所有文件 检查 TODO/FIXME 残留
docs/**/*.md 文档格式验证

提醒类 Hook 的写法示例:

json 复制代码
{
  "event": "PostToolUse",
  "tool": "Write|Edit",
  "glob": "backend/app/api/**/*.py",
  "action": "API 修改提醒更新文档",
  "message": "你修改了 API 文件,文档可能不同步。检查以下文档是否需要更新:\n1. docs/reference/api-spec.yaml\n2. docs/design/ 对应功能的状态标记"
}

六、所有可用事件速查

事件 触发时机 能阻断吗
SessionStart 会话启动/恢复 不能
UserPromptSubmit 用户提交 prompt 前
PreToolUse 工具执行前 (核心拦截点)
PermissionRequest 权限对话框弹出时
PostToolUse 工具执行后 不能(已执行)
PostToolBatch 一批工具都完成后 能(停止循环)
Notification 发送通知时 不能
SubagentStart 子 Agent 启动 不能
SubagentStop 子 Agent 完成
Stop AI 停止输出 能(让它继续干活)
PreCompact 上下文压缩前
PostCompact 上下文压缩后 不能
SessionEnd 会话结束 不能

七、Hook 脚本编写要点

输入处理

所有脚本通过 stdin 接收 JSON。Python 解析最方便:

bash 复制代码
INPUT=$(cat)
CMD=$(echo "$INPUT" | python3 -c "import sys,json; print(json.load(sys.stdin).get('tool_input',{}).get('command',''))")

PreToolUse 的输入示例:

json 复制代码
{
  "session_id": "abc123",
  "hook_event_name": "PreToolUse",
  "tool_name": "Bash",
  "tool_input": {
    "command": "npm test"
  }
}

PostToolUse 的输入多了 tool_responseduration_ms

输出控制

简单拦截exit 2 + stderr 反馈

bash 复制代码
echo "危险操作被拦截" >&2
exit 2

JSON 精细控制:exit 0 + stdout JSON

bash 复制代码
# PreToolUse 允许执行并注入上下文
echo '{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"allow","additionalContext":"当前环境: production"}}'

# Stop 阻止 AI 停下来,让它继续
echo '{"decision":"block","reason":"还有测试没跑完"}'

# SessionStart 注入上下文
echo '{"systemMessage":"最近变更: feat/auth-refactor 分支有未提交代码"}'

关键注意点

  1. 安全命令白名单 :拦截脚本里记得放行只读命令(lsgit statusecho),不然 AI 连查看目录都被拦
  2. 脚本要幂等:同一个 Hook 可能被多次触发,脚本要能安全重复执行
  3. 超时控制 :默认超时 600 秒,可以通过 timeout 字段调整
  4. stdout 只输出有效内容:shell 启动时的欢迎文本会干扰 JSON 解析

八、调试技巧

  • /hooks 命令 :在 Claude Code 里输入 /hooks,能看到所有已配置的 Hook 及其来源
  • claude --debug:debug 日志会记录每个 Hook 的匹配、执行、退出码
  • claude --debug-file <path>:指定 debug 日志输出位置
  • CLAUDE_CODE_DEBUG_LOG_LEVEL=verbose:更详细的匹配过程日志

九、进阶玩法

异步 Hook

后台执行,不阻塞 AI:

json 复制代码
{
  "type": "command",
  "command": "/path/to/run-tests.sh",
  "async": true,
  "timeout": 300
}

适合跑测试套件这种耗时操作,AI 继续工作,测试完了把结果反馈回来。

HTTP Hook

把事件发到远程服务:

json 复制代码
{
  "type": "http",
  "url": "http://localhost:8080/hooks/pre-tool-use",
  "headers": {
    "Authorization": "Bearer $MY_TOKEN"
  },
  "allowedEnvVars": ["MY_TOKEN"]
}

Prompt Hook

让 AI 判断该不该放行:

json 复制代码
{
  "type": "prompt",
  "prompt": "评估 Claude 是否该停止: $ARGUMENTS。检查所有任务是否完成。",
  "timeout": 30
}

底层调一个快模型返回 {ok: true/false} 判断。

Agent Hook

比 Prompt Hook 更强------能启动一个子 Agent 读文件、跑命令后再判断:

json 复制代码
{
  "type": "agent",
  "prompt": "验证所有单元测试是否通过。运行测试套件并检查结果。$ARGUMENTS",
  "timeout": 120
}

十、总结

我用 Hooks 解决的核心问题:

问题 Hook 方案 效果
AI 忘记 lint PostToolUse 自动 ruff format 写完就格式化
危险命令 PreToolUse 拦截 force push 等直接拦掉
临时文件污染 PreToolUse 拦截 根目录不让建 test.py
文档过时 PostToolUse 提醒 改 API 文件时弹提醒
上下文丢失 PreCompact 注入摘要 压缩后关键信息还在
会话不连续 Stop 保存 + SessionStart 恢复 开场就能接上

配置层级建议 :通用防护放全局 ~/.claude/settings.json,项目特定的放 .claude/settings.json,团队共享的提交到仓库。

调试口诀 :先用 /hooks 确认配置生效,再用 --debug 看执行日志。


十一、补充:.githooks(Git Hooks)

Claude Code Hooks 管 AI 的行为,Git Hooks 管人的行为(包括 AI 帮你 commit/push 时)。

两者配合形成完整防线:

复制代码
┌─────────────────────────────────────────────────────────────────┐
│                     双层防护体系                                 │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│   Claude Code Hooks          Git Hooks (.githooks)             │
│   ┌────────────────┐         ┌────────────────┐                │
│   │ AI 写代码时     │         │ git commit 时  │                │
│   │ • 拦截危险命令  │         │ • 垃圾文件检测  │                │
│   │ • 自动格式化    │   ──▶   │ • 敏感信息扫描  │                │
│   │ • 上下文保护    │         │ • commit 格式   │                │
│   │ • 文档同步提醒  │         │ • 测试运行      │                │
│   └────────────────┘         └────────────────┘                │
│        实时拦截                   提交门禁                       │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

为什么用 .githooks 而不是 .git/hooks

.git/hooks/ 不会被提交到仓库,团队成员拿不到。.githooks/ 放在项目根目录,通过 git config core.hooksPath .githooks 激活,团队共享。

激活方式

bash 复制代码
# 项目根目录执行一次即可
git config core.hooksPath .githooks

也可以在 AGENTS.mdCLAUDE.md 里写上这句,让 AI 在新项目初始化时自动执行。

我用的四个 Git Hook

1. pre-commit --- 提交前检查

三道关卡:

bash 复制代码
# ① 垃圾文件检测
# 扫描暂存区,发现 __pycache__/、.pyc、.DS_Store、*.tmp、*.bak 直接报错

# ② 敏感信息扫描
# 正则匹配 password=、api_key=、secret=、token=、sk-xxx 模式

# ③ ruff 代码检查(如果可用)
# 只检查暂存的 Python 文件

效果示例:

复制代码
[pre-commit] 运行检查...

[1/3] 检查垃圾文件...
[OK] 未检测到垃圾文件

[2/3] 检查敏感信息...
[WARNING] config.py 可能包含敏感信息 (pattern: api_key\s*=\s*["']...)

[3/3] ruff 检查...
[OK] ruff check 通过

[pre-commit] 所有检查通过

不通过时 commit 被阻止,必须修复后重试。用 git commit --no-verify 可以跳过,但显然不推荐。

2. commit-msg --- 提交格式校验

检查 commit message 是否符合 Conventional Commits 格式:

复制代码
feat(api): 添加用户认证接口
fix(parser): 修复空输入崩溃问题
docs: 更新 API 文档

这个 hook 只警告不阻断(exit 0),因为有时候确实需要写非标准格式的 commit message。另外检查标题长度是否超过 72 字符。

3. pre-push --- 推送前跑测试
bash 复制代码
# 支持 SKIP_PRE_PUSH_TESTS=1 git push 跳过
# 如果没有 tests/ 目录或 pytest 没装也自动跳过
# pytest 退出码 5(无测试收集)视为通过

确保推到远程的代码至少本地测试是通过的。

4. post-checkout --- 切换分支后清理缓存

切换分支时自动清理 __pycache__/.pyc.pyo,避免残留缓存文件造成干扰。

.githooks 目录结构

复制代码
.githooks/
├── pre-commit      # 提交前:垃圾文件 + 敏感信息 + lint
├── commit-msg      # 提交信息格式校验
├── pre-push        # 推送前:跑测试
└── post-checkout   # 切分支后:清理缓存

和 Claude Code Hooks 的分工

检查项 Claude Code Hook Git Hook 理由
危险命令拦截 PreToolUse (Bash) --- AI 专属场景
自动格式化 PostToolUse (Write/Edit) --- 实时修正
上下文保护 PreCompact / Stop --- AI 会话专属
垃圾文件 PreToolUse 拦截写入 pre-commit 拦截提交 双保险
敏感信息 --- pre-commit 扫描 提交是最后防线
commit 格式 --- commit-msg Git 专属
测试 --- pre-push 推送是最后防线

核心原则:本地 Hook 是开发反馈,CI 是合并门------两层独立,本地没启用 Hook 不会绕过 CI 检查。


参考链接

相关推荐
金融RPA机器人丨实在智能2 小时前
即通过视觉识别技术为现有GUI软件加上“AI适配器”
人工智能·ai
NOVAnet20232 小时前
AI 全球化部署网络瓶颈:算法模型跨地域、跨云互联核心痛点解析
算法·ai·sd-wan·专线·跨区域
是jin奥2 小时前
openclaw组成与配置简介
ai
HyperAI超神经3 小时前
MiniCPM5-1B采用RL+OPD训练,多项复杂任务达SOTA;面向复杂医疗业务自动化:医疗智能体评测数据集 CHI-Bench
人工智能·深度学习·ai·计算化学
摸鱼同学3 小时前
04-Embedding 和向量数据库:让机器真正理解语义
ai·chatgpt·embedding·agent·向量数据库
Bruce_Liuxiaowei3 小时前
2026年6月第1周网络安全形势周报
人工智能·安全·web安全·ai·智能体
TheRouter3 小时前
LLM 应用的RateLimiting 工程实战:Per-User Token 配额、滑动窗口限流与优先级队列的生产落地
ai
searchforAI3 小时前
2026年AI笔记工具对比实测:NotebookLM、通义听悟、Ai好记怎么选?
人工智能·笔记·gpt·ai·whisper·音视频·语音识别
周周爱喝粥呀5 小时前
4个AI 大模型排行榜的对比
人工智能·ai