<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:media="http://search.yahoo.com/mrss/"><channel><title>Hooks | Feisky</title><link>https://feisky.xyz/tags/hooks/</link><description>极客时间专栏作者，专注于 Kubernetes、AI Infra、AI Agent 领域的深度技术分享，让 AI 成为你的第二大脑</description><generator>Hugo 0.165.0</generator><language>zh-CN</language><managingEditor>Pengfei Ni</managingEditor><webMaster>Pengfei Ni</webMaster><lastBuildDate>Fri, 14 Aug 2026 12:39:05 +0000</lastBuildDate><atom:link href="https://feisky.xyz/tags/hooks/index.xml" rel="self" type="application/rss+xml"/><item><title>终于搞明白 Claude Code 为什么会忽略我的指令了</title><link>https://feisky.xyz/posts/2026-06-23-claude-code-steering/</link><pubDate>Tue, 23 Jun 2026 10:00:00 +0800</pubDate><dc:creator>Pengfei Ni</dc:creator><category>Claude Code</category><category>Anthropic</category><category>AI 编程</category><category>Harness</category><category>Skills</category><category>Hooks</category><guid>https://feisky.xyz/posts/2026-06-23-claude-code-steering/</guid><description>&lt;blockquote&gt;
&lt;p&gt;题记：本文编译自 Anthropic 工程博客《Steering Claude Code: skills, hooks, subagents and more》，原文链接：&lt;a href="https://www.anthropic.com/engineering/claude-code-best-practices"&gt;https://www.anthropic.com/engineering/claude-code-best-practices&lt;/a&gt;。本文在翻译基础上做了整理和补充。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;在使用 Claude Code 时，我的 CLAUDE.md 曾经写到几千行。项目规范、参考约定、编码风格、部署流程，还有日常开发中碰到的各种坑，全往里面塞。CLAUDE.md 的内容越来越丰富，Claude Code 也越来越好用。直到有一天我发现 Claude Code 开始选择性忽略某些指令，才反应过来，它的上下文太长了，它已经不能很好地遵循 CLAUDE.md 定义的各种规则了。&lt;/p&gt;</description><content:encoded>&lt;![CDATA[<blockquote><p>题记：本文编译自 Anthropic 工程博客《Steering Claude Code: skills, hooks, subagents and more》，原文链接：<a href="https://www.anthropic.com/engineering/claude-code-best-practices">https://www.anthropic.com/engineering/claude-code-best-practices</a>。本文在翻译基础上做了整理和补充。</p></blockquote><p>在使用 Claude Code 时，我的 CLAUDE.md 曾经写到几千行。项目规范、参考约定、编码风格、部署流程，还有日常开发中碰到的各种坑，全往里面塞。CLAUDE.md 的内容越来越丰富，Claude Code 也越来越好用。直到有一天我发现 Claude Code 开始选择性忽略某些指令，才反应过来，它的上下文太长了，它已经不能很好地遵循 CLAUDE.md 定义的各种规则了。</p><p>你是不是也碰到过类似的情况？明明写了“所有修改必须跑完整 e2e 测试”，结果只跑了一个单元测试就停了，需要你反复提示才执行。</p><p>我在这个问题上卡了很久，一度怀疑是 Claude 模型又降智了，后来才发现根本原因是上下文膨胀。把所有东西都塞进了 CLAUDE.md，这本身就是用错了 AI 工具。</p><p>Anthropic 最近发了一篇官方指南，系统梳理了提示 Claude Code 的 7 种方法和它们的实现原理。我之前踩过的很多坑，根因都是没搞清楚每种方法的加载时机和上下文成本。</p><p>下面是我对这篇指南的编译和解读，每一节加了自己的使用经验。</p><h2 id="claudemd写得越多质量越差">CLAUDE.md：写得越多，质量越差</h2><p>CLAUDE.md 是使用 Claude Code 所必需的第一步，所以也就成了大家最先接触、也是最容易写过头的配置方法。它在 Claude Code 会话启动时就加载，全程驻留在上下文空间中。</p><p>不过这里有个容易忽略的设计：CLAUDE.md 的写法其实分两种。</p><p>第一种，放在项目根目录的 CLAUDE.md 每次会话都加载，压缩后会被重新读取。适合放构建命令、目录结构、团队硬性约定这些 Claude 需要始终知道的信息。</p><p>第二种，子目录的 CLAUDE.md（比如<code>app/api/CLAUDE.md</code>）只在 Claude 读到该目录下的文件时才加载。离开这个目录，这些指令就不在上下文里了。</p><p><img src="/images/2026-06-23-claude-code-steering-claude-md-hierarchy.jpg" alt="CLAUDE.md 层级加载示意" loading="lazy" decoding="async"/></p><p>Anthropic 给的建议是：根 CLAUDE.md 控制在 200 行以内，给它一个 owner，像审查代码一样审查对它的修改。</p><p>这件事在团队协作的大仓库里尤其明显。CLAUDE.md 很容易变成一个没人维护的公共配置文件，每个组都往里加自己的规范，没人删旧的。</p><p>最终每个工程师的每次会话都要加载所有团队的规范，不管跟当前任务有没有关系。</p><p>要解决也很简单，在 monorepo 里给每个团队目录配置单独的 CLAUDE.md，让团队只加载自己的规范。还可以用<code>claudeMdExcludes</code> 跳过不相关团队的文件。</p><p>总结起来一句话，不要把 CLAUDE.md 当成垃圾桶，而是寸土寸金的黄金地段。能不放的，就别放。</p><h2 id="rules按路径触发不白占上下文">Rules：按路径触发，不白占上下文</h2><p>Rules 是<code>.claude/rules/</code> 目录下的 Markdown 文件。</p><p>不带路径限定的 Rule 跟根 CLAUDE.md 行为一样：每次会话都会加载、会话压缩后也会重新注入。其实本质上就是换了个目录放的 CLAUDE.md 内容。</p><p>真正有意思的是带路径限定的 Rule。给 Rule 加一个<code>paths</code> 字段，它就只在 Claude 碰到匹配路径的文件时才加载：</p><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span>---</span></span><span style="display:flex;"><span><span style="color:#f92672">paths</span>:</span></span><span style="display:flex;"><span> -<span style="color:#e6db74">"src/api/**"</span></span></span><span style="display:flex;"><span> -<span style="color:#e6db74">"**/*.handler.ts"</span></span></span><span style="display:flex;"><span>---</span></span><span style="display:flex;"><span><span style="color:#ae81ff">所有 API handler 必须用 Zod 校验输入参数.</span></span></span></code></pre></div><p>这条规则在你改文档的时候完全不占上下文，只有碰到 API 相关代码才会出现。</p><p>所以，凡是只对特定目录或文件类型生效的约束，都应该用 path-scoped Rule，而不是写在 CLAUDE.md 里。这是控制上下文膨胀最直接的手段。</p><p>什么时候用 Rule 而不是子目录 CLAUDE.md？当一个约束是跨目录的。比如“所有<code>.handler.ts</code> 文件都要校验输入”，它可能散布在多个目录下，放某一个目录的 CLAUDE.md 里不合适。</p><h2 id="skills按需加载用完即走">Skills：按需加载，用完即走</h2><p>Skills 住在<code>.claude/skills/</code> 目录里，每个 Skill 是一个文件夹，核心是一个<code>SKILL.md</code> 文件，里面包含了名称、描述和正文。</p><p>Skills 最关键的一个设计时只有名称和描述在会话启动时加载，正文只有在被调用时才进入上下文。</p><p><img src="/images/2026-06-23-claude-code-steering-skills-trigger.jpg" alt="Skills 触发机制" loading="lazy" decoding="async"/></p><p>它的调用方式有两种：通过斜杠命令（比如<code>/code-review</code>），或者 Claude 根据任务自动匹配。</p><p>在使用 Skills 的时候，也需要注意会话压缩的行为：压缩时，已调用的 Skills 会被重新注入，但所有 Skills 共享一个总 token 预算。一次会话里调用太多 Skills，最早调用的会被丢掉。</p><p>Anthropic 给的原则是：流程性的东西放 Skill，不要放 CLAUDE.md。部署流程、发布检查清单、代码审查规范，这些都应该是 Skill。CLAUDE.md 只放 Claude 需要始终知道的事实。</p><p>我自己的经历可也是如此。之前 CLAUDE.md 里写了一大段“发布+验证流程”，后来拆成 Skill，不发布的时候这些指令就不占空间了。省下来的上下文让 Claude 能记住更多真正相关的事情。</p><h2 id="subagents不是多一个帮手是多一块白板">Subagents：不是多一个帮手，是多一块白板</h2><p>Subagents 是<code>.claude/agents/</code> 目录下的 Markdown 文件，用 YAML frontmatter 定义名称、描述和工具权限，正文是这个子 Agent 的系统提示词。</p><p>名称、描述和工具列表在会话启动时加载。但正文永远不会进入主会话的上下文，它在子 Agent 自己的独立上下文窗口里运行，只有最终的摘要消息回到主会话。</p><p><img src="/images/2026-06-23-claude-code-steering-context-window.jpg" alt="Claude Code 上下文窗口结构" loading="lazy" decoding="async"/></p><p>这个设计对上下文管理的意义挺大的。Subagent 可以嵌套最多 5 层，动态工作流可以编排几十甚至上百个后台 Agent。中间结果全在脚本变量里，不污染主上下文。</p><p>那 Skill 和 Subagent 怎么选？Anthropic 给的判断标准是这样的：</p><ul><li>用 Skill：当你希望流程在主线程里执行，你能看到每一步、随时干预。</li><li>用 Subagent：当侧任务的中间结果你不需要再看（深度搜索、日志分析、依赖审计），只需要一个最终摘要。</li></ul><p>说白了，Subagent 的核心价值不是“多一个 Agent”，而是上下文隔离。让主会话保持干净，不被旁支任务的中间过程淹没。</p><p>我自己用 Subagent 最多的场景有两个：一个是让它先 explore 整个代码库，写一份结构报告回来，主 Agent 拿着报告再动手改代码；另一个是设计和实现分离，设计时需要进行大量的调研工作，但实现的时候只需要设计文档就足够了。</p><h2 id="hooks让-claude-code-100-执行">Hooks：让 Claude Code 100% 执行</h2><p>Hooks 是在 Claude Code 生命周期事件上触发的用户定义命令。注册在<code>settings.json</code> 里，在文件编辑、工具调用、会话启动等事件上自动触发。</p><p><img src="/images/2026-06-23-claude-code-steering-hooks-lifecycle.jpg" alt="Hooks 生命周期事件图" loading="lazy" decoding="async"/></p><p>Hook 有五种类型：command、HTTP、mcp_tool、prompt 和 agent。前三种确定性执行（跑脚本、发请求、调工具），后两种用模型判断来决定输出。</p><p>Hooks 的上下文成本极低，配置在主上下文窗口外面，harness 直接执行。只有少数 Hook 的输出会回到主上下文（比如阻断型 Hook 的错误信息，让 Claude Code 知道为什么被拒绝）。</p><p>Hooks 在整套 Claude Code 体系里最容易被忽略但最重要的一点是：</p><p>“每次 X 都必须做 Y” 如果放在 CLAUDE.md 里，本质上是在靠模型的遵从性来保证执行。模型大多数时候会遵守，但在长会话、上下文压力大、或者遇到 prompt injection 的时候，它可以不遵守。</p><p>想要确定性执行，必须用 Hook。比如“每次编辑后跑 prettier”，这不该是一条指令让 Claude Code 选择执行，而应该是一个<code>PostToolUse</code> Hook 在每次文件写入后自动触发。</p><p>同理，“绝对不能做 X” 这种约束也不该靠 CLAUDE.md。用<code>PreToolUse</code> Hook 检查调用，exit code 2 直接阻断。对企业来说，更严格的配置可以用 Managed Settings，管理员部署、用户不可覆盖。</p><p>所以，你要注意，凡是在 CLAUDE.md 里写了“必须”或“绝对不能”的规则，都别忘了问自己一句：这条规则失败了会怎样？如果后果严重，就赶紧改成 Hook。</p><h2 id="output-styles-和-append-system-prompt慎用杀伤力大">Output Styles 和 append-system-prompt：慎用，杀伤力大</h2><p>最后两种方法放在一起说，它们都作用在系统提示词层面，威力大但副作用也大。</p><p>Output Styles 是<code>.claude/output-styles/</code> 目录下的文件，注入系统提示词，永不压缩。注意一个关键细节：自定义 Output Style 默认会替换 Claude Code 的默认系统提示词，除非在 frontmatter 里设置<code>keep-coding-instructions: true</code>。</p><p>换句话说，一旦用了自定义 Output Style，Claude Code 默认的那些行为指导（怎么控制变更范围、什么时候加注释、安全关注点、跑测试再报完工）全部会被覆盖。Claude Code 就从一个软件工程助手变成一个通用助手了。</p><p>所以 Anthropic 的建议是：先看看内置的 Proactive、Explanatory、Learning 三个样式够不够用，再考虑自定义。</p><p>append-system-prompt 是另一种用法，它是 CLI 启动时传入的 flag，只对当前会话生效，不会持久化。它是纯追加的，不会替换默认行为，一般适合临时加一些格式偏好或领域知识。</p><p>我觉得大多数人不需要碰 Output Styles。内置样式加上 CLAUDE.md 已经够用了，除非你真的要把 Claude Code 改造成一个完全不同的角色。</p><h2 id="别踩这些坑">别踩这些坑</h2><p>最后整理一下 Anthropic 给的“反模式”清单，基本都是我自己踩过或见过别人踩的：</p><p>第一个是把“每次 X 都必须做 Y” 这种强制性约束写在 CLAUDE.md 里。模型的指令遵循和代码自动执行是两回事。如果这个行为必须可靠发生，一定要用 Hook。同理，“绝对不能做 X” 也不该靠 CLAUDE.md，禁止性约束在 prompt injection 面前毫无抵抗力，要用 Hook 或 Managed Settings 做墙纸约束。</p><p>第二个是把流程放在 CLAUDE.md 里面。CLAUDE.md 应该只放 Claude Code 需要始终知道的事实以及它最常犯的一些错误的经验教训，而流程则放到 Skills 里面。</p><p>第三个是 Rule 不加 paths。一条只对<code>src/api/</code> 生效的规则如果不加路径限定，效果等同于在 CLAUDE.md 里多了一行，每次都加载，每次都耗 token。个人偏好也是同样的道理，所有的配置方法都分为项目级和用户级，“永远用 semantic commit message” 这种个人习惯应该只放在本地，项目级只放团队共识。</p><hr><h2 id="速查表7-种方法一览">速查表：7 种方法一览</h2><table><thead><tr><th>方法</th><th>何时加载</th><th>压缩行为</th><th>上下文成本</th><th>适用场景</th></tr></thead><tbody><tr><td>CLAUDE.md（根目录）</td><td>会话启动，全程驻留</td><td>缓存式：读一次缓存，压缩后重读</td><td>高</td><td>构建命令、目录结构、编码规范、团队约定</td></tr><tr><td>CLAUDE.md（子目录）</td><td>按需加载，读到该目录下文件时触发</td><td>触发后才有，离开即丢</td><td>低</td><td>特定目录的局部规范</td></tr><tr><td>Rules</td><td>会话启动（无路径限定）或文件触发（有路径限定）</td><td>压缩后重新注入</td><td>中</td><td>具体约束（如“所有 API handler 必须用 Zod 校验”）</td></tr><tr><td>Skills</td><td>名称和描述在会话启动时加载，正文在调用时加载</td><td>已调用的 skill 按预算重新注入，超出则最旧的先丢</td><td>低</td><td>流程性工作（部署清单、发布检查、代码审查）</td></tr><tr><td>Subagents</td><td>名称、描述和工具列表在会话启动时加载，正文在被调用时加载</td><td>只有最终摘要回到主会话</td><td>低</td><td>并行任务或需要隔离的侧任务（深度搜索、日志分析、依赖审计）</td></tr><tr><td>Hooks</td><td>生命周期事件触发</td><td>完全绕过压缩</td><td>低</td><td>确定性自动化（跑 linter、发 Slack、拦截命令）</td></tr><tr><td>Output Styles</td><td>会话启动，注入系统提示词</td><td>永不压缩</td><td>高</td><td>大幅改变 Claude 的角色定位</td></tr></tbody></table><p>这张表最有价值的一列是“上下文成本”。搞清楚哪些指令需要全程驻留、哪些只在触发时加载，是用好这套系统的关键。</p><hr><h2 id="写在最后">写在最后</h2><p>说实话，这篇官方指南没介绍什么新功能，这 7 种方法早就存在了。但它的价值在于第一次把每种方法的加载时机、压缩行为和上下文成本都讲清楚了。</p><p>这 7 种方法按 harness 设计的思路大致可以整理成为四层：</p><ul><li>全局层（CLAUDE.md、unscoped Rules、Output Styles）：高成本、高权威，克制使用</li><li>触发层（path-scoped Rules、子目录 CLAUDE.md、Skills）：按需加载，中低成本</li><li>隔离层（Subagents）：零主上下文成本，只关注结果</li><li>确定性层（Hooks）：绕过模型，代码级保证</li></ul><p>搞清楚这四层，大部分“Claude 为什么忽略我的指令”的问题就有了答案。不是模型不听话，是你把指令放在了错误的层级，或者上下文爆满之后它被忽略掉了。</p><p>我推荐的实践顺序是这样的：所有项目第一步先给根 CLAUDE.md 瘦身，拆出去的流程丢进 Skills，跨目录的约束用 path-scoped Rules，必须 100% 执行的规则用 Hooks 做约束。然后在日常使用中持续观察、持续迭代修改，如果发现有的指令被忽略了，那大概率是相关的指令放错了层级。</p><p>上下文窗口就那么大，每一行指令都有成本。把对的指令放在对的层级，比写更多指令管用得多。</p><hr><p>原文：Steering Claude Code: skills, hooks, subagents and more<a href="https://www.anthropic.com/engineering/claude-code-best-practices">https://www.anthropic.com/engineering/claude-code-best-practices</a></p><hr><p>欢迎长按下面的二维码关注<strong>Feisky</strong> 公众号，了解更多云原生和 AI 知识。</p><p><img src="/images/mp.png" alt="Feisky 公众号二维码" loading="lazy" decoding="async"/></p>
]]></content:encoded><dc:extent>9 min read</dc:extent></item></channel></rss>