RAG已死?不,是Grep回归了!
这一年“RAG 已死”的说法甚嚣尘上比如《长上下文窗口、Agent 崛起RAG 已死》、《The RAG Obituary: Killed by Agents》。而像 Claude Code、Codex 这类新一代 Agent CLI 也纷纷放弃了 embedding官方直接承认不建索引、不用向量库靠 LLM 驱动 Grep 就够用。RAG 真的不适合现在的 Agent 了吗围绕这个问题我们展开了深入调研同时对Claude Code 等前沿解决方案的源码进行了拆解最终形成本文力求回答 RAG 在 Agent 时代是否还有一席之地这一核心关切点。01从Claude Code 的 Grep 说起Claude Code 的创建者 Boris Cherny 在多个公开场合提到过这个让很多人意外的事实Claude Code 不用 RAG不用 embedding不建索引。 核心搜索靠 LLM 驱动 Grep Grep 是 Unix 下的文本搜索工具给一个正则表达式它就在文件里逐行找匹配。在 X/Twitter 上他说得很直接“Early versions of Claude Code used RAG a local vector db, but we found pretty quickly that agentic search generally works better. (早期版本的 Claude 代码使用了 RAG 加上本地向量数据库但我们很快发现智能体式的搜索通常效果更好)”在 Pragmatic Engineer 的采访中更进一步“Plain glob and grep, driven by the model, beat everything. (由模型驱动的 glob 和 grep 击败了一切)”Anthropic 官方的 Context Engineering 博客也确认了这一架构Claude Code 使用 Grep 和 Glob 将代码动态加载到 context 中。这个选择不是拍脑袋做的Boris 在 Pragmatic Engineer 的采访 中提到他在 Meta 时观察到 Instagram 工程师在 IDE 的 click-to-definition 功能崩溃后所有人都回退到手动 Grep 搜代码。不过他也在 Latent Space 播客 中坦承放弃 RAG 的决策部分基于直觉。尽管 Anthropic 说了不用 RAG用 agentic search Grep但 Grep 具体怎么调用、LLM 怎么决定搜什么、工具调用循环长什么样这些实现细节都没有公开。2026 年 3 月Claude Code CLI 的一份源码快照因泄露被公开。我去看了一下发现确实如 Boris 所说源码中没有任何 embedding、vector、similarity search 相关的实现。但更有意思的是这套零索引内容搜索机制的具体实现方式。这篇文章就是基于这份源码以及一些行业实践从实现层面拆解 Claude Code 的代码搜索机制以及其背后的设计哲学。本文先拆解 Claude Code 如何驱动多轮 Grep 循环第二章再看暴力搜索为什么在本地项目上够快第三章最后和 Cursor 等行业方案对比讨论 Grep 方案的真实成本与收益第四章。为了让整套机制不停留在抽象层面我们用一个贯穿全文的例子来看。Claude Code 除了终端 CLI 模式外还有网页版和桌面版而这些模式下它通过一个叫 bridge 的远程控制系统运行由服务端 session 执行实际工作。假设你在读这份源码时产生了一个好奇当 LLM 调用 GrepTool 做搜索时bridge 是怎么追踪和记录这次工具调用的 你让 Claude Code 帮你从源码中找答案接下来会发生什么02LLM 驱动的多轮循环搜索机制Claude Code 的代码搜索可以用一句话概括LLM 自己决定搜什么、用什么工具搜、搜到后要不要继续搜直到信息充分为止。 没有预设的搜索流程没有固定的工具调用顺序一切由 LLM 在运行时决定。这一章先讲搜索循环怎么运转、循环里有哪些工具可用然后深入最核心的 GrepTool 看它怎么控制返回的信息量。最后用开篇提出的那个实战问题完整走一遍多轮搜索的过程。2.1 搜索循环与工具整套搜索机制的核心是一个循环将用户输入和可用工具列表传给 LLMLLM 返回文本或工具调用请求。如果是工具调用执行工具后把结果追加到对话历史然后带着更新后的完整历史再次调用 LLM。LLM 基于不断增长的上下文决定下一步做什么直到它认为信息充分、直接生成文本回答而不再调用工具循环自然结束。循环也有强制退出机制达到最大轮次上限、超出预算限制、用户中断、或工具调用被权限拒绝。这个循环对所有工具是平等的。LLM 可以在任何时候调用任何工具甚至在一次响应中同时调多个。没有硬编码的“必须先搜再读”。与代码搜索相关的核心工具有四个工具底层实现作用GrepToolripgrep (rg)正则搜索文件内容GlobToolglob 模式匹配按文件名/路径模式查找文件FileReadToolNode.js fs读取指定文件的指定行范围AgentTool独立 LLM 对话启动子 agent 做多步探索此外还有 LSPLanguage Server Protocol工具用 “go to definition”、“find references” 等语义精确的操作补充 Grep 的不足。但核心搜索架构建立在这四个工具之上。其中 AgentTool 比较特殊它不是直接搜索文件而是启动一个独立的子 agent让子 agent 在自己的 context window 里完成一整套搜索任务最后只把结论返回给主对话。子 agent 有多种类型与搜索最相关的是 Explore 类型它只配备搜索和读取工具Grep、Glob、Read不能编辑文件、不能执行命令、不能嵌套启动新的 Agent是一个纯只读的搜索专家。子 agent 的核心价值是 context 隔离。它从零开始构建自己的对话历史不继承主对话的消息这意味着它搜索过程中产生的大量 grep 结果、代码片段都留在自己的 context 里主对话只收到一段总结性的文本结论。对于需要大范围搜索的任务如果在主对话里直接搜索几轮 grep/read 下来 context 可能就被中间结果塞满了。因此交给子 agent 处理后主对话的 context 只增加一条结论消息。2.2 GrepTool 的信息量控制在一般实践中LLM 最常用的模式是“先定位再深入”先用 Grep/Glob 找到相关文件再用 Read 读具体内容。但 Grep 搜到文件后是不是每次都要接一个 Read 才能用不一定。关键在于 GrepTool 有三种输出模式返回的信息量完全不同files_with_matches 模式默认只返回匹配的文件路径列表不返回任何代码内容。比如搜 “class.*Transport” 会返回 cli/transports/WebSocketTransport.ts、cli/transports/SSETransport.ts 这样的路径。LLM 拿到的只有文件名所以这种模式下通常需要接 Read 才能看到具体代码。这也是为什么默认模式设计成只返回文件名即故意控制信息量避免一次 Grep 就把大量代码涌入 context window让 LLM 自己判断哪些文件值得深入读取。另外还有一个保护机制head_limit 默认 250即使搜到 10,000 条匹配也只返回前 250 条防止搜索结果淹没 context。content 模式返回匹配行及其上下文代码。比如 Grep({pattern: “TOOL_VERBS”, output_mode: “content”, “-C”: 5}) 会直接返回匹配行前后各 5 行的代码片段。对于很多场景例如确认一个常量的值、看一个函数签名、检查某个 import 是否存在这些片段就够了不需要再 Read 整个文件。count 模式只返回每个文件的匹配数量用于快速评估搜索词在项目中的分布密度不返回具体内容。所以实际的工具组合方式是灵活的Grep默认模式→ Read 是最常见的路径但 Grepcontent 模式可以独立使用LLM 也可以直接调 Read如果已经知道文件路径或者一次同时发起多个 Grep 并行搜索。这种灵活性是有意为之。其思想是用软引导代替硬约束system prompt 建议 LLM 先 Grep 定位再 Read 深入GrepTool 的默认输出模式也自然引导这个流程但不在代码里堵死其他路径让 LLM 根据具体情况做判断。2.3 实战追踪搜索工具的执行记录回到开篇的例子。当然这个问题是我刻意挑的因为答案分散在多个文件中需要多轮搜索才能拼出全貌目的是展示多轮搜索的完整过程。我把这个问题抛给了 Claude Code以下是真实的搜索过程。第 1 轮广撒网。 LLM 把问题中的 GrepTool 和 追踪 翻译成 grep 关键词用默认的 files_with_matches 模式扫一遍Grep({pattern: GrepTool|tool.*track|tool.*activity, glob: *.ts})→ 返回 4 个文件structuredIO.ts, sessionRunner.ts, bridgeUI.ts, bridgeStatusUtil.ts4 个文件其中 3 个在 bridge/ 目录下1 个在 cli/ 下。问题问的是 bridge 系统LLM 关注 bridge/ 下的文件。sessionRunner.tssession runner 会话执行器最可能包含工具执行追踪逻辑。第 2 轮看上下文。Grep 切换到 content 模式看 GrepTool 在 sessionRunner.ts 中的上下文Grep({pattern: GrepTool|tool.*activity, path: bridge/sessionRunner.ts, output_mode: content, -C: 5})返回的代码片段中能看到一张映射表的尾部显示 GrepTool: ‘Searching’、BashTool: ‘Running’但上文被截断了。LLM 判断需要 Read 整段代码才能看全。第 3 轮调用Read。 使用 Read 打开 sessionRunner.ts 的完整上下文一次看到了三个关键结构第一个是工具名→动词映射表TOOL_VERBS共 18 个条目这里列出与搜索相关的部分。每个搜索工具Grep、Glob在这里都被映射成 Searching。注意有两套命名比如内部名 Grep 和外部 SDK 名 GrepTool。这表明工具名是硬编码在映射表里的不是动态注册的。Grep: Searching, GrepTool: Searching, Glob: Searching, GlobTool: Searching, Read: Reading, FileReadTool: Reading, Edit: Editing, FileEditTool: Editing, Bash: Running, BashTool: Running, // 还有 Write, MultiEdit, WebFetch, WebSearch, Task, NotebookEditTool, LSP 等第二个是摘要生成函数它把动词和搜索目标拼接在一起动词来自上面的映射表目标则从工具调用的输入中提取优先取 file_path其次 pattern、command、url 等。所以一次 GrepTool({pattern: “reconnect|backoff”}) 调用的摘要就是 Searching reconnect|backoff。第三个是活动解析器它从 session 的 stdout 中逐行解析 JSON当发现工具调用事件时调用上面的摘要函数生成摘要打包成一条活动事件。到这里已经知道了怎么追踪和怎么记录但活动事件生成之后去了哪里第 4 轮追踪使用方。 Grep 搜 SessionActivity 被谁引用一次追出整条链Grep({pattern: SessionActivity|currentActivity, path: bridge/, output_mode: content, -C: 2})三个文件同时浮出水面bridge/types.ts 活动事件的类型定义只有 3 个字段类型、摘要、时间戳。每个 session 维护一个环形缓冲区和一个当前活动指针。bridge/bridgeMain.ts 一个定时器周期性轮询每个 session 的当前活动并维护最近 5 次工具调用的轨迹例如 Searching → Reading → Searching → Editing 这样的历史。bridge/bridgeUI.ts 收到工具启动事件后缓存摘要文字并渲染到 bridge 的状态面板。这样就拼出了完整的追踪链session 进程输出工具调用的 JSON → 活动解析器提取并生成摘要 → bridge 主进程定时轮询获取最新活动 → UI 模块渲染到状态面板。03性能原理暴力搜索为什么够快上一章展示了 Claude Code 如何用多轮 Grep 搜索代码。但这引出一个显而易见的问题每轮 Grep 都是在项目文件中暴力扫描。一个大一点的项目可能有几万个文件暴力扫描不会慢吗Grep 在今天是一个大家族。诞生于 1973 年的 GNU grep 是最经典的版本逐文件递归、不认识 .gitignore、默认单线程。而 Claude Code 的 GrepTool 底层调的并不是它而是 ripgrep在2016 年由 Andrew Gallant 用 Rust 重写的现代实现默认遵守 .gitignore、自动跳过二进制文件、多线程并行、用 SIMD 加速匹配为在大型代码库里快速搜索这个场景从头设计。源码佐证tools/GrepTool/GrepTool.ts:21 里 import { ripGrep } from ‘…/…/utils/ripgrep.js’ 所以真正干活的是 ripgrep不是系统自带的 grep。这一章解释为什么 ripgrep 的暴力扫描在开发者本地项目上足够快五层过滤怎么把搜索范围从几万文件缩小到几十个SIMD 和 Boyer-Moore 怎么加速文件内匹配以及代码搜索和向量检索在数据规模上的本质差异。3.4 节还有一组用 Claude Code 自己的源码做的 ripgrep vs GNU grep 实测数据可以直接看到差距。3.1 ripgrep 的五层过滤ripgrep 不是对每个文件都做正则匹配。它在真正搜索内容之前有多层过滤逐步缩小范围层级1: 目录级剪枝.gitignore — 跳过整棵目录子树连目录内容都不读取 层级2: 路径范围限制path 参数 — 限定目录遍历的起点 层级3: 文件类型过滤glob 参数 — 遍历目录但跳过不匹配文件 层级4: 二进制文件检测 — 读文件头几个字节发现是二进制就跳过 层级5: 内容搜索正则匹配 — 最后才对通过所有过滤的文件做匹配各层过滤是乘法叠加的。回到我们贯穿全文的例子第 4 轮搜索 Grep({pattern: “SessionActivity|currentActivity”, path: “bridge/”, glob: “*.ts”})。在泄露的 Claude Code 源码4,471 个文件上实际的过滤链是原始文件数: 4,471 层级1 .gitignore 剪枝: → 4,471 源码快照无 node_modules此层无效果 层级2 path 限制 bridge/: → 32 只遍历 bridge/ 目录 层级3 glob *.ts 过滤: → 32 bridge/ 下全是 .ts此层无额外过滤 层级4 二进制检测: → 32 全是文本文件 层级5 正则匹配: → 3 个文件命中bridgeStatusUtil.ts、sessionRunner.ts、bridgeUI.ts这个例子中 path 限制是最大的过滤器一步从 4,471 砍到 32。但如果是一个包含 node_modules/ 的完整 Node.js 项目.gitignore 剪枝的效果更大。因为一个典型项目中 node_modules/ 可能包含数万个文件一条规则就砍掉大量的文件数量。3.2 文件内搜索的加速手段通过过滤后需要实际搜索的文件ripgrep 在内容匹配层面也有多项优化SIMD 向量化匹配。 ripgrep 底层使用 Rust 的 regex crate它利用 CPU 的 SIMD 指令并行比较字节。普通逐字节比较一次处理 1 个字节AVX2 一次处理 32 个字节。搜索时先用 SIMD 快速扫描搜索词首字符的出现位置只在命中时才做完整匹配。对于多模式搜索ripgrep 使用 Teddy 算法实现 SIMD 级别的多模式并行匹配。Boyer-Moore 跳跃。 对于固定字符串搜索从 pattern 末尾开始比对遇到不匹配时根据 bad character table 直接跳过多个字符。长 pattern 时只需扫描约 n/m 个字符n 文件大小m pattern 长度。操作系统 Page Cache。 读过的文件内容会被操作系统缓存在内存中。对于经常使用的代码项目文件几乎永远在缓存中。首次搜索可能触发磁盘 I/O第二次搜索直接从内存返回。mmap 零拷贝。 对于大文件ripgrep 使用 mmap内存映射代替普通的 read() 系统调用。普通 read() 需要将数据从内核空间复制到用户空间mmap 让进程直接访问内核的 Page Cache省掉一次数据复制。对小文件反而因为系统调用开销不划算所以 ripgrep 会根据文件大小动态选择。多线程并行。 ripgrep 用线程池并行处理多个文件一个线程遍历目录树产出文件路径多个 worker 线程并行搜索不同文件结果通过 lock-free queue 汇总。3.3 性能实测数据用 Claude Code 自己的源码4,500 文件、95 万行代码做一组实测对比 ripgrep 和 GNU grep 在同一台机器上搜索同一个关键词的耗时取 3 次运行的稳定值搜索模式ripgrepGNU grep -r倍数TOOL_VERBS低频词0.09s2.55s28xasync.*generator正则0.10s3.30s33ximport.*from高频词0.10s2.45s25x两者搜索的文件范围几乎一样ripgrep 4,494 个文件 vs GNU grep 4,522 个差距主要来自 ripgrep 的多线程并行和 SIMD 向量化加速而非文件过滤。0.1 秒的搜索延迟对交互式使用来说基本无感。3.4 数据规模有限度一个很重要的原因Claude Code 面对的数据规模开发者本地项目恰好落在暴力搜索可行的范围内。向量检索Grep常见场景数据量GB ~MB ~ 几百 MB单次比较成本768 次浮点乘法余弦相似度1 次字节相等判断SIMD 加速后~24 次乘法/指令~32 次比较/指令暴力扫描总耗时秒 ~ 分钟数十毫秒一个 250MB 的代码库在 Page Cache 命中开发者的日常项目几乎总是命中的情况下连磁盘 I/O 都省了整份数据就躺在内存里。按现代开发机约 30GB/s 的内存带宽算把这 250MB 从 page cache 搬一遍的数据搬运下界约为 250MB / 30GB/s ≈ 8 毫秒。真实情况下还要加上 ripgrep 做 SIMD 模式匹配本身的 CPU 开销实测总耗时通常在几十到一百多毫秒因此没有构建索引的必要性。04行业对比与设计哲学Claude Code 选择零索引但行业中并非所有人都这么想。这一章把 Claude Code 和 Cursor、Codex 放在一起比较Cursor 的双索引架构长什么样Codex 为什么做出了和 Claude Code 几乎相同的选择但实现路径不同规模如何决定架构选择以及 Claude Code 自身的演进方向。然后回应 Grep 方案最常见的批评 即token 成本问题从源码看 Claude Code 用了哪些机制来控制成本。4.1 Cursor 的双索引架构Cursor 使用经典的 RAG 架构并在此基础上叠加了 trigram 索引。这里只介绍 Cursor 区别于 Claude Code 的索引部分因为Cursor 同样有 Grep 搜索工具可用见 4.2 节。语义索引 本地用 tree-sitter 把代码按语法边界切成块通过 Merkle Tree 做增量同步只传变化的部分代码块加密上传到 Cursor 服务端服务端用 embedding 模型生成向量后立即丢弃原始代码向量和元数据存入 Turbopuffer一个向量搜索引擎。搜索流程为用户提问 → embedding → 向量最近邻搜索 → top-K → reranking → 组装到 context。精确搜索索引 Cursor 在 2025-2026 年开发了 Instant Grep使用 trigram三字符组合倒排索引加速 grep 搜索。预处理时把文件内容切成 3 字符的滑动窗口如 “OAuth” → “OAu”, “Aut”, “uth”为每个 trigram 维护一个包含该 trigram 的文件列表。搜索时取所有 trigram 对应文件列表的交集得到候选文件只对候选文件跑正则匹配。总的来说Cursor 走的是预处理路线代码仓库在后台被分块、embedding向量写入 Turbopuffer同时再喂给 Merkle 树维护增量同步离线建好的索引是整条链路的前提。Claude Code 走的是按需路线没有索引、没有预处理LLM 在对话里实时决定用什么关键词 grep、读哪些文件所有语义理解都由模型自己在循环中完成。这两种架构对应两套取舍索引换来的是命中率和跨仓库扩展性零索引换来的是零启动、零维护和与开发者工作流的零摩擦。4.2 规模决定架构Cursor 的索引规模本身就说明了问题。Turbopuffer 的官方客户案例披露了 Cursor 的向量基础设施数据100 亿 向量、1,000 万 命名空间每个命名空间对应一个用户的一个代码库、写入吞吐量约 10GB/s。CTO Sualeh Asif 称 Turbopuffer 是“扩展过程中少数不需要操心的基础设施之一”。这个规模意味着 Cursor 面对的不只是小型个人项目。当代码库足够大时暴力 Grep 的延迟会变得不可接受。对于 Agent 场景来说搜索延迟直接决定了在有限时间内能做多少轮搜索也就决定了 Agent 对代码的理解深度。所以零索引和双索引不是技术优劣之分而是场景选择。Claude Code 面向开发者本地项目MB ~ 几百 MBripgrep 暴力扫描只需几十毫秒加上 LLM 的推理能力零索引意味着零启动延迟、零维护成本、零配置。Cursor 面向更广泛的场景包括大型代码库暴力扫描的延迟不可接受索引是必需的。但有一点值得玩味的是 Cursor 在 2025 年 3 月泄露的 Agent system prompt 里grep_search 被明确标注为主要探索工具MAIN exploration toolLLM 被要求先用一组宽泛关键词进行 Grepcodebase_search语义搜索只在“概念性查询”时作为补充。一家把语义搜索当核心卖点、为此自建整套向量基础设施的公司内部却把 Grep 放在第一个被调用的位置这说明在代码搜索这个任务上“精确匹配找到已知符号”远比“语义理解找到相似概念”来得高频和确定。向量检索解决的是 Grep 覆盖不到的长尾而不是反过来。行业趋势也在印证这一点有分析指出 Cursor 正在弱化纯向量搜索、转向混合搜索Claude Code 则把这条路线推到了极端即完全不用语义检索靠 LLM 把语义需求翻译成精确关键词再交给 Grep。值得注意的是Claude Code 自己也在演进。v2.0.74 版本引入了 LSPLanguage Server Protocol支持用 “go to definition” 这类语义精确的操作替代部分 Grep 多文件 read实测降低了约 40% 的 token 消耗。社区也在做补充有人开发了 Beacon 插件用 Claude Code 自带的 PreToolUse hooks 拦截 Grep 调用替换为混合搜索向量 BM25 rank fusion。4.3 Codex 的验证殊途同归的零索引前面对比了 Cursor双索引和 Claude Code零索引的不同选择。但还有一个重要的参照物OpenAI 的 Codex CLI。Codex 的代码搜索架构和 Claude Code 惊人地相似同样不建索引、不用 embedding、不用向量数据库。 社区提交的 向量索引功能请求 被 OpenAI 团队关闭明确表示“not currently on our roadmap”。但两者的实现路径有一个关键分歧代码搜索的工具设计不同。Claude Code 为搜索操作封装了专用工具。GrepTool 有三种输出模式和 head_limit 等参数GlobTool 做文件名匹配FileReadTool 按行范围读取。每个工具有明确的参数 schemaLLM 通过结构化的工具调用来使用它们。Codex 没有专门的搜索工具。它的核心工具是 shell执行任意 shell 命令和 apply_patch专用 diff 格式编辑文件此外还有 update_plan、view_image、web_search、spawn_agent多 agent 协作等。所有代码搜索操作通过 shell 工具完成。LLM 可以直接组合 rg、find、cat、git 等 Unix 命令来搜索。Codex 的多个 system prompt 文件中都写了同一条指令When searching for text or files, prefer using rg or rg --files respectively because rg is much faster than alternatives like grep.搜索模式同样是多轮迭代Grep → 读文件片段 → 调整关键词 → 再搜。方面Claude CodeCodex CLI搜索工具专用工具GrepTool、Glob、Read有结构化参数通过shell工具执行rg、find、cat无专用搜索工具索引无无子 agent内置Explore、Plan 等类型context 隔离内置spawn_agent/send_message/wait_agent等编辑方式Edit字符串替换apply_patchdiff 格式两种路径的核心分歧在搜索工具的封装程度上。Claude Code 把 Grep 封装成带结构化参数的专用工具LLM 不需要解析原始 shell 输出减少出错概率也让系统更容易控制信息量Codex 让模型直接写 shell 命令调用 rg给予最大灵活性可以自由组合管道、正则、路径过滤但需要模型自己处理非结构化的文本输出。真正值得注意的是两者的共识两个互为竞争对手的 AI 编程产品独立做出了几乎相同的架构决策用 LLM 驱动 ripgrep放弃向量检索。 这不太可能是巧合。这说明在当前 LLM 能力水平和开发者本地项目的规模范围内零索引 Grep 已经是一个被反复验证的有效方案。4.4 Grep 方案的成本问题与应对为什么选 Grep 而不用向量检索两个核心原因无需预建索引每次直接用 Grep 搜磁盘上的实时文件零启动延迟、零维护成本、不存在索引过期问题。此外代码搜索的核心需求是精确匹配Grep 比语义相似度可靠。但这带来了一个显而易见的成本问题多轮调用 Grep 和 Read不会很烧 token 吗毕竟搜索循环的每一轮都要把完整的对话历史发给 Claude APIcontext 越来越长。向量数据库厂商 MilvusZilliz的工程师曾发表文章 “Why I’m Against Claude Code’s Grep-Only Retrieval? It Just Burns Too Many Tokens” 直接质疑这一点。文章展示了一个实测案例用 Claude Code 调试一个 VSCode 扩展的 bugGrep 在仓库中反复搜索、倾倒大量无关文本最终花了 14 次工具调用、32.2k tokens、59.3 秒才找到答案但实际上正确的 10 行代码埋在 500 行噪声里。文章将问题归纳为三点token 膨胀每次 Grep 把大量无关代码塞进 context成本随仓库规模恶化、时间税AI向代码库问二十个问题开发者干等、零语义Grep 只做字面匹配不理解代码含义和关联。作为替代方案他们开源了基于向量检索的 MCP 插件 Claude Context声称在相同任务上 token 消耗降低约 40%、工具调用次数减少约 36%。那么 Claude Code 自己是怎么应对 context 膨胀的从源码看至少有三层机制需要指出的是这三层都是通用的工程手段embedding 方案同样可以使用并非 grep 独有的优势第一层prompt cache 降低重复计费。 API 会识别出本次请求的输入前缀和上次完全相同因为只是在末尾追加了最新一轮的工具结果。这样一来可以直接复用已有的计算缓存只为新增的增量部分付全价前面累积的大头按约 1/10 的缓存价计费。源码中可以看到 Claude Code 为此做了精细的工程优化system prompt 在发送前被拆成多个独立的文本块每个块可以单独标记缓存策略。这种分块设计确保不变的部分能精确命中缓存不会因为动态内容变化而失效。Vadim 在 2025 年 12 月的分析发现agentic 循环中 92% 的 prompt 前缀在相邻轮次间完全相同实测成本降低约 81%。第二层auto-compaction 压缩历史。 多轮 grep/read 会让对话历史持续增长。当累积的 token 数接近 context window 上限时Claude Code 自动触发对话压缩用 LLM 对旧的对话历史生成摘要然后用摘要替换原始消息直接缩短对话历史。这意味着 context 不是无限增长的早期搜索轮次的 grep 结果和 read 内容最终会被压缩成一段摘要为后续搜索腾出空间。第三层子 agent 隔离搜索结果。 第二章提到的 Explore 子 agent 本身就是一种 context 管理手段。大量 grep/read 的原始结果在子 agent 的独立 context 中处理和消化只有精炼后的结论返回主对话避免主 context 被搜索中间结果撑满。这三层机制让暴力多轮搜索在实践中可控但并没有消除 Grep 方案相对于 embedding 方案在单次检索精准度上的差距。Grep 方案的核心 tradeoff 是用更多的搜索轮次和更大的 context 开销换取零索引、零维护、零启动延迟的工程简洁性。这个 tradeoff 在开发者本地项目的规模上是合算的但在更大规模上是否仍然成立取决于搜索轮次和 context 成本的增长曲线。4.5 Grep 的有效性边界代码 vs 自然语言Milvus 的批评针对的是通用场景下的 token 开销。但在代码搜索这个具体场景下Grep 的表现可能比直觉预期的要好得多。一项系统性研究GrepRAG: An Empirical Study and Optimization of Grep-Like Retrieval for Code CompletionISSTA 26在 CrossCodeEval 和 RepoEval_Updated 两个代码基准数据集上做了严格对比让 LLM 自主生成 ripgrep 命令检索代码上下文然后用检索到的内容做代码补全。结果发现 即使是最朴素的单轮 Grep 检索代码补全效果也超过了基于 embedding 的 RAG 基线在 RepoEval_Updated 的 Python Line 补全任务上Naive GrepRAG 的 Exact Match 达到 38.61%而 Vanilla RAGBM25 embedding只有 24.99%。论文分析了 grep 在代码场景下成功的原因代码搜索的关键词 95% 是标识符类名36%、方法名41%、变量名18%。标识符本身就是代码的语义精确匹配恰好是最直接的检索方式。这和自然语言搜索不同自然语言中“词汇不匹配”是常态但代码中 getUserById 就是 getUserById不会被改述成 fetchPersonByIdentifier。不过这一切有个前提任务是代码搜索。一旦切换到自然语言问答这种场景结论会变得复杂得多。Zach Nussbaum 在 On the Lost Nuance of Grep vs. Semantic Search 里做过一组实测在 Natural Questions 数据集一个自然语言的问答数据集他直接用 ripgreprg -i -c把查询去掉停用词后作为关键词集合去搜做检索。初始的效果很差因为自然语言问答的 query 和答案文档之间常常存在严重的词汇不匹配query 里说的是概念文档里用的是同义词或改写。有意思的是只要加一步 LLM query expansion用一个便宜的小模型gpt-5-mini先把查询改写成一组更相关的关键词再把这些关键词喂给 Grep召回率就大约能提升5-10倍。换句话说来自 LLM 在查询端的语义理解能起到类似 embedding 的语义搜索效果。但即便做了这一步Grep 仍然追不上 embedding 在语义匹配上的能力当用户只记得某个概念的侧面特征、却想不起合适的关键词时向量检索依然是更合适的工具。代码里的函数名、类名是程序员亲手埋的精确锚点Grep 几乎总能命中自然语言里的一个概念可以有十几种表达就需要 LLM 或 embedding 帮忙把概念翻译成可能的关键词。Claude Code 选择放弃 embedding不是因为向量检索本身不行而是因为代码搜索恰好是 Grep 最适合的地方。需要指出的是无论是 GrepRAG 论文还是上述在 NQ 数据集上的测试采用的都是单轮检索没有“看结果不满意 → 换关键词再搜”的迭代过程。而 Claude Code 的搜索循环是多轮迭代的如第二章实战中的四轮搜索。多轮迭代理论上能进一步提升效果可以根据中间结果调整搜索方向但也意味着更多的 context 开销而这正是 Milvus 批评的痛点。多轮 grep 相比单轮到底能带来多大提升、又付出多大 context 代价目前还没有直接的实验数据。05总结RAG已死回到开头那个问题RAG 真的死了吗要回答这个问题得先问一件更基础的事我们说的 RAG 到底是什么如果按 Retrieval-Augmented Generation 本来的定义它指的是一个很宽的范式先检索相关内容再把检索结果塞进 context最后让模型基于这些内容生成回答。按这个定义Claude Code 做的事完全符合 RAG。它只是把检索这一层从 embedding 向量库换成了 LLM 驱动的 grep 和 glob整个“检索 → context → 生成”的骨架没动。但过去一年被反复唱衰的那个“RAG”指的其实是另一件更窄的事预先把代码分块、embedding写进向量库用户提问时再跑一次最近邻检索把 top-K 结果喂给模型。这是 RAG 最常见的一种落地形式但它只是范式的一种实现。所以更准确的说法是不是 RAG 死了而是“预先建索引、静态一次性检索”这种做 RAG 的方式在 某些场景下正在被替换掉。本文在上面已经解释了为什么在代码搜索这个具体场景上可以这么换总结有三个原因代码本身就是 Grep 友好的。 代码里的函数名、类名、常量本质是程序员埋进去的高精度锚点精确匹配恰好是最直接的检索方式。GrepRAG 的论文在 CrossCodeEval 等基准上验证了这一点单轮 grep 驱动的检索就能超过 embedding RAG 基线。这也解释了为什么连 Cursor 这种把语义索引当核心卖点的公司内部 system prompt 仍然把 grep_search 标为“主要探索工具”。开发者本地项目的规模撑得住暴力扫描。 4,500 个文件的项目 ripgrep 跑完只要 0.1 秒这个数量级根本用不着离线索引。“暴力搜索慢”的前提是数据大到暴力算法跑不动而大多数本地代码库离这个前提还差好几个数量级。Agent 带来的是检索模式的转变。 传统 RAG 是被动的系统在问题出现之前就预先决定“你可能需要看什么”一次性检索一批相关块塞进 context模型只能在这批给定的内容上做推理。而 Agent 时代的检索是主动的模型每一轮主动决定当前需要什么、用什么工具拿、拿到之后要不要继续找。第二章那四轮实战搜索就是主动搜索的具体形态每一步搜什么都由上一步的发现决定这条路径是任何预检索都猜不出来的。这种场景下Grep 的潜力能够充分发挥例如在4.5章节的实验中使用LLM对query进行改写后仅单轮搜索准确率就提升了5-10倍。这才是“RAG 已死”那批标题背后真正在发生的事死的不是检索增强生成这个范式而是代码搜索一定要靠 embedding 预索引这个默认假设。Claude Code 和 Codex 殊途同归地选择了零索引说明在代码搜索这个领域上用 LLM 驱动 Grep 已经是一个足够好、甚至更省心的替代方案。至于范围之外呢在自然语言问答这类软语义主导的场景里embedding 依然是重要的部分在更大规模的代码仓库上索引也无法被抛弃。总之技术的选择由数据的特性和规模决定不应该是信仰问题。学AI大模型的正确顺序千万不要搞错了2026年AI风口已来各行各业的AI渗透肉眼可见超多公司要么转型做AI相关产品要么高薪挖AI技术人才机遇直接摆在眼前有往AI方向发展或者本身有后端编程基础的朋友直接冲AI大模型应用开发转岗超合适就算暂时不打算转岗了解大模型、RAG、Prompt、Agent这些热门概念能上手做简单项目也绝对是求职加分王给大家整理了超全最新的AI大模型应用开发学习清单和资料手把手帮你快速入门学习路线:✅大模型基础认知—大模型核心原理、发展历程、主流模型GPT、文心一言等特点解析✅核心技术模块—RAG检索增强生成、Prompt工程实战、Agent智能体开发逻辑✅开发基础能力—Python进阶、API接口调用、大模型开发框架LangChain等实操✅应用场景开发—智能问答系统、企业知识库、AIGC内容生成工具、行业定制化大模型应用✅项目落地流程—需求拆解、技术选型、模型调优、测试上线、运维迭代✅面试求职冲刺—岗位JD解析、简历AI项目包装、高频面试题汇总、模拟面经以上6大模块看似清晰好上手实则每个部分都有扎实的核心内容需要吃透我把大模型的学习全流程已经整理好了抓住AI时代风口轻松解锁职业新可能希望大家都能把握机遇实现薪资/职业跃迁这份完整版的大模型 AI 学习资料已经上传CSDN朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费】