<?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>Harness | Feisky</title><link>https://feisky.xyz/tags/harness/</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/harness/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><item><title>Claude Code 在大型代码库里到底怎么用？Anthropic 给出了官方答案</title><link>https://feisky.xyz/posts/2026-05-16-claude-code-large-codebase/</link><pubDate>Sat, 16 May 2026 10:00:00 +0800</pubDate><dc:creator>Pengfei Ni</dc:creator><category>Claude Code</category><category>Anthropic</category><category>大型代码库</category><category>Harness</category><category>AI 编程</category><guid>https://feisky.xyz/posts/2026-05-16-claude-code-large-codebase/</guid><description>&lt;blockquote&gt;
&lt;p&gt;题记：本文编译自 Anthropic 工程团队官方博客《How Claude Code Works in Large Codebases: Best Practices and Where to Start》，原文链接：&lt;a href="https://claude.com/blog/how-claude-code-works-in-large-codebases-best-practices-and-where-to-start"&gt;https://claude.com/blog/how-claude-code-works-in-large-codebases-best-practices-and-where-to-start&lt;/a&gt;。本文在翻译基础上做了整理和补充。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Claude Code 在小项目里用着真挺丝滑的，基本上你碰到的问题它都能帮你解决。&lt;/p&gt;</description><content:encoded>&lt;![CDATA[<blockquote><p>题记：本文编译自 Anthropic 工程团队官方博客《How Claude Code Works in Large Codebases: Best Practices and Where to Start》，原文链接：<a href="https://claude.com/blog/how-claude-code-works-in-large-codebases-best-practices-and-where-to-start">https://claude.com/blog/how-claude-code-works-in-large-codebases-best-practices-and-where-to-start</a>。本文在翻译基础上做了整理和补充。</p></blockquote><p>Claude Code 在小项目里用着真挺丝滑的，基本上你碰到的问题它都能帮你解决。</p><p>不过一旦搬到大代码库，体验就开始打折扣。让它查找一个函数，grep 出来上千条匹配，你的上下文空间直接就被淹没了；改一个子服务，它非要跑全项目的测试用例，跑就跑吧还动不动超时偷懒，有时甚至自作聪明顺手改了一堆不该改的代码。</p><p>你在大型代码库里使用 Claude Code 是不是也碰到过这些问题？反正我是经常碰到。</p><p>前两天 Anthropic 工程团队发了一篇官方博客 How Claude Code Works in Large Codebases: Best Practices and Where to Start），系统讲解了大型代码仓库中用好 Claude Code 的方法论，推荐所有 Claude Code 用户都读一读。</p><p>下面是逐节的翻译，每一节我加上了自己的注解。</p><h2 id="一claude-code-是怎么浏览代码的">一、Claude Code 是怎么浏览代码的</h2><p>Anthropic 博客一开头就讲了一个容易被忽略的事实：Claude Code 在大代码库里搜代码的方式，跟我们一直理解的 RAG 方式是完全不同的思路。</p><p>RAG 的做法是把整个代码库做 embedding，查询时检索相关片段。听起来挺合理的，但在大代码库里有个死结：embedding 流程追不上工程团队的提交速度。等你查询的时候，索引反映的是几天甚至几周前的代码，搜出来的可能是已经被重命名的函数，或者已经被删掉的模块。</p><p>Claude Code 走的是另一条路，叫 agentic search。它就像一个工程师那样找代码：遍历文件系统、读文件、grep 关键字、跟着 reference 跳转。所有动作都是实时的，不依赖任何索引。</p><p>这个差异不是技术孰优孰劣，而是适用场景不同。小到中型、变化没那么频繁的代码库，RAG 可能更快。但大代码库、活跃项目、频繁重构这些场景，agentic 是唯一靠谱的方式。</p><p>要用好 agentic search 也有它的前提：你的代码库得让 Claude Code 快速定位到具体的位置。如果目录命名混乱、没有 README、没有任何线索告诉它从哪开始看，再聪明的模型也得绕远路遍历大量无关文件，导致上下文空间被白白浪费。后面 Anthropic 讲的所有最佳实践，本质都是在解决这个问题。</p><h2 id="二harness-比模型更重要">二、harness 比模型更重要</h2><p>Anthropic 在原文里给了一个清单，列出了塑造 Claude Code 能力的 harness 七件套：</p><ul><li>CLAUDE.md</li><li>Hooks</li><li>Skills</li><li>Plugins</li><li>LSP</li><li>MCP servers</li><li>Subagents</li></ul><p>这七件套加起来，决定了同样的模型在你手里跑出来是什么效果。</p><p>我自己的体验跟这个清单完全一致。同样是 Claude Opus 4.6 模型，裸装 Claude Code 写代码，跟调好 CLAUDE.md 、装备 subagent 、配上 skills 之后相比，效果不是一个量级的。</p><p>这跟之前 Anthropic 在 Harness 设计那篇文章（《<a href="https://mp.weixin.qq.com/s/6AexM5_VngU1KDcYCU7gaA">为什么单 Agent 搞不定复杂应用</a>》）里讲的逻辑是一致的：模型能力决定了天花板，harness 决定了你能走到天花板的多少。差的 harness 把模型能力浪费一大半都不夸张。</p><p>下面把这七件套一个一个聊聊。</p><h2 id="三claudemd分层是最大的杠杆">三、CLAUDE.md：分层是最大的杠杆</h2><p>CLAUDE.md 是每个会话启动时自动加载的上下文文件。Claude Code 会从当前目录往上一直走到根目录，把每一层的 CLAUDE.md 都读进来。</p><p>这个加载机制是叠加的，所以分层非常关键。Anthropic 给的原则是：根 CLAUDE.md 只放指针和关键注意事项。</p><p>Anthropic 还给了几条特实用的具体建议：</p><p>第一，给子目录创建 CLAUDE.md，而不是只是在根目录里。Claude 自动会往上走，所以你启动它的时候 cd 到任务相关的子目录，加载到的上下文最聚焦。</p><p>第二，lint 和 test 命令按子目录配置。改一个子服务却跑全项目的 test，是大代码库里最常见的浪费。耗时耗力不说，跑出来的输出信息还容易把 context 全淹了。子目录的 CLAUDE.md 应该写清楚“在这个目录下，跑测试用 X，跑 lint 用 Y”。</p><p>第三，用<code>.ignore</code> 文件（ripgrep 的标准 ignore 格式）排除生成目录、build 产物、第三方代码这些噪音，同时把<code>permissions.deny</code> 规则写到<code>.claude/settings.json</code> 里。后者会跟着 git 一起 commit 出去，团队每个人都自动生效，不用各自配。如果某些开发者就是要碰生成目录，可以在自己的本地 settings 里覆盖项目级规则，不影响其他人。</p><p>第四，如果你的代码库就是没有传统目录结构，那写一个 codebase map：根目录放一个简短的 markdown 文件，列出顶层目录每个是干嘛的，一句话描述，给 Claude Code 一个目录索引。</p><p>这一节是整篇文章里最值得反复读的。CLAUDE.md 调好，其他六件套的价值才能放出来。</p><h2 id="四hooks让你的-setup-自我进化">四、Hooks：让你的 setup 自我进化</h2><p>Hooks 是绑定在事件上的脚本。Stop hook 在 session 结束时跑，Start hook 在开始时跑，另外还有 PreToolUse、PostToolUse 这些。</p><p>Anthropic 给了三个典型用法：</p><p>第一个是 Stop hook 可以让 Claude 自己回顾这个 session，分析有什么经验值得沉淀，然后主动提议更新 CLAUDE.md。这其实是把 self-improvement 自动化了，让其越用越聪明。</p><p>第二个是 Start hook 可以根据当前路径或者当前用户动态加载团队特定的上下文。比如你今天在前端目录，自动加载 UI 团队的约定；明天切到后端目录，自动换成后端的那一套。每个开发者就不用手动维护自己模块的 setup 了。</p><p>第三个是强制规则用 hook 而不是 prompt。比如自动跑 lint、提交前必须过 typecheck、危险命令拦截，这些都很适合。Prompt 是建议，hook 是约束，能用 hook 就别只写在 prompt 里。这点跟我自己的体感完全一样：让模型自觉其实远不如代码里拦住它来得靠谱。</p><p>在我看来，Hooks 是 Claude Code 里最被低估的扩展点，配置门槛比 skill 低，杀伤力却大。建议先把基础 hook 配上，再去考虑其他扩展。</p><h2 id="五skills-和-plugins把好东西散播开">五、Skills 和 Plugins：把好东西散播开</h2><p>Skills 解决的是“专业能力按需出现”的问题。</p><p>大代码库里任务类型几十上百种，每个 session 都把所有能力塞进上下文是不现实的。Skills 用的是 progressive disclosure 的思路：能力描述常驻 context，具体内容只有用到才加载。这次 Anthropic 还提了一个进阶用法，skill 可以按路径 scope，只在特定子目录激活，避免无关 skill 互相打架。</p><p>说实话，写好一个 skill 门槛其实不低。Anthropic 之前专门写过一篇（《<a href="https://mp.weixin.qq.com/s/k_BmfjCByVE2HJz7nqtXRw">写好一个 Skill 有多难</a>》），踩了几百个坑才总结出来一套规则。这次大代码库文档里强调的“按路径 scope”算是新增的进阶建议。</p><p>Plugins 解决的是“好配置散播开”的问题。</p><p>大代码库里最常见的一个现象是：少数几个老员工把 skill、hook、MCP 配置摸透了用得很爽，新人入职完全不知道有这些东西。这种 tribal knowledge 进不了生产力分布，对组织来说是很可惜的。</p><p>Plugin 把 skill、hook、MCP server 打包成一个安装包，新人一条命令装完就跟老员工同样的能力。我自己开源过两个仓库（<a href="https://github.com/feiskyer/claude-code-settings">claude-code-settings</a> 和<a href="https://github.com/feiskyer/codex-settings">codex-settings</a>），初衷就是这个：把自己折腾出来的配置整理出来，让别人不用再走一遍弯路。</p><p>升级路径也是 plugin 的优势。所有人都装同一个 plugin，你修了一个 skill 的 bug，下一次更新所有人都拿到。靠口口相传根本做不到这种分发。</p><h2 id="六lsp从-grep-到-symbol">六、LSP：从 grep 到 symbol</h2><p>这一段可能是文档里最技术、但也最实用的一节。</p><p>Claude Code 默认搜代码靠 grep。grep 在小代码库还行，到了大代码库就是个灾难：你搜一个<code>getUser</code>，可能返回上千个匹配，分布在几百个文件里。Claude 为了搞清楚到底是哪个，得一个个打开看，context 瞬间被烧光。</p><p>LSP（Language Server Protocol）是编程 IDE 早就已经在用的东西。它知道你这个<code>getUser</code> 是哪个 class 的方法、有哪些 reference、定义在哪、被谁调用。把 LSP 的能力转给 Claude Code，搜索就从字符串变成了符号。</p><p>实际效果差距可能是几十倍。同一个查询，grep 返回的是上千条文本匹配，LSP 返回的可能只有几条，并且每一条都是真正引用这个符号的位置。Claude 不用再去打开一堆无关文件，context 也省下来了。</p><p>这个适用前提是你的语言有靠谱的 LSP，对 Go、TypeScript、Java、Python、Rust 这些主流语言都没问题。脚本类语言可能稍微弱一些。</p><h2 id="七mcp-和-subagent扩展和隔离">七、MCP 和 Subagent：扩展和隔离</h2><p>MCP server 主要是让 Claude 接入它本来够不到的那些东西：内部工具、私有 API、文档系统等等。我之前在《<a href="https://mp.weixin.qq.com/s/rLwm5v3IFRP7UcOarfqEZg">MCP 不只是开发工具</a>》里聊过生产级 MCP 怎么搭，这里就不展开了。</p><p>这次有个新的角度挺值得提：专门写一个 MCP server，把代码库的结构化搜索包装成 Claude 可以直接调用的工具。比如“查找所有 implements 这个 interface 的 class”、“查找所有调用这个 deprecated API 的地方”。这类查询用 grep 做不到，用 LSP 部分能做，但用专用 MCP 是最干净的。</p><p>Subagent 这个我想专门聊一下，因为是我用得最多的一个。</p><p>简单来说，Subagent 就是一个独立的 Claude Code 实例，有自己的 context window，接到任务、做完工作、只把最终结果返回给主 agent。</p><p>我用 Subagent 用得最多的场景就是 explore/edit 拆分。让一个 read-only 的 Explore subagent 先去摸目录、读文件、画出系统结构，写到一个文件里。主 agent 拿到这份报告，再带着完整图景去改代码。</p><p>为什么不让主 agent 自己 explore 自己 edit？因为 explore 阶段会读几十个文件，每个文件成百上千行，主 context 很快就被这些读取结果污染了。等到要写代码的时候，模型注意力已经分散在大量无关的细节上。</p><p>把 explore 隔离到 subagent 里，主 agent 只拿到一份精炼的总结，相当于拿到一张地图开始施工，而不是边挖边迷路。这跟之前讲上下文管理那篇文章（《<a href="https://mp.weixin.qq.com/s/ihzAIlFQZCe7AlvjLQfeCw">Claude Code 作者亲授：百万 token 上下文的正确用法</a>》）里“Subagent 本质上是上下文管理工具”的说法完全一致。</p><h2 id="八配置随模型升级要瘦身">八、配置随模型升级要瘦身</h2><p>这是整篇文档里我觉得最容易被忽视的一节。</p><blockquote><p>为旧模型写的指令，可能反过来限制新模型。</p></blockquote><p>模型在不停升级。你为 Sonnet 4.5 写的 CLAUDE.md 提示、为修补当时模型缺陷加的 hook、为绕过当时上下文管理 bug 写的 skill，到了 Opus 4.7 可能不仅没用，反而成了限制。</p><p>我自己有个真实例子。早期我在根 CLAUDE.md 里加了一段“请先列出所有计划再执行”，那是因为当时模型容易跳步。等模型升级后，规划能力本来就有了，这条提示反而让 Claude 每次都先输出一段冗长的计划，效率反而降了。</p><p>Anthropic 的建议是每 3 到 6 个月，或者每次大版本发布后，专门 review 一次 harness 配置：哪些规则还有意义、哪些已经过时、哪些 hook 可以删、哪些 skill 可以合并。</p><p>这个习惯在传统工程里叫技术债清理，放到 harness 上同样适用。CLAUDE.md 跟代码注释一样会腐烂，你不主动清，它就慢慢变成噪音。</p><h2 id="九组织准备driagent-manager跨职能工作组">九、组织准备：DRI、agent manager、跨职能工作组</h2><p>最后一节是组织层面的，大公司读者可能更关心。</p><p>Anthropic 观察到一个规律：Claude Code 推广最顺利的组织，都是在大规模铺开之前先做了一波基础设施建设。少数几个早期采用者负责把 plugin 库搭起来、把 MCP 接好、把 CLAUDE.md 模板写出来，然后才让全员上手。</p><p>新出现的一个角色叫 agent manager，是 PM + 工程师的混合角色，专门管理 Claude Code 生态。如果团队没这么奢侈，最起码也要有一个 DRI（Directly Responsible Individual），管 plugin marketplace、管 CLAUDE.md 约定、管 settings 决策。</p><p>问题是，光靠工程师自下而上的热情其实不够。热情会催生很多个人配置，但散乱、重复、互相冲突。这种时候需要有人来收口。</p><p>大公司还有一层是治理。安全、合规、代码审查流程要早立工作组。原文这点是比较国际化的语境，搬到中国团队还要再加上数据出境、审查留痕，以及敏感行业（金融、政务）的额外要求。这些事情早做比晚做要少很多痛苦。</p><p>哪怕你是个人开发者或者小团队，把配置维护这件事当成一个明确的责任分配下来，也比“大家都用一下吧”要有效得多。</p><h2 id="写在最后">写在最后</h2><p>正如 Claude Code 一直在持续不停迭代一样，要用好 Claude Code 的 harness 配置也不是一次配好就一劳永逸的，也需要随着模型迭代一起进化。CLAUDE.md、Hooks、Skills、MCP、LSP、Subagent，每个配置存在的理由都要定期审视，不能因为它已经在那就让它一直在那。</p><p>我自己的实践顺序是这样的：所有项目第一步先创建 CLAUDE.md（包括核心子目录中的 CLAUDE.md），然后再根据需要在项目的 .claude 里面配置所需要的 Hook、MCP 和 Skills，然后就可以用 Claude Code 玩起来了。之后在根据实际需要调整优化，并提醒 Claude Code 把经常出错的地方存入它的 Memory。</p><hr><p>相关资源：</p><ul><li>原文：<a href="https://claude.com/blog/how-claude-code-works-in-large-codebases-best-practices-and-where-to-start">https://claude.com/blog/how-claude-code-works-in-large-codebases-best-practices-and-where-to-start</a></li><li>Harness 设计前作：<a href="https://mp.weixin.qq.com/s/6AexM5_VngU1KDcYCU7gaA">为什么单 Agent 搞不定复杂应用</a></li><li>上下文管理：<a href="https://mp.weixin.qq.com/s/ihzAIlFQZCe7AlvjLQfeCw">Claude Code 作者亲授：百万 token 上下文的正确用法</a></li><li>Skill 写作经验：<a href="https://mp.weixin.qq.com/s/k_BmfjCByVE2HJz7nqtXRw">写好一个 Skill 有多难</a></li><li>我的 Claude Code 配置：<a href="https://github.com/feiskyer/claude-code-settings">feiskyer/claude-code-settings</a></li></ul><hr><p>欢迎长按下面的二维码关注<strong>Feisky</strong> 公众号，了解更多云原生和 AI 知识。</p><p><img src="/images/mp.png" alt="Feisky 公众号二维码" loading="lazy" decoding="async"/></p>
]]></content:encoded><dc:extent>10 min read</dc:extent></item></channel></rss>