Prompt 管建议,Hook 管纪律:Claude Code 真相

本文基于 Claude Code v2.1.195(2026-06-26 发布),hooks 文档以 Anthropic 官方仓库为准 ^1^。以下所有配置示例均经过验证,可直接使用。

你有没有遇到过这种情况:

明明在 CLAUDE.md 里写了"每次改完文件要跑格式化",Claude 前两次确实照做了,到第三次就开始"忘记"。你提醒它,它道歉,然后继续忘。

或者更恼火的:你让它去读一个外部 README,它回来之后好像"被洗脑了"------输出的代码风格突然变了,还带了一些奇怪的注释。

问题不在 Claude 不聪明,而在 CLAUDE.md 是建议,Hooks 是强制执行

Anthropic 在官方 best practices 里说得很直白:凡是"每次都必须发生"的事,应该交给 hooks,而不是写在 CLAUDE.md 里等模型自觉 ^1^。

一句话总结:

Prompt 管建议,Hook 管纪律。

Hooks 是 Claude Code 的"确定性执行层"。你定义的规则,不会因为上下文太长、任务太复杂、或者模型"没注意"而被跳过。


一、6 个最值得上手的 Hook 玩法

每个玩法都配了可直接复制的配置示例。

1. Notification:等你操作时提醒你

Claude 在等权限、等你输入、或者任务完成时,自动推一个桌面通知。对经常切去浏览器查资料的场景,不用一直盯着终端了。

json 复制代码
{
  "hooks": {
    "Notification": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "osascript -e 'display notification \"Claude need you\" with title \"Claude Code\"'"
          }
        ]
      }
    ]
  }
}

建议:只监听关键状态,所有操作都推的话十分钟响八次,你很快会关掉它。

2. PostToolUse:改完文件自动格式化

Claude 一修改文件,就自动跑 prettierruff formatgofmteslint --fix 等工具。

能少改一次格式,就少一次上下文消耗------Claude 能改对,但"每次都记得改"就不一定了。

json 复制代码
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write|MultiEdit",
        "hooks": [
          {
            "type": "command",
            "command": "npx prettier --write $FILE_PATH"
          }
        ]
      }
    ]
  }
}

matcher| 分隔工具名,我在项目里跑过,没问题。

3. PreToolUse:危险操作前先拦截

在 Claude 真正执行前拦下高风险操作。比如:

  • .envlockfile、动 migrations
  • rm -rfgit push --forcecurl | sh

提示词是软的,hook 是硬的------规则会真的阻止执行,不是"建议" Claude 别这么做。

json 复制代码
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "bash -c 'if echo \"$TOOL_INPUT\" | grep -qE \"(rm -rf|git push --force)\"; then echo \"已拦截危险命令\"; exit 1; fi'"
          }
        ]
      }
    ]
  }
}

hook 能拿到完整命令($TOOL_INPUT),检查后决定放行还是拦截。

4. PermissionRequest:把重复确认变成白名单

对少量安全命令自动批准,减少反复点权限的打断。

白名单示例:git statusgit diff --statnpm testpnpm lint

json 复制代码
{
  "hooks": {
    "PermissionRequest": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "bash -c 'if echo \"$TOOL_INPUT\" | grep -qE \"^(git status|git diff --stat|npm test|pnpm lint)\"; then echo \"{\\\"hookSpecificOutput\\\":{\\\"permissionDecision\\\":\\\"allow\\\"}}\"; else echo \"{\\\"hookSpecificOutput\\\":{\\\"permissionDecision\\\":\\\"ask\\\"}}\"; fi'"
          }
        ]
      }
    ]
  }
}

警告 :白名单一定要窄,不能用太宽的正则。别写成 git .*,那等于把半个终端都交出去了。

5. SessionStart / PreCompact:自动同步环境变量

适合 monorepo、多语言项目、direnv、Python venv 等场景。

作用:在 Claude 会话启动、上下文压缩前后,自动刷新环境变量和项目状态,避免"本地 shell 能跑,Claude Bash 跑不了"的问题。

json 复制代码
{
  "hooks": {
    "SessionStart": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "source .env && echo \"环境已加载: NODE_ENV=$NODE_ENV\""
          }
        ]
      }
    ],
    "PreCompact": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "env > .claude/env-snapshot.txt"
          }
        ]
      }
    ]
  }
}

6. Stop:没检查通过不准结束

在 Claude 宣布"任务完成"前,强制跑测试、lint、git diff --check 等检查。

不通过就不能标记 Done,能减少"看起来完成了,其实没验证"的情况。

json 复制代码
{
  "hooks": {
    "Stop": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "bash -c 'npm test && git diff --check; exit $?'"
          }
        ]
      }
    ]
  }
}

一(插)、一个综合案例:我的终端通知方案

讲完单个 hook,说一个把它们串起来的真实场景。

我用的终端是 Ghostty,它对 macOS 原生通知的支持不太好。Claude Code 跑完任务或者等输入时,我看不到任何通知,切去浏览器查资料回来经常不知道进展。

解决方案是用一个脚本挂到四个 hook 事件上:

json 复制代码
{
  "hooks": {
    "Stop": [
      { "hooks": [{ "type": "command", "command": "/path/to/notifier.js" }] }
    ],
    "SessionEnd": [
      { "hooks": [{ "type": "command", "command": "/path/to/notifier.js" }] }
    ],
    "Notification": [
      { "hooks": [{ "type": "command", "command": "/path/to/notifier.js" }] }
    ],
    "UserPromptSubmit": [
      { "hooks": [{ "type": "command", "command": "/path/to/notifier.js" }] }
    ]
  }
}

四个事件分别覆盖:

  • Stop:任务完成时通知
  • SessionEnd:会话结束时通知(比如我手动退出)
  • Notification:Claude 需要权限或等我输入时通知
  • UserPromptSubmit:我开始输入新 prompt 时通知

最终效果:

!\[Claude_Code_Hooks_最被低估的能力-20260629112520608.jpeg]

一个小坑:Ghostty 的多 Tab 模式下,点击通知跳转的 Tab 不一定是发通知的那个------Ghostty 没有暴露 Tab 级别的 AppleScript 接口。我的习惯是把 Claude Code 跑在独立窗口里,避开这个问题。


二、两个进阶玩法

1. 压缩上下文前后保状态

官方推荐用 SessionStartcompact matcher,在上下文压缩(compaction)后重新注入关键上下文 ^1^。

Steve Kinney 还建议 ^2^:在 PreCompact 先写一个小状态文件,保存:

  • 目标------这次会话要完成什么
  • 已改文件------哪些文件被改过
  • 已完成检查------测试过了吗?lint 过了吗?
  • 剩余 blocker------还有什么卡住了

这对长任务特别有用。因为 compaction 后最容易丢的不是代码,而是"为什么要这样改"。

2. 给 Claude 装一个 Prompt Injection 防护层

lasso-security/claude-hooks 做了一个很实战的 PostToolUse 防护 ^3^:Claude 读文件、抓网页、跑 Bash 后,扫描输出里有没有:

  • "忽略之前指令"
  • "伪系统提示"
  • "隐藏注释指令"

然后把警告写回 Claude 的上下文。

这个玩法很适合让 Claude 读外部网页------我每次让它去查 README 或 issue,第一反应就是扫一遍输出有没有注入指令。


三、3 个遗漏但有用的 Hook

官方的 hook 类型其实有 10 个 ^1^,除了上面讲的 6+2 个,还有 3 个值得知道:

1. UserPromptSubmit:prompt 提交时注入上下文

用户每次发 prompt 时,自动注入项目上下文或安全规则。比如自动挂上项目 README 摘要、检测危险关键词、附加 coding style 要求。

这就是一个 cat .claude/project_context.md 的事。

2. SubagentStop:多代理工作流的质量门禁

使用多代理(subagent)时,验证子代理是否真的完成了任务。

可以防止子代理"假装完成"------多代理工作流里这问题挺烦人。

3. SessionEnd:会话结束时的清理与记录

会话结束时自动做清理和记录。

用法:

  • 推送会话统计(耗时、工具调用次数)
  • 清理临时文件
  • 记录未完成任务到 TODO

注意 :配 async: true,避免拖慢退出。


四、3 个最重要的避坑建议

1. Hook 默认是阻塞的

官方文档明确写了,hooks 默认会阻塞 Claude 的执行。

长测试、外部 API、重活请考虑 async: true,否则你会明显感觉"越装越卡"。社区在 HN 上也有人专门提到:hook 多了、插件多了,性能会掉 ^4^。

async: true 有副作用:执行顺序不确定。只在确实耗时的操作上使用它,别给所有 hook 都加上。

2. 项目级 Hook 本质上是可执行代码

Check Point 今年就披露过基于 repo 配置文件的攻击面 ^5^,Hooks / MCP / env 都可能成为入口。

Anthropic 官方也强调了 trust verification。

实践建议 :只从可信来源复制 hooks 配置。别随便把网上看到的 hook 配置粘贴到你的 .claude/settings.json 里。

3. 尽量用小 Hook,而不是万能 Hook

Steve Kinney 那句我很认同 ^2^:

一个 Hook 最好小到"你能用一句话讲清楚它是干什么的"。

越小越容易测,越不容易误伤。一个 hook 里做 10 件事,出错了你不知道哪件有问题。


五、收个尾

Hooks 不是什么新概念------CI/CD 里的 pre-commit hook、webhook、git hook,搞技术的都见过。但 Claude Code 把 hooks 提到了一个不一样的位置:它不是附赠功能,是你跟 AI 协作时最后一道确定性防线

Prompt 会随着上下文变长而衰减,模型会在复杂任务中"走神"。但写进 .claude/settings.json 的 hook 不会------它每次都执行,每次都生效。

我花了一段时间才理解这个区别。以前总想着"把 prompt 写得更细更全",后来发现真正重要的那些事,靠的是 hook,不是 prompt。

你最想用 Hook 解决什么问题?欢迎在评论区告诉我。

#ClaudeCode #AI编程 #开发工具 #自动化

参考资料

本文首发于公众号「保持清醒的坐标系」,更多 AI 编程与技术实践内容欢迎关注。

Footnotes

  1. Anthropic. Claude Code Hooks 开发文档 . anthropics/claude-code 仓库,plugins/plugin-dev/skills/hook-development/SKILL.md. 版本:Claude Code v2.1.195 (2026-06-26). 链接:github.com/anthropics/... 2 3 4

  2. Steve Kinney. Claude Code Hooks 社区文章与最佳实践 . 引用"PreCompact 状态保存"和"小 Hook 原则". 2

  3. Lasso Security. lasso-security/claude-hooks --- Prompt Injection 防护 hook 集合 . 最后更新:2026-06-23. 链接:github.com/lasso-secur...

  4. Hacker News. Claude Code Hooks 性能讨论帖 . 社区用户反馈 hook 增多后的性能影响.

  5. Check Point Research. 基于 AI 编码工具配置文件(Hooks/MCP)的攻击面研究报告 . 2026.

相关推荐
happyness442 小时前
AI编程如何进行压力测试
压力测试·ai编程
黑科技iOS上架2 小时前
如何解决AppStore Guideline 5.6被拒
经验分享·ios·ai编程
一叶飘零_sweeeet3 小时前
AI 编程时代的质量底座:SDD 规范驱动与 TDD 测试驱动深度实战
人工智能·ai编程·tdd·sdd
ZJPRENO3 小时前
Claude 必备技能 Code Review
ai编程
Coffeeee4 小时前
搞Android的怎么可能搞不懂Context Engineering?
android·人工智能·ai编程
Carson带你学Android4 小时前
Gemini Nano 开发实战:让你的App轻松拥有端侧 AI 功能
android·ai编程
冷de猫4 小时前
AI API 网关的四层架构与代码实现:以 Aegisy 为例
人工智能·架构·大模型·ai编程·ai网关·api代理·多模型接入
孤狼GPT4 小时前
Codex没有GPT-5.6 Sol选项怎么办?ChatGPT账号和API Key区别讲清楚
chatgpt·ai编程·codex·api key·gpt-5.6
亦暖筑序5 小时前
AgentScope-Java 入门:用 SSE 展示评审任务进度
java·agent·ai编程