架构总览

Claude Code 源码架构总览

先看整体图

如果只从源码目录去看,很容易被大量文件吓住。
但从主干关系看,Claude Code 的架构并不乱,它大致可以抽象成下面这张图:

加载图表中...

再看一张更贴近源码目录的分层图

加载图表中...

第一层:启动与装配

main.tsx 的职责非常重,它不像普通 CLI 那样只是简单解析参数后执行一个函数。
它会在启动阶段做很多装配工作:

  • 预热性能敏感模块
  • 加载配置与托管设置
  • 初始化认证、遥测、策略限制
  • 初始化 MCP、LSP、插件、Skills
  • 汇总命令和工具
  • 根据模式启动 REPL、非交互流程或远程会话

所以 main.tsx 更像一个系统引导器。

对应源码片段

import { getSystemContext, getUserContext } from './context.js';
import { launchRepl } from './replLauncher.js';
import { getTools } from './tools.js';
import { filterCommandsForRemoteMode, getCommands } from './commands.js';
import { initializeLspServerManager } from './services/lsp/manager.js';
import { initBuiltinPlugins } from './plugins/bundled/index.js';
import { initBundledSkills } from './skills/bundled/index.js';

这段导入列表本身就很有信息量。
它说明入口层不是只拉一个 REPL,而是在同时装配:

  • 上下文系统
  • 工具系统
  • 命令系统
  • LSP
  • 插件
  • Skills

所以 main.tsx 在架构中的真实定位就是“装配根”。

这一层最重要的工程意义

启动层的价值不是“把东西 import 进来”,而是统一决定:

  • 当前 session 是什么形态
  • 哪些能力要启用
  • 哪些状态要预装
  • 哪些资源要在进入主循环前准备好

第二层:QueryEngine 主循环

QueryEngine.ts 是 Claude Code 的心脏。
它负责把一次用户任务转化为连续推进的执行过程。

它管理的核心对象包括:

  • 消息历史
  • 工具可用性
  • 权限拒绝记录
  • 文件缓存
  • token 与成本统计
  • 中断控制
  • 会话级状态延续

如果没有这一层,Claude Code 就会退化成“带一些工具描述的大模型调用器”。

对应源码片段

export class QueryEngine {
  private config: QueryEngineConfig
  private mutableMessages: Message[]
  private abortController: AbortController
  private permissionDenials: SDKPermissionDenial[]
  private totalUsage: NonNullableUsage
  private readFileState: FileStateCache

  constructor(config: QueryEngineConfig) {
    this.config = config
    this.mutableMessages = config.initialMessages ?? []
    this.abortController = config.abortController ?? createAbortController()
    this.permissionDenials = []
    this.readFileState = config.readFileCache
    this.totalUsage = EMPTY_USAGE
  }
}

只看这些字段就能知道,QueryEngine 管的不只是“发请求给模型”,还包括:

  • 历史消息
  • 中断控制
  • 权限拒绝
  • 文件缓存
  • usage 统计

这就是典型的会话级运行时,而不是一次性请求处理器。

加载图表中...

第三层:工具系统

Tool.ts 定义工具协议,tools.ts 负责注册和筛选工具。

这层的作用,是把底层能力统一包装成模型可调用的工具接口,例如:

  • 读写文件
  • Bash / PowerShell
  • 搜索与 glob
  • MCP 资源读取
  • LSP 能力调用
  • AskUserQuestion
  • Agent / Team / Task 相关工具

你可以把它理解为 Claude Code 的“行动层”。

对应源码片段

export function getAllBaseTools(): Tools {
  return [
    AgentTool,
    TaskOutputTool,
    BashTool,
    ...(hasEmbeddedSearchTools() ? [] : [GlobTool, GrepTool]),
    FileReadTool,
    FileEditTool,
    FileWriteTool,
    WebFetchTool,
    TodoWriteTool,
    WebSearchTool,
    AskUserQuestionTool,
    SkillTool,
    EnterPlanModeTool,
    ...(isEnvTruthy(process.env.ENABLE_LSP_TOOL) ? [LSPTool] : []),
    ListMcpResourcesTool,
    ReadMcpResourceTool,
  ]
}

这段代码直接说明 Claude Code 的能力不是抽象想象,而是明确注册出来的工具集合。

从这里你能非常直观地看到:

  • 文件能力
  • Shell 能力
  • 搜索能力
  • 交互能力
  • Skill 能力
  • LSP 与 MCP 能力

第四层:命令系统

除了模型可调用工具,Claude Code 还有大量显式命令。
commands.ts 聚合了很多斜杠命令,例如:

  • 配置类
  • 会话类
  • 审查类
  • 插件类
  • MCP 类
  • 计划类
  • 状态与统计类

命令系统服务的是“用户显式控制”,工具系统服务的是“模型隐式执行”,两者职能不同。

加载图表中...

第五层:上下文与状态

这套系统之所以能“像懂项目”,关键不只是工具,还包括上下文与状态:

  • context.ts 负责准备 Git 状态、CLAUDE.md、日期等上下文
  • AppStateStore.ts 管理 REPL、任务、通知、远程连接、MCP、插件等 UI 与会话状态

一个负责“给模型看什么”,一个负责“界面和会话当前处于什么状态”。

对应源码片段

export const getSystemContext = memoize(async (): Promise<{ [k: string]: string }> => {
  const gitStatus =
    isEnvTruthy(process.env.CLAUDE_CODE_REMOTE) ||
    !shouldIncludeGitInstructions()
      ? null
      : await getGitStatus()

  return {
    ...(gitStatus && { gitStatus }),
  }
})

这里能看出一个关键事实:
Claude Code 会主动把 Git 这样的工程上下文注入到后续对话里,这就是它“看起来懂项目”的重要原因之一。

第六层:扩展能力

从目录结构能看到,Claude Code 早就不是一个封闭工具,而是平台化形态:

  • services/mcp/*
  • services/lsp/*
  • plugins/*
  • skills/*
  • tools/AgentTool/*
  • remote/*

这些模块意味着 Claude Code 不只是执行内置工具,而是在持续向“可扩展工程智能体平台”演化。

目录体量为什么会这么大

当你看到这个仓库目录很多时,先不要急着认为它“设计很乱”。
更合理的理解是:Claude Code 同时承担了四类系统职责:

  • 终端交互应用
  • Agent 运行时
  • 工具与命令平台
  • 外部扩展集成层

把这四类职责叠起来,目录自然不会小。

架构主线与次要分支怎么区分

阅读时,建议把目录分成两类:

主干文件

  • main.tsx
  • QueryEngine.ts
  • Tool.ts
  • tools.ts
  • commands.ts
  • context.ts
  • state/AppStateStore.ts

延展文件

  • services/*
  • components/*
  • commands/*
  • tools/*
  • plugins/*
  • skills/*
  • remote/*

先抓住主干,再看延展,效率会高很多。

阅读源码时的正确顺序

如果你直接从海量目录乱翻,很容易迷失。
更推荐的顺序是:

  1. main.tsx
  2. QueryEngine.ts
  3. Tool.ts
  4. tools.ts
  5. commands.ts
  6. context.ts
  7. state/AppStateStore.ts
  8. 再进入 services/mcpservices/lsppluginsskills

这条线更接近系统真正的骨架。

小结

Claude Code 的源码架构可以概括成一句话:

main.tsx 把配置、命令、工具、上下文和扩展能力装配起来,再由 QueryEngine 驱动整个工程任务循环。

后面几篇文章,我们会沿着这条主干逐步往里拆。