堪称全球最强的 AI 编程工具 Claude Code 的 50 多万行源码泄露了!一家以 AI 安全著称的公司,自己却在代码发布环节翻了车。

针对这件事,我只想说两个字:

感谢!

这份源码对学技术的同学来说简直是宝藏资源啊,过年了过年了!

那 Claude Code 源码具体是怎么泄露的?源码里有哪些精妙的设计?为什么它能做到 AI 编程工具的天花板?

下面我利用 AI 带大家一起学习,学会它优秀的设计后,你可以改进自己的 AI 项目、或者面试的时候吊打一下面试官。

⭐️ 本文对应视频版:https://bilibili.com/video/BV1ZB9EBmEAU

到底是怎么泄露的

Claude Code 是通过 npm 发布的,你可以把 npm 理解为程序员的「应用商店」,开发者把写好的工具打包上传到这里,别人一行命令就能安装。

正常情况下,代码上线之前会经过「压缩混淆」处理,变成一坨人类看不懂的东西。

但在开发的时候,为了方便定位 Bug,代码打包工具会自动生成一个叫 Source Map 的文件,它相当于一张「翻译对照表」,能把加密后的代码还原成原始版本。但是这个文件只能在开发环境用,上线时必须删掉!

结果 Anthropic 的工程师在发布 Claude Code 2.1.88 版本的时候,打包工具 Bun 默认生成了 Source Map 文件,而他们忘了在发布配置里把 .map 文件排除掉。于是一个 59.8 MB 的 cli.js.map 文件就这么被直接发到了公开的 npm 仓库。

这个 map 文件本质上是一个 JSON,里面有两个关键数组,sources 存着所有文件的路径,sourcesContent 存着每个文件的完整源码,两者一一对应。只要写个脚本解析一下这个 JSON,按路径把内容写出来,所有源码就原样还原了。

而且据说 map 文件里甚至还引用了一个 Cloudflare R2 存储桶的公开地址,点进去直接就能下载打包好的完整源码目录,连脚本都不用写。

安全研究员 Chaofan Shou 最先发现了这个问题并发到了 X 上:

然后几个小时之内 GitHub 上就冒出了好几个镜像仓库,源码传遍了整个互联网,其中有个仓库不到 1 天就快 10w Star 了(而且仓库里早就没有 Claude Code 源码了)……

更搞笑的是,去年 2 月 Claude Code 刚发布的时候就出过一模一样的事故,同样的错误犯了两次!

怕不是 Claude Code 团队的开发者 Vibe Coding 上瘾,连基本操作都忘了?

源码里都有什么

这次泄露的是 Claude Code 客户端的源码,包括 1906 个 TypeScript 源文件、大约 51.2 万行代码。涵盖了 Agent 循环引擎、40 多个内置工具的完整实现、系统提示词的组装逻辑、记忆系统、上下文压缩、权限管控机制,还有一堆没上线的隐藏功能。但是不包括服务端的模型训练代码和 API 后端逻辑。

Claude Code 完整架构

整个项目用的是 React Ink 框架,简单说就是用 React 来写命令行界面,你可以理解为「在终端里写网页」。所以 Claude Code 的命令行交互才会比很多传统工具丝滑。

我用 AI 把它的架构从上到下梳理了一遍,大致分为 6 层:

1)最上面是 CLI 和界面层,你在终端里看到的所有交互都是这一层负责的

2)往下是 Agent 循环引擎,你可以把它理解为 Claude Code 的大脑,所有的决策都从这里发出

3)再往下是工具系统,40 多个内置工具加上 MCP 扩展

4)然后是记忆系统,解决 AI 聊着聊着就断片儿的老毛病

5)上下文压缩系统,解决 token 越来越贵、窗口越来越满的问题

6)最底层是权限和安全系统

Claude Code 分层架构图

接下来咱们结合源码,看看每个模块具体是怎么实现的,Claude Code 是怎么做到这么好用的?

一、Agent 循环

大家都知道现在的 AI 编程工具早已经不是简单的「一问一答」了,而是能连续执行、自主完成任务的 AI Agent。

可能有同学会觉得,这背后一定是什么特别复杂的架构,用了什么 AI Agent 开发框架、什么多 Agent 协作之类的吧?

但我打开负责核心对话循环的 query.ts 文件一看,好家伙,最核心的代码其实就是一个 while(true) 无限循环!

// query.ts
async function* queryLoop(params: QueryParams, consumedCommandUuids: string[]) {
  let state: State = {
    messages: params.messages,
    toolUseContext: params.toolUseContext,
    autoCompactTracking: undefined,
    maxOutputTokensRecoveryCount: 0,
    hasAttemptedReactiveCompact: false,
    turnCount: 1,
    // ...
  }

  // eslint-disable-next-line no-constant-condition
  while (true) {
    // 1. 上下文压缩(防止 token 爆炸)
    // 2. 调用大模型,流式获取响应
    // 3. 解析模型返回的工具调用
    // 4. 执行工具,获取结果
    // 5. 把结果追加到对话历史
    // 6. 如果没有新的工具调用,结束;否则继续循环
  }
}

就是这么朴素的一个循环。每一轮迭代里,程序先做上下文压缩、再调用大模型拿到响应,如果模型说「我要用某个工具」就去执行,把结果追加到对话历史里,然后进入下一轮,一直循环工作直到活儿干完了才

Logo

欢迎加入DeepSeek 技术社区。在这里,你可以找到志同道合的朋友,共同探索AI技术的奥秘。

更多推荐