乐于分享
好东西不私藏

Claude Code 源码泄露:拆解核心原理

Claude Code 源码泄露:拆解核心原理

Claude Code 源码泄露:拆解核心原理

第一部分:事件回顾

先快速说说发生了什么。

Anthropic 在 npm 上发布 Claude Code 包的时候,不知道是故意的还是手滑,把 Source Map 文件一起发了上去

Source Map 是什么?简单说就是”调试用的地图”。线上产品应该用压缩混淆后的代码,Source Map 是给开发者调试用的,不应该发布到生产环境。

但 Anthropic 发了。结果就是任何人下载这个包,解开一看 .map 文件,就能把压缩后的代码还原成完整的 TypeScript 源码——变量名、注释、目录结构,全在那儿。

这个消息最早是 Twitter 用户 @Fried_rice 发现的,然后就是你们看到的那个 GitHub 仓库。


第二部分:技术栈概览

在开始喷代码质量之前,先看看 Claude Code 用的是什么技术栈。

运行时:Bun语言:TypeScript 严格模式CLI UI:React + Ink(给 CLI 用的 React)CLI 参数解析:Commander.js模式验证:Zod v4代码搜索:ripgrep协议:MCP SDK,LSP认证:OAuth 2.0,JWT,macOS Keychain特性开关:GrowthBook遥测:OpenTelemetry + gRPC

有意思的几个点:

Bun 而不是 Node.js——Bun 号称比 Node.js 快几倍,Anthropic 选它可能就是为了 CLI 的启动速度。

React + Ink——用 React 写 CLI 界面,对前端开发者非常友好,降低了门槛。

Zod v4——运行时类型验证,用在工具输入输出上,确保 LLM 调用的工具参数是正确的。


第三部分:好用的核心原因

先说说 Claude Code 为什么好用。这个问题不吹不黑,它确实解决了实际问题。

原因一:工具调用 Loop

传统 AI 助手的玩法是:AI 生成命令 → 你复制粘贴 → 你执行 → 你把结果贴回去。

Claude Code 不是这样。它内置了一个工具调用循环。当你输入一个任务,Claude 会:

  1. 分析任务
  2. 决定调用哪个工具
  3. 自动执行
  4. 拿到结果
  5. 继续分析
  6. 重复直到完成

整个过程你不需要复制粘贴,Claude 直接替你干活。你只需要在危险操作(比如删除文件)时确认一下。

原因二:上下文感知

Claude Code 不是在你输入时才了解你的项目。它在启动时就开始收集上下文:

  • 用 ripgrep 扫描代码库结构
  • 读取 CLAUDE.md 了解项目规范
  • 通过 LSP 获取类型信息
  • 记忆对话历史

所以它的回复不是泛泛而谈,是真的贴合你的代码库。

原因三:并行 Agent

Claude Code 可以生成子 Agent。什么意思?

比如你说”帮我把这个项目拆成三个微服务”,它会:

  • 创建一个协调者 Agent
  • 协调者生成3个子 Agent
  • 3个子 Agent 并行分析不同模块
  • 汇总结果,生成统一的拆解方案

这种并行能力在处理大型任务时,时间节省是指数级的。

原因四:MCP 生态

Claude Code 支持 Model Context Protocol。这意味着它可以连接任何实现了 MCP 的服务——数据库、GitHub、Slack、飞书、各种内部系统。

你可以用自然语言操作一切,不需要记住命令。


第四部分:代码质量——问题远多于亮点

好,夸完了。现在开始说实话。

问题一:460 个 eslint-disable

我 grep 了一下,整个代码库有 460 个 eslint-disable 注释,分布在 242 个文件里。

这是什么概念?

eslint-disable 是用来禁用 ESLint 检查的。偶尔用一下是合理的,比如临时绕过某个误报。但460个——这说明代码里有大量违反代码规范的地方,开发者懒得修或者来不及修,就直接禁用了。

更离谱的是,有些文件的 eslint-disable 是成堆出现的。比如 REPL.tsx 有20个,bridgeMain.ts 有15个,main.tsx 有16个。

这意味着什么?代码质量管控基本靠”我不管了”

问题二:142 个 TODO/FIXME/HACK

代码里有 142 个 TODO、FIXME、HACK、XXX 标记,分布在 93 个文件里。

TODO 还好——正常开发节奏。但 FIXME 和 HACK 不是好兆头。

FIXME 意味着”这里有已知问题但还没修”。HACK 意味着”这里用了一种不优雅的临时方案”。

93个文件里都有未解决的技术债务。

问题三:84 处循环依赖

这是最严重的问题。

循环依赖就是 A 文件引用 B,B 文件又引用 A。在软件工程里,这会导致”先有鸡还是先有蛋”的问题——模块加载顺序不确定,容易引发奇怪的 bug。

Claude Code 代码库里,有 84 处循环依赖相关内容,分布在 64 个文件中。

最常见的应对方法是:用 require() 动态导入

比如在 main.tsx 里:

// Lazy require to avoid circular dependencyconstgetTeammateUtils=()=>require('./utils/teammate.js')

这是把动态加载当成了遮羞布。真正的解决办法应该是重新设计模块边界,但他们没时间或者没精力做这件事。

问题四:main.tsx 的 import 灾难

main.tsx 这个文件有 300 多行,几乎全是 import。

import{ profileCheckpoint, profileReport }from'./utils/startupProfiler.js';import{ startMdmRawRead }from'./utils/settings/mdm/rawRead.js';import{ ensureKeychainPrefetchCompleted, startKeychainPrefetch }from'./utils/secureStorage/keychainPrefetch.js';import{ feature }from'bun:bundle';import{ Command as CommanderCommand, InvalidArgumentError, Option }from'@commander-js/extra-typings';import chalk from'chalk';// ... 继续100多行

这种写法不是正常的代码结构。这是”先把所有东西引进来再说”的典型代表。

问题五:代码风格不一致

有的文件用 .ts,有的用 .tsx有的工具在 tools/ 目录,有的在 commands/ 目录。有的用箭头函数,有的用普通函数。命名有时候用 camelCase,有时候用 PascalCase。

没有一致的代码规范,或者有规范但没人执行。


第五部分:架构亮点

虽然代码质量堪忧,但 Claude Code 的架构设计还是有不少亮点的。

亮点一:特性开关的巧妙实现

他们用 Bun 的 bun:bundle 实现了一个很聪明的特性开关:

import{ feature }from'bun:bundle'const voiceCommand =feature('VOICE_MODE')?require('./commands/voice/index.js').default:null

这意味着在构建时,不用的特性会被完全剔除,不会增加包体积。同时也允许同一个代码库有多个版本——比如付费版有这个功能,免费版没有。

亮点二:并行预取

main.tsx 的开头做了并行预取:

// 这些操作并行执行startMdmRawRead();// MDM 设置startKeychainPrefetch();// 钥匙串读取

三个 I/O 操作同时启动,减少启动时间。

亮点三:懒加载大模块

OpenTelemetry 和 gRPC 是很重的模块。他们用动态 import 延迟加载:

const heavyModule =awaitimport('./heavyModule.js')

只有在需要的时候才加载,不影响启动速度。

亮点四:工具系统的模块化

每个工具都是独立的模块,有标准的接口:

// 工具定义const tool =buildTool({  name:'BashTool',  inputSchema: z.object({ command: z.string()}),  permissionMode:'dangerous',execute:async(input)=>{...}})

这种设计让新增工具变得简单,不需要动核心代码。


第六部分:一些有趣的发现

说几个花边新闻。

彩蛋:Buddy Sprite

代码里有个 buddy/ 目录,实现了 Companion Sprite(陪伴精灵)。可能以后 Claude Code 会有一只电子宠物?

远程会话

remote/ 目录实现了远程会话分享功能。类似 VS Code 的 Live Share,可以把当前会话分享给其他人。

Vim 模式

对 Vim 用户是好消息——有专门的 vim/ 目录原生支持 Vim 操作。

未完成的 KAIROS

代码里有很多 feature('KAIROS') 的判断——这是一个还没发布的功能,内部叫 KAIROS,可能是一种新的 AI 模式。


总结

Claude Code 源码泄露这件事,给了我们一个难得的机会去审视一个顶级 AI 公司的工程实践。

它好用的原因

  • 工具调用循环让 AI 真正能干活而不是只说话
  • 上下文感知让它理解你的项目
  • 并行 Agent 提升大型任务效率
  • MCP 生态让它能连接一切

但代码质量确实堪忧

  • 460 个 eslint-disable
  • 142 个 TODO/FIXME/HACK
  • 84 处循环依赖
  • 代码结构混乱,规范执行不力

这说明什么?

产品做得好,不代表代码写得好。

Claude Code 是一个面向用户的产品,它的价值在于解决了用户的痛点。至于代码里面的技术债务,那是内部的——只要产品能跑,只要用户满意,技术债务可以以后再还。

这是很多商业软件的常见选择:用技术债换速度

作为工程师,我们应该从中学到两件事:

第一,好的产品设计可以弥补代码质量的不足。Claude Code 证明了这一点。

第二,代码质量终究是会还的债。当你想加新功能、当你想重构、当你想让多人协作——技术债就会来收利息。

至于这次泄露是故意还是手滑——那就见仁见智了。

好了,这期就到这里。如果你觉得有用,点个赞。我们下期见。


本文基于 2026年3月31日泄露的 Claude Code 源码分析写成。

视频讲稿


开场

大家好,今天我们聊一个最近在技术圈炸锅的话题——Claude Code 的源码泄露。

2026年3月31日,有人在 GitHub 上传了一个仓库,据说是从 Anthropic 官方 npm 包的 .map 文件里扒出来的完整 TypeScript 源码。1900个文件,51万行代码,一夜之间全暴露了。

这事儿有意思的地方在于:这是我们第一次有机会真正看清 Claude Code 内部是怎么运作的。

但我今天不想只吹它有多牛——网上已经太多这种文章了。我想做一件更客观的事:拆开它的胸腔,看看里面的零件到底是精工制造还是粗制滥造


第一部分:事件回顾

先快速说说发生了什么。

Anthropic 在 npm 上发布 Claude Code 包的时候,不知道是故意的还是手滑,把 Source Map 文件一起发了上去

Source Map 是什么?简单说就是”调试用的地图”。线上产品应该用压缩混淆后的代码,Source Map 是给开发者调试用的,不应该发布到生产环境。

但 Anthropic 发了。结果就是任何人下载这个包,解开一看 .map 文件,就能把压缩后的代码还原成完整的 TypeScript 源码——变量名、注释、目录结构,全在那儿。

这个消息最早是 Twitter 用户 @Fried_rice 发现的,然后就是你们看到的那个 GitHub 仓库。


第二部分:技术栈概览

在开始喷代码质量之前,先看看 Claude Code 用的是什么技术栈。

运行时:Bun语言:TypeScript 严格模式CLI UI:React + Ink(给 CLI 用的 React)CLI 参数解析:Commander.js模式验证:Zod v4代码搜索:ripgrep协议:MCP SDK,LSP认证:OAuth 2.0,JWT,macOS Keychain特性开关:GrowthBook遥测:OpenTelemetry + gRPC

有意思的几个点:

Bun 而不是 Node.js——Bun 号称比 Node.js 快几倍,Anthropic 选它可能就是为了 CLI 的启动速度。

React + Ink——用 React 写 CLI 界面,对前端开发者非常友好,降低了门槛。

Zod v4——运行时类型验证,用在工具输入输出上,确保 LLM 调用的工具参数是正确的。


第三部分:好用的核心原因

先说说 Claude Code 为什么好用。这个问题不吹不黑,它确实解决了实际问题。

原因一:工具调用 Loop

传统 AI 助手的玩法是:AI 生成命令 → 你复制粘贴 → 你执行 → 你把结果贴回去。

Claude Code 不是这样。它内置了一个工具调用循环。当你输入一个任务,Claude 会:

  1. 分析任务
  2. 决定调用哪个工具
  3. 自动执行
  4. 拿到结果
  5. 继续分析
  6. 重复直到完成

整个过程你不需要复制粘贴,Claude 直接替你干活。你只需要在危险操作(比如删除文件)时确认一下。

原因二:上下文感知

Claude Code 不是在你输入时才了解你的项目。它在启动时就开始收集上下文:

  • 用 ripgrep 扫描代码库结构
  • 读取 CLAUDE.md 了解项目规范
  • 通过 LSP 获取类型信息
  • 记忆对话历史

所以它的回复不是泛泛而谈,是真的贴合你的代码库。

原因三:并行 Agent

Claude Code 可以生成子 Agent。什么意思?

比如你说”帮我把这个项目拆成三个微服务”,它会:

  • 创建一个协调者 Agent
  • 协调者生成3个子 Agent
  • 3个子 Agent 并行分析不同模块
  • 汇总结果,生成统一的拆解方案

这种并行能力在处理大型任务时,时间节省是指数级的。

原因四:MCP 生态

Claude Code 支持 Model Context Protocol。这意味着它可以连接任何实现了 MCP 的服务——数据库、GitHub、Slack、飞书、各种内部系统。

你可以用自然语言操作一切,不需要记住命令。


第四部分:代码质量——问题远多于亮点

好,夸完了。现在开始说实话。

问题一:460 个 eslint-disable

我 grep 了一下,整个代码库有 460 个 eslint-disable 注释,分布在 242 个文件里。

这是什么概念?

eslint-disable 是用来禁用 ESLint 检查的。偶尔用一下是合理的,比如临时绕过某个误报。但460个——这说明代码里有大量违反代码规范的地方,开发者懒得修或者来不及修,就直接禁用了。

更离谱的是,有些文件的 eslint-disable 是成堆出现的。比如 REPL.tsx 有20个,bridgeMain.ts 有15个,main.tsx 有16个。

这意味着什么?代码质量管控基本靠”我不管了”

问题二:142 个 TODO/FIXME/HACK

代码里有 142 个 TODO、FIXME、HACK、XXX 标记,分布在 93 个文件里。

TODO 还好——正常开发节奏。但 FIXME 和 HACK 不是好兆头。

FIXME 意味着”这里有已知问题但还没修”。HACK 意味着”这里用了一种不优雅的临时方案”。

93个文件里都有未解决的技术债务。

问题三:84 处循环依赖

这是最严重的问题。

循环依赖就是 A 文件引用 B,B 文件又引用 A。在软件工程里,这会导致”先有鸡还是先有蛋”的问题——模块加载顺序不确定,容易引发奇怪的 bug。

Claude Code 代码库里,有 84 处循环依赖相关内容,分布在 64 个文件中。

最常见的应对方法是:用 require() 动态导入

比如在 main.tsx 里:

// Lazy require to avoid circular dependencyconstgetTeammateUtils=()=>require('./utils/teammate.js')

这是把动态加载当成了遮羞布。真正的解决办法应该是重新设计模块边界,但他们没时间或者没精力做这件事。

问题四:main.tsx 的 import 灾难

main.tsx 这个文件有 300 多行,几乎全是 import。

import{ profileCheckpoint, profileReport }from'./utils/startupProfiler.js';import{ startMdmRawRead }from'./utils/settings/mdm/rawRead.js';import{ ensureKeychainPrefetchCompleted, startKeychainPrefetch }from'./utils/secureStorage/keychainPrefetch.js';import{ feature }from'bun:bundle';import{ Command as CommanderCommand, InvalidArgumentError, Option }from'@commander-js/extra-typings';import chalk from'chalk';// ... 继续100多行

这种写法不是正常的代码结构。这是”先把所有东西引进来再说”的典型代表。

问题五:代码风格不一致

有的文件用 .ts,有的用 .tsx有的工具在 tools/ 目录,有的在 commands/ 目录。有的用箭头函数,有的用普通函数。命名有时候用 camelCase,有时候用 PascalCase。

没有一致的代码规范,或者有规范但没人执行。


第五部分:架构亮点

虽然代码质量堪忧,但 Claude Code 的架构设计还是有不少亮点的。

亮点一:特性开关的巧妙实现

他们用 Bun 的 bun:bundle 实现了一个很聪明的特性开关:

import{ feature }from'bun:bundle'const voiceCommand =feature('VOICE_MODE')?require('./commands/voice/index.js').default:null

这意味着在构建时,不用的特性会被完全剔除,不会增加包体积。同时也允许同一个代码库有多个版本——比如付费版有这个功能,免费版没有。

亮点二:并行预取

main.tsx 的开头做了并行预取:

// 这些操作并行执行startMdmRawRead();// MDM 设置startKeychainPrefetch();// 钥匙串读取

三个 I/O 操作同时启动,减少启动时间。

亮点三:懒加载大模块

OpenTelemetry 和 gRPC 是很重的模块。他们用动态 import 延迟加载:

const heavyModule =awaitimport('./heavyModule.js')

只有在需要的时候才加载,不影响启动速度。

亮点四:工具系统的模块化

每个工具都是独立的模块,有标准的接口:

// 工具定义const tool =buildTool({  name:'BashTool',  inputSchema: z.object({ command: z.string()}),  permissionMode:'dangerous',execute:async(input)=>{...}})

这种设计让新增工具变得简单,不需要动核心代码。


第六部分:一些有趣的发现

说几个花边新闻。

彩蛋:Buddy Sprite

代码里有个 buddy/ 目录,实现了 Companion Sprite(陪伴精灵)。可能以后 Claude Code 会有一只电子宠物?

远程会话

remote/ 目录实现了远程会话分享功能。类似 VS Code 的 Live Share,可以把当前会话分享给其他人。

Vim 模式

对 Vim 用户是好消息——有专门的 vim/ 目录原生支持 Vim 操作。

未完成的 KAIROS

代码里有很多 feature('KAIROS') 的判断——这是一个还没发布的功能,内部叫 KAIROS,可能是一种新的 AI 模式。


总结

Claude Code 源码泄露这件事,给了我们一个难得的机会去审视一个顶级 AI 公司的工程实践。

它好用的原因

  • 工具调用循环让 AI 真正能干活而不是只说话
  • 上下文感知让它理解你的项目
  • 并行 Agent 提升大型任务效率
  • MCP 生态让它能连接一切

但代码质量确实堪忧

  • 460 个 eslint-disable
  • 142 个 TODO/FIXME/HACK
  • 84 处循环依赖
  • 代码结构混乱,规范执行不力

这说明什么?

产品做得好,不代表代码写得好。

Claude Code 是一个面向用户的产品,它的价值在于解决了用户的痛点。至于代码里面的技术债务,那是内部的——只要产品能跑,只要用户满意,技术债务可以以后再还。

这是很多商业软件的常见选择:用技术债换速度

作为工程师,我们应该从中学到两件事:

第一,好的产品设计可以弥补代码质量的不足。Claude Code 证明了这一点。

第二,代码质量终究是会还的债。当你想加新功能、当你想重构、当你想让多人协作——技术债就会来收利息。

至于这次泄露是故意还是手滑——那就见仁见智了。

好了,这期就到这里。如果你觉得有用,点个赞。我们下期见。


本文基于 2026年3月31日泄露的 Claude Code 源码分析写成。