Claude Code 项目架构分析

1. 项目定位

从代码结构看,这个项目本质上不是“若干命令拼起来的 CLI”,而是一个基于 Bun + TypeScript + React/Ink 的终端交互式应用框架。它的核心目标是:

  • 以终端 REPL 形式承载与模型的多轮会话
  • 在会话中统一调度命令、工具、权限、任务、子代理、插件、MCP 服务
  • 同时支持交互式 UI、SDK/无头模式、远程控制/Bridge 模式

换句话说,它的架构中心不是某个单独命令,而是“一次会话的生命周期管理”。

2. 代码规模与仓库边界

基于当前仓库快照统计:

  • src/ 下约 1902 个源码文件
  • src/ 顶层约 35 个一级子目录
  • 文件分布最重的目录是:utils/、components/、commands/、tools/、services/、hooks/

这说明项目已经进入“大型单体应用”阶段,但仍保持按能力域拆分的结构。

同时,这个仓库更像源码快照而不是完整工程根目录:

  • 仓库根目录未包含 package.json、tsconfig*.json、lockfile 等常见构建清单
  • 因此本分析聚焦于 src/ 中的运行时架构,而不是完整构建链路

3. 总体架构判断

这个项目可以概括为一个 事件驱动的终端 Agent 平台,采用“中心主循环 + 多能力注册 + 横切基础设施”的架构。

可抽象为下面这条主链路:

CLI 入口
  -> 初始化配置/环境/遥测/安全上下文
  -> 装配命令、工具、技能、插件、MCP、LSP
  -> 创建全局 AppState Store
  -> 启动 REPL 或 Headless QueryEngine
  -> 进入 query 主循环
  -> 模型输出 tool_use / 命令 / 子任务
  -> 权限判定 + 工具执行 + 状态更新 + UI 渲染
  -> 会话持久化 / 压缩 / 恢复 / 远程同步

这不是经典三层 Web 架构,也不是纯命令式 CLI,更接近:

  • 上层:终端 UI 与交互编排
  • 中层:会话与 Agent 主循环
  • 下层:工具、插件、MCP、LSP、Bridge 等执行能力
  • 横切:权限、配置、遥测、记忆、压缩、恢复

4. 启动与入口层

4.1 src/entrypoints/cli.tsx

这是最外层引导入口,特点是“按需动态加载”:

  • 对 --version、Bridge、daemon、background session 等路径做 fast-path
  • 通过 feature('...') 做大量编译期裁剪
  • 在真正进入完整 CLI 前,尽量避免大规模模块加载

这说明项目非常重视:

  • 启动性能
  • 多运行模式共存
  • 内部/外部构建差异的裁剪

4.2 src/main.tsx

main.tsx 是真实意义上的应用装配中心,职责非常重:

  • 提前触发 profiler、MDM 设置读取、keychain 预取
  • 初始化配置、GrowthBook、策略限制、远程托管设置
  • 组装命令、工具、技能、插件、MCP、LSP
  • 创建状态仓库并进入 REPL / headless 流程

可以把它视为项目的 composition root。

4.3 src/entrypoints/init.ts

init.ts 处理的是更底层的启动基础设施:

  • 配置系统启用
  • 安全环境变量注入
  • CA 证书 / mTLS / 代理 / upstream proxy
  • 清理回调注册
  • 远程设置与策略限制预加载
  • scratchpad、LSP cleanup 等基础资源初始化

因此启动层被明显分成了两段:

  • cli.tsx:入口分流与轻量 fast-path
  • main.tsx:应用级装配
  • init.ts:环境级初始化

这个分层是合理的。

5. 运行时主循环

5.1 REPL 是交互核心

src/screens/REPL.tsx 是交互式会话的核心屏幕。它不是简单视图组件,而是大型编排器,负责:

  • 输入提交
  • 消息流渲染
  • 工具权限交互
  • 后台任务展示
  • IDE / Remote / MCP / Sandbox / 通知集成
  • 队列、恢复、prompt suggestion、session backgrounding 等复杂行为

因此 REPL 在架构上承担了“终端 UI Shell + 会话控制器”的双重角色。

5.2 src/query.ts 是模型回合循环核心

query.ts 是最关键的运行时引擎之一。它实现的是典型的 agentic loop:

  1. 构建当前轮 query 配置
  2. 发起模型请求并流式接收输出
  3. 解析 tool_use
  4. 执行工具并注入 tool_result
  5. 必要时继续下一轮
  6. 处理 auto compact、stop hooks、预算、恢复等边界

这里还接入了:

  • StreamingToolExecutor
  • runTools(...)
  • auto compact / reactive compact
  • token budget / task budget

说明该项目的“Agent 能力”并不是外围补丁,而是主循环内建能力。

如果想继续往下读 src/query.ts 的真实执行细节,建议直接配合《Agent主循环》一起看。那篇文档会把这个文件里的状态字段、请求前预处理、流式采样、工具执行、恢复重试、stop hooks、预算续轮和终止条件按实际运行顺序拆开,而不是继续堆在总览文档里。

5.3 src/QueryEngine.ts 是 headless/SDK 抽象

QueryEngine 将相同的 query 逻辑抽象成可复用类,用于:

  • SDK 场景
  • headless 会话
  • 非 REPL 环境下的多轮消息提交

这说明作者已经意识到“UI 主循环”和“会话主循环”需要分离,但当前架构仍保留了较强耦合:REPL 和 QueryEngine 并存,主逻辑尚未完全统一。

6. 能力执行层:Tools、Commands、Tasks

6.1 Tools 是模型可调用能力

src/tools.ts 是工具注册中心,负责:

  • 汇总所有基础工具
  • 按 feature flag 裁剪工具
  • 按权限 deny rule 在暴露给模型前做过滤
  • 在需要时加入 MCP 工具、ToolSearchTool 等动态能力

这层的设计重点是“模型看到什么能力”。

从实现上看,Tool 是整个系统最核心的能力抽象之一,承载:

  • Shell / PowerShell
  • 文件读写与编辑
  • 搜索
  • Web fetch / Web search
  • MCP
  • Agent / Team / Task
  • Plan mode / Worktree 等会话控制能力

6.2 Commands 是用户显式入口

src/commands.ts 是 slash command 注册中心,负责整合:

  • 内建命令
  • 动态技能命令
  • 插件命令
  • bundled skills
  • builtin plugin skill commands

因此命令层的角色不是业务核心,而是“用户入口的统一索引层”。

一个重要结论是:

  • command 面向用户显式输入
  • tool 面向模型自主调用

两者共用同一会话上下文,但职责边界清晰。

6.3 Tasks 是后台执行与子代理承载

src/tasks/ 与 src/tasks/LocalAgentTask/LocalAgentTask.tsx 表明系统把后台 agent、子任务、远程任务统一建模为 Task。

Task 机制负责:

  • 注册/更新任务状态
  • 记录任务进度与消息
  • 在主会话与子代理之间传递通知
  • 支撑 foreground/background 切换

这使得“子代理”不是临时线程,而是系统内的一等运行单元。

7. 权限与安全控制

权限系统是该项目最突出的横切模块之一。

7.1 src/utils/permissions/permissionSetup.ts

这里负责:

  • 从磁盘加载权限规则
  • 构造 ToolPermissionContext
  • auto mode / plan mode 切换时修正权限
  • 剥离危险规则

尤其值得注意的是,它显式识别以下危险自动授权:

  • Bash 对解释器/任意脚本执行的宽泛放行
  • PowerShell 对嵌套 shell、表达式执行、进程启动的宽泛放行
  • AgentTool 的自动放行

这说明安全策略不是只在工具执行时判断,而是会提前改写能力边界。

7.2 src/services/tools/toolExecution.ts

工具执行层统一处理:

  • 权限校验
  • hook 调用
  • telemetry
  • MCP 异常归类
  • 工具结果消息化

也就是说,真正的工具调用不是工具对象自行直连执行,而是经过统一执行管线。

这是一个比较成熟的平台化设计。

8. 扩展体系:MCP、插件、技能、Bridge

8.1 MCP:外部能力总线

src/services/mcp/client.ts 负责把 MCP 服务接入为系统内能力,支持:

  • stdio / SSE / streamable HTTP / WebSocket 多种 transport
  • MCP tool 调用
  • resource 读取
  • auth / reauth
  • URL elicitation retry
  • 将 MCP tool/resource 包装为内部 Tool

这意味着 MCP 在本项目中不是“附加插件”,而是标准扩展协议。

8.2 插件:本地能力分发机制

src/utils/plugins/pluginLoader.ts 显示插件系统已经比较完整,具备:

  • marketplace / session-only / seed cache 等多来源加载
  • versioned cache
  • manifest 校验
  • hook / command / agent / settings 整合
  • 启停与错误收集

插件层更像“本地分发与装配机制”,而 MCP 更像“运行时协议接入机制”。

8.3 技能:Markdown 驱动的轻量能力封装

src/skills/loadSkillsDir.ts 说明技能系统本质上是:

  • 从 markdown/frontmatter 中加载描述、约束、参数、hooks、模型偏好
  • 可作为 slash command 使用
  • 可由 MCP skill builder 复用解析逻辑

这是一种很轻量的“提示工程资产化”方式,降低了扩展成本。

8.4 Bridge / Remote:远程控制与多环境调度

src/bridge/bridgeMain.ts 体现的是另一条非常重的架构支线:

  • 环境注册
  • session spawn
  • heartbeat
  • reconnectSession
  • worktree 管理
  • 远程工作分发

这说明项目不是单机 CLI,而是已经朝“本地终端 + 远程环境 + 会话调度”的平台方向演化。

9. 状态模型

src/state/AppStateStore.ts 里的 AppState 是系统统一状态核心,覆盖:

  • 设置与模型选择
  • 工具权限上下文
  • tasks
  • MCP clients/tools/resources
  • plugins
  • bridge / remote 状态
  • 通知、elicitation、todos、file history、session hooks

这说明项目采用的是集中式应用状态,而不是各功能局部自治。

优点:

  • 全局交互一致
  • 易于跨模块共享会话状态
  • 适合复杂终端 UI

代价:

  • 主状态过大
  • 模块耦合偏高
  • REPL 与状态变更逻辑容易继续膨胀

10. 横切能力

除了主链路,项目还有几类重要横切系统:

  • services/compact/:上下文压缩、自动 compact、恢复关键附件
  • memdir/、services/SessionMemory/、extractMemories/:长期/会话记忆
  • services/analytics/:遥测、feature gate、实验开关
  • services/lsp/:语言服务能力
  • migrations/:设置迁移
  • utils/sessionStorage.ts、conversationRecovery.ts:会话落盘与恢复

这些模块共同支撑了“长生命周期会话”这一产品特性。

11. 目录分层解读

可以把 src/ 粗分为 5 层:

11.1 入口与编排层

  • entrypoints/
  • main.tsx
  • screens/
  • commands/

11.2 会话运行层

  • query.ts
  • QueryEngine.ts
  • Task.ts
  • tasks/
  • state/

11.3 能力层

  • tools/
  • services/mcp/
  • services/lsp/
  • bridge/
  • remote/

11.4 扩展层

  • plugins/
  • skills/
  • commands/plugin/

11.5 横切基础设施层

  • utils/
  • services/analytics/
  • services/compact/
  • memdir/
  • migrations/
  • constants/

其中 utils/ 数量明显最多,说明大量通用能力被沉淀在基础设施层,但也意味着“工具化沉积”较重,后期需要警惕边界继续变模糊。

12. 架构优点

  • 入口清晰,fast-path 与完整装配链路区分明确
  • Tool、Command、Task 三种抽象边界相对清楚
  • 权限系统是平台级设计,不是零散校验
  • MCP、插件、技能三种扩展机制定位不同,层次合理
  • Query 主循环支持流式输出、工具调用、压缩、预算控制,能力完整
  • 支持 REPL、SDK、Remote/Bridge 多种运行模式,复用度高

13. 主要问题与风险

13.1 超大编排文件

以下文件承担了过多职责:

  • src/main.tsx
  • src/screens/REPL.tsx
  • src/query.ts
  • src/QueryEngine.ts

这类文件已经接近“巨型 orchestrator”,后续维护成本会持续上升。

13.2 UI 与业务编排耦合较深

尤其在 REPL.tsx 中,UI、权限交互、任务控制、消息处理、外部集成混在一起,未来如果要进一步拆出桌面端、Web 端或更纯净的 headless runtime,会有较高改造成本。

13.3 Feature flag 分支复杂

feature('...') 的广泛使用有利于构建裁剪,但也会带来:

  • 阅读路径分叉
  • 测试覆盖困难
  • 外部构建与内部构建行为差异增大

13.4 集中式状态继续膨胀

AppState 已经承载过多系统状态。若没有继续做领域切分,后续容易出现:

  • 修改影响面扩大
  • 非预期刷新/联动
  • 状态恢复与调试复杂化

14. 结论

这是一个大型单体、平台化、会话驱动的终端 Agent 系统。

它的核心架构不是传统 CLI 的“命令分发”,而是:

  • 以 main.tsx 完成装配
  • 以 REPL.tsx / QueryEngine.ts 承载会话入口
  • 以 query.ts 驱动模型-工具闭环
  • 以 tools/、tasks/、services/mcp/、plugins/ 构成能力平台
  • 以权限、压缩、记忆、恢复、遥测做横切支撑

如果只用一句话概括:

这是一个把终端 UI、Agent 运行时、工具平台、远程控制和扩展协议整合在同一进程模型中的大型 TypeScript 单体应用。

从工程角度看,它已经具备成熟平台的骨架;从维护角度看,下一阶段最值得投入的是“拆分超大编排器、收缩状态边界、降低 feature flag 带来的认知复杂度”。