Harness:Eager vs. Just-in-Time
我一直在构建自己的 coding harness,而我反复纠结的是第一轮、time to first byte,以及在最大化 cache reads 的同时尽量减少其他一切(input、output、cache creation tokens、server latency 等)。这些数字让我钻进了一个兔子洞,开始比较我能接触到的每一种 harness。
本质上,每个 coding agent 都会在第一次 tool call 触发之前下注。模型在开始推理前应该看到多少你的 workspace,以及它又应该自己去寻找多少?
这一个决策几乎驱动了人们围绕这些工具争论的一切。Token 账单。Latency。Agent 对你的 repo 的认知是当前的,还是二十分钟前的。它在周末项目和 monorepo 上是否表现一致。
我把这件事归纳为两个阵营。
Eager Hydration:Cline 的赌注
在 Cline 中打开一个任务,在模型还完全没有思考你的请求之前,它手里已经拿着你 working directory 中每个文件路径的递归列表。这个列表位于一个名为 environment_details 的块中。严格来说,这是随 system prompt 一起携带的 injected context,而不是 system prompt 本身的一部分,不过从成本角度看,这个区别几乎无关紧要。Cline 会随着 session 的进行刷新它。
团队对这里的理念很坦诚。目录结构存在的意义,是让模型永远不必重新发现你项目的形状。他们把 system prompt 描述为一部宪法、工具、环境、偏好,全部打包成一份 brief,在任何工作开始之前交给模型。我其实很尊重这个赌注的清晰度。为每个任务一开始支付一笔税,大小取决于你的 workspace,作为交换,agent 永远不会以“所以这个 repo 里有什么?”开场。
当然,问题在于,一旦有人添加或删除文件,这张地图就开始腐烂。因此需要刷新。稍后我会讲为什么这很重要,因为真正让你付出代价的并不是 token 成本。
Eager 的第二种风味:Aider 的精选地图
Aider 也是 eager 的,但它看了 Cline 的电话簿式做法后,决定改发组织架构图。
Tree-sitter 解析 repo。Aider 构建一个图,表示哪些文件定义了哪些 symbol、哪些文件引用了哪些 symbol,然后在图上运行 PageRank,并向已经出现在 conversation 中的文件加权。输出的是一张“repo map”:你的 codebase 中最常被引用的 class 和 function,以省略过的 snippet 形式呈现,并通过 binary search 压缩到约 1,024 tokens。每次请求都会带上。(look up graphiffy in github)
哲学上和 Cline 一样,但地图会在 agent 请求任何东西之前发出去。账单则截然不同。一个排序后的摘要是否真的胜过完整 listing,这是一个真正开放的问题,而我怀疑答案取决于你的 codebase 有多怪。PageRank 奖励受欢迎的东西。你的 bug 通常在某个不受欢迎的地方。
Just-In-Time Search:Claude Code / Codex / Gemini 的赌注
Claude Code 并不是偶然走到 just-in-time search 这条路上的。它是通过反转来到这里的,这让它更有意思。Anthropic 在早期版本中构建了 RAG 和 vector indexing,把它与 live agentic search 正面比较,然后把前者移除了。Claude Code 的创建者 Boris Cherny 曾说,在他们的测试中,agentic search 以很大优势获胜。不是“我们更偏好它”。就是赢了。
剩下的东西几乎简单到令人不好意思。Glob 用来匹配 path pattern。Grep 用来搜索内容。Read 在确认某个文件相关后把它拉进来。Agent 通过寻找结构来发现结构,就像你自己在一个陌生 repo 中靠 find 和 grep 摸索一样。当探索需要深入时,Claude Code 会在一个独立 context window 中启动一个只读的 Explore sub-agent,它最后只带回摘要,因此游荡过程永远不会污染主 session。
这里有一个_小小的_ eager 组件。CLAUDE.md 会无条件预先放进去。约定、build commands、所有那些精选内容。Anthropic 称整个系统为 hybrid,这很公平,而且在同一个 repo 上工作的多个用户仍然可以 prefix match。Codex CLI 和 Gemini CLI 也做出了同样选择,分别使用 AGENTS.md 和 GEMINI.md。没有预先构建的 tree。所有发现都通过 search 完成,成本分摊到各轮之中。
Token 实际落在哪里
总量会收敛吗?某种程度上会,但成本比总和更重要。
Cline 在前面一次性支付,成本与 workspace 大小成正比。十个文件,基本免费。数万个路径?每一个任务,在任何推理发生之前,都是真金白银。
Search 阵营分期付款。这里一个 Glob,那里一个 Grep,当候选项确认后再 Read。总量随搜索走了多少弯路而扩展。注意它_不_随 repo 大小扩展。Grep 不关心干草堆有多大。它关心的是你的 pattern 有多好。
所以曲线会交叉。在一个小而扁平的项目上,eager 胜出,而 JIT 正在为往返 latency 付费,只为学到一个 listing 本可以立刻交给它的东西。在一个大型、深层的 repo 上,情况反转。
但有一种成本是原始 token 数量遗漏的,坦白说,这也是让我想写这篇文章的真正原因:cache economics。
没人写进 README 的 Cache 问题
有机会去看看一个真实的 environment_details 块里到底装了什么。当前时间,精确到秒。开发者打开的 editor tabs。可见的 vscode files。一个正在运行的 context-window usage counter。
这些东西都不会跨 session 重复。它们绝对不会跨人重复。两个工程师,同一个团队,同一个 repo,完全相同的 git state。每次 prefix 都会分叉,因为这些 volatile fields 与代码毫无关系。而 prompt cache 的生死取决于 prefix 是否完全相同。Anthropic 的 caching docs 明确说明,entries 是按 organization 和 workspace 隔离的,而不是按 user 隔离。team-level cache sharing 的空间就摆在那里,在 API 里。Cline 的设计碰不到它,因为让每个请求变得独一无二的东西被嵌进了本该可复用的部分。
现在反过来看。Claude Code 的 static layer(system prompt、tool definitions、CLAUDE.md)不携带 timestamp、不携带 editor state、不携带任何个人化信息。同一个 repo 上的两个不同工程师,原则上可以产生 byte-identical prefixes,并预热同一个 cache。我还没看到有人在团队规模上 benchmark 过这一点,我也很想看到数字。但从结构上看,一种设计允许它,另一种设计则把它封死了。
关于 eager-vs-JIT 的常见框架是 turns versus tokens。Cline 因为地图已经加载,所以用更少轮次解决请求;search 阵营消耗 round-trips,但保持每一轮轻量。好吧,这是真的,随便。但我还没见过的框架是:这两种哲学实际上是在隐式下注,cache 是_给谁_用的。Eager 优化眼前的 session。JIT 几乎是无意中,仅仅因为保持 prefix 干净,就为团队做了优化。
真正的坐标轴
你要把赌注押在 staleness 还是 discovery cost 上?
Eager 认为一张稍微过时的地图胜过没有地图,而刷新可以让过时程度保持在可接受范围内。JIT 认为一次 live query 胜过任何 cached map,而提问的 overhead 值得,因为它永远不会错判磁盘上有什么。抽象地说,两者都不是绝对正确的。它们各自是否正确,取决于你的 repo 大小、churn rate,以及你的经济模型惩罚的是 tokens 还是 turns。问题不在于哪种 harness 更聪明。而在于押哪个赌注,以及为什么。
Cursor 不适配这个框架,而这正是重点
所有人都把 Cursor 归到 Cline 旁边。IDE-native,感觉 eager。但机制并不支持这个判断。Cursor 从不加载 tree。它在本地 chunk 你的 codebase,对 chunks 做 embedding,把它们保存在一个 persistent vector database 中,并在 query time 运行 nearest-neighbor search。任意一轮落入 context 的是定向结果,而不是一张地图。
基础设施上 eager,检索上 just-in-time。昂贵的部分一次性支付,并增量更新,而不是每个 task 都重新支付。它确实是第三种赌注:先构建 retrieval system,然后像 Glob 和 Grep 一样搜索它,只不过是语义搜索而不是词法搜索。还值得注意的是,这正是 Anthropic 测试后砍掉的架构。Cursor 保留了它,并基于它建立了一门生意。这里有人错了。或者更可能的是,他们在为不同用户优化。
三个打破框架的工具
Terminus 2 比所有人都更 JIT。像 1970 年代那样 raw dogging it。没有 Glob,没有 Grep,没有 Read。没有 file tools,完全没有。通过 tmux 使用原始 Bash,模型自己决定是 grep、find,还是像野兽一样打开 vim。甚至 context management 也是 reactive 的。只有当 window 快满时才触发 summarization。如果 Claude Code 是 just-in-time search,那么 Terminus 2 就是 just-in-time everything。
OpenCode 不是一种新哲学,而是一次确认。AGENTS.md 预先加载(包括 CLAUDE.md fallback),其余部分使用 Glob/Grep/Read,通过 Explore 和 Scout subagents 进行隔离式发现。一个独立的 open-source 团队看到了同一个问题,并画出了同样的架构。
Hermes Agent 甚至不在这个坐标轴上。它是一个 persistent multi-platform agent(CLI、messaging apps、scheduled jobs),其定义性选择是三层 system prompt(stable、context、volatile),skills 作为 slash commands 加载,所有东西都围绕一条近乎神圣的规则组织起来。永远不要 invalidate the prompt cache。
该给的肯定
在日常使用中,context 这条轴并不是区分这些工具的东西。所以,简短说说我对每个工具真正擅长之处的提炼版本。
Cline 提供了这组工具中最深的 VS Code integration,而它的 plan/act split——agent 先提出方案,只在批准后执行——对于任何希望每个变更都有 gate 的人来说,都是正确的形状。Aider 适合用 diff 思考的人。Git-native,每个被接受的变更都是自己的 commit,基本可以配合任何 model。Claude Code 是为可放手运行的 sub-agents、hooks、background execution,以及几乎不需要监督的 multi-step refactors 构建的。CodexCLI 把 OpenAI 的 reasoning models 放进 cloud sandbox,并在算法上困难、reasoning quality 胜过 speed 的问题上证明自己的价值。
Gemini CLI 值得单独一句,因为它可以容纳 1M-token window,默认分辨率下大约一小时的视频,降低分辨率时最多三个视频,并把它们与你的代码和文档放在同一个请求中。离谱。Google 自己的测试显示,它可以一次性推理带同步音频的 90 分钟视频。我读到过它能在几分钟内读取一段两小时视频,这看起来是准确的,但我没有亲自测试过这个说法。
Cursor 占据了 flow-state 这个 niche,拥有这里所有工具中最紧密的 autocomplete-to-agent loop。Terminus 2 完全没有脚手架,是这个领域最接近 control group 的东西,这让它成为衡量模型 raw ability 的正确 benchmark。OpenCode 是没有 lock-in 的 Claude Code ergonomics,model-agnostic,open-sourced。而迁移后的 Kilo Code 实际上就是 OpenCode 加上 managed billing 和面向希望拥有灵活性但不想自行管理 key 的团队的 model marketplace。
一个 Vendor 公开换了阵营
大多数 harness 在诞生时选择一种哲学,然后带着它死去。Kilo Code 没有,这正是这个转变有信息价值的原因。
最初的 Kilo 是 Cline fork,与 Roo Code 同源,同样使用 eager 的 environment_details listing。2026 年 4 月,他们从零重写了 CLI,而不是改进自己的 eager 方法,他们直接 fork 了 OpenCode。新的 Kilo CLI 原封不动地运行 OpenCode 的 tool registry。Glob、Grep、Read,底层是 ripgrep,explore subagent 也一并继承。整套 just-in-time toolkit,不是重建,而是继承。
你几乎从来没有机会公开看到这一幕。真实产品、真实用户、押上完整重写,而团队跨过了阵营线。到 Kilo 迁移时,JIT 阵营已经稳定了一年多。Claude Code 在 2025 年 2 月,Codex CLI 在 4 月,Gemini CLI 在 6 月。三个实验室,没有共享代码,四个月内内部呈现出同样的 tool shape,而且其中至少一个是在构建了替代方案后又将其砍掉才走到这里的。如果你读过我的 convergent engineering 那篇文章,你就知道这个模式。替代方案会被尝试,然后它们失败,或者以同样方式在各处收敛。
你的 Harness 是为谁而建?
这是我的落点,也是我不断回想的想法。
剥掉 token math,这两种哲学就不再关乎效率。它们是在回答一个没人明说的问题。这个 agent 的 context 是给谁的?
Eager hydration 的答案是:这个开发者,这个 session,这个时刻,精确到打开的 tabs 和 timestamp。一个人_当下_尽可能丰富的图像。与之绑定的代价,是别人无法复用的 context,并且从组装完成的那一秒开始老化。
Just-in-time search 给出了不同答案。通过拒绝让任何个人化或易腐坏的东西进入 prefix,它产生的 context 是团队中任何工程师都可以共享、cache 并信任的。
Agents 即将不再只是某个开发者的 sidekick。它们正在变成 fleets,并行、后台运行,多个 agent 同时为整个团队处理同一个 repo。在那个世界里,scope 到某个人 editor tabs 的 context 不是低效,而是完全错误的抽象。
赢得下一阶段的 harness,不会是那些最了解你 session 的工具。它们会是那些其知识从一开始就被设计为可共享的工具。
这个模式会扩展
一旦你退得足够远,看清它,这个比较就会浮现出来。
这些工具要解决的问题不是 file discovery。它是 context admission control。也就是哪些东西进入模型的 window,何时进入,以及为什么进入。Cline 的答案是预先接纳一切并支付税。Claude Code 的答案是先什么都不接纳,直到某样东西通过 search 证明自己值得进入。这个行业花了大约一年同时尝试两者,然后强烈收敛到后者。
这个原则不会止步于文件。同一个问题在 skills 这一层也存在。一个有 90 个 skills 的 plugin,不会把全部 90 个都加载进 system prompt,就像一个设计良好的 harness 不会加载你的整个 file tree 一样。它也存在于 MCP servers 中,那里 tool catalog 面临的 admission problem 与 skill catalog 一样。它还存在于 multi-agent system 中的 agents 本身,预先生成每一种可能的 sub-agent,就是 agentic 版本的 eager hydration。
修复方法在每种情况下都一样。你需要三样东西。一个 catalog,其中有足够的语义定义,使 retrieval 能够工作;一个 classifier 或 similarity search layer,只接纳当前请求真正需要的内容;以及始终加载的内容与通过努力获得进入资格的内容之间的清晰分离。pgvector 用于 catalog。Embeddings 或 lightweight router 用于 classifier。一个稳定、cacheable、在请求之间永不变化的 prefix 是_基础_。
Files、skills、tools、更多 skills、agents、policies。Admission control problem 是相同的。解决它的 architecture 也是相同的。那些弄清楚 just-in-time capability loading 的系统,将相对于没有弄清楚的系统拥有同样的成本和 cache 优势。
阅读清单
https://newsletter.pragmaticengineer.com/p/building-claude-code-with-boris-cherny
https://aider.chat/2023/10/22/repomap.html
https://x.com/bcherny/status/2017824286489383315
https://deepwiki.com/Aider-AI/aider/4.1-repository-mapping-system
https://platform.claude.com/docs/en/build-with-claude/prompt-caching
https://code.claude.com/docs/en/prompt-caching
https://www.anthropic.com/news/claude-code
https://openai.com/index/openai-codex-cli/
https://developers.googleblog.com/en/gemini-cli-your-open-source-ai-agent/
https://deepmind.google/technologies/gemini/
https://github.com/Kilo-Org/kilocode

