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

时间:2026-07-14 08:38:46 来源:互联网

您是否曾遇到过Claude Code不执行指定指令的情况?这通常是因为指令仅作为建议而非强制要求。

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

例如,在 CLAUDE.md 中明确要求每次修改文件后运行格式化,前两次Claude会执行,但第三次可能忽略,提醒后仍会遗忘。

另一个恼人的情况是,让Claude读取外部README后,其输出风格可能突变,并出现异常注释。

问题不在于Claude的智能水平,而在于 CLAUDE.md 提供的是建议,Hooks则提供强制执行力。

官方最佳实践明确指出,任何必须每次执行的操作都应通过Hooks实现,而非依赖模型自觉 [1]。

总结而言,

Hooks构成了Claude Code的确定性执行层,确保定义规则不受上下文长度或任务复杂度影响而跳过。

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

每个玩法均附有可直接复制的配置示例。

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

Claude在等待权限、输入或任务完成时,自动推送桌面通知,适用于频繁切换浏览器查资料的场景,无需持续盯着终端。

{"hooks": {"Notification": [{"hooks": [{"type": "command","command": "osascript -e 'display notification "Claude need you" with title "Claude Code"'"}]}]}}

建议仅监听关键状态,避免所有操作都推送通知,以免频繁干扰。

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

Claude一修改文件,就自动运行 prettierruff formatgofmteslint --fix 等工具。减少一次格式调整,就减少一次上下文消耗,Claude能改对,但每次都记住改则不一定。

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

matcher 使用 | 分隔工具名,项目中运行正常。

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

在Claude真正执行前,拦截高风险操作,例如:

  1. 修改 .envlockfilemigrations
  2. 运行 rm -rfgit push --forcecurl | sh

提示词是软的,Hook是硬的,规则会真正阻止执行,而非建议Claude避免。

{"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

{"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不能的问题。

{"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,减少看起来完成但未验证的情况。

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

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

讲完单个Hook,介绍一个串联起来的真实场景。使用的终端是Ghostty,它对macOS原生通知支持不佳。Claude Code运行任务或等待输入时,看不到任何通知,切回浏览器查资料常不知进展。解决方案是用一个脚本挂到四个Hook事件上:

{"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" }] }]}}

四个事件分别覆盖:

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

最终效果:

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

二、两个进阶玩法

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

官方推荐使用 SessionStartcompact matcher,在上下文压缩后重新注入关键上下文 [1]。有建议 [2] 在 PreCompact 先写一个小状态文件,保存目标、已改文件、已完成检查、剩余blocker。这对长任务特别有用,因为压缩后最容易丢失的不是代码,而是修改原因。

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

有一个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,否则会感觉越装越卡。社区反馈也提到Hook和插件增多会降低性能 [4]。但 async: true 有副作用,执行顺序不确定,仅在耗时操作上使用。

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

有研究披露了基于repo配置文件的攻击面 [5],Hooks、MCP、env都可能成为入口。官方也强调了trust verification。实践建议:仅从可信来源复制hooks配置,避免随意粘贴到 .claude/settings.json

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

有建议 [2] 认为,越小越容易测试,越不容易误伤。一个Hook里做10件事,出问题时难以定位。

五、收个尾

综上所述,Hooks是Claude Code中确保规则被强制执行的关键机制,它弥补了Prompt的不足,为AI协作提供了确定性保障,避免因上下文衰减或模型注意力分散而导致的规则遗漏。