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

46 阅读13分钟

哈喽,大家好,我是蝈蝈。

这篇文章是基于 Tw93的一篇长推整理写作的。作者是开源 terminal 项目 Kaku 的作者,深度使用 Claude Code 超过半年,踩了相当多的坑之后,把对Claude Code最核心的判断和工程经验写了出来。

我把里面最有价值的部分提炼整理,分享给大家。


别把 Claude Code 当 ChatBot 用,它是一整套系统

很多人刚上手 Claude Code,第一反应是把它当一个更聪明的 ChatBot,给它发指令、让它写代码。Tw93 说他自己也经历过这个阶段,然后很快发现不对劲:上下文越来越乱、工具越堆越多但效果越来越差、规则越写越长 Claude 却越来越不遵守。

折腾了一段时间之后他才意识到,这不是 Prompt 写得不够好的问题,而是这套系统的设计本来就是这样的。

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

收集上下文 → 采取行动 → 验证结果 → 完成 or 回到收集

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

理解这一点,是用好 Claude Code 的前提。


上下文不是"容量问题",是"噪声问题"

这是整篇文章我认为最有价值的判断之一。大多数人把上下文当成一个容量桶,觉得 200K 已经很大了,够用。但 Tw93 指出,卡住的地方通常不是不够长,而是太吵了,有用的信息被大量无关内容淹没了。

Claude Code 的 200K 上下文,实际上并非全部可用。真实的成本构成大概是这样:

图片

  • 固定开销约 15~20K:

    系统指令约 2K、所有启用的 Skill 描述符约 15K、MCP Server 工具定义约 1020K、LSP 状态约 2~5K

  • 半固定约 5~10K:

    CLAUDE.md 约 25K、Memory 约 12K

  • 真正动态可用的只有约 160~180K:

    对话历史 + 文件内容 + 工具调用结果

其中最大的隐形杀手是 MCP 工具定义。一个典型的 MCP Server(比如 GitHub)包含 2030 个工具定义,每个约 200 tokens,合计 4,0006,000 tokens。接 5 个 Server,光这部分固定开销就到了 **25,000 tokens,占总上下文的 12.5%。**在要读大量代码的场景,这 12.5% 真的很关键。

图片

除了工具定义,Tool Output 同样是个隐形杀手。cargo test 一次完整输出动辄几千行,git log、``find、``grep 在稍大的仓库里也能轻松塞满屏幕。这些输出 Claude 并不需要全看,但只要出现在上下文里,就是实实在在的 token 消耗。

Tw93 推荐了一个叫 RTK(Rust Token Killer) 的开源工具,它做的事很简单:在命令输出到 Claude 之前自动过滤,只留决策需要的核心信息。比如 cargo test 跑完几千行,走 RTK 之后 Claude 看到的只是:

✓ cargo test: 262 passed (1 suite, 0.08s)

图片

Claude 真正需要知道的只是"过了or 挂了,挂在哪里",其他都是噪声。


上下文分层管理,是工程化的核心

理解了上下文的成本结构,管理思路就清晰了。作者给出了一套推荐的分层策略:

  • 始终常驻

    → CLAUDE.md:项目契约 / 构建命令 / 禁止事项

  • 按路径加载

    → rules:语言 / 目录 / 文件类型特定规则

  • 按需加载

    → Skills:工作流 / 领域知识

  • 隔离加载

    → Subagents:大量探索 / 并行研究

  • 不进上下文

    → Hooks:确定性脚本 / 审计 / 阻断

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

对于上下文管理,几个高频命令的工程意义也值得关注:/context 用来查看 token 占用结构,排查 MCP 和文件读取占比;任务切换优先用 /clear;同一任务进入新阶段用 /compact。长会话主动用 /context 观察消耗,不要等系统自动压缩后再补救。

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

图片

解决方案是在 CLAUDE.md 里写明 **Compact Instructions,**明确告诉 Claude 压缩时必须按优先级保留什么:架构决策第一、修改过的文件第二、当前验证状态第三、未完成的 TODO 第四,Tool Output 可以删但要保留 pass/fail 结论。

## Compact Instructions

When compressing, preserve in priority order:

1. Architecture decisions (NEVER summarize)
2. Modified files and their key changes
3. Current verification status (pass/fail)
4. Open TODOs and rollback notes
5. Tool outputs (can delete, keep pass/fail only)

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


Skills:不是模板库,是用时才加载的工作流

很多人把 Skill 当成"保存的 Prompt",但两者差别挺大。Skill 的描述符常驻上下文,完整内容只在需要时加载。描述要让模型知道"何时该用我",而不是"我是干什么的",这两个说法差很多。

作者 总结了三种典型的 Skill 类型,都来自他在 Kaku 项目里的实际使用:

检查清单型(质量门禁):发布前跑一遍,确保不漏项。比如 release-check,把 cargo build --release 是否通过、版本号有没有更新、CHANGELOG 有没有写,逐条列出,任何一条 Fail 必须修完才能发布。

---
name:release-check
description:Usebeforecuttingareleasetoverifybuild,version,andsmoketest.
---

## Pre-flight (All must pass)
- [ ] `cargobuild--release`passes
- [ ] `cargoclippy---Dwarnings`clean
- [ ] VersionbumpedinCargo.toml
- [ ] CHANGELOGupdated
- [ ] `kakudoctor`passesoncleanenv

## Output
Pass/Failperitem.AnyFailmustbefixedbeforerelease.

工作流型(标准化操作):高风险操作用显式调用 + 内置回滚步骤。比如配置迁移,先备份、再 dry-run、再 apply、再 verify,回滚命令也写在里面,而且设置 disable-model-invocation: true,不允许 Claude 自己决定要不要跑。

---
name:config-migration
description:Migrateconfigschema.Runonlywhenexplicitlyrequested.
disable-model-invocation:true
---

## Steps
1. Backup:`cp~/.config/kaku/config.toml~/.config/kaku/config.toml.bak`
2. Dry run:`kakuconfigmigrate--dry-run`
3. Apply:remove`--dry-run`afterconfirmingoutput
4. Verify:`kakudoctor`allpass

## Rollback
`cp~/.config/kaku/config.toml.bak~/.config/kaku/config.toml`

领域专家型(封装决策框架):出问题时让 Claude 按固定路径收集证据,不要瞎猜。比如运行时诊断,先跑 kaku doctor,再看最近 50 行日志,再查插件状态,然后对照决策矩阵排查,输出格式固定为:根因 / 影响范围 / 修复步骤 / 验证命令。

---
name:runtime-diagnosis
description:Usewhenkakucrashes,hangs,orbehavesunexpectedlyatruntime.
---

## Evidence Collection
1.Run`kakudoctor`andcapturefulloutput
2.Last50linesof`~/.local/share/kaku/logs/`
3. Plugin state:`kaku--list-plugins`

## Decision Matrix
|Symptom|FirstCheck|
|---|---|
|Crashonstartup|doctoroutput→Luasyntaxerror|
|Renderingglitch|GPUbackend/terminalcapability|
|Confignotapplied|Configpath+schemaversion|

## Output Format
Rootcause/Blastradius/Fixsteps/Verificationcommand

工具设计:给 Agent 用的 API,和给人用的完全不是一回事

图片

Tw93 分享了一个很有意思的 Claude Code 团队内部工具演进案例。他们需要解决"任务中途停下来问用户"这个需求,前后试了三版:

**第一版:**给已有工具(如 Bash)加一个 question 参数。结果 Claude 大多数时候直接忽略这个参数,继续往下跑,根本不停下来问。

**第二版:**要求 Claude 在输出里写特定 Markdown 格式,外层解析到就暂停。问题是没有强制约束,Claude 经常"忘了"按格式写,提问逻辑非常脆弱。

**第三版:**做成独立的 AskUserQuestion 工具。Claude 想提问就必须显式调用它,调用即暂停,没有歧义。

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

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


Hooks:把不能交给 Claude 临场发挥的事,收回到确定性流程里

Hooks 很容易被当成"自动运行的脚本",但 Tw93 的理解更准确:它是把那些不能交给 Claude 临场发挥的事情,重新收回到确定性的流程里。

当前支持Hook的点:

图片

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

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

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

Tw93 强调 **CLAUDE.md + Skills + Hooks 三层缺一不可:**只写 CLAUDE.md 规则,Claude 经常当没看见;只靠 Hooks,细节判断又做不了;放在一起才比较稳。


Subagents:最大的价值不是并行,而是隔离

Subagent 是从主对话派出去的一个独立 Claude 实例,有自己的上下文窗口,只用你指定的工具,干完汇报结果。

它最大的价值不是"并行",而是隔离。 扫代码库、跑测试、做审查这类会产生大量输出的事,塞进主线程很快就把有效上下文挤没了,交给 Subagent 做,主线程只拿一个摘要,干净很多。

Claude Code 内置了三个:Explore(只读扫库,默认跑 Haiku 省成本)、Plan(规划调研)、General-purpose(通用)。配置时要显式约束:tools / disallowedTools 限定能用什么工具,别给和主线程一样宽的权限;探索任务用 Haiku/Sonnet,重要审查用 Opus;设置 maxTurns 防止跑飞。


Prompt Caching:Claude Code 整个架构都是围绕它构建的

这块在很多教程里很少被展开讲,但它其实非常影响 Claude Code 的成本结构。

工程界有句话:"Cache Rules Everything Around Me",对 Agent 同样如此。Anthropic 甚至会对缓存命中率跑告警,太低直接宣布 SEV(线上事故)。

Prompt 缓存按前缀匹配工作,所以顺序很重要:系统 Prompt 在最前面锁定,Tool Definitions 紧跟着锁定,Chat History 在后面动态增长,当前用户输入最后。破坏缓存的常见陷阱:在静态系统 Prompt 里放时间戳、非确定性地打乱工具定义顺序、会话中途增删工具。

图片

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

还有一个反直觉的结论:**假如你已经和 Opus 对话了 100K tokens,想问个简单问题,切换到 Haiku 实际上比继续用 Opus 更贵,**因为要为 Haiku 重建整个缓存。确实需要切换的话,用 Subagent 交接。


没有验证闭环,就没有工程上的 Agent

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

Tw93 给出了一个很简单的判断标准:假如一个任务你都说不清楚"Claude 怎么才算做对了",那它大概率也不适合直接丢给 Claude 自动完成。 验证标准本身都没有,Claude 再聪明也跑不出正确答案。

验证层级从低到高:命令退出码、lint、typecheck、unit test → 集成测试、截图对比、contract test、smoke test → 生产日志验证、监控指标、人工审查清单。写任务 Prompt 或 Skill 的时候,把验收标准提前说清楚,哪些命令跑完算完成,失败了先查什么,这些越早讲明白,后面越省事。


如何写一个真正有用的 CLAUDE.md

CLAUDE.md 不是团队文档,也不是知识库,它是你和 Claude 之间的协作契约,里面只放那些每次会话都得成立的事。

**应该放什么:**怎么 build、怎么 test、怎么跑(最核心);关键目录结构与模块边界;代码风格和命名约束;那些不明显的环境坑;绝对不能干的事(NEVER 列表);压缩时必须保留的信息(Compact Instructions)。

**不该放什么:**大段背景介绍;完整 API 文档;空泛原则(比如"写高质量代码");Claude 通过读仓库即可推断的显然信息;大量背景资料和低频任务知识(这些放到 Skills)。

Anthropic 官方自己的 CLAUDE.md 大约只有 **2.5K tokens,**可以作为参考。

有一个很好用的技巧:每次纠正 Claude 的错误后,让它自己更新 CLAUDE.md:

"Update your CLAUDE.md so you don't make that mistake again."

用久了确实越来越少犯同样的错。 不过也要定期 review,时间一长总会有些条目慢慢过时,当初有用的限制现在未必还适合。


用 Claude Code 的三个阶段

Tw93 最后总结了用 Claude Code 大概会经历的三个阶段:第一阶段把它当 ChatBot 用;第二阶段开始堆工具、堆规则,发现越堆越乱;第三阶段关注点悄悄变掉,从"这个功能怎么用"变成"怎么让 Agent 在约束下自己跑起来"。

这也是这篇文章最核心的方法论:Claude Code 不是一个更聪明的输入框,而是一套需要被工程化治理的系统。上下文是资源,工具是接口,Hooks 是控制平面,Subagents 是隔离边界,CLAUDE.md 是契约。每一层都要设计,只强化其中一层,系统就会失衡。

图片

AI 编程工具的竞争,已经从"模型够不够聪明"进化到了"系统够不够稳定"。真正能跑起来的 Agent,靠的不是无限制的自由,而是设计良好的约束。


如果这篇对你有帮助,帮忙**点赞关注,**帮助作者有动力继续更新!

欢迎关注公众号:**蝈蝈的AI笔记,**里面有更多干货内容。

原文: Tw93(@HiTw93)发布的长推

x.com/HiTw93/stat…