引言

在《Claude Code 高效使用指南》里,讲了 CLAUDE.md、Skills、Hooks、Subagents 这些上层扩展能力怎么配置和组合。

但你有没有想过一个问题:这些东西底下,Claude Code 到底是怎么跑起来的?

一个几百万行的 monorepo,Claude Code 怎么知道该读哪个文件?一个长会话跑了几百轮,为什么不会越来越慢、越来越贵?为什么 Claude Code、Codex 这些最火的 Agent 产品,不约而同都选了命令行?

这三个问题,指向同一个答案:Agent 的底层工程,才是真正拉开差距的地方。

这篇文章就把这三层机制拆开讲清楚。

很多人第一反应是:大代码库是不是要先建索引、做向量化、上 RAG?

Anthropic 给了一个很明确的答案:不是。

为什么索引方案在大代码库里容易失效

索引方案有一个致命的假设——代码是静态的。但大规模活跃代码库里,几千个工程师每天都在改代码:函数今天改名,模块明天迁移,旧服务后天删掉。如果索引管线跟不上,模型拿到的是旧世界的地图——它可能引用一个两周前已经改名的函数,也可能调一个上个 sprint 已经删掉的模块。

更麻烦的是,召回结果本身不会告诉你:“我过期了。”

Agentic Search:像工程师一样边搜边读

Claude Code 的思路更像一个真实工程师的工作方式:

  1. 先看报错关键词
  2. 用 grep 找相关接口
  3. 读调用链上的关键文件
  4. 找到核心逻辑
  5. 看测试怎么覆盖
  6. 修改最小范围
  7. 跑对应测试

它不是在某个中心索引里检索答案,而是在开发者机器上的实时代码库里工作。用 Anthropic 的话说,这叫 Agentic Search——不是"先把答案搜出来给模型",而是让 Agent 自己根据当前任务,一步一步决定下一步该搜什么、读什么、验证什么。

大代码库的关键不是"看更多",而是"找得准"

很多人觉得大代码库需要更大的上下文窗口。窗口大当然有用,但真正的问题不是"放不下全部代码"——因为无论窗口多大,你都不应该把整个仓库塞进去。

真正的问题是:Claude Code 能不能在读很少文件的情况下,找到真正相关的那几个文件?

所以大代码库要做的是上下文治理:

  • 该加载的规则提前加载
  • 不相关的目录不要读
  • 生成代码和构建产物要排除
  • 测试命令要按子目录收敛
  • 同名函数要靠 LSP 区分
  • 大范围探索交给 subagent

太多上下文会降低性能,太少上下文会让 Claude 盲搜。 这句话很适合放到团队规范里。

大代码库的配置顺序

落地顺序不是一步到位,而是逐步收敛:

  1. 先写根 CLAUDE.md——仓库结构、常用命令、全局禁区、最容易踩的坑
  2. 补子目录 CLAUDE.md——哪个目录最常被改就先补哪个,写本目录命令和规则
  3. 配置忽略和权限——生成代码、构建产物、三方依赖别让 Agent 去读
  4. 接 Hooks——format、lint、typecheck、单测,把"提醒模型"变成"触发就做"
  5. 重复流程抽成 Skills——安全审查、文档更新、发布检查,按需加载
  6. 再考虑 Plugins、MCP、LSP、Subagents——前面基础没做好,直接上复杂插件容易越配越乱

二、Prompt Cache:为什么长会话不会越跑越慢

Anthropic 有一篇博客标题就叫"Prompt caching is everything"。很多人以为缓存就是"问过的问题下次直接拿答案"。完全不是。

Prompt Cache 缓存的不是答案,是中间计算

Claude Code 每一轮跟模型交互,并不是只把你刚输入的那句话发过去。它要发一整套东西:系统提示词、工具定义、CLAUDE.md 里的项目规则、前面所有对话消息、工具调用结果、你这一轮的新输入。

模型本身不会在两次 API 请求之间"记住"上一次聊到哪了,所以每一轮都要带上完整上下文。如果没有缓存,长会话越聊越贵、越聊越慢。

Prompt Cache 解决的就是这个问题:前面已经算过、下一轮又完全一样的部分,就不要再算一遍。

缓存的死穴:前缀必须完全匹配

Prompt Cache 靠的是前缀匹配。不是"这段内容大概一样",也不是"这个文件之前读过"——而是从请求开头开始,连续一段内容必须一致,才能命中缓存。

这意味着什么?你改一个系统提示词里的时间戳,改一个工具定义的顺序,改一个 MCP 工具的加载方式——前缀一变,后面全断。

Claude Code 的请求组织非常讲究这一点:

  • 静态内容放前面:系统提示词、工具定义——全局稳定,不同项目都能复用
  • 项目上下文放中间:CLAUDE.md——同一个项目里稳定
  • 对话和工具结果放后面:随着聊天增长
  • 本轮新输入在末尾:每轮只让最后一点点内容变化

几个反直觉的工程结论

动态信息别改系统提示词,放进消息里。 当前时间变了、用户改了文件、权限状态变了——这些动态信息如果在系统提示词里更新,缓存就断了。正确的做法是:在下一条消息里追加一条系统提醒,前面的稳定前缀保持不变。

不要中途切模型,可能更贵。 Prompt Cache 按模型隔离。你在 Opus 里聊了 100k token,缓存在。你切到 Haiku——便宜?对,单次输出便宜。但 Haiku 没有 Opus 的缓存,要重新处理整段上下文。为了省一点输出成本,反而付出一大笔未缓存输入成本。

Plan Mode 不能靠"删掉写入工具"实现。 很多人设计 Plan Mode,第一反应是把编辑工具移除。但这会换掉工具集合,等于动前缀。Claude Code 的做法更聪明:始终保留完整工具集,把 EnterPlanMode / ExitPlanMode 做成工具,模式切换的信息放在对话末尾追加,不动前缀。

MCP 工具多了,不要每轮动态删工具。 工具集合变了,缓存前缀就变了。Claude Code 的思路不是"动态删工具",而是"延迟加载工具详情"——先在稳定前缀放轻量 stub(工具名 + 极少元信息),模型真需要时才加载完整 schema。

上下文压缩不能另起一个请求。 如果你单独发一个请求让模型总结,它的系统提示词和父会话完全不一样,缓存全废。Claude Code 走缓存友好分叉:用和父会话一样的前缀,只在末尾追加压缩指令,复用父会话缓存。

缓存命中率要像服务可用性一样监控

很多 Agent 性能问题,不是模型问题,是上下文组织问题。如果你的系统提示词每轮都变、工具定义顺序不稳定、MCP 工具动态增删、中途切了模型——缓存命中率就会很难看。用户体感就是:怎么突然变慢了?

做 Agent 要多看两类 token:cache creation input tokens(本轮写入缓存)和 cache read input tokens(本轮从缓存读取)。如果 read 很高、creation 很低,说明缓存用得好。如果 creation 连续很高,先别怀疑模型,先查上下文组织。

三、Agent CLI:为什么最火的 Agent 产品都回了命令行

这可能是最反直觉的一个趋势:AI 都发展到 Agent 了,最火的产品反而钻回了黑乎乎的命令行。

2025 年 2 月,Anthropic 把 Claude Code 作为终端里的研究预览发布;同年 4 月,OpenAI 上线开源的 Codex CLI,5 月才推出 Codex Web。两家公司同时撞上了同一个工程事实:聊天框适合模型"说",CLI 才方便 Agent 真正"做"。

CLI 不是"黑框里敲字",是可执行、可观察、可组合的反馈系统

你让 Claude Code 修一个登录 Bug,它不是吐一段代码就完事,而是顺着仓库继续干:搜索定位调用链,读取文件,修改代码,跑单测,看报错,再读 diff,直到证据说明任务完成。

CLI 把整个软件工具链压成了统一结构:

  • 输入是文本:需求、路径、参数都能明确传入
  • 动作是命令:Git、编译器、测试框架、数据库都能被调用
  • 反馈是证据:stdout、stderr、退出码、测试报告都能回到上下文
  • 组合靠管道:一次成功的交互,很容易固化成可重复执行的流程
  • 边界由操作系统兜底:工作目录、文件权限、网络策略限制爆炸半径

GUI 没输,只是它更适合人

GUI 最大的优势是把功能摊开给人看。设计稿、数据大盘、可视化调试,这些场景让人直接看比读几百行文本舒服得多。

但 Agent 操作 GUI,很多时候是在"猜像素":按钮换个位置、弹窗多一层、页面加载慢一点,执行路径就变了。CLI 则把动作命名了——git status 不会因为窗口缩放跑到右上角,退出码 1 也比截图里一行红字更容易判断。

真正的分工不是 CLI 干掉 GUI,而是分成两层:人用 IDE、App、Web 看计划、审 diff、做授权;Agent 在下面用 CLI、API、MCP 执行和取证。

CLI 还可递归

Agent 不只会调用 CLI,自己也能变成 CLI 的一环:

cat build-error.txt | claude -p "定位根因并给出修复建议"
git diff | codex exec "检查这次修改是否引入并发问题"

交互工具因此变成了脚本组件,可以进 CI、定时任务和无人值守流程。网页聊天框很难自然做到这一点。

CLI 不是终局,但会长期存在

当 Agent 从一次处理一个任务,变成同时管理十几个长期任务,纯终端很快就不够用了。你需要任务队列、并行状态、权限面板、diff 审核、通知和跨设备接力。

CLI 更像 Agent 世界里的"窄腰层":上面可以是 IDE、桌面 App、网页、手机,下面可以接 Git、测试、数据库、容器和云服务,中间通过命令和结构化结果完成交接。未来不会由一个入口通吃,而是"人类监督层—Agent 编排层—工具执行层"三层分工。

总结

三件事串起来看,其实是一条主线:

  • Agentic Search 解决了 Agent 在大代码库中"怎么找"的问题——不靠索引,靠边搜边读的工程化探索
  • Prompt Cache 解决了 Agent 在长会话中"怎么不越来越慢"的问题——前缀匹配的缓存策略,影响着产品设计的每一个决定
  • Agent CLI 解决了 Agent “在哪干活"的问题——命令行提供了可执行、可观察、可组合的最小执行单元

这三层不是独立的。CLI 执行的命令产出的反馈,是 Agentic Search 下一轮探索的依据;Prompt Cache 的分层策略,决定了上下文里哪些信息稳定、哪些可以动态变化。

Claude Code 不是在 CLI 里塞了一个强模型。它是在模型之外,做了一整套能长期运行的工程基础设施。理解了这三层,你对 Claude Code 的认知就不会停留在"它写代码挺快”——你会看到它底下那套让 Agent 能持续工作的架构。

参考链接

  • Anthropic Blog: How Claude Code works in large codebases
  • Anthropic Blog: Lessons from building Claude Code — Prompt caching is everything
  • Anthropic: Claude 3.7 Sonnet & Claude Code research preview