你不知道的 Claude Code:架构、治理与工程实践

你不知道的 Claude Code:架构、治理与工程实践

今天这篇文章源于最近半年深度使用 Claude Code、两个账号每月 40 刀氪金换来的一些踩坑经验,希望能给大伙一些输入。

刚开始我也把它当 ChatBot 用,后来很快发现不对劲:上下文越来越乱、工具越来越多但效果越来越差、规则越写越长却越不遵守,折腾了一段时间,研究了 Claude Code 本身之后才意识到,这不是 Prompt 问题,而是这套系统的设计就是这样的。

这篇文章想和大伙聊聊这几个事:Claude Code 底层怎么运作、上下文为什么会乱以及怎么治理、Skills 和 Hooks 应该怎么设计、Subagents 的正确用法、Prompt Caching 的架构影响,以及怎么写一个真正有用的 CLAUDE.md。

我觉得最直接的理解方式,是把 Claude Code 拆成六层来看:

层 职责 / rules / memory 长期上下文,告诉 Claude “是什么” / 动作能力,告诉 Claude “能做什么” 按需加载的方法论,告诉 Claude “怎么做” 强制执行某些行为,不依赖 Claude 自己判断 隔离上下文的工作者,负责受控自治

claude code 教程
验证闭环,让输出可验、可回滚、可审计

只强化其中一层,系统就会失衡,CLAUDE.md 写太长,上下文先污染自己了;工具堆太多了,选择就搞不清楚了;subagents 开得到处都是,状态就漂移了;验证这步跳过了,出了问题根本不知道是哪里挂的。


Agent Loop

Claude Code 的核心不是”回答”,而是一个反复循环的代理过程:

用了一段时间才意识到,卡住的地方几乎从来不是模型不够聪明,更多时候是给了它错误的上下文,或者写出来了但根本没法判断对不对,也没法撤回。

层面 核心问题 主要载体 哪些信息常驻,哪些按需加载 、rules、memory、skills Claude 当前具备哪些动作能力 built-in tools、MCP、plugins 哪些动作必须被约束、阻断或审计 permissions、sandbox、hooks 哪些任务需要隔离上下文和权限 subagents、worktrees、forked sessions 如何判断任务完成且结果可信 tests、lint、screenshots、logs、CI

对着这几个面看,很多问题就好排查了。结果不稳定,查上下文加载顺序,不是模型的事;自动化失控,看控制层有没有设计,不是 agent 太主动;长会话质量下降,中间产物把上下文污染了,换个新会话比反复调 prompt 有用得多。


概念 运行时角色 解决什么 典型误用 项目级持久契约 每次会话都必须成立的命令、边界、禁止项 写成团队知识库 路径或语言相关规则 目录、文件类型或语言级局部规范 所有规则都堆到根 内置能力 读文件、改文件、跑命令、搜索 把所有集成都塞进 shell 外部能力接入协议 让 Claude 访问 GitHub、Sentry、数据库 接太多 server,工具定义挤爆上下文 打包分发层 把 Skills/Hooks/MCP 一起分发 把 plugin 当成运行时 primitive 按需加载的知识/工作流 给 Claude 一个”方法包” skill 既像百科全书又像部署脚本 强制执行规则的拦截层 在生命周期事件前后执行规则 用 hook 替代所有模型判断 隔离上下文的工作单元 并行研究、限制工具与权限 无边界 fan-out,治理失控

简单记:给 Claude 新动作能力用 Tool/MCP,给它一套工作方法用 Skill,需要隔离执行环境用 Subagent,要强制约束和审计用 Hook,跨项目分发用 Plugin。


很多人把上下文当”容量问题”,但卡住的地方通常不是不够长,而是太吵了,有用的信息被大量无关内容淹没了。

Context Loading

Claude Code 的 200K 上下文并非全部可用:

你不知道的 Claude Code:架构、治理与工程实践

一个典型 MCP Server(如 GitHub)包含 20-30 个工具定义,每个约 200 tokens,合计 4,000-6,000 tokens。接 5 个 Server,光这部分固定开销就到了 25,000 tokens(12.5%)。我第一次算出这个数字的时候,真没想到有这么多,在要读大量代码的场景,这 12.5% 真的很关键。

说白了,偶尔用的东西就不要每次都加载进来。

  • 保持 短、硬、可执行,优先写命令、约束、架构边界。Anthropic 官方自己的 CLAUDE.md 大约只有 2.5K tokens,可以参考
  • 把大型参考文档拆到 Skills 的 supporting files,不要塞进 SKILL.md 正文
  • 使用 做路径/语言规则,不让根 承担所有差异
  • 长会话主动用 观察消耗,不要等系统自动压缩后再补救

/context 命令输出,可以看到各来源的 token 占比

  • 任务切换优先 ,同一任务进入新阶段用
  • 把 Compact Instructions 写进 CLAUDE.md,压缩后必须保留什么由你控制,不由算法猜

Session Continuity

默认压缩算法按”可重新读取”判断,早期的 Tool Output 和文件内容会被优先删掉,顺带把架构决策和约束理由也一起扔了。两小时后再改,可能根本不记得两小时前定了什么,莫名其妙的 Bug 就是这么来的。

解决方案就是在 CLAUDE.md 里写明:

除了写 Compact Instructions,还有一种更主动的方案:在开新会话前,先让 Claude 写一份 HANDOFF.md,把当前进度、尝试过什么、哪些走通了、哪些是死路、下一步该做什么写清楚。下一个 Claude 实例只读这个文件就能接着做,不依赖压缩算法的摘要质量:

在 HANDOFF.md 里写清楚现在的进展。解释你试了什么、什么有效、什么没用,让下一个拿到新鲜上下文的 agent 只看这个文件就能继续完成任务。

写完后快速扫一眼,有缺漏直接让它补,然后开新会话,把 HANDOFF.md 的路径发过去就行。

你不知道的 Claude Code:架构、治理与工程实践

Plan Mode 的核心是把探索和执行拆开,探索阶段不动文件,确认方案后再执行:

  • 探索阶段以只读操作为主
  • Claude 可以先澄清目标和边界,再提交具体方案
  • 执行成本在计划确认之后才发生

你不知道的 Claude Code:架构、治理与工程实践

对于复杂重构、迁移、跨模块改动,这样做比”急着出代码”有用多了,它能显著降低在错误假设上持续修改的概率。按两下 进入 Plan Mode,进阶玩法是开一个 Claude 写计划,再开一个 Codex 以”高级工程师”身份审这个计划,让 AI 审 AI,效果很好


Skill 官方描述是”按需加载的知识与工作流”,描述符常驻上下文,完整内容按需加载,用起来和”保存的 Prompt”差别挺大的。

  • 描述要让模型知道”何时该用我”,而不是”我是干什么的”,这两个差很多
  • 有完整步骤、输入、输出和停止条件,别写了个开头没有结尾
  • 正文只放导航和核心约束,大资料拆到 supporting files 里
  • 有副作用的 Skill 要显式设置 ,不然 Claude 会自己决定要不要跑

Claude Code 团队在内部设计中反复强调 “progressive disclosure”,意思不是让模型一次性看到所有信息,而是先获得索引和导航,再按需拉取细节:

  • 负责定义任务语义、边界和执行骨架
  • supporting files 负责提供领域细节
  • 脚本负责确定性收集上下文或证据

一个比较稳定的结构长这样:

下面几个例子都来自我在开源 terminal 项目 Kaku 里的实际 Skill,比较直观。

类型一:检查清单型(质量门禁)

发布前跑一遍,确保不漏项:

类型二:工作流型(标准化操作)

配置迁移高风险,显式调用 + 内置回滚步骤:

类型三:领域专家型(封装决策框架)

运行时出问题时让 Claude 按固定路径收集证据,不要瞎猜:

每个启用的 Skill,描述符常驻上下文。优化前后差距很大:

还有一个很重要的 使用策略:

  • 高频(>1 次/会话)→ 保持 auto-invoke,优化描述符
  • 低频(<1 次/会话)→ disable-auto-invoke,手动触发,描述符完全脱离上下文
  • 极低频(<1 次/月)→ 移除 Skill,改为 AGENTS.md 中的文档
  • 描述过短:(任何后端工作都能触发,哈哈)
  • 正文过长:几百行工作手册全塞进 SKILL.md 正文
  • 一个 Skill 覆盖 review、deploy、debug、docs、incident 五件事
  • 有副作用的 Skill 允许模型自动调用

我后面越用越觉得,给 Claude 的工具和给人写的 API 不是一回事。给人用的 API 往往会追求功能齐全,但给 agent 用,重点不是功能堆得多完整,而是让它更容易用对。

维度 好工具 坏工具 名称 , , , 参数 , , , , 返回 与下一步决策直接相关的信息 一堆 UUID、内部字段、原始噪声 规模 单一目标,边界清楚 多个动作混杂,副作用不透明 成本 默认输出受控、可截断 默认返回过大上下文 错误信息 包含修正建议 仅返回 opaque error code

几个实用设计原则:

  • 名称前缀按系统或资源分层:、
  • 对大响应支持
  • 错误响应要教模型如何修正,不要只抛 opaque error code
  • 能合并成高层任务工具时,不要暴露过多底层碎片工具,避免 让模型自行筛选

Finding the sweet spot

我看到 Claude Code 团队内部工具的这段演进时,感觉还挺有意思。像这种需要在任务中途停下来问用户的场景,他们前后试了三种做法:

  • 第一版:给已有工具(如 Bash)加一个 参数,让 Claude 在调用工具时顺带提问。结果 Claude 大多数时候直接忽略这个参数,继续往下跑,根本不停下来问。
  • 第二版:要求 Claude 在输出里写特定 markdown 格式,外层解析到这个格式就暂停。问题是没有强制约束,Claude 经常”忘了”按格式写,提问逻辑非常脆弱。
  • 第三版:做成独立的 工具。Claude 想提问就必须显式调用它,调用即暂停,没有歧义。效果显著好于前两版。

下面这张图刚好能解释,为什么第三版明显更稳:

Improving Elicitation & the AskUserQuestion tool

左边(markdown 自由输出)太松,模型格式随意、外层解析脆弱;右边(ExitPlanTool 参数)太死,等到退出计划阶段提问已经太晚; 独立工具落在中间,结构化且随时可调用,是这三者里最稳定的设计。

说白了,既然你就是要 Claude 停下来问一句,那就直接给它一个专门的工具。加个 flag 或者约定一段输出格式,很多时候它一顺手就略过去了。

Todo 工具的演进

Updating with Capabilities - Tasks & Todos

早期用 TodoWrite 工具 + 每 5 轮插入提醒让 Claude 记住任务。随着模型变强,这个工具反而成了限制,Todo 提醒让 Claude 认为必须严格遵循,无法灵活修改计划。挺有意思的教训:当初加这个工具是因为模型不够强,模型变强之后它反而变成了枷锁。值得过段时间回来检查一下,当初加的限制还成不成立。

搜索工具的演进:最初用 RAG 向量数据库,虽然快但需要索引、不同环境脆弱,最重要的是 Claude 不喜欢用。改成 Grep 工具让 Claude 自己搜索后,效果显著提升。后来又发现一个顺带的好处:Claude 读 Skill 文件,Skill 文件又引用其他文件,模型会递归读取,按需发现信息,不需要提前塞进去,这个模式后来被叫做”渐进式披露”。

  • 本地 shell 可以可靠完成的事情
  • 模型只需要静态知识,不需要真正与外部交互
  • 需求更适合 Skill 的工作流约束,而不是 Tool 的动作能力
  • 还没验证过工具描述、schema 和返回格式能被模型稳定使用

Hooks 很容易被当成”自动运行的脚本”,但我自己用下来,觉得它更像是把一些不能交给 Claude 临场发挥的事情,重新收回到确定性的流程里。

比如格式化要不要跑、保护文件能不能改、任务完成后要不要通知,这些事真不要指望 Claude 每次都自己记得。

Hooks 配置界面

适合:阻断修改受保护文件、Edit 后自动格式化/lint/轻量校验、SessionStart 后注入动态上下文(Git 分支、环境变量)、任务完成后推送通知。

不适合:需要读大量上下文的复杂语义判断、长时间运行的业务流程、需要多步推理和权衡的决策,这些该在 Skill 或 Subagent 里。

Hooks 在执行过程中的介入点

在 100 次编辑的会话中,每次节省 30-60 秒,累积节省 1-2 小时,还挺可观的。注意限制输出长度(),避免 Hook 输出反而污染上下文。

  • :声明”提交前必须通过测试和 lint”
  • :告诉 Claude 在什么顺序下运行测试、如何看失败、如何修复
  • :对关键路径执行硬性校验,必要时阻断

用下来感觉,三样少任何一层都会有漏洞。只写 CLAUDE.md 规则,Claude 经常当没看见;只靠 Hooks,细节判断又做不了,放在一起才比较稳。


Subagent 就是从主对话派出去的一个独立 Claude 实例,有自己的上下文窗口、只用你指定的工具、干完汇报结果。核心价值不是”并行”,而是隔离,扫代码库、跑测试、做审查这类会产生大量输出的事,交给 Subagent 做,主线程只拿摘要,不会被中间过程污染。Claude Code 内置了 Explore(只读扫库,跑 Haiku 省成本)、Plan(规划调研)、General-purpose(通用),也可以自定义。

  • / :限定能用什么工具,别给和主线程一样宽的权限
  • :探索任务用 Haiku/Sonnet,重要审查用 Opus
  • :防止跑飞
  • :需要动文件时隔离文件系统

另一个实用细节:长时间运行的 bash 命令可以按 移到后台,Claude 之后会用 BashOutput 工具查看结果,不会阻塞主线程继续工作。subagent 同理,直接告诉它「在后台跑」就行。

  • 子代理权限和主线程一样宽,隔离没有意义
  • 输出格式不固定,主线程拿到没法用
  • 子任务之间强依赖,频繁要共享中间状态,这种情况用 Subagent 不合适

这块我之前在很多教程里都没怎么看到有人展开讲,但它其实很影响 Claude Code 的成本结构和很多设计取舍。

工程界有句话 “Cache Rules Everything Around Me”,对 agent 同样如此,Claude Code 的整个架构都是围绕 Prompt 缓存构建的,高缓存命中率不只降低成本,也帮助创造更宽松的速率限制,Anthropic 甚至会对命中率运行告警,太低直接宣布 SEV。

Lay Out Your Prompt for Caching

Prompt 缓存是按前缀匹配工作的,从请求开头到每个 断点之前的内容都会被缓存。所以这里的顺序很重要:

破坏缓存的常见陷阱:

  • 在静态系统 Prompt 中放入带时间戳的内容(让它每次都变)
  • 非确定性地打乱工具定义顺序
  • 会话中途增删工具

那像当前时间这种动态信息怎么办?别去动系统 Prompt,放到下一条消息里传进去就行。Claude Code 自己也是这么做的,用户消息里加 标签,系统 Prompt 不动,缓存也就不会被打坏。

Prompt 缓存是模型唯一的。假如你已经和 Opus 对话了 100K tokens,想问个简单问题,切换到 Haiku 实际上比继续用 Opus 更贵,因为要为 Haiku 重建整个缓存。确实需要切换的话,用 Subagent 交接:Opus 准备一条”交接消息”给另一个模型,说明需要完成的任务就行。

Forking Context — Compaction

上图是 Compaction(上下文压缩)的执行流程:左边是上下文快满时的状态,中间是 Claude Code 开一个 fork 调用,把完整对话历史喂给模型,加一句”Summarize this conversation”,这一步命中缓存所以只需 1/10 的价格,右边是压缩完之后,原来几十轮对话被替换成一段 ~20k tokens 的摘要,System + Tools 还在,再挂上之前用到的文件引用,腾出空间继续新的轮次。

直觉上 Plan Mode 应该切换成只读工具集,但这会破坏缓存。实际实现是: 是模型可以自己调用的工具,检测到复杂问题时自主进入 plan mode,工具集不变,缓存不受影响。

Claude Code 有数十个 MCP 工具,每次请求全量包含会很贵,但中途移除会破坏缓存。解决方案是发送轻量级 stub,只有工具名,标记 。模型通过 ToolSearch 工具”发现”它们,完整的工具 schema 只在模型选择后才加载,这样缓存前缀保持稳定。


「Claude 说完成了」其实没啥用,你得能知道它做没做对、出了问题能退回来、过程还能查,这才算数。

  • 最低层:命令退出码、lint、typecheck、unit test
  • 中间层:集成测试、截图对比、contract test、smoke test
  • 更高层:生产日志验证、监控指标、人工审查清单

写任务 Prompt 或 Skill 的时候,最好把验收标准提前说清楚。哪些命令跑完算完成,失败了先查什么,截图和日志看到什么才算过,这些越早讲明白,后面越省事。

我自己有个很简单的判断:假如一个任务你都说不清楚「Claude 怎么才算做对了」,那它大概率也不适合直接丢给 Claude 自动完成。


这些命令说白了就干一件事:主动管理上下文,别等系统自己处理。

/mcp 连接状态,可以看到各 server 的工具数量和 token 消耗

:对刚改完的代码做三维检查,代码复用、质量和效率,发现问题直接修掉。特别适合改完一段逻辑后立刻跑一遍,代替手动 review。

:不是”撤销”,而是回到某个会话 checkpoint 重新总结。适合:Claude 已沿错误路径探索太久;想保留前半段共识但丢掉后半段失败。

:在不打断主任务的前提下快速问一个侧问题,适合”两个命令有什么区别”这类单轮旁路问答,不适合需要读仓库或调用工具的问题。

:实时 JSON 事件流,适合长任务监控、增量处理、流式集成到自己的工具。

:让 Claude 分析当前会话,提炼出哪些内容值得沉淀到 CLAUDE.md。用法是会话做了一段之后跑一次,它会指出”这个约定你们反复提到,但没有写进契约”之类的盲点,是迭代优化 CLAUDE.md 的好手段。

双击 ESC 回溯:按两次 ESC 可以回到上一条输入重新编辑,不用重新手打。Claude 走偏了、或者上一句话没说清楚,双击 ESC 修改后重发,比重新开会话省事得多。

对话历史都在本地:所有会话记录存放在 下,文件夹名按项目路径命名(斜杠变横杠),每个会话是一个 文件。想找某个话题的历史,直接 就能定位,或者直接告诉 Claude「帮我搜一下之前关于 X 的讨论」,它会自己去翻。


在我看来更像是你和 Claude 之间的协作契约,不是团队文档,也不是知识库,里面只放那些每次会话都得成立的事。

我自己的建议其实很简单,一开始甚至可以什么都不写。先用起来,等你发现自己老是在重复同一件事,再把它补进去。加法也不复杂,输入 可以把当前对话里的内容直接追加进 CLAUDE.md,或者直接告诉 Claude「把这条加到项目的 CLAUDE.md 里」,它会知道该改哪个文件。

Keep it simple

  • 怎么 build、怎么 test、怎么跑(最核心)
  • 关键目录结构与模块边界
  • 代码风格和命名约束
  • 那些不明显的环境坑
  • 绝对不能干的事(NEVER 列表)
  • 压缩时必须保留的信息(Compact Instructions)
  • 大段背景介绍
  • 完整 API 文档
  • 空泛原则,如”写高质量代码”
  • Claude 通过读仓库即可推断的显然信息
  • 大量背景资料和低频任务知识(这些放到 Skills)

用起来其实不复杂:每次都要知道的放 CLAUDE.md,只对部分文件生效的放 rules,只在某类任务中需要的放 Skills。

我最喜欢的一个技巧:每次纠正 Claude 的错误后,让它自己更新 CLAUDE.md:

“Update your CLAUDE.md so you don’t make that mistake again.”

Claude 在给自己补这类规则时其实还挺好用,用久了确实越来越少犯同样的错。不过也要定期 review,时间一长总会有些条目慢慢过时,当初有用的限制现在未必还适合,这件事后面第 14 节有个更系统的做法。


春节放假时,我用 Claude Code 做了一个开源 terminal 项目 Kaku,底层是 Rust + Lua,也带了一些 AI 能力。混合语言加上自定义配置系统,实际折腾下来反而暴露出不少典型的 agent 协作问题,顺手聊几个对我帮助比较大的经验。

Claude Code 调用的都是真实的 shell、git、package manager 和本地配置。这里面只要有一层不透明,它就只能开始猜;一旦走到猜环境这一步,可靠性通常就会掉得很快。这其实也不只是 Claude Code 的问题,很多 agent 都一样。

所以我后来很快就在 terminal 里加了个 命令,把环境状态、依赖和配置情况先统一收上来,输出一份结构化的健康报告。Claude Code 开始做事前先跑一次 doctor,确实能省掉很多”环境没搞清楚就开干”的问题。

另外我还发现,假如 CLI 本身就有 、、 这类语义清楚的子命令,Claude Code 用起来会稳不少,比让它自己去猜配置文件怎么摆要靠谱。先把状态收敛住,再暴露编辑入口,顺序一反过来就很容易乱。

两套语言、两套检查,其实挺适合用 Hooks 按文件类型分别触发:

每次编辑完立刻知道有没有编译错误,比”跑了一堆才发现最开始就挂了”舒服得多。

假如有同学想给自己项目配一套比较完整的 Claude Code 工程布局,可以参考这个结构,不用全做,按需裁剪:

全局约束()、路径约束()、工作流()和架构细节完全解耦,Claude Code 的执行稳定性会显著上升。假如你同时维护多个项目,可以把稳定的个人基线放在 ,各项目的差异放在项目级 ,通过同步脚本分发,不同项目之间就不会互相污染了。


反模式 症状 修复 CLAUDE.md 当 wiki 每次加载污染上下文,关键指令被稀释 只保留契约,资料拆到 Skills 和 rules Skill 大杂烩 描述无法稳定触发,工作流冲突 一个 Skill 只做一类事,副作用显式控制 工具太多描述模糊 选错工具,schema 挤爆上下文 合并重叠工具,做明确 namespacing 没有验证闭环 Claude 只能”觉得自己完成了” 给每类任务绑定 verifier 过度自治 多 agent 并行无边界,出错难止损 角色/权限/worktree 最小化,明确 maxTurns 上下文不做切分 研究、实现、审查全堆在主线程,有效上下文被稀释 任务切换 ,阶段切换 ,重型探索交给 subagent(Explore → Main 模式) 自治范围过宽但治理不足 多 agent、外部工具全开,但缺乏权限边界和结果回收边界 permissions + sandbox + hooks + subagent 组合边界 已批准命令堆积不清理 里残留 等危险操作,一旦触发不可逆 定期审查 的 列表

基于文章里的六层框架,我把这套检查整理成了一个开源 Skill 项目 ,可以一键检查你的 Claude Code 配置现在处于什么状态。

装好之后在任意会话里跑 ,它会自动识别项目复杂度,对 、、、、 和实际行为模式各跑一遍检查,输出一份优先级报告:需要立刻修 / 结构性问题 / 可以慢慢做。

如果你读完这篇文章想知道自己的配置离这些原则差多远,跑一次 是最快的方式。


用 Claude Code 大概会经历三个阶段:

阶段 关注点 效率感知 工具使用者 “这个功能怎么用” 有帮助但有限 流程优化者 “如何让协作更顺”,开始写 CLAUDE.md 和 Skills 明显提升 系统设计者 “如何让 Agent 在约束下自主运作” 质变

到了第三阶段,关注点会悄悄变掉,从「这个功能怎么用」变成「怎么让 agent 在约束下自己跑起来」,两件事感觉差很多。

有一个问题挺值得想的:假如一个任务你说不清楚「什么叫做完」,那大概率也不适合直接扔给 Claude 自主完成,验证标准本身都没有,Claude 再聪明也跑不出正确答案。

这些是半年折腾下来的一些总结,肯定还有很多没有挖掘到的地方,如果大伙有用得更 6 的技巧,欢迎告诉我。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:Ai探索者,转载请注明出处:https://javaforall.net/274583.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月13日 上午10:14
下一篇 2026年3月13日 上午10:14


相关推荐

关注全栈程序员社区公众号