目录

Claude Code 项目架构总览

Claude Code 项目架构总览

源码路径:/mnt/e/code/cc/claude-code-main
规模:~1900 文件,512K+ 行 TypeScript
技术栈:Bun + React/Ink + TypeScript (strict)


1. 项目入口与启动流程

1.1 入口文件链

cli.tsx (bootstrap) → main.tsx (main CLI) → run() → action handler → setup()/REPL

关键入口点 (src/entrypoints/cli.tsx):

// 快速路径:--version 零模块加载
if (args.length === 1 && (args[0] === '--version' || args[0] === '-v')) {
  console.log(`${MACRO.VERSION} (Claude Code)`);
  return;
}

// 动态导入 main.tsx(懒加载)
const { main: cliMain } = await import('../main.js');
await cliMain();

1.2 模块评估期并行预取

main.tsx 顶层在所有导入之前触发三大并行预取:

// main.tsx lines 1-20
import { profileCheckpoint, profileReport } from './utils/startupProfiler.js';
profileCheckpoint('main_tsx_entry');

import { startMdmRawRead } from './utils/settings/mdm/rawRead.js';
startMdmRawRead();  // 非阻塞,与 ~135ms 模块导入并行

import { startKeychainPrefetch } from './utils/secureStorage/keychainPrefetch.js';
startKeychainPrefetch();  // 非阻塞,立即返回

1.3 Commander.js 配置

使用 @commander-js/extra-typings,配置在 main.tsxrun() 函数中:

async function run(): Promise<CommanderCommand> {
  const program = new CommanderCommand()
    .configureHelp(createSortedHelpConfig())
    .enablePositionalOptions();

  // preAction hook:仅在执行命令时运行,显示帮助时跳过初始化
  program.hook('preAction', async thisCommand => {
    await Promise.all([
      ensureMdmSettingsLoaded(),   // 等待 MDM 预取完成
      ensureKeychainPrefetchCompleted()  // 等待 Keychain 预取完成
    ]);
    await init();
  });

  program.name('claude')
    .argument('[prompt]', 'Your prompt')
    .option('-d, --debug [filter]', 'Enable debug mode')
    .option('-p, --print', 'Print response and exit')
    .option('--bare', 'Minimal mode')
    .option('--model <model>', 'Model for session')
    // ... 50+ 更多选项
    .action(async (prompt, options) => { /* ... */ });
}

1.4 启动优化:三大并行预取

优化原理节省时间
MDM 预取macOS plutil 子进程并行读取~50ms
Keychain 预取OAuth + Legacy API key 并行读取~65ms
API 预连接TCP+TLS 握手与启动工作重叠~100-200ms

MDM 预取 (src/utils/settings/mdm/rawRead.ts):

export function startMdmRawRead(): void {
  if (rawReadPromise) return;
  rawReadPromise = fireRawRead();  // 非阻塞启动
  // plutil 读取多个 plist 路径,第一个成功结果被使用
}

Keychain 预取 (src/utils/secureStorage/keychainPrefetch.ts):

export function startKeychainPrefetch(): void {
  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 };
  });
}

API 预连接 (src/utils/apiPreconnect.ts):

export function preconnectAnthropicApi(): void {
  // HEAD 请求触发 TCP+TLS 握手,与后续工作并行
  void fetch(baseUrl, { method: 'HEAD', signal: AbortSignal.timeout(10_000) }).catch(() => {});
}

1.5 懒加载策略

延迟预取 (main.tsx lines 388-431) — REPL 渲染后才运行:

export function startDeferredPrefetches(): void {
  void initUser();
  void getUserContext();
  void countFilesRoundedRg(getCwd(), AbortSignal.timeout(3000), []);
  void initializeAnalyticsGates();
  void prefetchOfficialMcpUrls();
  void refreshModelCapabilities();
  void settingsChangeDetector.initialize();
}

条件导入 (DCE)

const coordinatorModeModule = feature('COORDINATOR_MODE') ? require('./coordinator/coordinatorMode.js') : null;

动态导入 (227+ 处使用):

const { App } = await import('./components/App.js');
const { initializeTelemetry } = await import('../utils/telemetry/instrumentation.js');

1.6 启动流程图

cli.tsx main()
├── --version 快速路径 → 直接返回
├── --dump-system-prompt → 动态加载 prompt 模块
├── --claude-in-chrome-mcp → MCP 服务器
└── 默认: 动态加载 main.tsx
    │
    ▼
main.tsx 模块评估
├── profileCheckpoint('main_tsx_entry')
├── startMdmRawRead() ────────────────┐
├── startKeychainPrefetch() ───────────┤ ← 并行子进程
│                                    │
main()                                │
├── process.env.NoDefaultCurrentDirectoryInExePath = '1'
├── initializeWarningHandler()
├── setIsInteractive() / setClientType()
└── run()
    │
    ▼
Commander preAction hook
├── await Promise.all([MDM, Keychain 预取完成])
├── init() ──────────────────────────┐
│   ├── enableConfigs()               │
│   ├── applyExtraCACertsFromConfig() │
│   ├── preconnectAnthropicApi() ← API 预连接
│   ├── configureGlobalMTLS()        │
│   └── initializeTelemetry()       │
│                                    │
└── action handler                    │
    │                                 │
    ▼                                 │
setup() / launchRepl()                │
├── 显示信任对话框                     │
├── startDeferredPrefetches() ───────┘
└── REPL 渲染完成

2. 核心模块职责

2.1 命令系统 vs 工具系统

Commands (src/commands.ts) — 用户输入的斜线命令:

  • 类型:prompt(展开为文本)、local(本地执行)、local-jsx(渲染 UI)
  • 来源:内置 + 插件 + Skills 目录 + MCP 服务器

Tools (src/tools.ts) — LLM 可调用的执行能力:

  • 使用 buildTool() 工厂模式,35+ 内置工具
  • 来源:内置 + MCP 工具

桥梁:SkillTool (src/tools/SkillTool/SkillTool.ts):

export const SkillTool: Tool = buildTool({
  name: 'Skill',
  async call({ skill, args }, context, canUseTool, parentMessage) {
    const commands = await getAllCommands(context);
    const command = findCommand(commandName, commands);
    const processedCommand = await processPromptSlashCommand(...);
    return { data: { success: true }, newMessages: processedCommand.messages };
  }
});

2.2 命令注册模式

// 多源聚合
const loadAllCommands = memoize(async (cwd: string): Promise<Command[]> => {
  const [skillDirCommands, pluginSkills, bundledSkills, builtinPluginSkills] = await Promise.all([
    getSkillDirCommands(cwd),
    getPluginSkills(),
    getBundledSkills(),
    getBuiltinPluginSkillCommands(),
  ]);
  return [...bundledSkills, ...builtinPluginSkills, ...skillDirCommands, ...COMMANDS()];
});

// 可用性过滤
export function meetsAvailabilityRequirement(cmd: Command): boolean {
  if (!cmd.availability) return true;
  for (const a of cmd.availability) {
    if (a === 'claude-ai' && isClaudeAISubscriber()) return true;
    if (a === 'console' && !isUsing3PServices() && isFirstPartyAnthropicBaseUrl()) return true;
  }
  return false;
}

2.3 工具注册模式

// 工具工厂 (Tool.ts lines 757-791)
const TOOL_DEFAULTS = {
  isEnabled: () => true,
  isConcurrencySafe: (_input?) => false,
  isReadOnly: (_input?) => false,
  isDestructive: (_input?) => false,
  checkPermissions: (input, _ctx) => Promise.resolve({ behavior: 'allow', updatedInput: input }),
};

export function buildTool<D extends ToolDef>(def: D): BuiltTool<D> {
  return { ...TOOL_DEFAULTS, userFacingName: () => def.name, ...def } as BuiltTool<D>;
}

// 工具池组装
export function assembleToolPool(permissionContext, mcpTools): Tools {
  const builtInTools = getTools(permissionContext);
  const allowedMcpTools = filterToolsByDenyRules(mcpTools, permissionContext);
  return uniqBy([...builtInTools].sort(byName).concat(allowedMcpTools.sort(byName)), 'name');
}

3. 目录结构分析

src/
├── [Core Files]
│   ├── main.tsx           # 入口 (~4684 lines)
│   ├── QueryEngine.ts     # LLM 查询引擎核心 (47KB)
│   ├── Tool.ts            # 工具基类 (30KB)
│   ├── commands.ts       # 命令注册 (132KB)
│   ├── tools.ts          # 工具注册 (17KB)
│   └── query.ts           # 查询处理 (69KB)
│
├── commands/             # 90+ 斜线命令实现
│   ├── init.ts           # /init
│   ├── commit.ts         # /commit
│   ├── review.ts         # /review
│   └── ...
│
├── components/            # 140+ React UI 组件
│   ├── App.tsx            # 根组件
│   ├── Messages.tsx       # 消息列表 (148KB)
│   ├── VirtualMessageList.tsx  # 虚拟化列表 (149KB)
│   └── ...
│
├── hooks/                 # 70+ React Hooks
│   ├── useTypeahead.tsx   # 自动补全 (213KB)
│   ├── useReplBridge.tsx  # REPL 桥接 (116KB)
│   ├── useCanUseTool.tsx  # 工具权限 (40KB)
│   └── ...
│
├── services/              # 外部服务集成
│   ├── api/               # Anthropic API 客户端 (126KB)
│   ├── mcp/               # MCP 协议实现 (119KB)
│   └── ...
│
├── tools/                 # 50+ Agent 工具
│   ├── BashTool/
│   ├── FileEditTool/
│   ├── AgentTool/
│   ├── SkillTool/
│   └── ...
│
├── context/               # React Context
│   ├── AppStateContext.tsx
│   └── ...
│
├── state/                 # Zustand 状态管理
│   └── AppStateStore.ts
│
├── ink/                   # React-Ink 终端 UI 桥接
│   ├── ink.tsx            # 核心渲染器 (252KB)
│   ├── reconciler.ts     # React Reconciler 配置
│   ├── root.ts            # createRoot API
│   └── components/        # Ink 基础组件
│
├── bridge/                # IDE 桥接 (VS Code/JetBrains)
│   ├── bridgeMain.ts      # 116KB
│   └── replBridge.ts      # 101KB
│
├── services/
│   ├── api/claude.ts      # API 客户端 (126KB)
│   └── mcp/client.ts      # MCP 客户端 (119KB)
│
└── [其他模块]
    ├── memdir/            # 持久化内存系统
    ├── skills/            # Skill 加载
    ├── plugins/           # 插件系统
    ├── migrations/        # 数据迁移
    └── ...

架构分层图

┌─────────────────────────────────────────────────────┐
│                    main.tsx                         │
│              React/Ink App Bootstrap                 │
└─────────────────────────────────────────────────────┘
                         │
     ┌───────────────────┼───────────────────┐
     ▼                   ▼                   ▼
┌──────────┐    ┌──────────┐    ┌──────────┐
│components/│    │  hooks/  │    │ context/ │
│ UI Layer  │◄───│ Business │◄───│  State   │
│ 140+     │    │  Logic   │    │ Providers│
└──────────┘    └──────────┘    └──────────┘
     │                   │                   │
     └───────────────────┼───────────────────┘
                         ▼
┌─────────────────────────────────────────────────────┐
│               QueryEngine.ts (Core)                │
│  • LLM Query Loop    • Streaming Response           │
│  • Tool Call Loop    • Retry Logic  • Token Count   │
└─────────────────────────────────────────────────────┘
            │                       │
            ▼                       ▼
┌──────────────────┐    ┌──────────────────┐
│      tools/      │    │     services/    │
│   50+ Agent      │    │  API / MCP / etc │
│     Tools        │    │    (External)    │
└──────────────────┘    └──────────────────┘
            │
            ▼
┌──────────────────┐    ┌──────────────────┐    ┌──────────────────┐
│    commands/    │    │      bridge/     │    │     memdir/      │
│   90+ Slash     │    │  IDE Extension   │    │     Memory       │
│    Commands     │    │                  │    │                  │
└──────────────────┘    └──────────────────┘    └──────────────────┘

4. 技术栈:Bun Runtime

4.1 bun:bundle Feature Flags

主要 Bun 特性:196+ 处使用 bun:bundle 进行功能开关控制:

import { feature } from 'bun:bundle';

// 条件功能加载(构建时 DCE)
if (feature('COORDINATOR_MODE')) {
  const mod = require('./coordinator/coordinatorMode.js');
}

// 运行时功能检查
if (feature('DUMP_SYSTEM_PROMPT') && args[0] === '--dump-system-prompt') {
  // ...
}

4.2 bun:ffi Native Syscall

用于 Linux 安全加固(设置 process dumpable flag):

// src/upstreamproxy/upstreamproxy.ts
const ffi = require('bun:ffi');
const lib = ffi.dlopen('libc.so.6', {
  prctl: { args: ['int', 'u64', 'u64', 'u64', 'u64'], returns: 'int' },
} as const);
lib.symbols.prctl(4, 0n, 0n, 0n, 0n);  // PR_SET_DUMPABLE = 4

5. 技术栈:Ink/React CLI UI

5.1 React Reconciler 定制

使用 react-reconciler + Yoga 布局引擎实现终端渲染:

// src/ink/reconciler.ts
const reconciler = createReconciler<
  ElementNames, Props, DOMElement, DOMElement, TextNode,
  DOMElement, unknown, unknown, DOMElement, HostContext,
  null, NodeJS.Timeout, -1, null
>({
  getRootHostContext: () => ({ isInsideText: false }),
  getChildHostContext: (parentHostContext, type) => ({
    isInsideText: type === 'ink-text' || type === 'ink-virtual-text'
  }),
  shouldSetTextContent: () => false,
  createInstance: (type, props, root, hostContext) => { /* 创建 DOM 节点 */ },
  // ...
});

5.2 Ink 渲染流程

React Component Tree → Yoga Layout → Screen Buffer Diff → Terminal Write

核心类 Ink (src/ink/ink.tsx):

export default class Ink {
  private readonly container: FiberRoot;
  private frontFrame: Frame;
  private backFrame: Frame;

  private onRender() {
    // 1. 计算 Yoga 布局
    this.rootNode.yogaNode?.calculateLayout(this.terminalColumns);
    
    // 2. 生成当前帧
    const frame = this.renderer({ frontFrame, backFrame });
    
    // 3. Diff against previous frame
    const diff = this.log.render(prevFrame, frame);
    
    // 4. 写入终端
    writeDiffToTerminal(this.terminal, diff);
  }
}

5.3 终端协议支持

  • Kitty Keyboard Protocol — 扩展键支持
  • Bracketed Paste Mode — 安全粘贴
  • DEC Private Modes — 光标隐藏/显示
  • SGR Mouse Tracking — 鼠标点击/滚动
  • Focus Events — focusin/focusout

5.4 性能优化

优化原理
StylePool/CharPool对象复用,减少 GC
帧 Diff仅重绘变化区域
Microtask 延迟queueMicrotask 批量渲染
Yoga 布局缓存缓存计算结果

6. 关键文件速查

文件行数职责
main.tsx~4684入口、初始化、Commander 配置
QueryEngine.ts~1500LLM 查询循环、流式响应、工具调用
commands.ts~4000150+ 命令注册
tools.ts~600工具池组装
ink/ink.tsx~5000核心渲染器
bridge/bridgeMain.ts~3000IDE 桥接主逻辑
services/api/claude.ts~3000Anthropic API 客户端
components/Messages.tsx~4000消息列表 UI
hooks/useTypeahead.tsx~5000自动补全逻辑

7. 下一步

  • 第二阶段QueryEngine.ts 深度解读 — 流式响应、工具调用循环、重试逻辑
  • 第三阶段tools/ 工具实现模式 — 工厂模式、权限系统、工具执行流程
  • 第四阶段ink/ 渲染引擎深度分析 — Reconciler、Yoga 布局、事件处理

文档版本:v1.0 | 生成时间:2026-04-02