Claude Code 源码全曝光:51万行代码,10大架构设计拆个底朝天
Claude Code 源码全曝光:10大架构设计亮点解析 摘要 Claude Code 完整源码意外曝光,包含1884个TypeScript文件、9.8万行核心代码。本文提炼出10大关键架构设计亮点: 启动优化:利用import评估空隙并行执行I/O操作,节省65ms延迟 三元权限决策:Hook、Classifier、User三路异步竞争机制 Bash工具安全:2600行权限检查代码,实现三层防
Claude Code 源码全曝光:51万行代码,10大架构设计拆个底朝天
摘要
Claude Code 源码意外曝光,1884 个 TypeScript 文件、9.8 万行核心代码、42 个工具模块、189 个斜杠命令。本文带你逐一拆解 10 大架构设计亮点,从启动优化到权限系统,从 MCP 深度融合到多 Agent 编排,看看 Anthropic 的工程团队究竟在 CLI 里藏了多少"黑科技"。
就在今天,Claude Code 的完整源码被逆向还原并在 GitHub 上公开,全网开发者集体炸锅。
1884 个 TypeScript 文件、src/ 目录 9.8 万行代码、389 个终端 UI 组件、42 种工具、189 个斜杠命令。 这不是一个简单的 CLI 工具——这是一个完整的 AI 操作系统。
我花了大半天时间把源码翻了个底朝天。坦率说,看完之后只有一个感受:这是我见过的工程质量最高的 AI 工具项目,没有之一。
下面,我挑出 10 个最值得聊的架构设计,逐一拆解。
一、启动魔法:import 空隙里省出 65ms
Claude Code 打开速度很快,你以为这是理所当然?不,这背后有精心的工程优化。
看 main.tsx 的前 20 行:
profileCheckpoint('main_tsx_entry')
startMdmRawRead() // 立刻启动 MDM 子进程
startKeychainPrefetch() // 立刻启动 Keychain 预读
还没等其他模块加载完,这三行就已经跑起来了。
为什么放在最前面?因为 Bun 在 import 其他模块时会有一段"评估时间"(module evaluation),这段时间 JavaScript 主线程是空闲的,但事件循环的 I/O 通道是通的。
Anthropic 的工程师利用了这个空隙:
startMdmRawRead()在 macOS 上并行读取多个 plist 文件(通过plutil子进程),在 Windows 上并行查询两个注册表路径(HKLM和HKCU)startKeychainPrefetch()同时启动 OAuth Token 和 Legacy API Key 两个 Keychain 查询
// keychainPrefetch.ts
export function startKeychainPrefetch(): void {
if (process.platform !== 'darwin' || prefetchPromise || isBareMode()) return
const oauthSpawn = spawnSecurity(
getMacOsKeychainStorageServiceName(CREDENTIALS_SERVICE_SUFFIX),
)
const legacySpawn = spawnSecurity(getMacOsKeychainStorageServiceName())
prefetchPromise = Promise.all([oauthSpawn, legacySpawn]).then(
([oauth, legacy]) => {
if (!oauth.timedOut) primeKeychainCacheFromPrefetch(oauth.stdout)
if (!legacy.timedOut) legacyApiKeyPrefetch = { stdout: legacy.stdout }
},
)
}
原来这两个 Keychain 读取是在后面 applySafeConfigEnvironmentVariables() 里串行执行的,加起来大约 65ms。现在提前并行化后,这段延迟几乎归零。
启动 Profiling 也很有意思:100% 内部用户采样、0.5% 外部用户采样,持续监控每个启动阶段的耗时。这种"对自己产品的性能永远保持敬畏"的态度,值得学习。
二、三元权限决策:Hook、Classifier、User 的级联竞争
Claude Code 的权限系统不是简单的"允许/拒绝"二选一,而是一个三路竞争的异步决策架构。
当 AI 要执行一个工具时,三条决策路径同时启动:
- Hook 路径:检查用户配置的自动化规则
- Classifier 路径:用 AI 分类器判断命令是否安全
- User 路径:弹出交互确认框
谁先返回结果,谁就赢。
但问题来了:三个异步回调可能在几毫秒内先后返回,如果不做保护,可能同时触发两个 resolve(),导致权限被批准两次。
这就是 ResolveOnce 的用武之地:
function createResolveOnce<T>(resolve: (value: T) => void): ResolveOnce<T> {
let claimed = false
let delivered = false
return {
resolve(value: T) {
if (delivered) return
delivered = true
claimed = true
resolve(value)
},
claim() {
if (claimed) return false
claimed = true
return true // 返回 true 表示"我赢了"
},
}
}
claim() 实现了一个原子的 Check-and-Mark 操作。三条路径竞争时,只有第一个调用 claim() 并返回 true 的赢家才能最终决定权限。
这是一种非常优雅的异步竞态解决方案,比传统的 mutex/lock 轻量得多。
三、Bash 工具的 2600 行权限检查
42 个工具里,BashTool 的权限逻辑最复杂,单独的 bashPermissions.ts 就有近 2600 行。
权限检查分三层:
第一层:精确匹配(最高优先级)
const exactMatchResult = bashToolCheckExactMatchPermission(input, context)
if (exactMatchResult.behavior === 'deny' || exactMatchResult.behavior === 'ask') {
return exactMatchResult // 精确拒绝/询问直接生效
}
第二层:前缀规则(拒绝 > 询问 > 允许)
const { matchingDenyRules, matchingAskRules, matchingAllowRules } =
matchingRulesForInput(input, context, 'prefix', {
skipCompoundCheck: astCommand !== undefined,
})
第三层:通行证(兜底,要求用户确认)
还有一个特别巧妙的设计——安全包装器剥离:
const SAFE_WRAPPER_PATTERNS = [
/^\s*time\s+/,
/^\s*nohup\s+(?:--\s+)?/,
/^\s*timeout\s+(?:[^\s]+\s+)*(?:\d+(?:\.\d+)?[smhd])?\s+/,
/^\s*nice\s+(?:-n\s*-?\d+\s+(?:--\s+)?)?/,
]
如果有人试图用 time nice -n 10 sudo rm -rf / 绕过检查怎么办?系统会循环剥离这些安全包装器,直到露出真实命令,然后才做权限判断。
命令前缀提取也是一道安全防线:
export function getSimpleCommandPrefix(command: string): string | null {
// NODE_ENV=prod npm run build → 'npm run'(安全变量可跳过)
// MY_VAR=val npm run build → null(不安全变量,回退精确匹配)
// chmod 755 file → null(数字不是 subcommand)
}
这套设计的核心理念很清晰:安全默认、纵深防御、宁可误拦不可漏放。
四、Classifier 的投机执行
权限系统还有一个性能优化:投机执行(Speculative Execution)。
当权限对话框弹出等用户确认时,Classifier 已经在后台默默跑起来了:
export function startSpeculativeClassifierCheck(
command: string,
toolPermissionContext: ToolPermissionContext,
signal: AbortSignal,
): boolean {
const promise = classifyBashCommand(command, cwd, allowDescriptions, ...)
promise.catch(() => {}) // 防止未处理的 rejection
speculativeChecks.set(command, promise)
return true
}
如果 Classifier 判定"高置信度允许",对话框会自动关闭,用户甚至不需要手动确认。如果 Classifier 还没返回,用户手动确认了,投机结果就被丢弃。
这是 CPU 分支预测思想在 AI 权限系统中的应用——预测大概率结果,提前执行,失败了再回退。
五、42 个工具的极致模块化
Claude Code 的工具系统用 TypeScript 泛型定义了一套统一接口:
export type Tool<Input, Output> = {
name: string
call(args: Input, context: ToolUseContext, ...): Promise<ToolResult<Output>>
description(input: Input, options: ...): Promise<string>
inputSchema: Input
isConcurrencySafe(input: Input): boolean // 是否可并行
isReadOnly(input: Input): boolean // 是否只读
isDestructive?(input: Input): boolean // 是否有破坏性
checkPermissions(input): Promise<PermissionResult>
}
每个工具都是一个独立目录:index.ts(主逻辑)、prompt.ts(AI 提示词)、constants.ts(名称常量)。
buildTool() 函数会自动填充安全默认值:
const TOOL_DEFAULTS = {
isConcurrencySafe: () => false, // 默认不可并行
isReadOnly: () => false, // 默认可写
isDestructive: () => false, // 默认无破坏性
}
失败关闭(Fail-Closed) 原则贯穿始终:新工具如果忘了声明并发安全,就默认串行执行,宁可慢一点也不出错。
六、MCP 深度融合:12 万行让外部服务"透明化"
MCP(Model Context Protocol)客户端是整个项目中最大的单文件——3348 行、12 万字符。
MCP 工具和原生工具共享同一个 Tool<Input, Output> 接口。融合的关键代码:
const fullyQualifiedName = buildMcpToolName(client.name, tool.name)
// 如 mcp__github__create_issue
return {
...MCPTool, // 继承基础 MCPTool 模板
name: fullyQualifiedName,
description: async () => serverDescription,
call: async (args, context) => {
const mcpResult = await callMCPTool({ ... })
return { data: mcpResult }
},
}
用户完全感知不到 MCP 工具和原生工具的区别。 在 AI 的视角里,Bash、FileRead 和 mcp__github__create_issue 都只是"工具",调用方式完全一致。
传输层支持五种协议:SSE、WebSocket、Stdio、SDK Control、In-Process。其中 InProcessTransport 最有意思——用 queueMicrotask() 在两个对等端之间传递消息,零网络开销:
async send(message: JSONRPCMessage): Promise<void> {
queueMicrotask(() => {
this.peer?.onmessage?.(message)
})
}
OAuth 动态刷新也做得非常完善:令牌到期前 5 分钟主动刷新,并发刷新请求会复用同一个 Promise,还专门处理了 Slack 等非标准 OAuth 实现的兼容问题。
七、多 Agent 编排:Swarm 架构的三种隔离
Claude Code 支持三种 Agent 隔离模式:
| 模式 | 隔离级别 | 适用场景 |
|---|---|---|
| 同进程 | 共享内存,AsyncLocalStorage 隔离 | 快速子任务 |
| Worktree | 独立 Git 分支,文件系统隔离 | 代码修改 |
| 远程 CCR | 完全隔离的远程环境 | 高风险操作 |
Agent 着色系统用 8 种颜色区分不同 Agent 的输出:
export const AGENT_COLORS: readonly AgentColorName[] = [
'red', 'blue', 'green', 'yellow',
'purple', 'orange', 'pink', 'cyan',
]
记忆快照系统让 Agent 可以跨会话保留经验。记忆分三个作用域:
user:~/.claude/agent-memory/(跨项目)project:<cwd>/.claude/agent-memory/(项目级)local:<cwd>/.claude/agent-memory-local/(本地临时)
Worktree 隔离模式还会把 node_modules 等大目录做符号链接,避免磁盘膨胀:
async function symlinkDirectories(repoRootPath, worktreePath, dirs) {
for (const dir of dirs) {
if (containsPathTraversal(dir)) continue // 防路径遍历
await symlink(sourcePath, destPath, 'dir')
}
}
八、自动 Compact:AI 驱动的上下文压缩
当对话快要撑爆上下文窗口时,Claude Code 不是简单地截断,而是用 AI 重新摘要早期对话。
export const AUTOCOMPACT_BUFFER_TOKENS = 13_000
export const WARNING_THRESHOLD_BUFFER_TOKENS = 20_000
const MAX_CONSECUTIVE_AUTOCOMPACT_FAILURES = 3
关键设计:断路器模式。代码注释里写着一行令人印象深刻的数据:
BQ 2026-03-10: 1,279 sessions had 50+ consecutive failures wasting ~250K API calls/day globally.
于是他们加了断路器——连续失败 3 次就停止重试。这条注释本身就是工程文化的缩影:数据驱动决策,注释记录决策背景。
四级阈值逐步升级:Warning(20k) → Error(20k) → AutoCompact(13k) → Blocking(3k)。
九、终端渲染:为什么 Claude Code 比其他 CLI 流畅得多
答案藏在 src/ink/ 目录的 96 个文件里。
核心优化:DECSTBM 硬件滚动。
普通终端应用滚动时,需要重新绘制整个可视区域。Claude Code 利用了 VT100 的 DECSTBM(Set Top and Bottom Margins)指令,让终端硬件自己处理滚动:
if (altScreen && next.scrollHint && decstbmSafe) {
const { top, bottom, delta } = next.scrollHint
shiftRows(prev.screen, top, bottom, delta)
scrollPatch = [{
type: 'stdout',
content:
setScrollRegion(top + 1, bottom + 1) + // CSI top;bot r
(delta > 0 ? csiScrollUp(delta) : csiScrollDown(-delta)) +
RESET_SCROLL_REGION + CURSOR_HOME,
}]
}
比例排水算法处理大量输出时的滚动:每帧消化 3/4 的待滚动行数,用 log₄ 帧数收敛到目标位置——既快速赶上又平滑减速。
还有一个 CharPool 字符驻留池:
export class CharPool {
private ascii: Int32Array = initCharAscii()
intern(char: string): number {
if (char.length === 1) {
const code = char.charCodeAt(0)
if (code < 128) {
const cached = this.ascii[code]!
if (cached !== -1) return cached // ASCII 直接数组查找
}
}
// 非 ASCII 走 Map
}
}
ASCII 字符直接用数组索引查找(O(1)),不走 Map 的哈希路径。跨帧复用字符 ID,屏幕 diff 时只比较整数,比字符串比较快一个数量级。
十、Bun 特性开关:编译时消除死代码
Claude Code 用 Bun 的 feature() 做编译时特性开关:
import { feature } from 'bun:bundle'
const getCoordinatorUserContext = feature('COORDINATOR_MODE')
? require('./coordinator/coordinatorMode.js').getCoordinatorUserContext
: () => ({})
如果 COORDINATOR_MODE 在当前构建中未启用,整个 coordinatorMode.js 模块不会被打包——彻底的死代码消除,不是运行时 if,是编译时直接砍掉。
已知的特性开关包括:
| 标志 | 功能 |
|---|---|
COORDINATOR_MODE |
多 Agent 协调器 |
BASH_CLASSIFIER |
Bash 命令 AI 分类 |
CONTEXT_COLLAPSE |
上下文折叠 |
VOICE_MODE |
语音输入 |
EXTRACT_MEMORIES |
记忆提取 |
REACTIVE_COMPACT |
被动压缩 |
这种方式的好处:外部构建的二进制体积更小,而且不会泄露内部功能的名称和实现。
快速推理的冷却管理
快速推理模式(Fast Mode)遇到速率限制时,不是简单报错,而是进入冷却状态:
export type FastModeRuntimeState =
| { status: 'active' }
| { status: 'cooldown'; resetAt: number; reason: CooldownReason }
resetAt 是一个时间戳,到期后自动恢复,无需后台轮询。每次查询状态时检查一下时间就行:
export function getFastModeRuntimeState(): FastModeRuntimeState {
if (runtimeState.status === 'cooldown' && Date.now() >= runtimeState.resetAt) {
runtimeState = { status: 'active' }
}
return runtimeState
}
用户偏好和运行时状态分离——你设置了"我要快速模式",但系统可能因为限流临时切回普通模式,限流解除后自动恢复,全程无感。
写在最后
拆完这 10 个模块,我最大的感受不是某个单点有多炫,而是整体工程哲学的一致性:
- 安全默认:权限三元竞争、工具失败关闭、命令包装器剥离
- 性能敬畏:启动 65ms 优化、投机执行、DECSTBM 硬件滚动、CharPool 字符驻留
- 数据驱动:断路器阈值来自真实生产数据(250K 浪费调用)、采样率精确到 0.5%
- 透明抽象:MCP 工具与原生工具无缝统一、Agent 隔离对用户透明
这不是一个"先跑起来再优化"的项目。每一行代码都能看出经过反复打磨和生产验证的痕迹。
对于开发者来说,这份源码的价值不仅仅是"看看 Anthropic 怎么写代码",更是一本关于"如何构建生产级 AI 工具"的教科书。
觉得有用?转发给你身边写代码的朋友。有什么想深入讨论的架构细节,评论区见。
更多推荐



所有评论(0)