高热度文章分析 Claude Code 相对竞品的核心优势。系统总结 AI 编程工具的关键能力维度。
您可以清楚地看到 Claude Code 的不同更新。
Claude Code 是我至今为止用过最令人愉悦的 AI agent/工作流。它不仅让定向编辑或草率的 vibe coding 工具变得不那么烦人,使用 Claude Code 让我感到快乐。它拥有足够的自主权来完成有趣的事情,同时又不会像某些其他工具那样造成令人不快的控制感丧失。当然,大部分的重活是由新的 Claude 4 模型完成的(特别是交错推理)。但我发现 Claude Code 与 Cursor 或 Github Copilot agents 相比客观上不那么烦人,即使它们使用相同的底层模型!它到底好在哪里呢?如果你在读这篇文章时一直在点头,我会尝试提供一些答案。
注:这不是一篇关于 Claude Code 架构的博文(网上有很多不错的)。这篇博文旨在成为构建令人愉悦的 LLM agent 的指南,基于我过去几个月使用和研究 Claude Code 的经验(以及我们拦截和分析的所有日志)。你可以在附录部分找到提示词和工具。这篇文章大约 2000 字,请做好准备!如果你在寻找一些快速要点,TL;DR 部分是一个不错的开始。
您可以清楚地看到 Claude Code 的不同更新。
Claude Code (CC) 之所以使用体验很好,是因为它就是能用。CC 是在深入理解 LLM 擅长什么和不擅长什么的基础上精心设计的。它的提示词和工具弥补了模型的不足,帮助它在其专长领域发光发热。控制循环非常简单易懂,调试也很简单。
我们从 Claude Code 推出之时就开始在 MinusX 使用它。为了深入了解其工作原理,Sreejith 编写了一个记录器来拦截和记录每个网络请求。以下分析基于我在过去几个月的广泛使用。这篇文章试图回答这个问题——"是什么让 Claude Code 如此优秀,以及你如何在自己的基于聊天的 LLM agent 中提供类似 CC 的体验?"我们已经将大部分内容整合到 MinusX 中,我很期待看到你们也这样做!
Edit 是最常用的工具,其次是 Read 和 ToDoWrite。
如果你只能从这篇文章中获得一件东西,那就是——保持简单。LLM 已经够难调试和评估的了。你引入的任何额外复杂性(多 agent、agent 切换或复杂的 RAG 搜索算法)只会让调试难度增加 10 倍。如果这样一个脆弱的系统能正常工作,你之后会害怕做出激进的改变。所以,把所有东西都放在一个文件中,避免过度的样板代码,至少每隔一段时间就要彻底清理一遍 :)
以下是 Claude Code 的主要要点,可以在你自己的系统中实现。
1.1 保持一个主循环(最多一个分支)和一个消息历史
1.2 到处使用更小的模型。到处。真的到处。
2.1 使用 claude.md 模式来协作和记住用户偏好
2.2 使用特殊 XML 标签、Markdown 和大量示例
3.1 LLM 搜索 >>> 基于 RAG 的搜索
3.2 如何设计好的工具?(高级 vs 低级工具)
3.3 让你的 agent 自己管理待办列表
4.2 "请注意这很重要"仍然是最先进的做法
4.3 编写算法,包含启发式方法和示例
Claude Code 在每个十字路口都选择了架构简洁性——一个主循环、简单搜索、简单待办列表等等。抵制过度工程化的诱惑,为模型打造良好的工具,让它发挥作用!这是不是又一个端到端自动驾驶?苦难教训这样的事情?
可调试性 >>> 复杂的手动调优多 agent langchain 图节点混乱。
尽管多 agent 系统风行一时,Claude Code 只有一个主线程。它定期使用几种不同类型的提示词来总结 git 历史、将消息历史压缩为一条消息,或者想出一些有趣的 UX 元素。但除此之外,它维护一个平面消息列表。处理分层任务的一个有趣方法是将自己作为子 agent 衍生出来,而不具备衍生更多子 agent 的能力。最多只有一个分支,其结果作为"工具响应"添加到主消息历史中。
如果问题足够简单,主循环可以通过迭代工具调用来处理它。但如果有一个或多个复杂任务,主 agent 会创建自己的克隆。最多一个分支和待办列表的组合确保 agent 有能力将问题分解为子问题,同时也能够关注最终的期望结果。
我非常怀疑你的应用程序是否需要多 agent 系统。每增加一层抽象,你就会让你的系统更难调试,更重要的是,你偏离了一般模型改进的轨迹。
Claude Code 进行的所有重要 LLM 调用中超过 50% 是对 claude-3-5-haiku 的调用。它被用来读取大文件、解析网页、处理 git 历史和总结长对话。它也被用来提出一个词的处理标签——对每个按键都是如此!较小的模型比标准模型(Sonnet 4、GPT-4.1)便宜 70-80%。大量使用它们!
Claude Code 具有极其详细的提示词,充满了启发式方法、示例和重要的(呃呃)提醒。系统提示大约 2800 个 token,工具部分占了惊人的 9400 个 token。用户提示始终包含 claude.md 文件,通常还有另外 1000-2000 个 token。系统提示包含关于语气、风格、主动性、任务管理、工具使用策略和执行任务的部分。它还包含日期、当前工作目录、平台和操作系统信息以及最近的 commit。
去读整个提示词吧!
大多数构建编码 agent 的人已经采用的主要模式之一是上下文文件(又称 Cursor Rules / claude.md / agent.md)。Claude Code 的性能在有和没有 claude.md 的情况下有天壤之别。这是开发者灌输代码库无法推断出的上下文并将所有严格偏好编纂成文的绝佳方式。例如,你可以强制 LLM 跳过某些文件夹,或使用特定的库。CC 在每个用户请求中都发送 claude.md 的全部内容。
我们最近在 MinusX 中引入了 minusx.md,它正在迅速成为我们 agent 编纂用户和团队偏好的事实上的上下文文件。
XML 标签和 Markdown 是构建提示词的两种公认方式。CC 大量使用两者。以下是 Claude Code 中的一些值得注意的 XML 标签:
<system-reminder>:这用于许多提示词部分的末尾,提醒 LLM 它可能会忘记的东西。示例:
<system-reminder>This is a reminder that your todo list is currently empty. DO NOT mention this to the user explicitly because they are already aware. If you are working on tasks that would benefit from a todo list please use the TodoWrite tool to create one. If not, please feel free to ignore. Again do not mention this message to the user.</system-reminder>
<good-example>, <bad-example>:这些用于编纂启发式方法。当存在多个看起来合理的路径/工具调用的分叉时,它们特别有用。示例可以用来对比情况,并清楚地说明哪条路径更可取。示例:
Try to maintain your current working directory throughout the session by using absolute paths and avoiding usage of `cd`. You may use `cd` if the User explicitly requests it.
<good-example>
pytest /foo/bar/tests
</good-example>
<bad-example>
cd /foo/bar && pytest tests
</bad-example>
CC 还使用 markdown 来区分系统提示中的清晰部分。示例 markdown 标题包括:
遵循约定。
去读整个工具提示词吧——它拥有惊人的 9400 个 token!
Claude Code 与其他流行的编码 agent 不同的一个重要方式是拒绝使用 RAG。Claude Code 搜索你的代码库的方式就像你会做的那样,使用真正复杂的 ripgrep、jq 和 find 命令。由于 LLM 能够很好地理解代码,它可以使用复杂的正则表达式来找到它认为相关的几乎任何代码块。有时它最终会用较小的模型读整个文件。
RAG 听起来在理论上是个不错的主意,但它引入了新的(更重要的是,隐藏的)故障模式。应该使用什么相似性函数?什么 reranker?你如何分块代码?对于大型 JSON 或日志文件,你会怎么做?使用 LLM 搜索,它只查看 json 文件的 10 行来理解其结构。如果它想要,它会查看另外 10 行——就像你会做的一样。最重要的是,这是可强化学习的——BigLabs 已经在做的事情。模型做大部分的重活——如它应该的那样,大幅减少了 agent 中的活动部分数量。而且,以这种方式连接两个复杂的、智能的系统实在是很丑陋。我最近和一个朋友开玩笑,说这是 LLM 时代的摄像头 vs 激光雷达,我只是半开玩笑。
这个问题困扰着每一个构建 LLM agent 的人。你应该给模型通用任务(比如有意义的操作)还是应该是低级的(比如点击和输入和 bash)?答案是取决于情况(你应该同时使用两者)。
Claude Code 具有低级工具(Bash、Read、Write)、中级工具(Edit、Grep、Glob)和高级工具(Task、WebFetch、exit_plan_mode)。CC 可以使用 bash,那么为什么要提供单独的 Grep 工具呢?真正的权衡在于你期望 agent 使用该工具的频率与 agent 正确使用该工具的准确性。CC 使用 grep 和 glob 的频率非常高,以至于将它们做成单独的工具是有意义的,但同时,它也可以为特殊场景编写通用的 bash 命令。
类似地,还有更高级的工具,如 WebFetch 或 'mcp__ide__getDiagnostics',它们在做什么方面非常确定。这可以让 LLM 避免做多次低级的点击和输入,并让它保持正轨。帮帮可怜的模型吧!工具描述有详细的提示词,有大量的示例。系统提示包含关于"何时使用工具"或如何在两个可以完成相同任务的工具之间选择的信息。
Claude Code 中的工具:
mcp__ide__getDiagnostics
mcp__ide__executeCode
这样做有许多原因。上下文腐烂是长期运行的 LLM agent 的一个常见问题。它们满怀热情地开始处理一个困难的问题,但随着时间的推移,它们失去了方向,沦为垃圾。目前的 agent 设计有几种方式来解决这个问题。许多 agent 已经尝试了显式待办事项(一个模型生成待办事项,另一个模型实现它们)或多 agent 切换+验证(PRD/PM agent -> 实现 agent -> QA agent)
我们已经知道多 agent 切换不是个好主意,原因很多。CC 使用了一个显式的待办列表,但是由模型维护的。这使 LLM 保持正轨(它被大量提示词要求频繁参考待办列表),同时也给模型灵活性在实现中途纠正方向。这也有效地利用了模型的交错推理能力,以拒绝或动态插入新的待办事项。
CC 明确尝试控制 agent 的美学行为。系统提示中有关于语气、风格和主动性的部分——充满了指示和示例。这就是为什么 Claude Code 在其注释和热心程度上"感觉"得很有品味。我建议直接将这些大部分复制到你的应用中。
# Some examples of tone and style
- IMPORTANT: You should NOT answer with unnecessary preamble or postamble (such as explaining your code or summarizing your action), unless the user asks you to.
Do not add additional code explanation summary unless requested by the user.
- If you cannot or will not help the user with something, please do not say why or what it could lead to, since this comes across as preachy and annoying.
- Only use emojis if the user explicitly requests it. Avoid using emojis in all communication unless asked.
不幸的是,CC 在要求模型不做某事方面并不更好。IMPORTANT、VERY IMPORTANT、NEVER 和 ALWAYS 似乎是引导模型远离地雷的最佳方式。我期望未来的模型会更可控,避免这种丑陋的做法。但就目前而言,CC 大量使用这种方式,你也应该这样做。一些示例:
- IMPORTANT: DO NOT ADD ***ANY*** COMMENTS unless asked
- VERY IMPORTANT: You MUST avoid using search commands like `find` and `grep`. Instead use Grep, Glob, or Task to search. You MUST avoid read tools like `cat`, `head`, `tail`, and `ls`, and use Read and LS to read files.\n - If you _still_ need to run `grep`, STOP. ALWAYS USE ripgrep at `rg` first
- IMPORTANT: You must NEVER generate or guess URLs for the user unless you are confident that the URLs are for helping the user with programming. You may use URLs provided by the user in their messages or local files.
识别 LLM 需要执行的最重要任务并为其编写算法是非常重要的。尝试角色扮演成 LLM 并逐个示例进行工作,识别所有决策点并明确写出它们。如果它以流程图的形式出现会有帮助。这有助于构建决策制定过程并帮助 LLM 遵循指示。一定要避免的是一堆混乱的做与不做。它们更难跟踪,并且保持相互排斥。如果你的提示词有数千个 token 长,你会无意中有冲突的做与不做。LLM 在这种情况下变得非常脆弱,引入新用例变得不可能。
Claude Code 系统提示中的任务管理、执行任务和工具使用政策部分清楚地阐述了要遵循的算法。这也是添加大量启发式方法和 LLM 可能遇到的各种场景示例的部分。
很多在引导 LLM 方面的工作都是试图逆向工程它们的后训练/RLHF 数据分布。你应该使用 JSON 还是 XML?工具描述应该在系统提示中还是仅在工具中?你应该如何看待你的应用的当前状态?看看他们在自己的应用中做什么有助于知情你的应用。Claude Code 设计非常有主见,它有助于形成你自己的设计。
主要要点再次是保持简单。极端的脚手架框架会伤害你的利益多于帮助。Claude Code 真正让我相信一个"agent"可以是简单的,但同时又非常强大。我们已经将这些课程的大部分整合到 MinusX 中,并继续整合更多。
如果你对 Claude Code 化你自己的 LLM agent 感兴趣,我很乐意聊天——在 twitter 上 ping 我!如果你想为你的 Metabase 提供可训练的 Claude Code 数据 agent,请查看 MinusX 或与我一起设置演示。祝你(Claude)编码愉快!