Claude Code 是如何构建的

转载

作者: Gergely Orosz 发布日期: 2025年9月24日 来源: The Pragmatic Engineer


概述

Claude Code 自今年 5 月正式发布以来,在开发者世界中掀起了风暴。该工具目前年化收入超过 5 亿美元,自 5 月发布以来的三个月内,使用量增长了超过 10 倍。

我最近与 Claude Code 的两位创始工程师进行了深入交流:Boris Cherny(提出原始原型想法的项目创始工程师)和 Sid Bidasaria(Claude Code 的第 2 号工程师,subagents 功能的创建者),以及创始产品经理 Cat Wu。

我了解了 Claude Code 是如何构建的,并深入了解了成功的"AI 优先工程团队"是如何运作的。这有点像窥探水晶球,看到了快速发展的初创公司未来的运作方式。好消息是,软件工程师在这个未来中仍然非常有需求......

本文涵盖内容

  1. 一切是如何开始的 - Claude Code 的想法来源于一个使用 Claude 来告知工程师工作时正在听什么音乐的命令行工具。在获得文件系统访问权限后,它在 Anthropic 内部像野火一样传播开来。如今,Claude Code 已拥有自己成熟的团队。

  2. 技术栈和架构 - TypeScript、React、Ink、Yoga 和 Bun。技术栈的选择是为了"分布内"并发挥模型的优势。有趣的事实:Claude Code 中 90% 的代码是由其自身编写的!

  3. 以天而不是周为单位构建和发布功能 - 团队以极快的速度工作,每个工程师每天大约发布 5 个版本。原型制作速度惊人:我们为一个新功能制作了 10 多个实际原型。看起来 AI agents 确实加速了迭代过程。

  4. 重新设计终端用户体验 - Claude Code 为终端用户体验带来了许多创新功能,这些功能在我们能够与 LLM 驱动的终端交互之前是不需要的。让我们来看看其中的一些。

  5. "AI 优先"软件工程是什么样的 - 使用 AI agents 进行代码审查和测试、测试驱动开发(TDD)的复兴、自动化事件响应,以及谨慎使用功能标志。这是否预示着未来"AI 优先"工程团队的工作方式?

  6. 构建子代理 - 深入了解 subagents 功能是如何在短短三天内构建完成的,其中两天的工作被废弃。

  7. AI 辅助工程团队的未来? - 工程团队可以从 Anthropic 的运作中学到什么,以及需要记住哪些使其独特但可能不太容易转移的东西。


1. 一切是如何开始的

Boris Cherny 于 2024 年 9 月加入 Anthropic,并开始使用 Claude 3.6 模型构建一系列不同的原型。当时,他想更熟悉 Anthropic 的公共 API。Boris 回忆道:

"我开始在终端中使用 Claude 进行实验。第一个版本非常简陋:它无法读取文件,无法使用 bash,完全不能做任何工程相关的事情。但它可以与计算机交互。

我将这个原型连接到 AppleScript:它可以告诉我工作时正在听什么音乐。然后它还可以根据我的输入更改正在播放的音乐。

这是一个很酷的演示,但并不是很有趣。"

与此同时,Cat Wu 正在研究 AI agents 的计算机使用情况,以及 agents 使用它们时产生的新能力。在与 Cat 交谈后,Boris 有了给终端提供比仅使用 AppleScript 更多功能的想法。他说:

"我尝试给它一些与文件系统和批处理交互的工具;它可以读取文件、写入文件和运行批处理命令。

突然间,这个 agent 变得非常有趣。我在我们的代码库中运行它,并开始询问相关问题。Claude 然后开始探索文件系统并读取文件。它会读取一个文件,查看导入,然后读取导入中定义的文件!它一直继续,直到找到好的答案。Claude 探索文件系统对我来说是惊人的,因为我从未使用过这样的工具。

在 AI 中,我们谈论"产品过载",这就是我们在原型中发现的。产品过载意味着模型能够做特定的事情,但 AI 运行其中的产品并没有以能够捕捉这种能力的方式构建。我发现 Claude 探索文件系统是纯粹的产品过载。模型已经能够做到这一点,但没有围绕这个能力构建产品!"

产品市场匹配

Boris 开始在工作中每天使用他的原型。然后他与将成为 Claude Code 核心团队的成员分享了它,其他开发人员也开始每天使用它。

Boris 和 Claude Code 团队在 2024 年 11 月发布了适合内部测试的版本------距离第一个原型两个月后。第一天,大约 20% 的工程团队使用了它,到第五天,50% 的工程师都在使用 Claude Code。那时,Boris 相当确信 Claude Code 在外部世界也会成为热门产品。

但对于是否要发布这个工具,还是仅供内部使用,内部存在争议。Boris 回忆道:

"我们实际上甚至不确定是否要公开发布 Claude Code,因为我们认为这可能成为我们的竞争优势,就像我们的'秘密武器':如果它给我们带来优势,为什么要发布它?

最终,我们达成了以下立场:

  • Anthropic 的核心是一家模型安全公司
  • 我们了解模型安全和能力的方式是制作人们使用的工具
  • Claude Code 几乎肯定会成为人们使用的工具,因为整个 Anthropic 都对它上了瘾

因此,通过发布这个工具,我们可以更多地了解模型安全性和能力。"

组建 Claude Code 工程团队

最初,团队只有 Boris。2024 年 11 月,Sid Bidasaria 加入 Anthropic 并遇到了早期版本的 Claude Code。他喜欢这个想法并加入了 Boris 的项目。

他们的两人团队工作方式有很多自由度。Sid 告诉我:

"我们大部分工作都是非常快速地制作原型,并构建展示底层模型强大能力的产品。团队内部没有正式流程:一切都超级灵活。我们可以几乎随心所欲地工作,所以我们一直选择最有前景的想法。"

到 7 月,团队增长到约 10 名工程师,此后招聘一直在继续。如今,它是一个成熟的完整产品团队,包括工程师、产品管理、设计和数据科学人员------而且他们还在招聘。

Claude Code 不仅面向编码人员

如今,超过 80% 编写代码的 Anthropic 工程师日常使用 Claude Code,但不仅仅是他们。Boris 说:

"我走进办公室时,瞥了一眼一位数据科学家的屏幕。他正在运行 Claude Code。我说:'等等,你为什么在运行 Claude Code?'他说:'我搞清楚了如何让这个东西为我写查询。'

这些天,当我走过数据科学家的一排时,他们都在运行 Claude Code------其中许多人同时运行多个实例------运行查询、创建可视化以及做其他类型的有帮助的工作。"

有趣的一点是,Boris 心中只想着为软件工程师设计 Claude Code------因此得名!但该产品表明它在其他领域也有进一步的实用性。

团队规模翻倍的同时提高工程产出

如果我们以每个工程师的 pull requests 作为指标;当工程团队规模迅速翻倍时,这个过程通常会拉低这个指标。这是因为现有工程师花更多时间培训新同事,编码时间更少,而新加入者需要先熟悉情况。像任何指标一样,每个工程师的 pull requests(PR)不是完美的指标,但它确实给人一种迭代节奏的感觉。PR 吞吐量被 GitHub、Dropbox、Monzo、Adyen 等公司衡量。

但 Anthropic 在团队规模翻倍的同时看到了 67% 的 PR 吞吐量增长------这要归功于 Claude Code。平均 PR 合并指标下降本来是正常的,但实际上却上升了!这归功于 Claude Code:工程师们使用它能更快地完成 PR。在一系列可能幸运的事件中,Anthropic 在 Claude Code 被整个工程部门采用的大致时间将工程人员数量翻了一番。

我也注意到,使用 Claude Code 完成工作明显更快,而且我在编码任务上取得了更好的进展。当我构建 Claude Code 可以通过运行程序并检查输出来验证代码正确性的东西时,它也很有帮助。


2. 技术栈和架构

Claude Code 的技术栈:

  • TypeScript - Claude Code 建立在这种语言之上
  • React with Ink - UI 使用 React 编写,使用 Ink 框架实现交互式命令行元素
  • Yoga - 布局系统,由 Meta 开源。它是一个基于约束的布局系统,效果很好。基于终端的应用程序有需要支持所有终端尺寸的缺点,所以你需要一个布局系统来实用地做到这一点
  • Bun - 用于构建和打包。团队选择它是为了与 Webpack、Vite 等其他构建系统相比的速度优势

Ink 框架是一个出色的组件,允许在终端中创建美观的 UI。例如,要创建这个 UI

你可以用 React 编写代码:

ini 复制代码
import React, { useState, useEffect } from 'react';
import { render, Text } from 'ink';

const Counter = () => {
  const [counter, setCounter] = useState(0);

  useEffect(() => {
    const timer = setInterval(() => {
      setCounter(previousCounter => previousCounter + 1);
    }, 100);

    return () => {
      clearInterval(timer);
    };
  }, []);

  return <Text color="green">{counter} tests passed</Text>;
};

render(<Counter />);

npm 用于分发 Claude Code。它是 Node 生态系统中最流行的包管理器。要开始使用 Claude Code,你需要安装 Node 18 或更高版本,然后运行:

bash 复制代码
npm install -g @anthropic-ai/claude-code

完成后,你可以使用 claude 命令启动工具。

技术栈选择:分布内

技术栈的选择是为了 Claude 模型的"分布内"。在 AI 中,有"分布内"和"分布外"这两个术语。"分布内"意味着模型已经知道如何做,"分布外"意味着它不擅长。

团队希望为 Claude 选择一个它已经很擅长的"分布内"技术栈。TypeScript 和 React 是模型非常擅长的两种技术,因此是合理的选择。然而,如果团队选择了 Claude 不太擅长的更奇特的技术栈,那将是"分布外"技术栈。Boris 总结道:

"使用分布外技术栈,模型仍然可以学习。但你必须指导它并投入工作。我们想要一个不需要我们教的技术栈:一个 Claude Code 可以自我构建的技术栈。而且效果很好;Claude Code 中大约 90% 的代码是用 Claude Code 编写的。"

架构:选择最简单的选项

有趣的是,就模块、组件和复杂的客户端业务逻辑而言,Claude Code 并没有那么多内容。对于一个执行诸如遍历文件系统和代码库等相当复杂任务的工具来说,这有点令人惊讶!但 Claude Code 只是 Claude 模型之上的一个轻量级外壳。这是因为模型完成了几乎所有的工作:

  • 定义 UI,并暴露钩子让模型修改它
  • 暴露工具供模型使用
  • ......然后让开道路

Claude Code 团队尝试编写尽可能少的业务逻辑。Boris 告诉我:

"这听起来可能很奇怪,但我们构建这个东西的方式是希望人们尽可能原始地感受模型。我们相信模型可以做比今天产品允许的更多的事情。

当你看到很多编码产品时,它们阻碍了模型;它们通过添加 UI 元素和其他混乱的部分来添加脚手架,所以在这些工具中运行的模型感觉像是在单腿跳跳。旨在对用户有帮助的功能最终限制了模型。因此,我们尽量使 UI 尽可能最小。

每次有新模型发布时,我们都会删除一堆代码。例如,对于 4.0 模型,我们删除了大约一半的系统提示,因为我们不再需要它了。我们尽量在模型周围放置尽可能少的代码,这包括最小化提示和最小化工具数量。我们不断删除工具并试验新的工具。"

本地运行而非虚拟化

Claude Code 不使用虚拟化------它在本地运行。一个主要的设计决定是是否在虚拟机中运行 Claude Code------比如在 Docker 容器中,或在云端------从而创建沙箱环境。但团队决定使用本地运行的版本,因为:简单!Boris 说:

"对于每个设计决定,我们几乎总是选择最简单的选项。对于"在哪里运行批处理命令?"和"从哪里读取文件系统?"这些问题的最简单答案是什么?就是在本地做。

所以我们选择了这样:Claude Code 在本地运行批处理命令,并读写文件系统。没有虚拟化。"

权限系统

Claude Code 最复杂的部分是权限系统。在本地运行 Claude Code 的风险是 agent 可能会做它不应该做的不可逆转的事情,比如删除文件。但这如何安全地完成呢?

再次,团队选择了简单性,并构建了一个在执行操作之前寻求权限的权限系统。然后用户可以决定:

  • 授予权限一次
  • 为未来的会话也授予权限
  • 拒绝权限

Boris 告诉我,正确处理权限需要努力:

"我们最重要的原则是:如果你开始运行 Claude Code,它不应该在没有权限的情况下更改你系统上的东西。这可能是危险的。

但是,我们也应该给人们提供选择退出的方式,比如说出诸如"实际上,在我工作的上下文中,我不想每次都给予权限"这样的话。

不过,权限系统中有很多细微差别。例如,当命令进来时,我们对其进行静态分析,以检查这是否是设置文件中(settings.json 文件中)已经允许的内容。

设置系统是一个多层系统,可以按项目、按用户和按公司进行配置。你还可以与团队共享设置。我们观察到团队共享设置文件,将命令列入白名单,这样 Claude Code 就不会请求权限,比如检查到源代码控制中。"

其他功能

Claude Code 在某些方面很简单,但有很多功能增加了其复杂性。其中一些已被记录。值得注意的是:

  • Hooks:为 Claude Code 创建自定义 shell 命令
  • MCP 支持:通过连接到 MCP 服务器给 Claude Code 更多功能。请参阅我们关于模型上下文协议(MCP)的深度解析
  • GitHub 和 GitLab 支持:使用 GitHub Actions 并将 Claude Code 集成到 GitLab CI/CD 中
  • 输出样式 :能够切换输出样式,或定义自己的样式。可以切换的内置输出样式包括:
    • 解释性:向你解释实现选择
    • 学习性:协作风格,Claude 要求你自己做小任务。这是一个非常聪明的方法来保持参与度、动手实践和学习!对于经验较少的工程师或那些不熟悉的人来说,这可能是一个很好的学习方式
  • 配置:使用各种配置文件和设置来配置你的终端、模型、状态行等
  • Subagents:下文将详细介绍
  • 企业功能:设置身份和访问管理(IAM)以在整个组织中使用 Claude Code,并访问组织范围的分析以跟踪使用情况
  • Claude Code SDK:使用驱动 Claude Code 的 agent 构建自定义 AI agents
  • ......以及 Claude Code 中最近新功能的汇总

3. 以天而不是周为单位构建和发布功能

对于一个大约十几名工程师的团队来说,他们工作得非常快:

  • 每天约 60-100 次内部发布 - 每当工程师对 Claude Code 进行更改时,他们会在内部发布一个新的 npm 包。Anthropic 的每个人都使用内部版本,开发团队会获得快速反馈。

  • 夏季期间,工程师每天推动大约 5 个 pull requests - 这比大多数科技公司每天 1-2 个 pull requests 的正常速度快得多。

  • 每天 1 次外部发布 - 几乎每天都会发布新版本作为部署的一部分。

2 天内 20 个原型:构建 todo 列表

这种开发让我惊讶的是,团队比我所习惯的看到的多得多地使用 Claude Code 进行原型制作。例如,Boris 向我展示了他在两天内几个小时内为新功能 todo 列表制作了大约 20 个原型。

他慷慨地分享了他为各种迭代使用的实际提示。每次之后,Boris 会:

  • 有时调整结果
  • 尝试使用它
  • 如果感觉良好,与同事分享以获得反馈
  • 当感觉不对时,他用新的提示构建一个新原型

原型 #1:显示完成的 todos

想法:todo 列表是跟踪 Claude 进展的最简单方法之一,所以他们尝试将列表放在最近一次工具调用的正下方。

提示:

rust 复制代码
> make it so instead of todos showing up as they come in, we hide the tool use and result for todos, and render a fixed todo list above the input. title it "/todo (1 of 3)" in grey

看起来如何:

原型 #2:在底部显示进度

另一个变体是内联显示每个 todo 更新。

提示:

vbnet 复制代码
> actually don't show a todo list at all, and instead render the tool used inline, as bold headings when the model starts working on a todo. keep the "step 2 of 4" or whatever, and add middot /todo to see after in grey

看起来如何:

原型 #3 和 #4:交互式药丸

如果 todos 是一个交互式药丸(控制台底部的一个矩形),你可以拉起来查看进度,就像后台任务一样?

提示和输出:

css 复制代码
> also add a todo pill under the text input, similar to bg tasks. it should render "todos: 1 of 3" or whatever

原型 #3

shell 复制代码
> make the pill interactive, like the bg tasks pill

原型 #4

原型 #5 和 #6:使用抽屉

如果我们有一个'抽屉'可以滑入并在旁边显示 todos 怎么样?

提示和输出:

sql 复制代码
> actually undo both the pill and headings. instead, make the todo list render to the right of the input, vertically centered with a grey divider. show it when todos are active, hide it when it's done

原型 #5,todos 作为右侧的"抽屉"。参见动画版本

vbnet 复制代码
> it's a little jumpy, can you also animate it like a drawer

原型 #6。参见动画版本

原型 #7、8 和 9:可见性实验

为了使 todo 列表尽可能可见,Boris 尝试让它始终显示在输入上方。

提示和输出:

css 复制代码
> actually what if you show the todo list above the input instead

原型 #7

shell 复制代码
> truncate at 5 and show "... and 4 more" or whatever

原型 #8

arduino 复制代码
> add a heading "Todo:" in grey text

原型 #9

原型 #10-20:移动加载动画 UI 元素

Boris 继续尝试 todo 列表可见性应该放在哪里,经过几个更多的原型后,最终将 todo 列表移到了加载动画,最大化了可见性,并开始感觉良好。经过几次迭代后,他们有了最终公开发布的版本。

在大约原型 #20 时,在尝试了可见性和加载动画后

再一次迭代

团队从社区收到了很多反馈,他们希望能够看到所有的 todos。所以团队添加了用 CTRL + T 切换它们的能力。这就是现在实时运行的功能!

这个迭代(大约 #21 左右)目前正在生产中------按 Tab 键切换正在执行的步骤列表

快速原型制作

每天构建和测试 5-10 个原型想法是可能的,使用 AI agents。原型制作过去非常耗时,如果有两天时间进行原型制作,到结束时能构建两个不同的原型就很幸运了。但现在,agents 可以非常快地构建原型,所以每天测试 5-10 个原型很容易做到,就像 Claude Code 团队所做的那样。

我不建议每个人都能这么快地构建那么多原型,但我认为忘记原型制作过去需要多长时间是明智的:这些工具改变了原型制作可以多快!

这些原型制作中的很多都是关于让 UI"感觉良好":你可以在这个线程中看到动画原型。我建议观看原型步骤的视频,以了解功能是如何演变的,以及 Boris 如何不断尝试新想法,将其缩小到今天工具中 todo 列表的样子。


相关推荐
Keely402856 小时前
Claude 配置使用墨刀MCP(modao-proto-mcp)
前端·aigc·claude
jump_jump1 天前
Claude vs Doubao Seek Code 产码能力对比
ai编程·claude·代码规范
小溪彼岸1 天前
Claude发布新功能Agent Skills,让你的Agent更专业
aigc·claude
yaocheng的ai分身2 天前
如何使用Superpowers MCP强制Claude Code在编码前进行规划
claude
yaocheng的ai分身2 天前
我如何使用每一个 Claude Code 功能
claude
yaocheng的ai分身2 天前
使用 Claude Code 优化博客写作:我的完整工作流程
claude
yaocheng的ai分身3 天前
【转载】Claude Code 帮我整理了笔记
claude
webmote3 天前
使用Claude Code进行编程——国内用户使用指南
ai编程·claude·代理·码农·claude code
撒币使我快乐4 天前
Windows安装Claude Code全流程
linux·windows·claude