Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Claude Code 源码分析 - 项目总览

项目概述

Claude Code 是 Anthropic 官方推出的 CLI 工具,允许用户通过终端与 Claude AI 进行交互式对话,执行软件工程任务。项目使用 TypeScript 编写,基于 React Ink 构建终端 UI,采用 Bun 作为运行时和打包工具。

技术栈

技术用途
TypeScript主要开发语言
React + Ink终端 UI 框架(深度定制 Fork)
Bun运行时 & 打包工具
Zod运行时类型校验
Yoga LayoutFlexbox 布局引擎(纯 TS 简化移植)
OpenTelemetry可观测性/遥测
OAuth 2.0认证体系
WebSocket / SSE实时通信
MCP (Model Context Protocol)工具扩展协议

源码统计

  • 总文件数: 1884 个 TypeScript/TSX 文件
  • 模块目录数: 35 个顶层模块
  • 根级文件数: 18 个核心入口文件

整体架构拓扑

以下所有连线均基于源码 import 语句验证。实线 = 直接 import,虚线 = 间接依赖(通过 hooks 或 type-only import)。

graph TB
    subgraph Entry["🚀 入口层"]
        CLI["CLI 入口<br/><small>entrypoints/cli</small>"]
        SDK["SDK 入口<br/><small>entrypoints/sdk</small>"]
        MCP_E["MCP Server<br/><small>entrypoints/mcp</small>"]
    end

    subgraph Orchestrator["🎯 编排层"]
        Main["main.tsx<br/><small>4683 行 · 应用主入口<br/>初始化 · 工具注册 · 路由</small>"]
    end

    subgraph Bootstrap["⚡ 启动层"]
        BS["bootstrap/state<br/><small>全局状态 · 配置加载 · 认证</small>"]
    end

    subgraph UI["🖥️ 终端 UI 层"]
        REPL["REPL.tsx<br/><small>5005 行 · 主交互屏幕</small>"]
        Resume["ResumeConversation<br/><small>会话恢复</small>"]
        Doctor["Doctor<br/><small>系统诊断</small>"]
        Components["components/<br/><small>389 React 组件文件</small>"]
        INK["ink/<br/><small>定制 Ink 引擎<br/>Yoga 布局 · 事件系统<br/>终端协议栈</small>"]
    end

    subgraph Core["🧠 AI 交互核心"]
        QueryTS["query.ts<br/><small>1729 行 · 查询主循环</small>"]
        QueryDir["query/<br/><small>config · deps · tokenBudget<br/>stopHooks · transitions</small>"]
        Services["services/<br/><small>API 调用 · 流式处理<br/>消息压缩 · 分析</small>"]
    end

    subgraph ToolChain["🔧 工具链"]
        Tools["tools/<br/><small>40 个 AI 工具<br/>buildTool 工厂</small>"]
        Skills["skills/<br/><small>技能系统</small>"]
        Plugins["plugins/<br/><small>插件系统</small>"]
    end

    subgraph HookSys["🪝 钩子层"]
        ReactHooks["hooks/<br/><small>104 React Hooks</small>"]
        ExecHooks["utils/hooks/<br/><small>钩子执行引擎<br/>28 种生命周期事件</small>"]
    end

    subgraph Infra["🏗️ 基础设施"]
        State["state/<br/><small>AppState 状态管理</small>"]
        Context["context/<br/><small>上下文构建</small>"]
        Schemas["schemas/<br/><small>Zod 验证</small>"]
        Utils["utils/<br/><small>564 工具文件<br/>31 子目录</small>"]
        NativeTS["native-ts/<br/><small>yoga-layout<br/>file-index · 色差</small>"]
    end

    subgraph Connect["🌐 连接层"]
        Bridge["bridge/<br/><small>IDE 桥接</small>"]
        Remote["remote/<br/><small>远程会话</small>"]
        Server["server/<br/><small>HTTP/WS</small>"]
        Coord["coordinator/<br/><small>多实例协调</small>"]
    end

    subgraph Extra["✨ 增强功能"]
        KB["keybindings/<br/><small>17 上下文</small>"]
        Vim["vim/<br/><small>Vim 模式</small>"]
        Voice["voice/<br/><small>语音交互</small>"]
        Memdir["memdir/<br/><small>自动记忆</small>"]
        Tasks["tasks/<br/><small>后台任务</small>"]
    end

    %% 入口 → 编排
    CLI --> Main
    SDK --> Main
    MCP_E --> Main

    %% 编排层依赖(main.tsx 直接 import)
    Main --> BS
    Main --> Services
    Main --> Tools
    Main --> Skills
    Main --> Plugins
    Main --> Bridge
    Main --> Server
    Main --> Coord
    Main --> Remote

    %% 启动层 → 屏幕(screens 均 import bootstrap/state)
    BS --> REPL
    BS --> Resume
    BS --> Doctor

    %% REPL 直接 import(源码验证)
    REPL --> QueryTS
    REPL --> Components
    REPL --> ReactHooks
    REPL --> State
    REPL --> KB
    REPL --> Tasks
    REPL -.->|type only| Remote
    REPL -.->|type only| Server

    %% 组件 → 渲染引擎
    Components --> INK

    %% 查询核心(query.ts 直接 import)
    QueryTS --> QueryDir
    QueryTS --> Services
    QueryTS --> Tools
    QueryTS --> ExecHooks

    %% 查询子模块(query/stopHooks.ts 直接 import)
    QueryDir --> Services
    QueryDir --> Memdir
    QueryDir --> KB

    %% 钩子层
    ReactHooks --> ExecHooks
    ReactHooks -.->|间接访问| Bridge
    ReactHooks -.->|间接访问| Vim
    ReactHooks -.->|间接访问| Voice

    %% 基础设施
    INK --> NativeTS
    Services --> Utils
    Tools --> Utils
    ExecHooks --> Utils

    style Entry fill:#4a9eff,stroke:#2d7cd6,color:#fff
    style Orchestrator fill:#e056fd,stroke:#be2edd,color:#fff
    style Bootstrap fill:#ff9f43,stroke:#d68536,color:#fff
    style UI fill:#a55eea,stroke:#8344c4,color:#fff
    style Core fill:#ee5a24,stroke:#c44a1e,color:#fff
    style ToolChain fill:#6ab04c,stroke:#58964a,color:#fff
    style HookSys fill:#22a6b3,stroke:#1b8a94,color:#fff
    style Infra fill:#778ca3,stroke:#5f7186,color:#fff
    style Connect fill:#0fb9b1,stroke:#0c9690,color:#fff
    style Extra fill:#f7b731,stroke:#c99528,color:#fff

架构图连线依据

连线源码依据
CLI/SDK/MCP → main.tsx三个入口点均通过 main.tsx 启动应用
main.tsx → bootstrap/main.tsx:87from './bootstrap/state.js'
main.tsx → services/main.tsx — 多处 import analytics, api, mcp, policyLimits
main.tsx → tools/main.tsx:45-46 — SyntheticOutputTool, AgentTool
main.tsx → skills/main.tsx — 直接 import skills/
main.tsx → plugins/main.tsx — 直接 import plugins/
main.tsx → bridge/main.tsx — 直接 import bridge/
main.tsx → server/main.tsx — 直接 import server/
main.tsx → coordinator/main.tsx — 直接 import coordinator/
matsx → remote/main.tsx — 直接 import remote/
bootstrap → screensREPL.tsx:32, Resume.tsx:6, Doctor.tsx:10 — 均 import bootstrap/state
REPL → query.tsscreens/REPL.tsx:146import { query } from '../query.js'
REPL → components/screens/REPL.tsx — 14 处 import(VirtualMessageList, PromptInput 等)
REPL → hooks/screens/REPL.tsx — 21 处 import(useSearchInput, useTerminalSize 等)
REPL → state/screens/REPL.tsx:170import { useAppState } from '../state/AppState.js'
REPL → keybindings/screens/REPL.tsx — KeybindingProviderSetup, useShortcutDisplay
REPL → tasks/screens/REPL.tsx:44-45 — InProcessTeammateTask, LocalAgentTask
REPL -.- remote/screens/REPL.tsx:279import type { RemoteSessionConfig } (type-only)
REPL -.- server/screens/REPL.tsx:62import type { DirectConnectConfig } (type-only)
components → ink/组件使用 ink/ 提供的 Box, Text 等基础组件渲染
query.ts → query/query.ts — import stopHooks, config, deps, transitions, tokenBudget
query.ts → services/query.ts:7-95 — api/withRetry, compact, toolUseSummary, analytics, tools
query.ts → tools/query.ts:91import { SLEEP_TOOL_NAME } from './tools/SleepTool/prompt.js'
query.ts → utils/hooks/query.ts:92-93 — postSamplingHooks, executeStopFailureHooks
query/ → services/query/deps.ts — api/claude, compact/autoCompact, compact/microCompact
query/ → memdir/query/stopHooks.tsimport { isExtractModeActive } from '../memdir/paths.js'
query/ → keybindings/query/stopHooks.tsimport { getShortcutDisplay }
hooks/ → utils/hooks/hooks/useSkillImprovementSurvey.ts, hooks/toolPermission/PermissionContext.ts
hooks/ -.- bridge/hooks/useReplBridge.tsx import bridge/
hooks/ -.- vim/hooks/useVimInput.ts import vim/
hooks/ -.- voice/hooks/useVoiceIntegration.tsx import voice/
ink/ → native-ts/ink/reconciler.ts, ink/ink.tsx — import yoga-layout
services/tools/utils → utils/多处 import utils/ 下的工具函数

REPL 不直接 import 的模块:bridge/、vim/、voice/、memdir/、skills/、coordinator/。这些模块通过 hooks/ 间接访问,或由 main.tsx 在启动时编排。


核心数据流

sequenceDiagram
    participant U as 用户终端
    participant R as REPL.tsx
    participant Q as query.ts
    participant S as services/api
    participant A as Claude API
    participant T as tools/
    participant H as utils/hooks/

    U->>R: 输入文本/命令
    R->>R: 解析命令 (/ 开头?)

    R->>Q: import { query } 直接调用

    loop 查询主循环
        Q->>Q: microcompact 消息压缩
        Q->>Q: autocompact 检查
        Q->>S: callModel() 流式请求
        S->>A: HTTP Stream
        A-->>S: 流式响应 (文本/工具调用)
        S-->>Q: yield 响应块

        alt 文本响应
            Q-->>R: yield 文本块
            R-->>U: 渲染到终端 (ink/)
        else 工具调用
            Q->>H: executePostSamplingHooks()
            Q->>T: runTools() 执行工具
            T-->>Q: 工具结果
            Q->>Q: 追加结果到消息
        end

        Q->>Q: checkTokenBudget()
        Note over Q: 连续2次 delta < 500 且续传≥3 → 停止
    end

    Q->>H: 执行停止钩子 (stopHooks.ts)
    Note over H: 记忆提取 · 自动推理 · 提示建议
    Q-->>R: 查询完成
    R->>R: 会话持久化 (utils/sessionStorage)

工具执行流程

flowchart LR
    A["AI 请求<br/>工具调用"] --> B{"权限检查<br/><small>hooks/useCanUseTool</small>"}
    B -->|自动允许| D["执行工具<br/><small>services/tools/<br/>toolOrchestration</small>"]
    B -->|需确认| C["显示权限对话框<br/><small>components/permissions/</small>"]
    C -->|允许| D
    C -->|拒绝| E["返回拒绝结果"]
    D --> F["收集结果"]
    F --> G["更新文件状态缓存<br/><small>utils/fileStateCache</small>"]
    G --> H["追加到消息"]
    H --> I["继续查询循环"]

    style A fill:#4a9eff,color:#fff
    style B fill:#f7b731,color:#fff
    style D fill:#20bf6b,color:#fff
    style E fill:#ee5a24,color:#fff

模块依赖关系(基于 import 验证)

graph LR
    subgraph 编排
        M[main.tsx]
    end

    subgraph 核心
        B[bootstrap]
        SC[screens/REPL]
        Q[query.ts]
        SV[services]
    end

    subgraph 工具链
        TL[tools]
        SK[skills]
        PL[plugins]
    end

    subgraph 钩子
        RH[hooks]
        EH[utils/hooks]
    end

    subgraph 渲染
        CP[components]
        IK[ink]
        NT[native-ts]
    end

    subgraph 基础
        ST[state]
        UT[utils]
    end

    subgraph 连接
        BR[bridge]
        RM[remote]
        SRV[server]
        CO[coordinator]
    end

    M --> B
    M --> SV
    M --> TL
    M --> SK
    M --> PL
    M --> BR
    M --> SRV
    M --> CO
    M --> RM

    B --> SC
    SC --> Q
    SC --> CP
    SC --> RH
    SC --> ST

    Q --> SV
    Q --> TL
    Q --> EH

    CP --> IK
    IK --> NT

    RH --> EH
    RH -.-> BR
    RH -.-> RM

    SV --> UT
    TL --> UT
    EH --> UT

    style M fill:#e056fd,color:#fff
    style Q fill:#ee5a24,color:#fff
    style SC fill:#a55eea,color:#fff
    style UT fill:#778ca3,color:#fff

启动流程

flowchart TB
    A["bun run cli.tsx"] --> B["解析 CLI 参数"]
    B --> C["main.tsx 初始化"]
    C --> D["bootstrap/state<br/><small>加载 settings.json · CLAUDE.md</small>"]
    D --> E["认证检查<br/><small>OAuth / API Key</small>"]
    E --> F["注册工具 & 加载插件<br/><small>tools/ · skills/ · plugins/</small>"]
    F --> G["初始化连接层<br/><small>bridge/ · server/ · coordinator/</small>"]
    G --> H{"入口模式?"}

    H -->|交互式| I["启动 REPL"]
    H -->|--print / -p| J["单次查询"]
    H -->|SDK| K["返回 Agent 实例"]
    H -->|MCP| L["启动 MCP Server"]

    I --> M["渲染终端 UI<br/><small>components/ → ink/ 引擎</small>"]
    M --> N["等待用户输入"]

    style A fill:#4a9eff,color:#fff
    style C fill:#e056fd,color:#fff
    style H fill:#f7b731,color:#fff
    style I fill:#a55eea,color:#fff
    style M fill:#20bf6b,color:#fff

模块目录树

src/
├── main.tsx                    # 应用主入口 · 编排器 (4683 行)
├── Tool.ts                     # 工具工厂 buildTool() (792 行)
├── Task.ts                     # 任务类型定义 (125 行)
├── query.ts                    # 查询主循环 (1729 行)
├── QueryEngine.ts              # 查询引擎封装 (1295 行)
│
├── entrypoints/                # 入口点(CLI/SDK/MCP)
├── bootstrap/                  # 应用启动 & 全局状态
├── cli/                        # CLI 传输层 & 处理器
├── commands/                   # 86 个斜杠命令子目录 + 15 个根级命令文件
├── screens/                    # 主要 UI 屏幕(REPL/Doctor/Resume)
├── components/                 # 389 个 React UI 组件文件(31 子目录)
├── ink/                        # Ink 终端渲染引擎(深度定制 Fork)
│
├── query/                      # 查询配置/依赖注入/Token预算/停止钩子
├── services/                   # 服务层(20 子目录 + 16 根级文件 · API/分析/压缩)
├── tools/                      # 40 个 AI 工具实现
├── skills/                     # 技能系统(bundled + custom)
├── plugins/                    # 插件系统
├── hooks/                      # 104 React UI Hooks
│
├── state/                      # 应用状态管理
├── context/                    # 上下文收集(git/系统/用户)
├── constants/                  # 常量定义
├── types/                      # 全局类型定义
├── schemas/                    # Zod Schema 定义
│
├── bridge/                     # Web/IDE 桥接通信
├── coordinator/                # 多实例协调器
├── remote/                     # 远程会话管理
├── server/                     # HTTP/WebSocket 服务器
│
├── keybindings/                # 快捷键系统(17 上下文)
├── vim/                        # Vim 模式支持
├── voice/                      # 语音uddy/                      # Buddy 彩蛋(6 文件)
│
├── utils/                      # 工具函数库(564 文件 · 31 子目录)
├── native-ts/                  # 纯 TS 原生实现(yoga/file-index/色差)
├── memdir/                     # 自动记忆系统(8 文件)
├── migrations/                 # 配置迁移(11 迁移文件)
├── tasks/                      # 后台任务管理(5 种任务类型 + 根级辅助文件)
├── outputStyles/               # 输出样式加载
├── upstreamproxy/              # 上游代理
└── assistant/                  # 会话历史管理

01 - 根级文件源码分析

路径: src/*.ts / src/*.tsx 文件数: 18 个

这些文件是整个 Claude Code 应用的核心入口和基础抽象层,定义了应用的启动流程、核心类型和顶层模块导出。


1. main.tsx — 应用主入口

行数: 4683 行

功能概述

应用的最顶层入口文件,负责解析 CLI 参数、初始化环境、选择运行模式并启动对应的屏幕。

核心逻辑

CLI 参数解析 → 环境初始化 → 模式选择 → 渲染对应屏幕
  1. 解析命令行参数(--resume, --continue, --print 等)
  2. 调用 setup.ts 进行环境初始化
  3. 根据参数选择运行模式:
    • 交互式 REPL 模式 → 渲染 REPL 屏幕
    • 恢复会话模式 → 渲染 ResumeConversation 屏幕
    • 诊断模式 → 渲染 Doctor 屏幕
    • 非交互式打印模式 → 直接输出
  4. 使用 Ink 渲染 React 组件到终端

关键依赖

  • screens/REPL.tsx — 主交互屏幕
  • screens/ResumeConversation.tsx — 会话恢复屏幕
  • screens/Doctor.tsx — 诊断屏幕
  • setup.ts — 环境初始化
  • ink/ink.tsx — Ink 渲染器

2. Tool.ts — 工具抽象基类

行数: 792 行

功能概述

定义了 AI 工具的核心抽象。所有工具通过 buildTool(def) 工厂函数构建(不是链式 Builder),接收 ToolDef 对象,返回展开后的 BuiltTool

导出

  • buildTool(def) — 工厂函数,将 ToolDef 转为 BuiltTool
  • ToolDef 类型 — 工具定义接口
  • BuiltTool 类型 — 构建后的工具对象
  • TOOL_DEFAULTS — 安全默认值

工厂模式

// 源码 src/Tool.ts:783-792
export function buildTool<D extends AnyToolDef>(def: D): BuiltTool<D> {
  return {
    ...TOOL_DEFAULTS,
    userFacingName: () => def.name,
    ...def,
  } as BuiltTool<D>
}

设计亮点

  • 工厂函数 + 对象展开: 不是类继承,而是 TOOL_DEFAULTSdef 展开合并
  • 安全默认值: TOOL_DEFAULTS 提供默认权限检查、默认非并发安全等
  • MCP 集成: 支持 Model Context Protocol 工具协议
  • 60+ 工具: 类型系统通过 0-error typecheck 验证所有工具定义

3. Task.ts — 任务类型定义

行数: 125 行

功能概述

定义后台任务的类型系统,支持 7 种任务类型和 5 种状态。任务 ID 使用 randomBytes(8) 生成,带单字符类型前缀。

导出

  • TaskType — 任务类型联合类型
  • TaskStatus — 任务状态联合类型
  • Task — 任务接口
  • generateTaskId() — 任务 ID 生成函数

任务类型

类型说明
local_bash本地 Shell 命令
local_agent本地子 Agent
remote_agent远程 Agent
in_process_teammate进程内队友
local_workflow本地工作流
monitor_mcpMCP 监控
dream后台推理任务

任务状态

pending → running → completed
                  → failed
                  → killed

ID 生成

  • 使用 randomBytes(8) 生成(不是 crypto.randomUUID()
  • 36 字符字母表(a-z + 0-9)
  • 单字符类型前缀:b=local_bash, a=local_agent, r=remote_agent, t=in_process_teammate, w=local_workflow, m=monitor_mcp, d=dream
  • 36^8 ≈ 2.8 万亿种组合,足以抵抗暴力符号链接攻击

4. QueryEngine.ts — 查询引擎

行数: 1295 行

功能概述

查询引擎的顶层抽象,封装了与 Claude API 的交互逻辑。

核心职责

  • 管理查询生命周期
  • 协调模型调用和工具执行
  • 处理流式响应
  • 管理 token 预算

5. commands.ts — 命令注册中心

行数: 754 行

功能概述

中央命令注册表,聚合来自多个来源的斜杠命令(/help, /commit, /review 等)。

导出

  • getCommands() — 获取所有可用命令(带缓存)
  • REMOTE_SAFE_COMMANDS — 远程安全命令集合
  • BRIDGE_SAFE_COMMANDS — 桥接安全命令集合
  • INTERNAL_ONLY_COMMANDS — 仅内部使用的命令

命令来源

bundled skills (内置技能)
  + plugin skills (插件技能)
  + skill directories (.skills/ 目录)
  + workflows (工作流)
  + built-in commands (内置命令)
  = 完整命令列表

安全过滤

  • REMOTE_SAFE: 远程会话中允许执行的命令白名单
  • BRIDGE_SAFE_COMMANDS: 桥接模式中允许的命令白名单
  • INTERNAL_ONLY_COMMANDS: 对 AI 隐藏的内部命令

缓存机制

使用 memoization 确保命令只发现一次,后续调用直接返回缓存结果。


6. context.ts — 上下文收集

行数: 189 行

功能概述

收集对话所需的上下文信息,包括 git 仓库状态和系统/用户上下文。

导出

  • getGitStatus() — 收集 git 状态(memoized)
  • getSystemContext() — 收集系统上下文(memoized)
  • getUserContext() — 收集用户上下文(memoized)
  • setSystemPromptInjection() — 设置缓存破坏注入(调试用)

收集内容

  1. Git 状态: 分支名、工作区状态(截断到 2000 字符)、最近提交、用户信息
  2. CLAUDE.md 文件: 从项目目录树中发现并加载所有 CLAUDE.md 文件
  3. 缓存破坏注入: 用于调试的缓存破坏机制

特性

  • Memoized 缓存,避免重复收集
  • 支持 bare mode(最小上下文)
  • 支持显式添加额外目录
  • 诊断日志带 PII 过滤

7. cost-tracker.ts — 费用追踪器

行数: 323 行

功能概述

全面的 API 使用费用监控系统,支持按模型粒度追踪。

追踪指标

指标说明
输入 tokens发送给模型的 token 数
输出 tokens模型生成的 token 数
缓存读取 tokens从缓存读取的 token 数
缓存创建 tokens写入缓存的 token 数
Web 搜索请求网页搜索调用次数
USD 费用计算的美元费用

持久化

  • 会话数据持久化到项目配置
  • 支持通过 session ID 跨会话恢复
  • 进程退出时自动保存

8. costHook.ts — 费用摘要 Hook

行数: 22 行

功能概述

React Hook,在进程退出时显示格式化的费用摘要。

导出

  • useCostSummary() — React Hook

逻辑

  • 使用 useEffect 监听进程退出事件
  • 格式化显示总费用、token 使用量
  • 与计费访问控制系统集成

9. dialogLaunchers.tsx — 对话框启动器

行数: 132 行

功能概述

提供各种对话框的启动函数,用于在 REPL 中弹出模态对话框。

典型对话框

  • 权限确认对话框
  • 设置对话框
  • 模型选择对话框
  • 帮助对话框

10. history.ts — 历史记录管理

行数: ~150 行

功能概述

管理对话历史记录的加载、保存和查询。

核心功能

  • 加载历史会话列表
  • 按项目/仓库过滤会话
  • 渐进式加载(分页)
  • 会话元数据管理(标题、时间戳、消息数)

11. ink.ts — Ink 模块导出

行数: ~30 行

功能概述

Ink 终端 UI 框架的顶层导出文件,重新导出 ink/ 目录中的核心组件和 hooks。

导出内容

  • React 组件: Box, Text, Spacer
  • Hooks: useInput, useApp, useStdin
  • 渲染函数: render

12. interactiveHelpers.tsx 行数**: ~80 行

功能概述

提供交互式 UI 的辅助组件和函数。

典型功能

  • 确认提示
  • 选择列表
  • 进度指示器
  • 错误显示

13. projectOnboardingState.ts — 项目引导状态

行数: ~50 行

功能概述

管理项目首次使用时的引导流程状态。

功能

  • 检测是否为新项目
  • 追踪引导步骤完成状态
  • 持久化引导进度

14. query.ts — 查询入口

行数: 1729 行

功能概述

查询主循环的完整实现(不是简单导出),包含与 Claude API 交互、工具调用处理、流式响应、token 预算管理等核心逻辑。

核心流程

query(messages, tools, config)
  → 构建请求
  → 调用模型(流式)
  → 处理工具调用
  → 返回响应

15. replLauncher.tsx — REPL 启动器

行数: 22 行


16. setup.ts — 环境初始化

行数: ~200 行

功能概述

应用启动时的环境初始化,在 main.tsx 中最先调用。

初始化步骤

  1. 设置进程信号处理
  2. 初始化日志系统
  3. 加载用户配置
  4. 初始化 OpenTelemetry
  5. 设置错误处理
  6. 检查更新
  7. 运行配置迁移

17. tasks.ts — 任务模块导出

行数: ~30 行

功能概述

tasks/ 目录的顶层导出文件。


18. tools.ts — 工具模块导出

行数: ~100 行

功能概述

tools/ 目录的顶层导出,注册并导出所有可用的 AI 工具。

注册的工具

  • Bash — 执行 Shell 命令
  • Read — 读取文件
  • Write — 写入文件
  • Edit — 编辑文件
  • Glob — 文件模式匹配
  • Grep — 内容搜索
  • Agent — 子 Agent 启动
  • WebFetch — 网页获取
  • WebSearch — 网页搜索
  • Notebook — Jupyter Notebook 编辑
  • TodoWrite — 任务列表管理
  • 更多 MCP 工具…

文件间依赖关系

main.tsx
  ├── setup.ts (初始化)
  ├── context.ts (上下文)
  ├── commands.ts (命令)
  ├── tools.ts (工具)
  │     └── Tool.ts (基类)
  ├── tasks.ts (任务)
  │     └── Task.ts (类型)
  ├── query.ts (查询)
  │     └── QueryEngine.ts (引擎)
  ├── cost-tracker.ts (费用)
  │     └── costHook.ts (Hook)
  └── replLauncher.tsx (启动器)
        └── screens/REPL.tsx (主屏幕)

02 - entrypoints 模块源码分析

路径: src/entrypoints/ 功能: 多入口点系统,支持 CLI、SDK、MCP 三种运行模式


模块概述

entrypoints/ 定义了 Claude Code 的多种启动方式。不同的入口点决定了应用以何种模式运行——交互式 CLI、程序化 SDK、还是 MCP 服务器。

文件清单

文件行数说明
cli.tsx302CLI 主入口
init.ts340初始化入口(文档之前遗漏)
mcp.ts196MCP 服务器入口
sandboxTypes.ts156沙箱类型定义
agentSdkTypes.ts443Agent SDK 类型定义(re-export hub + stub 函数)
sdk/coreTypes.ts62SDK 核心类型(HOOK_EVENTS, EXIT_REASONS 常量)
sdk/coreSchemas.ts1889SDK 核心 Schema(文档之前遗漏,最大文件)
sdk/controlSchemas.ts663SDK 控制协议 Schema

1. cli.tsx — CLI 主入口

行数: 302 行(比预期小得多,大量逻辑已拆分到其他模块)

功能概述

这是用户在终端执行 claude 命令时的入口点。负责完整的 CLI 生命周期管理。

核心流程

命令行解析 → 认证检查 → 模式路由 → 屏幕渲染 → 退出处理

详细步骤

  1. 命令行参数解析

    • 使用自定义解析器处理参数
    • 支持子命令: auth, config, doctor, mcp, plugin
    • 支持标志: --print, --resume, --continue, --model
  2. 认证流程

    • 检查 OAuth token 有效性
    • 支持 API Key 和 OAuth 两种认证方式
    • 处理 token 刷新
  3. 模式路由

    claude                    → 交互式 REPL
    claude -p "prompt"        → 非交互式打印模式
    claude --resume           → 恢复会话
    claude doctor             → 诊断模式
    claude auth login         → 认证登录
    claude config             → 配置管理
    claude mcp                → MCP 服务器管理
    
  4. 屏幕渲染

    • 使用 Ink 渲染 React 组件到终端
    • 管理终端原始模式
    • 处理窗口大小变化
  5. 退出处理

    • 保存会话状态
    • 清理临时资源
    • 发送遥测数据

2. mcp.ts — MCP 服务器入口

行数: 197 行

功能概述

将 Claude Code 作为 MCP (Model Context Protocol) 服务器运行,允许其他 AI 应用通过标准协议调用 Claude Code 的工具。

导出

  • MCP 服务器启动函数

核心逻辑

// 伪代码
async function startMCPServer() {
  // 1. 初始化 MCP 传输层(stdio)
  const transport = new StdioTransport()

  // 2. 注册可用工具
  const tools = loadTools()

  // 3. 处理 MCP 请求
  transport.onRequest(async (request) => {
    switch (request.method) {
      case 'tools/list':
        return { tools: tools.map(t => t.toMCPSchema()) }
      case 'tools/call':
        return await executeTool(request.params)
    }
  })

  // 4. 启动服务器
  await transport.start()
}

MCP 协议支持

  • ListToolsRequest — 列出可用工具(含 Zod→JSON Schema 转换)
  • CallToolRequest — 调用工具(含输入验证和权限检查)
  • 注意:当前不支持 resources 相关处理(无 resources/listresources/read

3. sandboxTypes.ts — 沙箱类型定义

行数: 156 行

功能概述

使用 Zod Schema 定义沙箱环境的配置和权限,不是简单的 interface。

核心 Schema

// 实际是 Zod schema,包含细粒度配置
const SandboxConfigSchema = z.object({
  network: z.object({ ... }),           // 网络访问控制
  filesystem: z.object({
    allowRead: z.array(z.string()),     // 允许读取的路径
    denyRead: z.array(z.string()),      // 禁止读取的路径
    allowManagedDomainsOnly: z.boolean(), // 仅允许托管域名
  }),
  // ... 更多细粒度配置
})

4. agentSdkTypes.ts — Agent SDK 类型定义

行数: ~500+ 行

功能概述

定义 Agent SDK 的完整类型系统,包括消息格式、事件类型和钩子事件。

核心类型

// SDK 消息类型
type SDKMessage = {
  type: 'usesistant' | 'system' | 'tool_use' | 'tool_result'
  content: ContentBlock[]
  // ...
}

// 钩子事件类型
type HookEvent =
  | 'PreToolUse'      // 工具执行前
  | 'PostToolUse'     // 工具执行后
  | 'Stop'            // 回合结束
  | 'TeammateIdle'    // 队友空闲
  | 'TaskCompleted'   // 任务完成
  | 'Notification'    // 通知
  | 'SubagentStop'    // 子Agent停止

// 导出的常量
const HOOK_EVENTS: HookEvent[] = [...]

设计特点

  • 使用 discriminated union 实现类型安全的消息路由
  • 钩子事件覆盖完整的工具生命周期
  • 支持子 Agent 和队友模式的事件

5. sdk/coreTypes.ts — SDK 核心类型

行数: 63 行

功能概述

SDK 的最基础类型定义,被其他 SDK 文件广泛引用。

导出

// 内容块类型
type ContentBlockParam =
  | TextBlock
  | ImageBlock
  | ToolUseBlock
  | ToolResultBlock

// 消息角色
type Role = 'user' | 'assistant'

// 停止原因
type StopReason =
  | 'end_turn'        // 正常结束
  | 'max_tokens'      // 达到 token 上限
  | 'stop_sequence'   // 遇到停止序列
  | 'tool_use'        // 需要执行工具

6. sdk/controlSchemas.ts — SDK 控制协议 Schema

行数: 664 行

功能概述

使用 Zod 定义 SDK 控制协议的完整 Schema,用于 CLI 和 Web/IDE 之间的双向通信。

控制请求类型

// 服务器 → 客户端的控制请求
type ServerControlRequest =
  | { type: 'initialize', payload: InitializePayload }
   type: 'set_model', payload: SetModelPayload }
  | { type: 'interrupt', payload: InterruptPayload }
  | { type: 'set_permission_mode', payload: SetPermissionModePayload }
  | { type: 'set_max_thinking_tokens', payload: SetMaxThinkingTokensPayload }

控制响应类型

// 客户端 → 服务器的控制响应
type ClientControlResponse = {
  requestId: string
  success: boolean
  error?: string
  data?: unknown
}

Schema 验证

  • 所有控制消息都经过 Zod Schema 验证
  • 支持版本协商
  • 类型安全的序列化/反序列化

模块间关系

entrypoints/
├── cli.tsx ──────────→ screens/REPL.tsx (交互模式)
│                    → screens/Doctor.tsx (诊断模式)
│                    → screens/ResumeConversation.tsx (恢复模式)
│
├── mcp.ts ──────────→ tools/ (注册工具为 MCP 资源)
│
├── agentSdkTypes.ts → 被 bridge/, hooks/, query/ 广泛引用
│
└── sdk/
    ├── coreTypes.ts → 基础类型,被所有 SDK 相关代码引用
    └── controlSchemas.ts → 被 bridge/ 用于消息验证

设计亮点

  1. 多入口架构: 同一套核心代码支持 CLI、SDK、MCP 三种运行模式
  2. 协议分层: 控制协议与业务逻辑分离,Schema 独立定义
  3. 类型驱动: 使用 Zod Schema 同时提供运行时验证和编译时类型
  4. 渐进式复杂度: 从简单的 MCP 服务器到完整的交互式 CLI,复杂度逐层递增

03 - bootstrap 模块源码分析

路径: src/bootstrap/ 文件数: 1 个(但极其庞大) 功能: 全局应用状态管理 — 整个应用的“神经系统“


模块概述

bootstrap/ 模块只有一个文件 state.ts,但它是整个 Claude Code 应用最核心的状态容器。它维护了一个全局单例 STATE 对象,通过 150+ 个 getter/setter 函数提供类型安全的状态访问。


state.ts — 全局状态容器

行数: 1758 行 导出数量: 215 个(函数、类型、常量等)

架构设计

┌─────────────────────────────────────────┐
│              STATE (单例对象)              │
├─────────────────────────────────────────┤
│  会话管理    │  费用追踪    │  Token 统计  │
│  路径管理    │  模型配置    │  遥测指标    │
│  Agent 状态  │  API 缓存    │  错误日志    │
│  插件系统    │  权限管理    │  Cron 任务   │
│  Hook 系统   │  技能追踪    │  提示缓存    │
│  模式标志    │  团队创建    │  调试状态    │
└─────────────────────────────────────────┘
         ↕ (通过 getter/setter 访问)
    整个应用的所有模块

状态分类详解

1. 会话管理 (Session Management)

// 核心函数
getSessionId(): SessionId           // 获取当前会话 ID
regenerateSessionId(): void         // 重新生成会话 ID
switchSession(id: SessionId): void  // 切换到指定会话
getParentSessionId(): SessionId | undefined  // 获取父会话 ID(子Agent场景)

设计说明: 会话 ID 使用 randomUUID() 生成(通过 src/utils/crypto.js 封装),支持父子会话关系(用于子 Agent 场景)。switchSession 在恢复历史会话时使用。注意:parentSessionId 只有 getter,没有独立的 setter。

2. 路径管理 (Path Management)

getOriginalCwd(): string            // 获取原始工作目录
setOriginalCwd(path: string): void
getProjectRoot(): string            // 获取项目根目录
setProjectRoot(path: string): void
getCwdState(): string             // 获取当前工作目录状态
setCwdState(state: string): void

设计说明: 区分“原始工作目录“(用户启动 CLI 的位置)和“项目根目录“(git 仓库根目录),这对于正确解析相对路径至关重要。

3. 费用与性能追踪 (Cost & Performance Tracking)

// 费用
addToTotalCostState(cost: number, modelUsage: ModelUsage, model: string): void
getTotalCostUSD(): number

// API 耗时
getTotalAPIDuration(): number
getTotalAPIDurationWithoutRetries(): number

// 工具耗时(按回合)
addToTurnHookDuration(ms: number): void
addToTurnToolDuration(ms: number): void
addToTurnClassifierDuration(ms: number): void
getTurnHookDurationMs(): number
getTurnToolDurationMs(): number
getTurnClassifierDurationMs(): number

设计说明: 性能追踪分为“总计“和“按回合“两个维度。回合级别的追踪用于识别单次交互中的性能瓶颈。

4. Token 统计 (Token Tracking)

// 全局 Token 统计
getTotalInputTokens(): number
getTotalOutputTokens(): number
getTotalCacheReadInputTokens(): number
getTotalCacheCreationInputTokens(): number

// 按模型统计
getModelUsage(): { [modelName: string]: ModelUsage }

注意:不存在独立的 recordModelUsage()getTotalTokensAcrossModels() 函数。模型使用数据通过 addToTotalCostState() 的第二、三个参数间接记录。


**ModelUsage 结构**:
```typescript
interface ModelUsage {
  inputTokens: number
  outputTokens: number
  cacheReadInputTokens: number
  cacheCreationInputTokens: number
  apiCalls: number
  totalDurationMs: number
}

设计说明: 使用 lodash-es/sumBy 聚合跨模型的 token 统计。支持多模型场景(主模型 + 分类器模型)。

5. 模型配置 (Model Configuration)

getMainLoopModelOverride(): ModelSetting | undefined
setMainLoopModelOverride(model: ModelSetting | undefined): void
getInitialMainLoopModel(): ModelSetting
setInitialMainLoopModel(model: ModelSetting): void
getModelStrings(): ModelStrings | null
setModelStrings(settings: ModelStrings): void

设计说明: 支持运行时模型切换(通过 /model 命令),同时保留初始模型配置用于回退。

6. OpenTelemetry 遥测 (Telemetry)

// Meter(指标)
setMeter(meter: Meter): void
getMeter(): Meter | undefined

// 各种计数器
getSessionCounter(): Counter
getLocCounter(): Counter          // 代码行数计数器
getPrCounter(): Counter           // PR 计数器
getCommitCounter(): Counter       // 提交计数器
getCostCounter(): Counter         // 费用计数器
getTokenCounter(): Counter        // Token 计数器
getCodeEditToolDecisionCounter(): Counter  // 代码编辑决策计数器
getActiveTimeCounter(): Counter   // 活跃时间计数器

// Logger & Tracer
setLoggerProvider(provider: LoggerProvider): void
getEventLogger(): Logger | undefined
setMeterProvider(provider: MeterProvider): void
setTracerProvider(provider: BasicTracerProvider): void

设计说明: 完整集成 OpenTelemetry 标准,支持 Metrics、Logs、Traces 三大支柱。计数器覆盖了从会话到代码编辑的各个维度。

7. Agent 与 UI (Agent & UI)

getAgentColorMap(): Map<string, AgentColorName>    // Agent ID → 颜色映射

设计说明: 多 Agent 场景下,每个 Agent 分配不同颜色用于 UI 区分。颜色从预定义调色板中循环分配。

8. API 请求缓存 (API Request Caching)

getLastAPIRequest(): unknown
setLastAPIRequest(request: unknown): void
getLastAPIRequestMessages(): Message[]
setLastAPIRequestMessages(messages: Message[]): void
getLastClassifierRequests(): unknown[]
setLastClassifierRequests(requests: unknown[]): void

设计说明: 缓存最近的 API 请求用于调试和重试。分别缓存主模型请求和分类器请求。

9. 错误日志 (Error Logging)

addToInMemoryErrorLog(errorInfo: { error: string; timestamp: string }): void

设计说明: 内存中的错误日志,用于 doctor 诊断命令和调试。不持久化到磁盘。注意:只有写入函数,没有独立的 getInMemoryErrorLog() getter。

10. 插件系统 (Plugin System)

getInlinePlugins(): Array<string>
setInlinePlugins(plugins: Array<string>): void
getUseCoworkPlugins(): boolean
setUseCoworkPlugins(enabled: boolean): void

11. 权限与信任 (Permissions & Trust)

getSessionBypassPermissionsMode(): boolean
setSessionBypassPermissionsMode(bypass: boolean): void
getSessionTrustAccepted(): boolean
setSessionTrustAccepted(accepted: boolean): void

设计说明: bypassPermissions 用于自动化场景(如 CI/CD),trustAccepted 记录用户是否已接受项目信任提示。

12. Cron 任务 (Cron Tasks)

getSessionCronTasks(): SessionCronTask[]
addSessionCronTask(task: SessionCronTask): void
removeSessionCronTasks(ids: string[]): void
getScheduledTasksEnabled(): boolean
setScheduledTasksEnabled(enabled: boolean): void

设计说明: 支持会话内的定时任务(如定期检查部署状态),任务随会话结束而销毁。

13. Hook 系统 (Hook System)

registerHookCallbacks(hooks: Partial<Record<HookEvent, RegisteredHookMatcher[]>>): void
getRegisteredHooks(): Partial<Record<HookEvent, RegisteredHookMatcher[]>> | null
clearRegisteredHooks(): void

14. 技能追踪 (Skills Tracking)

addInvokedSkill(skillName: string, skillPath: string, content: string, agentId: string | null = null): void
getInvokedSkills(): Map<string, InvokedSkillInfo>
clearInvokedSkills(): void

设计说明: 追踪已调用的技能,在消息压缩(compaction)事件后保持持久化。

15. 提示缓存 (Prompt Caching)

getPromptCache1hAllowlist(): string[] | null
setPromptCache1hAllowlist(allowlist: string[] | null): void
getPromptCache1hEligible(): boolean | null
setPromptCache1hEligible(eligible: boolean): void
getCachedClaudeMdContent(): string | null
setCachedClaudeMdContent(content: string): void

设计说明: 1 小时提示缓存白名单机制,减少重复的系统提示发送。CLAUDE.md 内容也被缓存以避免重复读取。

16. 模式标志 (Mode Flags)

getAfkModeHeaderLatched(): boolean | null    // AFK 模式(离开键盘)
setAfkModeHeaderLatched(v: boolean): void
getFastModeHeaderLatched(): boolean   // 快速模式
setFastModeHeaderLatched(v: boolean): void
getCacheEditingHeaderLatched(): boolean  // 缓存编辑模式
setCacheEditingHeaderLatched(v: boolean): void

设计说明: 使用“锁存“(latched)模式,一旦设置在整个会话中不再改变。这些标志通过 HTTP 头传递给 API。


设计模式分析

1. 单例模式

整个模块维护一个 STATE 对象,所有状态集中管理。

2. 函数式访问器

不直接暴露 STATE 对象,而是通过 getter/setter 函数访问,确保类型安全和封装性。

3. 不可变性倾向

虽然 STATE 本身是可变的,但通过函数式接口鼓励单向数据流。

4. 关注点分离

150+ 个函数按功能域组织,每个域独立管理自己的状态切片。


为什么这个文件这么大?

state.ts 的 1758 行看起来很多,但考虑到:

  • 它是整个应用唯一的全局状态容器
  • 215 个导出大多是简单的 getter/setter(平均每个 ~8 行)
  • 集中管理避免了状态分散导致的一致性问题
  • 类型安全的访问器比直接操作全局对象更可靠

这是一个经过深思熟虑的架构决策,而非代码膨胀。

04 - cli 模块源码分析

路径: src/cli/ 功能: CLI 传输层、IO 处理、子命令处理器


模块概述

cli/ 模块负责 CLI 的底层通信基础设施,包括传输协议(WebSocket/SSE/HTTP)、结构化 IO、子命令处理器和输出格式化。

文件清单

文件行数说明
structuredIO.ts859SDK 消息协议核心实现
remoteIO.ts255远程双向流式 IO
print.ts5594输出打印/格式化(最大文件)
ndjsonSafeStringify.ts33NDJSON 安全序列化
exit.ts32退出辅助函数
update.ts422版本更新检查
handlers/auth.ts331OAuth 认证处理
handlers/plugins.ts879插件管理处理
handlers/autoMode.ts171自动模式配置
handlers/agents.ts71Agent 列表显示
handlers/util.tsx110杂项子命令
handlers/mcp.tsx361MCP 服务器管理
transports/HybridTransport.ts283混合传输(WS读+HTTP写)
transports/WebSocketTransport.ts~200WebSocket 传输
transports/SSETransport.ts~200SSE 传输
transports/SerialBatchEventUploader.ts~150批量事件上传
transports/WorkerStateUploader.ts~100Worker 状态上传
transports/ccrClient.ts~200CCR v2 客户端
transports/transportUtils.ts~100传输工具函数

核心文件详解

1. structuredIO.ts — SDK 消息协议核心

行数: 859 行

功能概述

实现 SDK 模式下的完整消息协议,处理控制请求/响应、权限管理、Hook 回调和 MCP 消息转发。

导出

  • StructuredIO
  • SANDBOX_NETWORK_ACCESS_TOOL_NAME 常量

核心架构

外部客户端 (Web/IDE/SDK)
    ↕ JSON 消息
StructuredIO
    ├── 控制请求处理 (control_request)
    │   ├── initialize
    │   ├── set_model
    │   ├── interrupt
    │   ├── set_permission_mode
    │   └── set_max_thinking_tokens
    │
    ├── 控制响应处理 (control_response)
    │   └── 权限请求的响应
    │
    ├── 权限管理
    │   ├── sendPermissionRequest()
    │   ├── handlePermissionResponse()
    │   └── cancelPermissionRequest()
    │
    ├── Hook 回调
    │   └── 转发 hook 执行结果
    │
    └── MCP 消息转发
        └── 透传 MCP 协议消息

关键实现细节

class StructuredIO {
  // 防重复:追踪已处理的 tool_use ID
  private readonly resolvedToolUseIds = new Set<string>()

  // 消息发送(带 NDJSON 安全序列化)
  send(message: SDKMessage): void {
    const json = ndjsonSafeStringify(message)
    this.transport.write(json + '\n')
  }

  // 控制请求处理
  async handleControlRequest(request: ServerControlRequest): Promise<void> {
    switch (request.type) {
      case 'initialize':
        // 版本协商、能力交换
        break
      case 'set_model':
        // 运行时模型切换
        setMainLoopModelOverride(request.payload.model)
        break
      case 'interrupt':
        // 中断当前执行
        this.abortController.abort()
        break
    }
  }
}

2. remoteIO.ts — 远程双向流式 IO

行数: 255 行

功能概述

扩展 StructuredIO,添加远程会话支持(WebSocket/SSE 传输、会话令牌刷新和 keep-alive 机制)。

导出

  • RemoteIO 类(继承 StructuredIO

核心特性

class RemoteIO extends StructuredIO {
  // CCR v2 客户端集成
  private ccrClient: CCRClient

  // 120 秒 keep-alive 帧
  private keepAliveInterval = setInterval(() => {
    this.send({ type: 'keep_alive' })
  }, 120_000)

  // 动态会话令牌刷新
  async refreshSessionToken(): Promise<void> {
    const newToken = await this.ccrClient.refreshToken()
    this.transport.updateAuth(newToken)
  }
}

3. ndjsonSafeStringify.ts — NDJSON 安全序列化

行数: 33 行

功能概述

解决 NDJSON(Newline DeliON)传输中的 Unicode 行终止符问题。

核心逻辑

export function ndjsonSafeStringify(value: unknown): string {
  const json = JSON.stringify(value)
  // 转义 U+2028 (行分隔符) 和 U+2029 (段落分隔符)
  // 这两个 Unicode 字符在 JSON 中合法,但会破坏 NDJSON 的行分割
  return json.replace(/[\u2028\u2029]/g, (char) =>
    char === '\u2028' ? '\\u2028' : '\\u2029'
  )
}

4. handlers/auth.ts — OAuth 认证处理

行数: 331 行

功能概述

完整的 OAuth 2.0 认证流程实现,支持 claude.ai 和 Console 两种认证源。

导出

  • installOAuthTokens() — 安装 OAuth 令牌
  • authLogin() — 登录流程
  • authStatus() — 认证状态查询
  • authLogout() — 登出

authLogin() ├── 检查环境变量 CLAUDE_CODE_OAUTH_REFRESH_TOKEN(快速路径) │ └── 直接使用,跳过浏览器流程 │ └── 标准 OAuth 流程 ├── 启动本地 HTTP 服务器(回调接收) ├── 打开浏览器到授权页面 ├── 等待用户授权 ├── 接收授权码 ├── 交换 access_token + refresh_token ├── 获取用户 profile ├── 创建 API Key(如需要) └── 存储令牌到本地


#### 令牌存储
- 令牌存储在 `~/.claude/` 目录下
- 支持多账户切换
- 自动刷新过期令牌

---

### 5. handlers/plugins.ts — 插件管理处理

**行数**: 879 行

#### 功能概述
完整的插件生命周期管理,包括安装、卸载、启用、禁用、更新和市场操作。

#### 导出
- 多个插件操作处理函数

#### 支持的操作

| 操作 | 说明 |
|------|------|
| install | 安装插件(从市场或本地路径) |
| uninstall | 卸载插件 |
| enable | 启用已安装的插件 |
| disable | 禁用插件(保留安装) |
| update | 更新插件到最新版本 |
| list | 列出已安装插件 |
| search | 搜索市场插件 |

#### 作用域

```typescript
type PluginScope = 'user' | 'project' | 'local'

// user: ~/.claude/plugins/ — 全局插件
// project: .claude/plugins/ — 项目级插件
// local: 本地路径引用

–cowork 标志

支持 --cowork 标志,启用协作插件模式。


6. handlers/autoMode.ts — 自动模式配置

行数: 171 行

功能概述

管理自动模式的分类器规则,控制哪些操作自动允许、软拒绝或受环境限制。

导出

  • autoModeDefaultsHandler() — 默认规则管理
  • autoModeConfigHandler() — 规则配置
  • autoModeCritiqueHandler() — 规则审查(使用 LLM)

规则类别

type RuleCategory = 'allow' | 'soft_deny' | 'environment'

// allow: 自动允许的操作(如读取文件)
// soft_deny: 软拒绝(提示用户确认)
// environment: 环境限制(如网络访问)

LLM 审查

autoModeCritiqueHandler 使用 LLM 来审查用户编写的规则,确保规则的合理性和安全性。


传输层架构

HybridTransport — 混合传输

行数: 283 行

┌─────────────────────────────────────┐
│          HybridTransport            │
├─────────────────────────────────────┤
│  读取: WebSocket (实时推送)          │
│  写入: HTTP POST (批量上传)          │
├─────────────────────────────────────┤
│  SerialBatchEventUploader           │
│  ├── 100ms 缓冲窗口                 │
│  ├── 合并 stream_event             │
│  └── 指数退避重试                    │
├─────────────────────────────────────┤
│  超时配置:                           │
│  ├── POST 超时: 15 秒               │
│  └── 关闭优雅期: 3 秒               │
└─────────────────────────────────────┘

设计原因

  • WebSocket 适合实时读取(低延迟推送)
  • HTTP POST 适合可靠写入(自动重试、批量合并)
  • 混合模式兼顾了实时性和可靠性

模块依赖关系

cli/
├── structuredIO.ts ← entrypoints/sdk/ (类型定义)
│   └── remoteIO.ts (继承扩展)
│
├── handlers/
│   ├── auth.ts ← constants/oauth (OAuth 配置)
│   ├── plugins.ts ← services/ (插件服务)
│   ├── autoMode.ts ← services/api/ (LLM 调用)
│   └── mcp.tsx ← tools/ (MCP 工具注册)
│
└── transports/
    ├── HybridTransport.ts
    │   ├── WebSocketTransport.ts (基类)
    │   └── SerialBatchEventUploader.ts (批量上传)
    ├── SSETransport.ts
    └── ccrClient.ts (CCR v2 协议)

cli 模块 — handlers 子目录

路径: src/cli/handlers/ 功能: CLI 子命令处理器


文件清单

文件行数说明
auth.ts331OAuth 2.0 认证流程(登录/登出/状态)
plugins.ts879插件完整生命周期(安装/卸载/启用/禁用/更新/市场)
autoMode.ts171自动模式分类器规则管理(allow/soft_deny/environment)
agents.ts71Agent 列表显示(按来源分组)
util.tsx110杂项子命令(setupToken/doctor/install)
mcp.tsx~1500+MCP 服务器管理(最大的 handler)

auth.ts 详解

导出

  • installOAuthTokens() — 安装 OAuth 令牌
  • authLogin() — 登录流程
  • authStatus() — 认证状态查询
  • authLogout() — 登出

登录流程

authLogin()
  ├── 快速路径: CLAUDE_CODE_OAUTH_REFRESH_TOKEN 环境变量
  └── 标准 OAuth 流程
      ├── 启动本地 HTTP 服务器(回调接收)
      ├── 打开浏览器到授权页面
      ├── 等待用户授权 → 接收授权码
      ├── 交换 access_token + refresh_token
      ├── 获取用户 profile
      └── 存储令牌到 ~/.claude/

plugins.ts 详解

支持的操作

操作说明
install从市场或本地路径安装
uninstall卸载插件
enable启用已安装的插件
disable禁用(保留安装)
update更新到最新版本
list列出已安装插件
search搜索市场

三种作用域

  • user: ~/.claude/plugins/ — 全局
  • project: .claude/plugins/ — 项目级
  • local: 本地路径引用

autoMode.ts 详解

三种规则类别

  • allow — 自动允许(如读取文件)
  • soft_deny — 软拒绝(提示用户确认)
  • environment — 环境限制(如网络访问)

LLM 审查

autoModeCritiqueHandler 使用 LLM 审查用户编写的规则,确保合理性和安全性。

cli 模块 — transports 子目录

路径: src/cli/transports/ 功能: 网络传输层 — WebSocket/SSE/HTTP 传输协议实现


文件清单

文件行数说明
HybridTransport.ts283混合传输(WS 读 + HTTP POST 写)
WebSocketTransport.ts~200WebSocket 传输基类
SSETransport.ts~200Server-Sent Events 传输
SerialBatchEventUploader.ts~150批量事件上传器
WorkerStateUploader.ts~100Worker 状态上传
ccrClient.ts~200CCR v2 客户端
transportUtils.ts~100传输工具函数

HybridTransport — 核心传输

┌─────────────────────────────────────┐
│          HybridTransport            │
├─────────────────────────────────────┤
│  读取: WebSocket (实时推送,低延迟)   │
│  写入: HTTP POST (批量上传,可靠)     │
├─────────────────────────────────────┤
│  SerialBatchEventUploader           │
│  ├── 100ms 缓冲窗口                 │
│  ├── 合并 stream_event              │
│  └── 指数退避重试                    │
├─────────────────────────────────────┤
│  超时: POST 15s / 关闭优雅期 3s      │
└─────────────────────────────────────┘

设计原因

  • WebSocket 适合实时读取(低延迟推送)
  • HTTP POST 适合可靠写入(自动重试、批量合并)
  • 混合模式兼顾实时性和可靠性

ccrClient.ts — CCR v2 协议

CCR(Claude Code Remote)v2 客户端,处理远程会话的创建、令牌刷新和消息传输。

05 - commands 模块源码分析

路径: src/commands/ 功能: 斜杠命令实现 — 内置命令的具体逻辑


模块概述

commands/ 包含所有内置斜杠命令的具体实现。这些命令通过 /命令名 在 REPL 中调用,涵盖会话管理、配置、调试、模型切换等功能。

典型命令列表

命令功能
/help显示帮助信息
/clear清空对话
/compact压缩对话历史
/model切换模型
/config配置管理
/cost显示费用
/doctor运行诊断
/login登录认证
/logout登出
/permissions权限管理
/mcpMCP 服务器管理
/vim切换 Vim 模式
/theme切换主题
/fast切换快速模式
/bug报告 Bug
/init初始化项目配置
/memory记忆管理
/tasks任务管理
/hooks钩子管理
/listen语音模式

命令注册模式

每个命令文件导出一个 Command 对象:

// 典型命令结构
export const helpCommand: Command = {
  name: 'help',
  description: '显示帮助信息',
  isEnabled: () => true,
  isHidden: false,
  userFacing: true,
  execute: async (args, context) => {
    // 命令逻辑
  },
  render: (props) => {
    // React 组件渲染
    return <HelpScreen />
  }
}

命令分类

会话管理命令

  • /clear — 清空当前对话,重新开始
  • /compact — 压缩对话历史,减少 token 使用
  • /resume — 恢复之前的会话

配置命令

  • /config — 查看/修改配置
  • /permissions — 管理权限规则
  • /model — 切换 AI 模型
  • /theme — 切换 UI 主题
  • /vim — 切换 Vim 编辑模式
  • /fast — 切换快速模式

诊断命令

  • /doctor — 运行系统诊断
  • /cost — 显示当前会话费用
  • /bug — 生成 Bug 报告

认证命令

  • /login — OAuth 登录
  • /logout — 登出

扩展命令

  • /mcp — MCP 服务器管理
  • /hooks — 钩子配置
  • /tasks — 后台任务管理
  • /memory — 自动记忆管理

命令安全分类

// 注意:这两个集合存放的是 Command 对象,不是字符串
const REMOTE_SAFE_COMMANDS: Set<Command> = new Set([...])
const BRIDGE_SAFE_COMMANDS: Set<Command> = new Set([...])

// 内部命令 — 对 AI 隐藏
const INTERNAL_ONLY_COMMANDS = new Set([...])

commands 模块 — 86 个斜杠命令完整清单

路径: src/commands/ 子目录数: 86 个 每个命令一个独立目录,通过 load: () => import() 懒加载


会话管理(11 个)

命令别名行数说明
/clearreset, new19清空对话历史,重新开始
/compact15清空历史但保留摘要,支持非交互模式
/branchfork14创建对话分支
/resumecontinue12恢复之前的对话
/rewindcheckpoint13回退代码/对话到之前的点
/rename12重命名当前对话(立即执行)
/export11导出对话到文件或剪贴板
/tag12给会话打标签(仅内部用户)
/exitquit12退出 REPL(立即执行)
/btw11快速旁白问题,不打断主对话
/thinkback132025 年度回顾(特性门控)

配置与设置(13 个)

命令行数说明
/config11打开配置面板(别名 settings)
/theme10切换主题
/color16设置提示栏颜色(立即执行)
/model16切换 AI 模型
/effort13设置推理努力级别(low/medium/high/max/auto)
/fast26切换快速模式(受限可用性)
/vim11切换 Vim/Normal 编辑模式
/keybindings13打开/创建快捷键配置文件
/privacy-settings14查看/更新隐私设置(订阅用户)
/remote-env15配置默认远程环境
/sandbox-toggle50配置沙箱设置(动态状态显示)
/voice20切换语音模式(claude.ai,特性门控)
/output-style11已弃用,隐藏

诊断与监控(7 个)

命令行数说明
/doctor12诊断安装和设置问题
/status12显示综合状态(立即执行)
/stats10显示使用统计和活动
/cost23显示会话费用和时长(订阅用户隐藏,内部用户除外)
/usage9显示计划使用限制(claude.ai 用户)
/diff8查看未提交变更和每轮 diff
/heapdump12转储 JS 堆(隐藏,内部用)

认证与账户(4 个)

命令行数说明
/login14登录或切换账户
/logout10登出
/upgrade16升级到 Max 计划(claude.ai 用户)
/passes22分享免费周给朋友(推荐系统)

远程与桥接(4 个)

命令行数说明
/bridge26远程控制会话(特性门控,禁用时隐藏)
/session16显示远程会话 URL 和 QR 码(别名 remote)
/remote-setup20在 Web 上设置 Claude Code(命名 web-setup)
/desktop26在 Claude Desktop 中继续会话(平台特定)

IDE 与集成(6 个)

命令行数说明
/ide11管理 IDE 集成
/chrome13Chrome 中的 Claude 设置(claude.ai 用户)
/mobile11显示移动端 QR 码(别名 ios, android)
/terminalSetup23安装终端快捷键绑定(终端特定)
/plugin11管理插件(别名 plugins, marketplace,立即执行)
/reload-plugins18激活待处理的插件变更

上下文与文件(5 个)

命令行数说明
/context24查看上下文(交互式彩色网格 / 非交互式)
/files12列出上下文中的文件(仅内部用户)
/add-dir11添加新的工作目录
/memory10编辑 Claude 记忆文件
/copy15复制 Claude 最后回复到剪贴板

规划与任务(3 个)

命令行数说明
/plan11启用计划模式或查看会话计划
/tasks11列出和管理后台任务(别名 bashes)
/agents10管理 Agent 配置

MCP 与工具(3 个)

命令行数说明
/mcp12管理 MCP 服务器(立即执行)
/permissions11管理 allowed-tools)
/hooks11查看钩子配置

帮助与反馈(5 个)

命令行数说明
/help10显示帮助和可用命令
/feedback26提交反馈(别名 bug,多重限制)
/release-notes11查看发布说明
/stickers11订购 Claude Code 贴纸
/skills10列出可用技能

内部/禁用存根(5 个)

命令说明
autofix-pr禁用存根(1 行)
ant-trace禁用存根(1 行)
bughunter禁用存根(1 行)
backfill-sessions禁用存根(1 行)
break-cache禁用存根(1 行)

其他特殊命令

命令行数说明
/share分享对话
/summary生成对话摘要 /review
/issueGitHub Issue 操作
/install-github-app安装 GitHub App
/install-slack-app安装 Slack App
/good-claude正向反馈
/thinkback-play17播放 thinkback 动画(隐藏)

命令注册模式

// 每个命令目录的 index.ts(典型 10-26 行)
export default {
  type: 'local',              // 'local' | 'local-jsx'
  name: 'help',
  description: 'Show help',
  isEnabled: () => true,      // 动态启用检查
  isHidden: false,            // 是否在帮助中隐藏
  userFacing: true,
  aliases: [],
  immediateExecution: false,  // 是否立即执行(不进入对话)
  load: () => import('./HelpCommand.js'),  // 懒加载
}

可用性限制类型

claude-ai only     — 仅 claude.ai 用户
ant-only           — 仅 Anthropic 内部用户
subscriber-only    — 仅付费订阅用户
feature-gated      — 受特性标志控制
policy-based       — 受组织策略控制
platform-specific  — 特定平台

06 - screens 模块源码分析

路径: src/screens/ 文件数: 3 个 功能: 主要 UI 屏幕 — REPL、会话恢复、诊断


模块概述

screens/ 包含 Claude Code 的三个主要用户界面屏幕。其中 REPL.tsx 是整个应用最核心、最庞大的组件。


1. REPL.tsx — 主交互屏幕(应用心脏)

行数: 5005 行(整个项目最大的单文件)

功能概述

REPL(Read-Eval-Print Loop)是 Claude Code 的核心交互界面,管理整个对话流程、工具执行、权限处理和用户交互。

架构分层

┌─────────────────────────────────────────────────┐
│                   REPL 组件                       │
├─────────────────────────────────────────────────┤
│  输入层: PromptInput 组件                         │
│  ├── 用户文本输入                                 │
│  ├── 命令解析 (/help, /commit 等)                │
│  └── 附件处理(图片、文件)                        │
├─────────────────────────────────────────────────┤
│  处理层: 消息处理 & 查询执行                       │
│  ├── 消息队列管理                                 │
│  ├── query() 调用 → Claude API                   │
│  ├── 流式响应处理                                 │
│  ├── 工具调用分发                                 │
│  └── 权限请求处理                                 │
├─────────────────────────────────────────────────┤
│  状态层: 会话 & 文件状态                           │
│  ├── 对话消息数组                                 │
│  ├── 文件状态缓存                                 │
│  ├── 归因状态(用于 commit)                       │
│  ├── 后台任务状态                                 │
│  └── Swarm/团队成员状态                           │
├─────────────────────────────────────────────────┤
│  渲染层: UI 输出                                  │
│  ├── 消息列表(虚拟滚动)                          │
│  ├── 任务列表 (TaskListV2)                        │
│  ├── 权限对话框                                   │
│  ├── 费用摘要                                     │
│  ├── 处理中 Spinner                               │
│  └── 全屏布局模式                                 │
└─────────────────────────────────────────────────┘

核心状态

// 主要 useState 状态
const [messages, setMessages] = useState<Message[]>([])        // 对话消息
const [isProcessing, setIsProcessing] = useState(false)        // 是否处理中
const [permissionRequest, setPermissionRequest] = useState()    // 权限请求
const [fileStateCache, setFileStateCache] = useState()          // 文件状态
const [attribution, setAttribution] = useState()                // 归因信息
const [backgroundTasks, setBackgroundTasks] = useState()        // 后台任务

消息处理流程

用户输入
  ↓
解析命令 (/ 开头?)
  ├── 是 → 执行命令处理器
  └── 否 → 构建用户消息
           ↓
         添加到消息数组
           ↓
         调用 query(messages, tools, config)
           ↓
         流式接收响应
           ├── 文本块 → 追加到助手消息
           ├── 工具调用 → 检查权限 → 执行工具 → 返回结果
           └── 停止信号 → 执行停止钩子 → 完成回合

工具执行流程

AI 请求工具调用
  ↓
权限检查
  ├── 自动允许 → 直接执行
  ├── 需要确认 → 显示权限对话框
  │   ├── 用户允许 → 执行
  │   └── 用户拒绝 → 返回拒绝结果
  └── 沙箱权限 → 沙箱权限管理
           ↓
         执行工具
           ↓
         收集结果
           ↓
         更新文件状态缓存
           ↓
         追踪执行指标

高级功能

功能说明
语音集成条件加载的语音输入/输出
IDE Diff 同步与 IDE 的文件差异同步
远程会话支持远程 SSH 会话
主动建议条件启用的主动提示建议
定时任务/触发器条件启用的计划任务
Web 浏览器工具条件启用的浏览器自动化
消息编辑支持编辑和重新提交消息
压缩操作手动/自动消息压缩
会话分叉从任意点分叉会话

会话管理

// 自动保存
useEffect(() => {
  const interval = setInterval(() => {
    saveSessionState(messages, metadata)
  }, AUTO_SAVE_INTERVAL)
  return () => clearInterval(interval)
}, [messages])

// 会话标题生成
useEffect(() => {
  if (messages.length > 2 && !sessionTitle) {
    generateSessionTitle(messages).then(setSessionTitle)
  }
}, [messages.length])

2. ResumeConversation.tsx — 会话恢复屏幕

行数: 398 行

功能概述

允许用户浏览和恢复之前的对话会话,支持同仓库和跨项目的会话查找。

核心流程

加载会话列表(渐进式)
  ↓
显示会话选择器
  ├── 按仓库过滤
  ├── 按 PR 编号过滤
  └── 跨项目搜索
  ↓
用户选择会话
  ↓
检查跨项目情况
  ├── 同项目 → 直接恢复
  └── 跨项目 → 显示切换命令
  ↓
恢复会话数据
  ├── restoreSessionMetadata() — 恢复会话元数据
  ├── restoreWorktreeForResume() — 恢复 Worktree 状态
  ├── adoptResumedSessionFile() — 接管会话文件指针
  ├── restoreAgentFromSession() — 恢复 Agent 上下文
  └── recordContentReplacement() — 记录内容替换
  ↓
渲染 REPL 组件(带恢复的消息)

关键函数

// 渐进式加载会话日志
loadSameRepoMessageLogsProgressive()   // 同仓库会话
loadAllProjectsMessageLogsProgressive() // 所有项目会话

// PR 过滤
parsePrIdentifier(input: string)  // 解析 PR 标识符

// 跨项目检测
checkCrossProjectResume(session, currentProject)

// 会话分叉
forkSession(originalSession)  // 创建会话副本

会话恢复(真实函数)

// 源码 src/screens/ResumeConversation.tsx:254-261
restoreSessionMetadata(...)       // 恢复会话元数据
restoreWorktreeForResume(...)     // 恢复 Worktree 状态
adoptResumedSessionFile()         // 接管会话文件指针

注意:之前文档中写的 adoptSession() 抽象函数不存在


3. Doctor.tsx — 诊断屏幕

行数: 574 行

功能概述

系统诊断和健康检查屏幕,显示系统信息、配置状态、验证错误和版本信息。

诊断内容

Doctor 诊断报告
├── 系统信息
│   ├── Claude Code 版本
│   ├── 操作系统版本
│   ├── Node/Bun 运行时版本
│   └── Shell 类型
│
├── Agent 信息
│   ├── 活跃 Agent 列表(按来源分组)
│   │   ├── built-in (内置)
│   │   ├── user (用户级)
│   │   ├── project (项目级)
│   │   └── plugin (插件)
│   ├── Agent 目录路径
│   └── 加载失败的 Agent 文件
│
├── 配置验证
│   ├── settings.json 验证错误
│   ├── MCP 解析警告
│   ├── 环境变量验证
│   │   ├── BASH_MAX_OUTPUT_LENGTH
│   │   ├── TASK_MAX_OUTPUT_LENGTH
│   │   └── CLAUDE_CODE_MAX_OUTPUT_TOKENS
│   └── 快捷键冲突
│
├── 版本信息
│   ├── 当前版本
│   ├── 可用版本(stable/latest)
│   ├── 自动更新渠道
│   └── npm/GCS dist tags
│
├── 锁管理
│   ├── PID 版本锁状态
│   ├── 活跃锁列表
│   └── 已清理的过期锁
│
└── 沙箱诊断
    └── 沙箱环境状态

导出

  • Doctor — 主组件
  • DistTagsDisplay — 版本标签显示辅助组件

UI 结构

<Pane title="Claude Code Doctor">
  <SystemInfo />
  <AgentInfo />
  <ValidationErrors />
  <VersionInfo />
  <LockStatus />
  <SandboxDiagnostic />
  <Text>"Press Enter to continue"</Text>
</Pane>

模块间关系

screens/
├── REPL.tsx
│   ├── ← components/ (UI 组件)
│   ├── ← query/ (查询执行)
│   ├── ← tools/ (工具注册)
│   ├── ← hooks/ (钩子系统)
│   ├── ← services/ (API/分析)
│   ├── ← state/ (状态管理)
│   └── ← keybindings/ (快捷键)
│
├── ResumeConversation.tsx
│   ├── ← utils/sessionStorage (会话存储)
│   ├── ← utils/fileHistory (文件历史)
│   └── → REPL.tsx (恢复后渲染)
│r.tsx
    ├── ← services/analytics (诊断数据)
    ├── ← schemas/ (配置验证)
    └── ← cli/update (版本检查)

07 - components 模块源码分析

路径: src/components/ 根级文件数: 110+ 个 .tsx/.ts 文件 子目录数: 31 个 功能: React UI 组件库 — 终端界面的所有可视化组件


模块概述

components/ 是 Claude Code 中文件数量最多的模块。基于 Ink 框架,这些组件在终端中渲染富文本界面。


根级核心组件(精选)

消息显示

文件说明
Messages.tsx消息列表容器
Message.tsx单条消息渲染
MessageRow.tsx消息行布局
VirtualMessageList.tsx虚拟滚动消息列表(性能优化)
MessageResponse.tsx助手响应渲染
MessageSelector.tsx消息选择器
MessageTimestamp.tsx消息时间戳
MessageModel.tsx消息模型标识
Markdown.tsxMarkdown 渲染器
MarkdownTable.tsxMarkdown 表格

代码与 Diff

文件说明
StructuredDiff.tsx结构化代码差异显示
StructuredDiffList.tsx差异列表
FileEditToolDiff.tsx文件编辑工具的 diff 显示
HighlightedCode.tsx代码语法高亮

对话框与交互

文件说明
AutoModeOptInDialog.tsx自动模式选择对话框
BridgeDialog.tsx桥接对话框
BypassPermissionsModeDialog.tsx权限绕过对话框
CostThresholdDialog.tsx费用阈值对话框
ExportDialog.tsx导出对话框
GlobalSearchDialog.tsx全局搜索对话框
HistorySearchDialog.tsx历史搜索对话框
ModelPicker.tsx模型选择器
ThemePicker.tsx主题选择器
OutputStylePicker.tsx输出样式选择器

状态与信息

文件说明
StatusLine.tsx状态行
StatusNotices.tsx状态通知
Spinner.tsx加载动画
TaskListV2.tsx任务列表
Stats.tsx使用统计
TokenWarning.tsxToken 警告
MemoryUsageIndicator.tsx内存使用指示器

布局与导航

文件说明
App.tsx应用根组件
FullscreenLayout.tsx全屏布局
ScrollKeybindingHandler.tsx滚动快捷键处理
TagTabs.tsx标签页
SearchBox.tsx搜索框

工具相关

文件说明
ToolUseLoader.tsx工具调用加载器
FallbackToolUseErrorMessage.tsx工具错误回退消息
FallbackToolUseRejectedMessage.tsx工具拒绝回退消息
FileEditToolUpdatedMessage.tsx文件编辑更新消息

远程与桥接

文件说明
TeleportProgress.tsxTeleport 进度
TeleportError.tsxTeleport 错误
RemoteCallout.tsx远程提示
RemoteEnvironmentDialog.tsx远程环境对话框

其他

文件说明
TextInput.tsx基础文本输入
VimTextInput.tsxVim 模式文本输入
BaseTextInput.tsx文本输入基类
Onboarding.tsx新手引导
Feedback.tsx反馈组件
DevBar.tsx开发者工具栏

子目录(31 个)

PromptInput/ — 用户输入(21 文件)

最核心的交互组件目录:

文件说明
PromptInput.tsx主输入组件
ShimmeredInput.tsx带闪烁效果的输入
PromptInputFooter.tsx底部快捷键和状态
PromptInputFooterLeftSide.tsx底部左侧
PromptInputFooterSuggestions.tsx底部建议
PromptInputHelpMenu.tsx帮助菜单
PromptInputModeIndicator.tsx模式指示器
PromptInputQueuedCommands.tsx排队命令
PromptInputStashNotice.tsxStash 通知
VoiceIndicator.tsx语音指示器
HistorySearchInput.tsx历史搜索输入
IssueFlagBanner.tsxIssue 标记横幅
Notifications.tsx通知
SandboxPromptFooterHint.tsx沙箱提示
inputModes.ts输入模式定义
inputPaste.ts粘贴处理
useMaybeTruncateInput.ts输入截断 Hook
usePromptInputPlaceholder.ts占位符 Hook
useShowFastIconHint.ts快速模式提示 Hook
useSwarmBanner.tsSwarm 横幅 Hook
utils.ts工具函数

permissions/ — 权限请求(30+ 文件)

子目录/文件说明
PermissionDialog.tsx基础权限对话框
PermissionRequest.tsx权限请求组件
PermissionPrompt.tsx权限提示
PermissionRequestTitle.tsx请求标题
PermissionExplanation.tsx权限解释
PermissionRuleExplanation.tsx规则解释
WorkerBadge.tsxWorker 标记
BashPermissionRequest/Shell 命令审批
FileEditPermissionRequest/文件编辑审批
FileWritePermissionRequest/文件写入审批
FilePermissionDialog/文件权限对话框
WebFetchPermissionRequest/HTTP 请求审批
AskUserQuestionPermissionRequest/用户提问审批
EnterPlanModePermissionRequest/计划模式审批
ExitPlanModePermissionRequest/退出计划审批
ComputerUseApproval/计算机使用审批
SandboxPermissionRequest.tsx沙箱权限
SkillPermissionRequest/技能权限
ellPermissionRequest/`PowerShell 权限
NotebookEditPermissionRequest/Notebook 编辑权限
SedEditPermissionRequest/Sed 编辑权限
FilesystemPermissionRequest/文件系统权限
rules/权限规则子目录

messages/ — 消息组件(33 文件)

文件说明
UserPromptMessage.tsx用户输入消息
UserTextMessage.tsx用户文本消息
UserImageMessage.tsx用户图片消息
UserBashInputMessage.tsx用户 Bash 输入
UserBashOutputMessage.tsx用户 Bash 输出
UserCommandMessage.tsx用户命令消息
UserTeammateMessage.tsx用户队友消息
UserChannelMessage.tsx用户频道消息
AssistantTextMessage.tsx助手文本回复
AssistantToolUseMessage.tsx助手工具调用
AssistantThinkingMessage.tsx助手思考过程
AssistantRedactedThinkingMessage.tsx助手编辑后思考
AttachmentMessage.tsx附件消息
SystemTextMessage.tsx系统文本消息
SystemAPIErrorMessage.tsxAPI 错误消息
RateLimitMessage.tsx速率限制消息
CompactBoundaryMessage.tsx压缩边界消息
HookProgressMessage.tsx钩子进度消息
PlanApprovalMessage.tsx计划审批消息
TaskAssignmentMessage.tsx任务分配消息
ShutdownMessage.tsx关闭消息
HighlightedThinkingText.tsx高亮思考文本
GroupedToolUseContent.tsx分组工具调用内容
CollapsedReadSeant.tsx折叠的读取/搜索内容
AdvisorMessage.tsx顾问消息
UserToolResultMessage/用户工具结果(子目录)

diff/ — 代码差异(3 文件)

文件说明
DiffDetailView.tsx详细 diff 视图
DiffDialog.tsxDiff 对话框
DiffFileList.tsx变更文件列表

其他子目录

目录说明
agents/Agent 管理和创建向导
teams/团队协作组件
tasks/后台任务 UI
mcp/MCP 服务器管理界面
skills/技能相关组件
memory/记忆管理组件
sandbox/沙箱管理组件
shell/Shell 相关组件
hooks/组件级自定义 Hooks
ui/通用 UI 工具组件
design-system/设计系统(ThemedText、Dialog、Pane 等)
w/向导流程组件
grove/Grove 相关组件
CustomSelect/自定义选择列表
Settings/设置面板
HelpV2/帮助界面 v2
LogoV2/Logo 显示 v2
Spinner/加载动画(子目录)
StructuredDiff/结构化 diff(子目录)
TrustDialog/项目信任对话框
FeedbackSurvey/反馈调查
Passes/通行证/推荐
DesktopUpsell/桌面版推广
ClaudeCodeHint/使用提示
LspRecommendation/LSP 推荐
HighlightedCode/代码高亮(子目录)
ManagedSettingsSecurityDialog/托管设置安全对话框

components 模块 — 31 个组件子目录分类

路径: src/components/ 子目录数: 31 个 总文件数: 150+


设计系统(design-system/)

基础 UI 原语,被其他所有组件使用:

  • ThemedText — 主题感知文本(从主题键或原始颜色解析)
  • Dialog — 基础对话框(取消/确认,可配置快捷键)
  • Pane — 带边框的面板容器
  • FuzzyPicker — 模糊搜索选择界面
  • Tabs — 标签页导航
  • ProgressBar — 进度条
  • Tooltip — 悬停信息
  • Badge — 状态标记
  • Divider — 分隔线
  • ErrorBoundary — 错误边界

核心交互组件

PromptInput/(20+ 文件)

用户输入的主入口,最复杂的组件目录:

  • PromptInput — 主输入组件
  • ShimmeredInput — 带闪烁效果的输入
  • InputFooter — 底部快捷键和状态
  • InputHeader — 顶部上下文信息
  • AttachmentList — 附件管理
  • InputHistory — 命令历史导航
  • InputSuggestions — 自动补全建议
  • MultilineInput — 多行输入
  • CodeInput — 代码输入(语法高亮)

CustomSelect/

自定义选择列表(键盘导航、搜索过滤、多选、分组)

Spinner/

加载动画指示器


权限组件(permissions/,30+ 文件)

组件说明
PermissionDialog基础权限对话框包装器(圆角边框、标题)
BashPermissionRequestShell 命令审批
FileEditPermissionRequest文件修改审批
FileReadPermissionRequest文件读取审批
FileWritePermissionRequest文件写入审批
WebFetchPermissionRequestHTTP 请求审批
MCPToolPermissionRequestMCP 工具执行审批
AgentPermissionRequestAgent 操作审批
NetworkPermissionRequest网络访问审批
WorkerBadge显示请求权限的 worker/agent

消息组件(messages/,30+ 文件)

组件说明
UserPromptMessage用户输入显示(10k 字符截断:头 2.5k + 尾 2.5k)
AssistantTextMessage助手文本回复
AssistantToolUseMessage工具调用显示
ThinkingMessage思考过程显示
ToolResultMessage工具执行结果
ErrorMessage错误显示
SystemMessage系统通知
CodeBlockMessage代码块(语法高亮)
DiffMessage代码变更可视化
ImageMessage图片内容

任务组件(tasks/,12 文件)

后台任务的 UI 展示:

  • BackgroundTasksDialog — 后台任务管理对话框
  • RemoteSessionProgress — 远程会话进度
  • ShellProgress — Shell 命令执行进度
  • TaskList / TaskItem / TaskStatus / TaskProgress

MCP 组件(mcp/,13 文件)

MCP 服务器管理界面:

  • MCPSettings — 配置界面
  • MCPReconnect — 重连处理
  • MCPToolListView — 可用工具列表
  • MCPServerStatus — 连接状态
  • MCPServerList — 服务器列表

Agent 组件(agents/,20+ 文件)

Agent 管理和创建向导:

  • AgentsMenu — Agent 选择和管理
  • CreateAgentWizard — 多步骤创建向导
    • AgentNameStepAgentDescriptionStepAgentInstructionsStepAgentToolsStepAgentReviewStep
  • AgentList / AgentCard / AgentStatus

Diff 组件(diff/,3 文件)

代码差异显示:

  • DiffFileList — 变更文件列表
  • DiffDialog — 代码比较界面
  • DiffDetailView — 详细 diff(语法高亮)

其他组件目录

目录说明
hooks/组件级自定义 Hooks
ui/通用 UI 工具组件
shell/Shell 相关组件
sandbox/沙箱管理组件
memory/记忆管理组件
skills/技能相关组件
teams/团队协作组件
wizard/向导流程组件
grove/Grove 相关组件
TrustDialog/项目信任对话框
Settings/设置面板
HelpV2/帮助界面 v2
LogoV2/Logo 显示 v2
HighlightedCode/代码高亮显示
StructuredDiff/结构化 diff
FeedbackSurvey/反馈调查
Passes/通行证/推荐
DesktopUpsell/桌面版推广
ClaudeCodeHint/使用提示
LspRecommendation/LSP 推荐
ManagedSettingsSecurityDialog/托管设置安全对话框

关键设计模式

  • 主题系统: resolveColor() 处理主题键和原始颜色(rgb/hex/ansi256)
  • React Compiler: 所有组件使用 _c 函数优化
  • 截断策略: 大内容 >10k 字符截断,防止按键延迟
  • Feature Flags: KAIROS/KAIROS_BRIEF 控制布局模式

08 - ink 模块源码分析

路径: src/ink/ 文件数: 96 个 功能: 深度定制的 Ink 终端渲染引擎


模块概述

ink/ 是对 Ink(React 终端 UI 框架)的深度定制版本。Claude Code 没有直接使用 npm 上的 ink 包,而是将其 fork 并大幅扩展,添加了自定义布局引擎、事件系统、终端查询、搜索高亮等功能。


架构总览

ink/
├── 核心渲染
│   ├── ink.tsx              # Ink 主入口 & render()
│   ├── reconciler.ts        # React Reconciler(自定义)
│   ├── renderer.ts          # 渲染管线
│   ├── root.ts              # 根节点管理
│   ├── dom.ts               # 虚拟 DOM 节点
│   └── instances.ts         # 实例管理
│
├── 布局系统
│   ├── layout/
│   │   ├── engine.ts        # 薄包装:createLayoutNode() → createYogaLayoutNode()
│   │   ├── node.ts          # 布局节点
│   │   ├── geometry.ts      # 几何计算
│   │   └── yoga.ts          # Yoga 集成(真正的布局核心,308 行)
│   ├── styles.ts            # 样式处理
│   └── get-max-width.ts     # 最大宽度计算
│
├── 输出管线
│   ├── output.ts            # 输出缓冲
│   ├── render-node-to-output.ts  # 节点→输出
│   ├── render-border.ts     # 边框渲染
│   ├── render-to-screen.ts  # 输出→屏幕
│   ├── frame.ts             # 帧管理
│   └── log-update.ts        # 增量屏幕更新
│
├── 文本处理
│   ├── stringWidth.ts       # 字符串宽度计算
│   ├── wrapAnsi.ts          # ANSI 文本换行
│   ├── widest-line.ts       # 最宽行计算
│   ├── squash-text-nodes.ts # 文本节点合并
│   ├── bidi.ts              # 双向文本支持
│   ├── colorize.ts          # 颜色化
│   └── tabstops.ts          # Tab 停止位
│
├── 事件系统
│   ├── events/
│   │   ├── emitter.ts       # 事件发射器
│   │   ├── dispatcher.ts    # 事件分发器
│   │   ├── event.ts         # 基础事件
│   │   ├── input-event.ts   # 输入事件
│   │   ├── keyboard-event.ts # 键盘事件
│   │   ├── click-event.ts   # 点击事件
│   │   ├── focus-event.ts   # 焦点事件
│   │   └── terminal-event.ts # 终端事件
│   ├── parse-keypress.ts    # 按键解析
│   └── hit-test.ts          # 点击测试
│
├── 终端交互
│   ├── terminal.ts          # 终端抽象
│   ├── terminal-querier.ts  # 终端能力查询
│   ├── terminal-focus-state.ts # 终端焦点状态
│   ├── supports-hyperlinks.ts  # 超链接支持检测
│   └── termio/              # 终端 IO 协议
│       ├── tokenize.ts      # 令牌化
│       ├── parser.ts        # 解析器
│       ├── ansi.ts          # ANSI 序列
│       ├── csi.ts           # CSI 序列
│       ├── sgr.ts           # SGR(颜色/样式)
│       ├── osc.ts           # OSC 序列
│       ├── esc.ts           # ESC 序列
│       ├── dec.ts           # DEC 私有序列
│       └── types.ts         # 类型定义
│
├── 基础组件
│   ├── components/
│   │   ├── Box.tsx          # 盒模型容器
│   │   ├── Text.tsx         # 文本组件
│   │   ├── Spacer.tsx       # 间距组件
│   │   ├── Newline.tsx      # 换行组件
│   │   ├── Link.tsx         # 超链接组件
│   │   ├── Button.tsx       # 按钮组件
│   │   ├── ScrollBox.tsx    # 滚动容器
│   │   ├── NoSelect.tsx     # 不可选择区域
│   │   ├── RawAnsi.tsx      # 原始 ANSI 输出
│   │   ├── AlternateScreen.tsx # 备用屏幕
│   │   ├── ErrorOverview.tsx   # 错误概览
│   │   ├── App.tsx          # 应用根组件
│   │   └── 上下文提供者...
│   └── Ansi.tsx             # ANSI 渲染组件
│
├── Hooks
│   ├── hooks/
│   │   ├── use-input.ts     # 输入处理
│   │   ├── use-stdin.ts     # stdin 访问
│   │   ├── use-app.ts       # 应用上下文
│   │   ├── use-selection.ts # 选择状态
│   │   ├── use-interval.ts  # 定时器
│   │   ├── use-animation-frame.ts # 动画帧
│   │   ├── use-terminal-viewport.ts # 终端视口
│   │   ├── use-terminal-title.ts    # 终端标题
│   │   ├── use-terminal-focus.ts    # 终端焦点
│   │   ├── use-declared-cursor.ts   # 光标声明
│   │   ├── use-tab-status.ts        # Tab 状态
│   │   └── use-search-highlight.ts  # 搜索高亮
│
├── 优化
│   ├── optimizer.ts         # 渲染优化器
│   ├── node-cache.ts        # 节点缓存
│   └── line-width-cache.ts  # 行宽缓存
│
├── 焦点管理
│   ├── focus.ts             # 焦点系统
│   └── selection.ts         # 选择管理
│
├── 搜索
│   └── searchHighlight.ts   # 搜索高亮
│
└── 常量
    ├── constants.ts         # 常量定义
    └── warn.ts              # 警告工具

核心渲染管线

` React 组件树 ↓ (reconciler.ts — 自定义 React Reconciler) 虚拟 DOM 树 (dom.ts) ↓ (layout/engine.ts — Yoga Flexbox 布局) 布局树(带位置和尺寸) ↓ (render-node-to-output.ts) 输出缓冲 (output.ts) ↓ (render-border.ts — 边框渲染) ↓ (colorize.ts — 颜色化) ↓ (render-to-screen.ts) ANSI 字符串 ↓ (log-update.ts — 增量更新) 终端屏幕


---

## 关键子系统

### 1. 自定义 React Reconciler

```typescript
// reconciler.ts
// 使用 react-reconciler 创建自定义渲染器
// 将 React 组件映射到终端虚拟 DOM 节点
const reconciler = createReconciler({
  createInstance(type, props) {
    return new DOMNode(type, props)
  },
  aToContainer(container, child) {
    container.appendChild(child)
  },
  // ... 完整的 reconciler 接口实现
})

2. 终端 IO 协议栈 (termio/)

原始字节流
    ↓ tokenize.ts (令牌化)
令牌流 (ANSI/CSI/SGR/OSC/ESC/DEC)
    ↓ parser.ts (解析)
结构化事件
    ↓ 分发到对应处理器

支持的终端协议

  • ANSI: 基础控制序列
  • CSI: 控制序列引入(光标移动、清屏等)
  • SGR: 选择图形再现(颜色、粗体等)
  • OSC: 操作系统命令(超链接、标题等)
  • ESC: 转义序列
  • DEC: DEC 私有序列(光标样式等)

3. 事件系统

终端原始输入
    ↓ parse-keypress.ts
键盘事件 (KeyboardEvent)
    ↓ hit-test.ts
点击事件 (ClickEvent) — 如果是鼠标输入
    ↓ dispatcher.ts
事件分发到组件树
    ↓ emitter.ts
组件事件处理器

4. 焦点管理

// focus.ts
// 管理组件焦点状态
// 支持 Tab 导航和程序化焦点切换
class FocusManager {
  focusNext(): void
  focusPrevious(): void
  focus(id: string): void
  blur(): void
}

与标准 Ink 的差异

特性标准 InkClaude Code Ink
布局引擎yoga-wasm纯 TS Yoga 移植
事件系统基础键盘完整事件系统(键盘/鼠标/焦点)
终端协议基础 ANSI完整协议栈(CSI/SGR/OSC/DEC)
搜索高亮内置搜索高亮
点击测试支持鼠标点击
超链接OSC 8 终端超链接
双向文本BiDi 支持
渲染优化基础节点缓存 + 行宽缓存 + 优化器
光标管理基础声明式光标系统

设计亮点

  1. 零 WASM 依赖: 用纯 TS Yoga 替代 yoga-wasm,避免 WASM 加载问题
  2. 完整终端协议: 部能力(超链接、鼠标、焦点追踪)
  3. 声明式光标: 组件声明光标位置,框架自动管理
  4. 增量渲染: log-update 只更新变化的行,减少闪烁
  5. 多层缓存: 节点缓存 + 行宽缓存 + 布局缓存,确保渲染性能

ink 模块 — 5 个子目录详解

路径: src/ink/ 子目录: layout/, events/, hooks/, components/, termio/


1. layout/ — Flexbox 布局引擎(4 文件)

文件行数说明
yoga.ts309Yoga 布局引擎 TS 移植,createYogaNode 工厂
node.ts153LayoutNode 接口定义(几何 + 样式属性)
geometry.ts98几何原语(Rect, Point, Size, Edges)
engine.ts6布局节点工厂函数

2. events/ — DOM 风格事件系统(10 文件)

文件行数说明
event.ts12基础 Event 类
terminal-event.ts108TerminalEvent 基类,DOM 风格传播 API(capture/bubble)
dispatcher.ts234事件分发系统,capture/bubble 两阶段
keyboard-event.ts52KeyboardEvent 实现
focus-event.ts22FocusEvent(带 relatedTarget)
click-event.ts39ClickEvent(带本地坐标)
input-event.ts206输入解析,支持 Kitty 键盘协议
emitter.ts40自定义 EventEmitter(stopImmediatePropagation)
event-handlers.ts74事件处理器类型定义
terminal-focus-event.ts终端焦点事件

3. termio/ — 终端 IO 协议栈(9 文件)

原始字节流 → tokenize.ts → parser.ts → 结构化事件
文件行数说明
ansi.ts76C0 控制字符和 ESC_TYPE 常量
types.ts237语义类型(Color, TextStyle, Action)
tokenize.ts320流式令牌化器,X10 鼠标支持
parser.ts395语义动作生成器,grapheme 分割
sgr.ts309SGR 参数解析(颜色/样式),扩展色支持
csi.ts320CSI 序列类型和生成器
osc.ts494OSC 序列解析(剪贴板、超链接、标题)
esc.ts68ESC 序列解析
dec.ts61DEC 私有模式序列

4. components/ — 基础 UI 组件(18 文件)

文件行数说明
App.tsx657应用根组件(React Compiler 优化)
Text.tsx254核心文本渲染(样式、颜色、粗体等)
Box.tsx213盒模型布局容器(Flexbox 属性)
ScrollBox.tsx237滚动容器(命令式 API,视口裁剪)
Button.tsx192交互按钮(focus/hover/active 状态)
AlternateScreen.tsx80备用屏幕缓冲管理
Link.tsx42超链接(OSC 8 终端超链接)
Newline.tsx39换行插入
Spacer.tsx20弹性间距
RawAnsi.tsx~50原始 ANSI 输出
NoSelect.tsx~30不可选择区域
ErrorOverview.tsx~100错误概览
AppContext.ts~20应用上下文
StdinContext.ts~20stdin 上下文
ClockContext.tsx时钟上下文(定时刷新)
CursorDeclarationContext.ts光标声明上下文
TerminalFocusContext.tsx终端焦点上下文
TerminalSizeContext.tsx终端尺寸上下文

5. hooks/ — React Hooks(12 文件)

文件行数说明
use-input.ts93键盘输入处理
use-app.ts8应用上下文访问
use-stdin.ts~30stdin 访问
use-selection.ts~50选择状态管理
use-interval.ts~30定时器 Hook
use-animation-frame.ts~40动画帧 Hook
use-terminal-viewport.ts~50终端视口尺寸
use-terminal-title.ts~30终端标题设置
use-terminal-focus.ts~30终端焦点追踪
use-declared-cursor.ts~40声明式光标位置
use-tab-status.ts~30Tab 状态
use-search-highlight.ts~50搜索高亮

09 - query 模块源码分析

路径: src/query/ 文件数: 5 个 功能: 查询执行核心 — 与 Claude API 交互的主循环


模块概述

query/ 是 Claude Code 与 AI 模型交互的核心引擎。它管理查询生命周期、token 预算、依赖注入和停止钩子执行。设计上追求纯函数化,便于测试和未来的 step() 提取。


1. config.ts — 查询配置快照

行数: 46 行

功能概述

query() 入口点创建不可变的配置快照,将运行时配置与可变状态分离。

导出

  • QueryConfig 类型 — 配置快照结构
  • buildQueryConfig() — 工厂函数

配置结构

type QueryConfig = {
  sessionId: SessionId
  gates: {
    streamingToolExecution: boolean  // gate: tengu_streaming_tool_execution2
    emitToolUseSummaries: boolean
    isAnt: boolean
    fastModeEnabled: boolean         // 字段名是 fastModeEnabled,不是 fastMode
  }
}

构建逻辑

function buildQueryConfig(): QueryConfig {
  return {
    sessionId: getSessionId(),
    gates: {
      // Statsig 特性门控(使用缓存值,可能过期)
      streamingToolExecution: checkStatsigFeatureGate_CACHED_MAY_BE_STALE('streaming_tool_exec'),
      // 环境变量控制
      emitToolUseSummaries: isEnvTruthy('EMIT_TOOL_USE_SUMMARIES'),
      // 内部用户检测
      isAnt: detectIsAnt(),
      // 快速模式(内联检测,避免引入重模块图)
      fastMode: isFastModeEnabled(),
    }
  }
}

设计亮点

  • 不可变快照: 配置在 query() 入口创建后不再变化,避免中途配置变更导致的不一致
  • 刻意排除 feature() 门控: 为了 tree-shaking 优化,不引入 bun:bundle 的 feature() 函数
  • 内联检测: fastMode 检测内联实现,避免引入 heavy module graph

2. deps.ts — 依赖注入容器

行数: 40 行

功能概述

query() 函数提供依赖注入,允许测试时注入 fake 实现而无需 spyOn

导出

  • QueryDeps 类型 — 依赖接口
  • productionDeps() — 生产环境依赖工厂

依赖接口

type QueryDeps = {
  callModel: typeof queryModelWithStreaming   // 模型 API 调用
  microcompact: typeof microcompactMessages   // 消息微压缩
  autocompact: typeof autoCompactIfNeeded     // 自动压缩
  uuid: typeof randomUUID                     // UUID 生成
}

生产实现

function productionDeps(): QueryDeps {
  return {
    callModel: queryModelWithStreaming,
    microcompact: microcompactMessages,
    autocompact: autoCompactIfNeeded,
    uuid: randomUUID,
  }
}

设计亮点

  • typeof 同步: 使用 typeof fn 保持签名与真实实现自动同步
  • 窄范围: 刻意只注入 4 个依赖,作为模式验证(proof of pattern)
  • 无 mock 测试: 测试直接注入 fake 对象,比 jest.spyOn 更可靠

3. tokenBudget.ts — Token 预算管理

行数: 93 行

功能概述

追踪 token 使用量,在预算耗尽或收益递减时决定停止查询继续。

导出

  • BudgetTracker 类型 — 预算追踪状态
  • createBudgetTracker() — 创建追踪器
  • TokenBudgetDecision 类型 — 决策联合类型
  • checkTokenBudget() — 主决策函数

常量

const COMPLETION_THRESHOLD = 0.9    // 90% 预算使用率阈值
const DIMINISHING_THRESHOLD = 500   // 收益递减阈值(tokens)

决策流程

checkTokenBudget(tracker, currentTokens, budget, agentId)
  │
  ├── agentId 存在? → STOP(子Agent不续传)
  ├── budget 为 null/0? → STOP
  │
  ├── 计算当前使用百分比
  ├── 计算自上次检查的 delta
  │
  ├── 检测收益递减:
  │   └── 连续 2 次 delta < 500 tokens 且续传次数 ≥ 3
  │       → STOP(附带 completion_event)
  │
  ├── 未递减 且 < 90% 预算
  │   → CONTINUE(附带 nudge 消息)
  │
  └── 超过 90% 或递减
      → STOP(附带 completion_event + 指标)

决策类型

type ContinueDecision = {
  action: 'continue'
  nudgeMessage: string
  continuationCount: number
  pct: number              // 字段名是 pct,不是 percentage
  turnTokens: number
  budget: number
}

type StopDecision = {
  action: 'stop'
  completionEvent?: {
    totalTokens: number
    budget: number
    continuations: number
    pct: number            // 同上
    diminishingReturns: boolean
  }
}

4. stopHooks.ts — 停止钩子编排器

行数: 474 行

功能概述

在每个查询回合结束时编排停止钩子的执行,管理后台任务(记忆提取、自动推理、提示建议),协调钩子结果。

导出

  • handleStopHooks() — 异步生成器函数

执行流程

handleStopHooks(context)
  │
  ├── 1. 设置阶段
  │   ├── 创建钩子上下文(消息、系统提示、工具上下文)
  │   ├── 保存缓存安全参数(仅主会话)
  │   └── 运行模板任务分类(如果在 job 模式)
  │
  ├── 2. 后台任务(fire-and-forget,bare 模式跳过)
  │   ├── 提示建议执行
  │   ├── 记忆提取(如果 extract 模式激活)
  │   └── 自动推理(非子Agent)
  │
  ├── 3. Chicago MCP 清理
  │   └── 自动取消隐藏 & 释放计算机使用锁
  │
  ├── 4. Stop 钩子执行
  │   ├── 通过生成器执行钩子
  │   ├── 追踪进度消息、钩子计数、错误
  │   ├── 收集阻塞错误
  │   ├── 检查续传阻止标志
  │   └── 处理中止信号
  │
  ├── 5. 队友特定钩子(如果队友模式)
  │   ├── TaskCompleted 钩子(每个进行中的任务)
  │   └── TeammateIdle 钩子
  │
  └── 6. 结果聚合
      ├── 返回 StopHookResult
      │   ├── blockingErrors: Error[]
      │   └── preventContinuation: boolean
      └── yield件、摘要

钩子类型

钩子事件触发时机说明
Stop每个回合结束通用停止钩子
TaskCompleted任务完成时队友模式专用
TeammateIdle队友空闲时队友模式专用

后台任务

// 提示建议(fire-and-forget)
executePromptSuggestion(context).catch(logError)

// 记忆提取(条件执行)
if (isExtractModeActive()) {
  extractMemories(context).catch(logError)
}

// 自动推理(非子Agent)
if (!isSubagent) {
  autoDream(context).catch(logError)
}

5. 查询主循环(推断)

虽然 src/query/ 目录包含配置、依赖注入、token 预算和停止钩子,但真正的查询主循环在根级 src/query.ts(1729 行),不需要“推断“。

query(messages, tools, config, deps)
  │
  ├── 构建配置快照 (c
  ├── 注入依赖 (deps.ts)
  ├── 创建预算追踪器 (tokenBudget.ts)
  │
  ├── 主循环:
  │   ├── 微压缩消息 (deps.microcompact)
  │   ├── 自动压缩检查 (deps.autocompact)
  │   ├── 调用模型 (deps.callModel) — 流式
  │   ├── 处理响应:
  │   │   ├── 文本块 → yield 给 UI
  │   │   ├── 工具调用 → 执行工具 → 追加结果
  │   │   └── 停止信号 → 退出循环
  │   ├── 检查 token 预算 (tokenBudget.ts)
  │   │   ├── CONTINUE → 继续循环
  │   │   └── STOP → 退出循环
  │   └── 循环继续...
  │
  └── 执行停止钩子 (stopHooks.ts)

模块设计哲学

  1. 纯函数化追求: config 和 deps 的分离是为了将 query() 逐步重构为纯 reducer
  2. 可测试性优先: 依赖注入而非模块 mock
  3. 渐进式停止: token 预算不是硬切断,而是通过收益递减检测智能停止
  4. **生opHooks 使用 async generator,允许调用方逐步消费结果
  5. 关注点分离: 配置、依赖、预算、钩子各自独立,互不耦合

10 - services 模块源码分析

路径: src/services/ 子目录数: 20 个 根级文件数: 15 个 功能: 服务层 — API 调用、分析、压缩、MCP、OAuth 等核心服务


模块概述

services/ 是 Claude Code 的服务层,封装了与外部系统交互的核心逻辑。

重要纠正: 之前文档中列出的 services/permissions/services/sandbox/ 目录不存在。权限相关实现在 src/utils/permissions/,沙箱相关在 src/utils/sandbox/


真实目录结构

子目录(20 个)

目录说明
api/Claude API 交互(流式调用、重试、错误处理、用量、会话入口等)
analytics/分析与遥测(GrowthBook、事件日志、DataDog、指标)
compact/消息压缩(自动压缩、微压缩、分组、时间策略等)
mcp/MCP 客户端(连接管理、传输层、配置、认证、权限等)
oauth/OAuth 服务
tools/工具执行服务(流式工具执行器、工具编排、工具钩子)
plugins/插件服务
lsp/LSP 集成(Language Server Protocol)
policyLimits/策略限制(组织级使用限制)
remoteManagedSettings/远程托管设置
settingsSync/设置同步
teamMemorySync/团队记忆同步
tips/使用提示系统
toolUseSummary/工具使用摘要
AgentSummary/Agent 执行结果摘要
MagicDocs/魔法文档(自动文档生成)
PromptSuggestion/提示建议(主动建议下一步)
SessionMemory/会话记忆(跨回合上下文保持)
autoDream/自动推理(后台记忆整合)
extractMemories/记忆提取(从对话中提取值得记忆的信息)

根级文件(15 个)

文件说明
awaySummary.ts离开摘要
claudeAiLimits.tsclaude.ai 使用限制
claudeAiLimitsHook.ts限制 Hook
diagnosticTracking.ts诊断追踪
internalLogging.ts内部日志
mockRateLimits.ts模拟速率限制
notifier.ts通知器
preventSleep.ts防止休眠
rateLimitMessages.ts速率限制消息
rateLimitMocking.ts速率限制模拟
tokenEstimation.tsToken 估算
vcr.tsVCR 录制/回放
voice.ts语音服务
voiceKeyterms.ts语音关键词
voiceStreamSTT.ts语音流式 STT

核心服务详解

1. api/ — Claude API 交互

文件数: 20 个

文件说明
claude.ts主 API 调用(流式)
client.tsAPI 客户端
bootstrap.tsAPI 启动初始化
withRetry.ts重试策略
errors.ts错误类型定义
errorUtils.ts错误处理工具
usage.ts用量追踪
logging.tsAPI 日志
sessionIngress.ts会话入口
filesApi.ts文件 API
grove.tsGrove 集成
adminRequests.ts管理请求
dumpPrompts.ts提示转储(调试)
emptyUsage.ts空用量对象
firstTokenDate.ts首 token 时间
metricsOptOut.ts指标退出
overageCreditGrant.ts超额信用
promptCacheBreakDetection.ts提示缓存破坏检测
referral.ts推荐系统
ultrareviewQuota.tsUltrareview 配额

注意:之前文档中写的 models.tsrateLimit.tsheaders.ts 在此目录中不存在


2. analytics/ — 分析与遥测

文件数: 9 个

文件说明
index.ts事件日志主入口
growthbook.tsGrowthBook 特性门控
config.ts分析配置
datadog.tsDataDog 集成
metadata.ts事件元数据
sink.ts事件接收器
sinkKillswitch.ts接收器 kill-switch
firstPartyEventLogger.ts第一方事件日志
firstPartyEventLoggingExporter.ts第一方事件导出

注意:之前文档中写的 statsig.tsotel.tsevents.ts 在此目录中不存在


3. compact/ — 消息压缩

文件数: 11 个

文件说明
autoCompact.ts自动压缩(上下文窗口管理)
microCompact.ts微压缩(截断过长工具结果)
apiMicrocompact.tsAPI 级微压缩
compact.ts压缩核心逻辑
prompt.ts压缩提示词
grouping.ts消息分组
sessionMemoryCompact.ts会话记忆压缩
timeBasedMCConfig.ts基于时间的微压缩配置
compactWarningHook.ts压缩警告钩子
compactWarningState.ts压缩警告状态
postCompactCleanup.ts压缩后清理

4. mcp/ — MCP 客户端

文件数: 22 个

文件说明
client.tsMCP 客户端实现
config.tsMCP 配置
types.tsMCP 类型定义
auth.tsMCP 认证
MCPConnectionManager.tsx连接管理器(React 组件)
InProcessTransport.ts进程内传输
SdkControlTransport.tsSDK 控制传输
channelAllowlist.ts频道白名单
channelPermissions.ts频道权限
channelNotification.ts频道通知
elicitationHandler.ts引出处理器
envExpansion.ts环境变量展开
normalization.ts规范化
officialRegistry.ts官方注册表
utils.tsMCP 工具函数
xaa.ts / xaaIdpLogin.tsXAA 认证
claudeai.tsclaude.ai 集成
oauthPort.tsOAuth 端口
headersHelper.ts请求头辅助
mcpStringUtils.ts字符串工具
vscodeSdkMcp.tsVS Code SDK MCP
useManageMCPConnections.ts连接管理 Hook

注意:之前文档中写的 discovery.tstransport.ts 在此目录中不存在


5. tools/ — 工具执行服务

文件数: 4 个

文件说明
StreamingToolExecutor.ts流式工具执行器
toolExecution.ts工具执行核心
toolOrchestration.ts工具编排
toolHooks.ts工具钩子集成

不存在的目录(之前文档错误)

以下目录在 src/sces/不存在

  • services/permissions/ → 实际在 src/utils/permissions/
  • services/sandbox/ → 实际在 src/utils/sandbox/

设计亮点

  1. 流式优先: API 调用使用 AsyncGenerator 实现流式处理
  2. 多层压缩: 自动压缩(LLM 摘要)+ 微压缩(截断)+ 基于时间的策略
  3. GrowthBook 门控: 特性标志控制渐进式发布
  4. MCP 标准: 完整实现 MCP 协议,22 个文件覆盖连接、认证、权限、传输
  5. 工具编排: 独立的工具执行服务层,支持流式执行和钩子集成

services 模块 — 20 个服务子目录

路径: src/services/ 子目录数: 20 个


服务清单

核心服务

目录说明
api/Claude API 交互(流式调用、模型选择、重试、速率限制、请求头)
analytics/分析与遥测(GrowthBook + Statsig 双门控、OpenTelemetry、事件日志)
compact/消息压缩(自动压缩 LLM 摘要 + 微压缩截断)
oauth/OAuth 服务(令牌管理、刷新、存储)
mcp/MCP 客户端(服务器发现、连接、工具调用、资源读取)

AI 增强服务

目录说明
autoDream/自动推理(后台记忆整合)
extractMemories/记忆提取(从对话中提取值得记忆的信息)
SessionMemory/会话记忆(跨回合的上下文保持)
AgentSummary/Agent 摘要(子 Agent 执行结果摘要)
PromptSuggestion/提示建议(主动建议下一步操作)
MagicDocs/魔法文档(自动生成文档)

工具与权限服务

目录说明
tools/工具服务(工具注册、发现、执行协调)
toolUseSummary/工具使用摘要(生成工具调用的摘要)
plugins/插件服务(插件加载、验证、生命周期)

配置与策略服务

目录说明
policyLimits/策略限制(组织级别的使用限制)
remoteManagedSettings/远程托管设置(从服务器同步配置)
settingsSync/设置同步(跨设备设置同步)
teamMemorySync/团队记忆同步(团队共享记忆的同步)

其他服务

目录说明
lsp/LSP 集成(Language Server Protocol,代码智能)
tips/提示系统(使用技巧和建议)

11 - tools 模块源码分析

路径: src/tools/ 功能: AI 工具实现 — Claude 可调用的所有工具


模块概述

tools/ 包含 Claude Code 中 AI 可以调用的所有工具实现。每个工具通过 buildTool(def) 工厂函数构建(不是类继承),接收 ToolDef 对象定义,返回 BuiltTool


工具清单

文件操作工具

工具功能只读破坏性
Read读取文件内容
Write创建/覆写文件
Edit精确字符串替换编辑
NotebookEditJupyter Notebook 编辑
Glob文件模式匹配搜索
Grep文件内容正则搜索

系统操作工具

工具功能只读破坏性
Bash执行 Shell 命令
Agent启动子 Agent

网络工具

工具功能只读破坏性
WebFetch获取网页内容
WebSearch网页搜索

任务管理工具

工具功能只读破坏性
TodoWrite写入任务列表

注意:TodoReadTool 目录不存在,只有 TodoWriteTool

特殊工具

工具功能
AskUser向用户提问
EnterPlanMode进入计划模式
ExitPlanMode退出计划模式
Skill调用技能
CronCreate创建定时任务
CronDelete删除定时任务
CronList列出定时任务
EnterWorktree进入 Git Worktree
ExitWorktree退出 Git Worktree
RemoteTrigger远程触发器

核心工具详解

1. Bash — Shell 命令执行

权限检查

needsPermission: (input) => {
  const { command } = input
  // 检查是否匹配自动允许规则
  if (matchesAllowRule(command)) return false
  // 检查是否是只读命令
  if (isReadOnlyCommand(command)) return false
  // 默认需要权限
  return true
}

执行逻辑

execute: async (input, context) => {
  const { command, timeout } = input
  // 1. 创建子进程
  const proc = spawn('sh', ['-c', command], {
    cwd: context.cwd,
    timeout: timeout || 120000,  // 默认 2 分钟超时
    env: { ...process.env, ...context.env },
  })
  // 2. 收集输出
  let stdout = '', stderr = ''
  proc.stdout.on('data', (d) => stdout += d)
  proc.stderr.on('data', (d) => stderr += d)
  // 3. 等待完成
  const exitCode = await waitForExit(proc)
  // 4. 截断过长输出
  return { stdout: truncate(stdout), stderr: truncate(stderr), exitCode }
}

安全特性

  • 命令白名单/黑名单
  • 超时控制(默认 120 秒)
  • 输出长度限制
  • 沙箱环境支持
  • 网络访问控制

2. Read — 文件读取

功能特性

  • 支持文本文件、图片、PDF、Jupyter Notebook
  • 行号显示(cat -n 格式)
  • 支持 offset/limit 分页读取
  • 支持 PDF 页码范围
  • 图片以多模态内容返回
execute: async (input) => {
  const { file_path, offset, limit, pages } = input

  // 检测文件类型
  if (isImage(file_path)) {
    return { type: 'image',ait readFileAsBase64(file_path) }
  }
  if (isPDF(file_path)) {
    return { type: 'text', content: await extractPDFText(file_path, pages) }
  }
  if (isNotebook(file_path)) {
    return { type: 'text', content: await renderNotebook(file_path) }
  }

  // 文本文件
  const content = await readFileWithLineNumbers(file_path, offset, limit)
  return { type: 'text', content }
}

3. Edit — 精确编辑

核心逻辑

execute: async (input) => {
  const { file_path, old_string, new_string, replace_all } = input

  // 1. 读取文件
  const content = await readFile(file_path, 'utf-8')

  // 2. 查找 old_string
  if (!content.includes(old_string)) {
    throw new Error('old_string not found in file')
  }

  // 3. 检查唯一性(除非 replace_all)
  if (!replace_all) {
    const count = countOccurrences(content, old_string)
    if (count > 1) {
      throw new Error('old_string is not unique, provide more context')
    }
  }

  // 4. 执行替换
  const newContent = replace_all
    ? content.replaceAll(old_string, new_string)
    : content.replace(old_string, new_string)

  // 5. 写入文件
  await writeFile(file_path, newContent)

  return { success: true }
}

安全特性

  • 要求先 Read 再 Edit(防止盲改)
  • old_string 唯一性检查
  • 保留原始缩进

4. Agent — 子 Agent 启动

execute: async (input, context) => {
  const { prompt, subagent_type, model, isolation } = input

  // 1. 选择 Agent 类型
  const agentConfig = resolveAgentType(subagent_type)

  // 2. 创建隔离环境(可选)
  let workDir = context.cwd
  if (isolation === 'worktree') {
    workDir = await createGitWorktree()
  }

  // 3. 启动子 Agent
  const agent = await spawnAgent({
    prompt,
    model: model || agentConfig.model,
    tools: agentConfig.tools,
    cwd: workDir,
    parentSessionId: context.sessionId,
  })

  // 4. 等待完成
  const result = await agent.waitForCompletion()

sult
}

Agent 类型

  • general-purpose — 通用 Agent
  • Explore — 代码探索 Agent(只读)
  • Plan — 计划 Agent(只读)
  • claude-code-guide — 使用指南 Agent

5. Glob — 文件模式匹配

execute: async (input) => {
  const { pattern, path } = input
  // 使用 fast-glob 进行文件搜索
  const files = await glob(pattern, {
    cwd: path || process.cwd(),
    ignore: ['node_modules/**', '.git/**'],
    onlyFiles: true,
  })
  // 按修改时间排序
  return files.sort((a, b) => b.mtime - a.mtime)
}

6. Grep — 内容搜索

exee: async (input) => {
  const { pattern, path, glob: fileGlob, output_mode } = input
  // 使用 ripgrep 进行搜索
  const results = await ripgrep(pattern, {
    path: path || process.cwd(),
    glob: fileGlob,
    maxResults: input.head_limit || 250,
  })

  switch (output_mode) {
    case 'content': return formatContentResults(results)
    case 'files_with_matches': return formatFileResults(results)
    case 'count': return formatCountResults(results)
  }
}

工具注册流程

// tools.ts — 工具注册入口
function registerAllTools(): Tool[] {
  return [
    buildBashTool(),
    buildReadTool(),
    buildWriteTool(),
    buiol(),
    buildGlobTool(),
    buildGrepTool(),
    buildAgentTool(),
    buildWebFetchTool(),
    buildWebSearchTool(),
    buildTodoReadTool(),
    buildTodoWriteTool(),
    buildAskUserTool(),
    // ... 更多工具
    // MCP 工具动态注册
    ...await discoverMCPTools(),
  ]
}

设计亮点

  1. Builder 模式: 统一的工具构建接口,安全默认值
  2. 权限分层: 只读/非破坏性/破坏性三级权限
  3. MCP 扩展: 通过 MCP 协议动态发现和注册第三方工具
  4. 输出控制: 所有工具输出都有长度限制,防止上下文溢出
  5. 沙箱支持: 工具可在沙箱环境中受限执行

tools 模块 — 42 个工具子目录完整清单

路径: src/tools/ 每个工具一个独立目录


文件操作工具

工具目录行数功能权限
FileReadTool/1184读取文件(文本/图片/PDF/Notebook),支持分页、去重、图片压缩只读
FileWriteTool/435创建/覆写文件,强制 LF 换行,过期检查,LSP 通知破坏性
FileEditTool/626精确字符串替换编辑,唯一性检查,1GiB 上限,技能发现破坏性
NotebookEditTool/~200Jupyter Notebook 单元格编辑破坏性
GlobTool/199文件模式匹配搜索,100 结果上限,路径相对化只读
GrepTool/578ripgrep 内容搜索,250 默认上限,分页支持只读

系统操作工具

工具目录行数功能权限
BashTool/~800Shell 命令执行,120s 超时,输出截断,沙箱支持破坏性
PowerShellTool/~300PowerShell 命令执行(Windows)破坏性
AgentTool/~500启动子 Agent(general/Explore/Plan/guide),worktree 隔离非破坏性
REPLTool/~200交互式 REPL 工具非破坏性
SleepTool/~50等待指定时间只读

网络工具

工具目录行数功能权限
WebFetchTool/~400获取网页内容,HTML→Markdown 转换,15 分钟缓存只读
WebSearchTool/~300网页搜索只读

任务管理工具

工具目录行数功能权限
TaskCreateTool/~150创建任务非破坏性
TaskGetTool/~80获取任务详情只读
TaskListTool/~80列出所有任务只读
TaskUpdateTool/~150更新任务状态/内容非破坏性
TaskOutputTool/~100获取任务输出只读
TaskStopTool/~80停止运行中的任务非破坏性
TodoWriteTool/~150写入待办列表非破坏性

计划模式工具

工具目录行数功能权限
EnterPlanModeTool/127进入计划模式,激活分类器只读
ExitPlanModeTool/494退出计划模式,呈现计划供审批,队友邮箱审批破坏性

Worktree 工具

工具目录行数功能权限
EnterWorktreeTool/128创建隔离 git worktree,验证 slug 格式破坏性
ExitWorktreeTool/330退出 worktree(keep/remove),统计未提交变更破坏性

MCP 工具

工具目录行数功能权限
MCPTool/~300调用 MCP 服务器工具动态
ListMcpResourcesTool/124列出 MCP 资源,LRU 缓存只读
ReadMcpResourceTool/~100读取 MCP 资源只读
McpAuthTool/~150MCP 认证处理非破坏性

通信工具

工具目录行数功能权限
AskUserQuestionTool/~200向用户提问(多选/单选/预览)只读
SendMessageTool/~150发送消息给其他 Agent非破坏性
BriefTool/205发送消息给用户(助手模式主输出通道)只读

配置工具

工具目录行数功能权限
ConfigTool/468获取/设置 Claude Code 配置,支持点号嵌套动态
SkillTool/~200调用技能非破坏性

定时任务工具

工具目录行数功能权限
ScheduleCronTool/~200创建/删除/列出定时任务非破坏性
RemoteTriggerTool/~150远程触发器管理非破坏性

团队工具

| 工具目录 | 功能 | 权限 | |–––––|——|——|——| | TeamCreateTool/ | ~200 | 创建团队(Swarm 模式) | 非破坏性 | | TeamDeleteTool/ | ~100 | 删除团队 | 破坏性 |

代码智能工具

工具目录行数功能权限
LSPTool/861代码智能(定义跳转/引用/符号/悬停),10MB 上限只读
ToolSearchTool/~100搜索可用工具只读

其他

工具目录行数功能权限
SyntheticOutputTool/~100合成输出(内部用)只读
shared/工具间共享代码
testing/测试工具

12 - skills 模块源码分析

路径: src/skills/ 文件数: 20 个 功能: 技能系统 — 可扩展的斜杠命令(/batch, /simplify, /debug 等)

注意:/commit/review 不是 bundled skill,而是 src/commands/ 中的独立命令。


模块概述

skills/ 实现了 Claude Code 的技能系统,即用户通过 /命令名 调用的预定义工作流。技能可以来自内置捆绑、用户自定义目录、插件或 MCP 提供者。


核心基础设施

1. bundledSkills.ts — 内置技能注册表

行数: 221 行

功能概述

内置技能的核心注册表,管理随 CLI 一起发布的技能。

导出

  • registerBundledSkill(def) — 注册内置技能
  • getBundledSkills() — 获取所有内置技能
  • clearBundledSkills() — 清空(测试用)
  • getBundledSkillExtractDir() — 获取技能文件提取目录
  • BundledSkillDefinition 类型

注册流程

// 源码 src/skills/bundledSkills.ts:15-40
export type BundledSkillDefinition = {
  name: string
  description: string
  aliases?: string[]
  whenToUse?: string
  argumentHint?: string
  allowedTools?: string[]
  model?: string
  disableModelInvocation?: boolean
  userInvocable?: boolean
  isEnabled?: () => boolean
  hooks?: HooksSettings
  context?: 'inline' | 'fork'
  agent?: string
  files?: Record<string, string>  // 参考文件(懒提取到磁盘)
  getPromptForCommand: (args: string, context: ToolUseContext) => Promise<ContentBlockParam[]>
}

安全文件提取

// 懒提取技能文件到临时目录
// 使用 O_NOFOLLOW | O_EXCL 防止符号链接攻击
// Memoize 提取 Promise 避免重复提取
async function extractSkillFile(relativePath: string): Promise<string> {
  const targetPath = join(extractDir, relativePath)
  // 验证相对路径防止目录遍历
  if (relativePath.includes('..')) throw new Error('Path traversal detected')
  const fd = await open(targetPath, O_WRONLY | O_CREAT | O_EXCL | O_NOFOLLOW)
  // ...
}

2. loadSkillsDir.ts — 技能目录发现与加载

行数: 1087 行(最大的技能文件)

功能概述

.skills/ 目录发现和加载用户自定义技能,解析 SKILL.md frontmatter,创建 Command 对象。

导出

  • getSkillDirCommands() — 获取目录技能命令
  • loadSkillsFromSkillsDir() — 从目录加载技能
  • createSkillCommand() — 创建技能命令
  • parseSkillFrontmatterFields() — 解析 frontmatter
  • discoverSkillDirsForPaths() — 发现技能目录
  • addSkillDirectories() — 添加技能目录
  • activateConditionalSkillsForPaths() — 激活条件技能
  • getDynamicSkills() — 获取动态技能
  • clearSkillCaches() — 清空缓存

SKILL.md 格式

---
name: my-skill
description: 我的自定义技能
model: claude-sonnet-4-6
allowed-tools: [Bash, Read, Write]
user-invocable: true
condition: "src/**/*.ts"
---

这里是技能的提示词内容...

发现流程

项目根目录
  ├── .skills/           ← 项目级技能
  │   ├── commit/
  │   │   └── SKILL.md
  │   └── review/
  │       └── SKILL.md
  │
  ├── ~/.claude/skills/  ← 用户级技能
  │   └── my-skill/
  │       └── SKILL.md
  │
  └── 插件提供的技能目录

条件技能

// 条件技能只在匹配的文件路径下激活
// 使用 minimatch 进行 glob 匹配
activateConditionalSkillsForPaths(paths: string[]) {
  for (const skill of conditionalSkills) {
    if (paths.some(p => minimatch(p, skill.condition))) {
      activateSkill(skill)
    }
  }
}

去重机制

  • 使用 realpath() 解析符号链接后去重
  • 缓存已发现的技能目录
  • 遵守 .gitignore 规则过滤

3. mcpSkillBuilders.ts — MCP 技能构建器注入

行数: 45 行

功能概述

依赖注入注册表,打破 MCP 技能发现与技能加载之间的循环依赖。

type MCPSkillBuilders = {
  createSkillCommand: typeof createSkillCommand
  parseSkillFrontmatterFields: typeof parseSkillFrontmatterFields
}

// 写入一次,之后只读
let builders: MCPSkillBuilders | undefined

function registerMCPSkillBuilders(b: MillBuilders): void {
  builders = b
}

function getMCPSkillBuilders(): MCPSkillBuilders {
  if (!builders) throw new Error('MCP skill builders not registered')
  return builders
}

内置技能详解

4. bundled/index.ts — 初始化入口

行数: 80 行

调用所有内置技能的注册函数:

function initBundledSkills(): void {
  registerClaudeApiSkill()
  registerBatchSkill()
  registerDebugSkill()
  registerSimplifySkill()
  registerKeybindingsSkill()
  registerRememberSkill()
  registerUpdateConfigSkill()
  registerSkillifySkill()
  registerVerifySkill()
  registerStuckSkill()
  registerLoremIpsumSkill()
  registerClaudeInChromeSkill()
  // ... 受 feature flag 控制的技能
}

5. bundled/batch.ts — 批量并行执行

行数: 125 行

功能

编排大规模并行代码变更,在隔离的 git worktree 中生成 5-30 个 Agent。

工作流

/batch "将所有 console.log 替换为 logger.info"
  ↓
分析变更范围
  ↓
创建 5-30 个 git worktree
  ↓
每个 worktree 中启动独立 Agent
  ↓
Agent 并行执行变更
  ↓
收集结果,合并到主分支

6. bundled/claudeApi.ts — Claude API 开发辅助

行数: 197 行

功能

帮助用户构建使用 Claude API 的应用,自动检测项目语言并提供对应示例。

function registerClaudeApiSkill(): void {
  // 检测项目语言
  const language = detectProjectLanguage() // TypeScript | Python | other

  // 懒加载 247KB 文档包
  const docs = await loadDocBundle(language)

  registerBundledSkill({
    name: 'claude-api',
    description: 'Build apps with the Claude API',
    prompt: SKILL_PROMPT,
    referenceFiles: SKILL_FILES[language],
  })
}

7. bundled/simplify.ts — 代码审查与简化

行数: 70 行

功能

三阶段代码审查工作流,启动三个并行审查 Agent。

/simplify
  ↓
Phase 1: git diff 识别变更
  ↓
Phase 2: 启动 3 个并行 Agent
  ├── Agent 1: 代码复用审查
  ├── Agent 2: 代码质量审查
  └── Agent 3: 效率审查
  ↓
Phase 3: 聚合发现,修复问题

8. bundled/updateConfig.ts — 配置管理

行数: 476 行

功能

settings.json 配置管理技能,动态生成 JSON Schema 文档。

特性

  • 从 Zod SettingsSchema 动态生成 JSON Schema
  • 文档化三层配置系统(user/project/local)
  • 完整的 hooks 文档(所有事件类型和钩子类型)
  • 强调“先读后写“模式

9. bundled/keybindings.ts — 快捷键自定义

行数: 340 行

功能

生成快捷键系统的完整文档,包括默认绑定、保留键和自定义格式。


10. bundled/remember.ts — 记忆管理

行数: 83 行(仅内部用户可用)

工作流

/remember
  ↓
Step 1: 收集记忆层
  ├── CLAUDE.md
  ├── CLAUDE.local.md
  ├── 自动记忆
  └── 团队记忆
  ↓
Step 2: 按目标分类条目
  ↓
Step 3: 识别清理机会(重复/过期/冲突)
  ↓
Step 4: 呈现结构化报告,等待用户批准

11. bundleskillify.ts — 工作流捕获

行数: 197 行(仅内部用户可用)

功能

将当前会话的工作流捕获为可复用的技能文件。

/skillify
  ↓
提取会话中的用户消息
  ↓
四轮访谈:
  1. 高层确认
  2. 细节补充
  3. 步骤分解
  4. 最终问题
  ↓
生成 SKILL.md(含 frontmatter)
  ↓
预览 → 用户确认 → 保存

12. bundled/debug.ts — 调试日志

行数: 104 行

// 启用调试日志
enableDebugLogging()
// 读取最后 100 行日志
const logs = await readLastLines(getDebugLogPath(), 100)
// 提供日志路径
console.log(`Debug log: ${getDebugLogPath()}`)

13. bundled/loremIpsum.ts — 长文本生成

行数: 283 行(仅内部用户可用)

功能

生成填充文本用于长上下文测试。

  • 使用 200 个经过验证的单 token 词汇
  • 句子长度 10-20 词
  • 随机段落分隔
  • 上限 500k n- 输入验证

14. bundled/stuck.ts — 卡住诊断

行数: 80 行(仅内部用户可用)

功能

诊断冻结/缓慢的 Claude Code 会话。

  • 调查机器上的其他 Claude Code 进程
  • 识别卡住迹象(高 CPU、D/T/Z 进程状态、高 RSS)
  • 收集诊断上下文
  • 仅诊断,不杀进程

15. bundled/verify.ts — 变更验证

行数: 31 行(仅内部用户可用)

通过运行应用来验证代码变更。


内容包文件

claudeApiContent.ts (76 行)

在构建时内联 markdown 文档,提供模型变量、技能提示和参考文件。

verifyContent.ts (14 行)

在构建时内联 SKILL.md 和示例文件。


架构总结

skills/
├── 基础设施
│   ├── bundledSkills.ts    ← 内置技能注册表
│   ├── loadSkillsDir.ts    ← 目录技能发现
│   └── mcpSkillBuilders.ts ← DI 打破循环依赖
│
├── 初始化
│   └── bundled/inde    ← 统一初始化入口
│
├── 开发工具技能
│   ├── claudeApi.ts        ← API 开发辅助
│   ├── claudeInChrome.ts   ← Chrome 自动化
│   ├── batch.ts            ← 批量并行执行
│   ├── debug.ts            ← 调试日志
│   └── simplify.ts         ← 代码审查
│
├── 配置技能
│   ├── updateConfig.ts     ← settings.json 管理
│   └── keybindings.ts      ← 快捷键自定义
│
├── 记忆/工作流技能
│   ├── remember.ts         ← 记忆管理
│   └── skillify.ts         ← 工作流捕获
│
├── 诊断技能
│   ├── stuck.ts            ← 卡住诊断
│   ├── verify.ts           ← 变更验证
│   └── loremIp       ← 长文本测试
│
└── 内容包
    ├── claudeApiContent.ts ← API 文档包
    └── verifyContent.ts    ← 验证文档包

13 - plugins 模块源码分析

路径: src/plugins/ 文件数: 2 个 功能: 插件系统 — 内置插件注册与管理


模块概述

plugins/ 是一个相对精简的模块,提供内置插件的注册表和初始化入口。插件的安装/卸载等生命周期管理在 cli/handlers/plugins.ts 中实现。


1. builtinPlugins.ts — 内置插件注册表

行数: 160 行

导出

  • registerBuiltinPlugin(def) — 注册内置插件
  • getBuiltinPlugins() — 获取所有内置插件(按用户设置过滤)
  • getBuiltinPluginSkillCommands() — 获取插件提供的技能命令
  • isBuiltinPluginId(id) — 检查是否为内置插件 ID
  • clearBuiltinPlugins() — 清空注册表(测试用)
  • BuiltinPluginDefinition 类型

核心逻辑

// 返回 enabled/disabled 两个数组,不是单个过滤后的数组
export function getBuiltinPlugins(): {
  enabled: LoadedPlugin[]
  disabled: LoadedPlugin[]
}

内置插件可以携带 skillshooksmcpServers,ID 采用 {name}@builtin 格式。


2. bundled/index.ts — 初始化入口

行数: 24 行

功能

空的初始化函数,作为未来插件系统扩展的占位符。

export function initBuiltinPlugins(): void {
  // 未来在此注册内置插件
  // 当前为空实现
}

插件系统全景

虽然 plugins/ 模块本身很小,但插件系统涉及多个模块的协作:

插件系统全景
├── plugins/                    ← 插件注册表(本模块)
│   ├── builtinPlugins.ts       ← 内置插件定义
│   └── bundled/index.ts        ← 初始化入口
│
├── cli/handlers/plugins.ts     ← 插件生命周期管理
│   ├── install / uninstall
│   ├── enable / disable
│   ├── update
│   └── marketplace 操作
│
├── schemas/                    ← 插件配置 Schema
│   └── plugins.ts              ← Zod 验证
│
├── skills/                     ← 插件提供的技能
│   └── loadSkillsDir.ts        ← 从插件目录加载技能
│
└── settings.json               ← 插件启用/禁用配置
    └── disabledPlugins: []

插件作用域

~/.claude/plugins/          ← 用户级插件(全局)
.claude/plugins/            ← 项目级插件
本地路径引用                 ← 本地插件

14 - hooks 模块源码分析

路径: src/hooks/(React UI hooks)+ src/utils/hooks/(钩子执行引擎) 功能: 钩子系统 — 工具生命周期事件的拦截与扩展


重要说明:两个目录的区别

目录内容文件数
src/hooks/React UI hooks(useArrowKeyHistory、useCanUseTool、useGlobalKeybindings 等)85+
src/utils/hooks/钩子执行引擎(execPromptHook、execHttpHook、execAgentHook 等)17

文档以下内容描述的是 src/utils/hooks/ 中的钩子执行系统,不是 src/hooks/ 中的 React hooks。


src/hooks/ — React UI Hooks(85+ 文件)

这些是标准的 React hooks,用于 UI 状态管理,与钩子执行系统无关:

src/hooks/
├── useArrowKeyHistory.tsx      # 箭头键历史导航
├── useCanUseTool.tsx           # 工具可用性检查
├── useGlobalKeybindings.tsx    # 全局快捷键
├── useReplBridge.tsx           # REPL 桥接
├── useVoice.ts                 # 语音模式
├── useCommandQueue.ts          # 命令队列
├── useDiffData.ts              # Diff 数据
├── useExitOnCtrlCD.ts          # Ctrl+C/D 退出
├── useDynamicConfig.ts         # 动态配置
├── notifs/                     # 通知相关 hooks
├── toolPermission/             # 工具权限相关 hooks
└── ... 80+ 其他 React hooks

src/utils/hooks/ — 钩子执行引擎(17 文件)

这才是真正的钩子配置与执行系统:

src/utils/hooks/
├── AsyncHookRegistry.ts        # 异步钩子注册表与生命周期管理
├── sessionHooks.ts             # 会话级钩子注册
├── hookEvents.ts               # 钩子事件发射系统
├── hookHelpers.ts              # 钩子辅助函数
├── hooksConfigManager.ts       # 钩子配置管理
├── hooksConfigSnapshot.ts      # 钩子配置快照
├── hooksSettings.ts            # 钩子设置验证
├── execAgentHook.ts            # Agent 钩子执行器
├── execHttpHook.ts             # HTTP Webhook 执行器
├── execPromptHook.ts           # LLM 提示钩子执行器
├── apiQueryHookHelper.ts       # API 查询钩子辅助
├── postSamplingHooks.ts        # 采样后钩子
├── registerFrontmatterHooks.ts # Frontmatter 钩子注册
├── registerSkillHooks.ts       # 技能钩子注册
├── skillImprovement.ts         # 技能改进
├── fileChangedWatcher.ts       # 文件变更监听
└── ssrfGuard.ts                # SSRF 防护(HTTP 钩子安全)

钩子事件类型(28 个)

源码 src/entrypoints/sdk/coreTypes.ts:25-53

事件说明
PreToolUse工具执行前,可阻止执行
PostToolUse工具执行后,可检查结果
PostToolUseFailure工具执行失败后
Notification通知发送时
UserPromptSubmit用户提交提示时
SessionStart会话开始
SessionEnd会话结束
Stop回合结束时,可阻止结束
StopFailure停止失败时
SubagentStart子 Agent 启动时
SubagentStop子 Agent 停止时
PreCompact消息压缩前
PostCompact消息压缩后
PermissionRequest权限请求时
PermissionDenied权限被拒绝时
Setup初始化设置时
TeammateIdle队友空闲时
TaskCreatedTaskCompleted
Elicitation引出(向用户提问)时
ElicitationResult引出结果返回时
ConfigChange配置变更时
WorktreeCreateWorktree 创建时
WorktreeRemoveWorktree 移除时
InstructionsLoaded指令加载完成时
CwdChanged工作目录变更时
FileChanged文件变更时

钩子类型(4 种)

1. Shell 命令钩子 (command)

{
  "type": "command",
  "command": "npm test",
  "shell": "bash",
  "timeout": 30000,
  "if": "Bash(npm *)"
}

执行器: src/utils/hooks/ 中通过 shell 子进程执行

2. LLM 提示钩子 (prompt)

{
  "type": "prompt",
  "prompt": "检查这个代码变更是否安全",
  "model": "claude-haiku-4-5",
  "timeout": 60000
}

执行器: src/utils/hooks/execPromptHook.ts

3. HTTP Webhook 钩子 (http)

{
  "type": "http",
  "url": "https://api.example.com/hook",
  "headers": { "Authorization": "Bearer $TOKEN" },
  "timeout": 10000
}

执行器: src/utils/hooks/execHttpHook.ts(含 ssrfGuard.ts SSRF 防护)

4. Agent 验证器钩子 (agent)

{
  "type": "agent",
  "prompt": "验证代码变更符合团队规范",
  "model": "claude-sonnet-4-6",
  "timeout": 120000
}

执行器: src/utils/hooks/execAgentHook.ts


钩子配置格式

// settings.json
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash(*)",
        "hooks": [
          {
            "type": "command",
            "command": "echo '即将执行: $TOOL_INPUT'",
            "timeout": 5000
          }
        ]
      }
    ],
    "PostToolUse": [
      {
        "matcher": "Write(*)",
        "hooks": [
          {
            "type": "command",
            "command": "eslint --fix $FILE_PATH",
            "timeout": 30000
          }
        ]
      }
    ],
    "Stop": [
      {
        "hooks": [
          {
        : "prompt",
            "prompt": "总结本次对话的关键变更"
          }
        ]
      }
    ]
  }
}

钩子执行流程

工具调用请求
    ↓
PreToolUse 钩子 (src/utils/hooks/)
    ├── matcher 匹配检查
    ├── if 条件检查
    ├── 执行钩子(并行)
    ├── 收集结果
    │   ├── 阻塞错误 → 阻止工具执行
    │   └── 非阻塞 → 继续
    ↓
工具执行
    ↓
PostToolUse 钩子
    ├── 同样的匹配和执行流程
    ├── 可以检查工具结果
    └── 可以触发后续操作
    ↓
回合结束
    ↓
Stop 钩子
    ├── 执行停止钩子
    ├── 后台任务(记忆提取等)
    └── 可以阻止回合结束

设计亮点

  1. 双目录分离: React UI hooks (src/hooks/) 与钩子执行引擎 (src/utils/hooks/) 完全分离
  2. 28 种事件: 覆生命周期的完整事件链
  3. **: HTTP 钩子内置 SSRF 安全守卫
  4. Matcher 模式: 使用 glob 模式匹配工具名和参数
  5. 条件执行: if 字段支持权限规则语法过滤
  6. 并行执行: 同一事件的多个钩子并行执行
  7. 超时控制: 每个钩子独立超时

15 - state 模块源码分析

路径: src/state/ 文件数: 6 个 总行数: 1190 行 功能: React 感知的应用状态管理 — 组件级订阅与重渲染


模块概述

state/bootstrap/state.ts 的全局单例不同,这里的状态是 React 感知的,支持组件级别的订阅和选择性重渲染。类似 Zustand 的设计模式。


文件详解

1. store.ts — 状态存储核心(34 行)

核心 API

type Store<T> = {
  getState: () => T
  setState: (updater: (prev: T) => T) => void  // 接受 updater 函数,不是部分状态
  subscribe: (listener: () => void) => () => void  // listener 无参数,返回 unsubscribe
}

function createStore<T>(
  initialState: T,
  onChange?: (args: { newState: T; oldState: T }) => void
): Store<T>

注意:setState 接受 updater 函数 (prev) => next,不是直接传入部分状态对象。subscribe 的 listener 不接收参数。onChange 回调(接收新旧状态)是 createStore 的第二个参数。


2. AppStateStore.ts — 应用状态定义(569 行)

功能

定义完整的应用状态结构和初始值。

实际 AppState 关键字段

interface AppState {
  // 设置与配置
  settings: SettingsJson
  verbose: boolean
  mainLoopModel: ModelSetting
  expandedView: boolean

  // 权限
  toolPermissionContext: ToolPermissionContext

  // 任务(对象映射,非数组)
  tasks: { [taskId: string]: TaskState }

  // MCP
  mcp: MCPState

  // 插件
  plugins: PluginState

  // 推测执行
  speculation: SpeculationState

  // 团队视图
  viewingAgentTaskId?: string

  // 消息与对话
  messages: Message[]

  // 文件历史
  fileHistory: FileHistoryState

  // 归因追踪
  attribution: AttributionState

  // 通知
  notifications: Notification[]

  // 待办列表
  todoList: TodoList | null

  // ... 更多字段
}

注意:tasks{ [taskId: string]: TaskState } 对象映射,不是数组。


3. selectors.ts — 状态选择器(76 行)

功能

派生状态选择器,用于从 AppState 中提取计算状态。

实际导出

// 获取当前查看的队友任务
function getViewedTeammateTask(
  appState: Pick<AppState, 'viewingAgentTaskId' | 'tasks'>
): InProcessTeammateTaskState | undefined

// 确定用户输入应路由到哪个 Agent
type ActiveAgentForInput =
  | { type: 'leader' }
  | { type: 'viewed'; task: InProcessTeammateTaskState }
  | { type: 'named_agent'; task: LocalAgentTaskState }

function getActiveAgentForInput(appState: AppState): ActiveAgentForInput

4. AppState.tsx — React Provider(199 行)

功能

React Context Provider,将状态存储注入组件树。

// Context 名称
const AppStoreContext = createContext<Store<AppState>>(...)
const HasAppStateContext = createContext<boolean>(false)  // 防嵌套

// 消费 Hook
function useAppState<T>(selector: (state: AppState) => T): T {
  const store = useContext(AppStoreContext)
  return useSyncExternalStore(
    store.subscribe,
    () => selector(store.getState())
  )
}

5. onChangeAppState.ts — 状态变更监听(171 行)

功能

硬编码的状态变更副作用处理器,响应特定字段的变化。

// 接收新旧状态,内部硬编码了对以下字段变化的响应:
function onChangeAppState({ newState, oldState }: {
  newState: AppState
  oldState: AppState
}): void {
  // toolPermissionContext.mode 变化 → 通知权限模式变更
  // mainLoopModel 变化 → 设置模型覆盖
  // expandedView 变化 → 保存配置
  // verbose 变化 → 保存配置
  // settings 变化 → 应用环境变量、清除凭证缓存
}

注意:这不是一个通用的注册机制,而是一个具体的函数,内部硬编码了对特定字段变化的响应逻辑。


6. teammateViewHelpers.ts — 队友视图辅助(141 行)

实际导出

function enterTeammateView(appState: AppState, taskId: string): void
function exitTeammateView(appState: AppState): void
function stopOrDismissAgent(appState: AppState, taskId: string): void

与 bootstrap/state.ts 的区别

特性bootstrap/state.tsstate/ 模块
类型全局单例对象React 感知的 Store
访问方式getter/setter 函数useAppState Hook
重渲染不触发自动触发组件重渲染
用途非 UI 状态(API、遥测)UI 相关状态(消息、任务)
生命周期进程级组件树级

16 - context 模块源码分析

路径: src/context/ 功能: 上下文收集 — git 状态、CLAUDE.md、环境信息注入系统提示


模块概述

context/ 负责收集对话所需的各种上下文信息并注入到系统提示中,帮助 AI 理解当前项目环境。所有收集操作都带 memoization 缓存。


收集的上下文类型

1. Git 上下文

interface GitContext {
  branch: string           // 当前分支名
  status: string           // 工作区状态(截断到 2000 字符)
  recentCommits: string[]  // 最近 N 条提交
  user: string             // git 用户名
  isRepo: boolean          // 是否在 git 仓库中
  mainBranch: string       // 主分支名(main/master)
}
  • git status 输出截断到 2000 字符,防止大仓库状态溢出
  • 最近提交用于 AI 理解项目活跃度和变更方向

2. CLAUDE.md 上下文

发现路径优先级(从高到低):
1. 项目根目录/CLAUDE.md          ← 项目级指令
2. 项目根目录/CLAUDE.local.md    ← 本地个人指令(gitignore)
3. 当前目录/CLAUDE.md            ← 子目录级指令
4. 父目录链中的 CLAUDE.md        ← 继承链
5. ~/.claude/CLAUDE.md           ← 全局指令

3. 环境上下文

interface EnvironmentContext {
  platform: string         // darwin / linux / win32
  shell: string            // bash / zsh / fish
  osVersion: string        // Darwin 24.6.0
  cwd: string              // 当前工作目录
  projectRoot: string      // 项目根目录
}

核心函数

// 主入口 — 带 memoization 缓存
const gatherContext = memoize(async (): Promise<ConversationContext> => {
  const [git, claudeMd, env] = await Promise.all([
    gatherGitContext(),
    gatherClaudeMdContext(),
    gatherEnvironmentContext(),
  ])
  return { git, claudeMd, env }
})

特性

  • Memoized: 避免重复收集,同一会话内只收集一次
  • Bare 模式: 最小上下文,用于轻量级场景
  • 显式目录添加: 支持手动添加额外目录的 CLAUDE.md
  • 诊断日志: 带 PII 过滤的调试日志
  • 缓存破坏: 调试用的缓存破坏注入机制

17 - constants 模块源码分析

路径: src/constants/ 功能: 常量定义 — 产品信息、OAuth 配置、模型列表、UI 常量


核心常量文件

product.ts — 产品信息

export const PRODUCT_NAME = 'Claude Code'
export const PRODUCT_COMMAND = 'claude'
export const CLI_VERSION = '...'  // 从 package.json 读取
export const USER_AGENT = `claude-code/${CLI_VERSION}`

oauth.ts — OAuth 配置

export function getOauthConfig() {
  return {
    clientId: '...',
    authorizationEndpoint: 'https://claude.ai/oauth/authorize',
    tokenEndpoint: 'https://claude.ai/oauth/token',
    scopes: ['openid', 'profile', 'email'],
    redirectUri: 'http://localhost:{port}/callback',
  }
}

models.ts — 模型配置

export const MODEL_ALIASES = {
  'opus': 'claude-opus-4-6',
  'sonnet': 'claude-sonnet-4-6',
  'haiku': 'claude-haiku-4-5',
  'opus[1m]': 'claude-opus-4-6[1m]',
  'sonnet[1m]': 'claude-sonnet-4-6[1m]',
}

outputStyles.ts — 输出样式类型

interface OutputStyleConfig {
  name: string
  description: string
  prompt: string
  source: 'user' | 'project' | 'plugin'
  keepCodingInstructions: boolean
}

18 - types 模块源码分析

路径: src/types/ 文件数: ~11 个 功能: 全局类型定义 — 消息、工具、权限、设置等核心类型


核心类型

message.ts — 消息类型

type Message = {
  role: 'user' | 'assistant'
  content: ContentBlock[]
  id?: string
  timestamp?: number
}

type ContentBlock =
  | { type: 'text'; text: string }
  | { type: 'image'; source: ImageSource }
  | { type: 'tool_use'; id: string; name: string; input: unknown }
  | { type: 'tool_result'; tool_use_id: string; content: unknown }
  | { type: 'thinking'; thinking: string }

ids.ts — ID 类型(品牌类型)

// 使用品牌类型防止 ID 混用
type SessionId = string & { __brand: 'SessionId' }
type TaskId = string & { __brand: 'TaskId' }
type AgentId = string & { __brand: 'AgentId' }

permissions.ts — 权限类型

type PermissionMode = 'default' | 'auto' | 'bypassAll'

type PermissionRequest = {
  toolName: string
  toolInput: unknown
  requestId: string
}

type PermissionUpdate = {
  behavior: 'allow' | 'deny'
  rule?: string  // 持久化规则
}

settings.ts — 设置类型

interface Settings {
  model?: string
  theme?: string
  vimMode?: boolean
  autoMemory?: boolean
  permissions?: PermissionRule[]
  hooks?: HooksSettings
  env?: Record<string, string>
  mcpServers?: Record<string, MCPServerConfig>
  // ...
}

tool.ts — 工具相关类型

interface ToolUseContext {
  sessionId: SessionId
  agentId?: AgentId
  cwd: string
  abortSignal: AbortSignal
}

hooks.ts — 钩子系统类型

interface HookContext {
  messages: Message[]
  systemPrompt: string
  toolName?: string
  toolInput?: unknown
  toolResult?: unknown
}

type HookCallback = (context: HookContext) => Promise<HookResult>

mcp.ts — MCP 协议类型

interface MCPServerConfig {
  command: string
  args?: string[]
  env?: Record<string, string>
}

interface MCPTool {
  name: string
  description: string
  inputSchema: JSONSchema
}

theme.ts — 主题类型

type Theme = 'dark' | 'light' | 'light-daltonized' | 'dark-daltonized'

model.ts — 模型配置类型

interface ModelSetting {
  model: string
  contextWindow: number
  maxOutputTokens: number
}

agent.ts — Agent 类型

interface AgentDefinition {
  name: string
  description: string
  model?: string
  tools?: string[]
  systemPrompt?: string
  source: 'built-in' | 'user' | 'project' | 'plugin'
}

plugin.ts — 插件类型

interface Plugin {
  id: string
  name: string
  version: string
  enabled: boolean
  scope: 'user' | 'project' | 'local'
}

19 - schemas 模块源码分析

路径: src/schemas/ 功能: Zod Schema 定义 — 运行时类型验证


hooks.ts — 钩子 Schema

行数: 223 行

核心设计

使用 lazySchema 打破循环依赖(settings/types.ts ↔ plugins/schemas.ts)。

四种钩子类型的 discriminated union

const HookCommandSchema = z.discriminatedUnion('type', [
  // Shell 命令钩子
  z.object({
    type: z.literal('command'),
    command: z.string(),
    shell: z.enum(SHELL_TYPES).optional(),
    timeout: z.number().optional(),
    if: IfConditionSchema.optional(),
    statusMessage: z.string().optional(),
    once: z.boolean().optional(),
    asyncRewake: z.boolean().optional(),
  }),

  // LLM 提示钩子
  z.object({
    type: z.literal('prompt'),
    prompt: z.string(),
    model: z.string().optional(),
    timeout: z.number().optional(),
    if: IfConditionSchema.optional(),
  }),

  // HTTP Webhook 钩子
  z.object({
    type: z.literal('http'),
    url: z.string().url(),
    headers: z.record(z.string()).optional(),
    allowedEnvVars: z.array(z.string()).optional(),
    timeout: z.number().optional(),
  }),

  // Agent 验证器钩子
  z.object({
    type: z.literal('agent'),
    prompt: z.string(),
    model: z.string().optional(),
    timeout: z.number().optional(),
  }),
])

匹配器 Schema

const HookMatcherSchema = z.object({
  matcher: z.string().optional(),  // glob 模式,如 "Bash(git *)"
  hooks: z.array(HookCommandSchema),
})

完整钩子配置

const HooksSchema = z.record(
  z.enum(HOOK_EVENTS),           // PreToolUse, PostToolUse, Stop, ...
  z.array(HookMatcherSchema)
).partial()

IfConditionSchema — 条件过滤

// 可选的权限规则语法,控制钩子何时运行
// 例如: "Bash(git *)" 只在 Bash 工具执行 git 命令时触发
const IfConditionSchema = z.string()

设计亮点

  1. lazySchema: 使用懒加载打破 settings/types.ts 和 plugins/schemas.ts 之间的循环依赖
  2. discriminated union: 通过 type 字段实现类型安全的钩子路由
  3. 独立提取: 从 settings/types.ts 中提取出来,避免循环引用

20 - bridge 模块源码分析

路径: src/bridge/ 文件数: 31 个 功能: Web/IDE 桥接通信 — 连接 CLI 与 Web UI/IDE 扩展


模块概述

bridge/ 是 Claude Code 最复杂的通信模块之一,负责在 CLI 进程与 Web 界面(claude.ai/code)或 IDE 扩展(VS Code/JetBrains)之间建立双向通信桥梁。支持多会话管理、断线重连、权限代理和状态同步。


架构总览

┌──────────────┐     WebSocket/SSE      ┌──────────────────┐
│  Web UI      │ ◄──────────────────────► │                  │
│  (claude.ai) │                         │   Bridge Layer    │
└──────────────┘                         │                  │
                                         │  ├── 消息路由     │
┌──────────────┐     WebSocket/SSE      │  ├── 权限代理     │
│  IDE 扩展    │ ◄──────────────────────► │  ├── 状态同步     │
│  (VS Code)   │                         │  ├── 断线重连     │
└──────────────┘                         │  └── 多会话管理   │
                                         │                  │
                                         └────────┬─────────┘
                                                  │
                                         ┌────────▼─────────┐
                                         │   CLI 核心        │
                                         │  (REPL/Query)     │
                                         └──────────────────┘

核心文件详解

1. bridgeMessaging.ts — 消息处理核心

行数: 462 行

功能概述

传输层消息处理,提供纯函数用于解析 WebSocket 消息、路由控制请求和去重回声。

导出

  • isSDKMessage() — SDK 消息类型守卫
  • isSDKControlResponse() — 控制响应类型守卫
  • isSDKControlRequest() — 控制请求类型守卫
  • isEligibleBridgeMessage() — 桥接消息资格检查
  • extractTitleText() — 提取标题文本
  • handleIngressMessage() — 入站消息处理
  • handleServerControlRequest() — 服务器控制请求处理
  • makeResultMessage() — 构造结果消息
  • BoundedUUIDSet 类 — 有界 UUID 集合

BoundedUUIDSet — FIFO 环形缓冲去重

class BoundedUUIDSet {
  private set = new Set<string>()
  private queue: string[] = []
  private maxSize: number

  add(uuid: string): boolean {
    if (this.set.has(uuid)) return false // 重复
    this.set.add(uuid)
    this.queue.push(uuid)
    if (this.queue.length > this.maxSize) {
      const oldest = this.queue.shift()!
      this.set.delete(oldest)
    }
    return true // 新消息
  }
  // O(1) 操作,防止回声消息重复处理
}

控制请求处理

async function handleServerControlRequesServerControlRequest) {
  switch (request.type) {
    case 'initialize':     // 初始化连接
    case 'set_model':      // 切换模型
    case 'interrupt':      // 中断执行
    case 'set_permission_mode':  // 设置权限模式
    case 'set_max_thinking_tokens':  // 设置思考 token 上限
  }
}

2. bridgePointer.ts — 崩溃恢复指针

行数: 211 行

功能概述

会话启动时写入指针文件,用于崩溃恢复和 --continue 功能。

导出

  • BRIDGE_POINTER_TTL_MS — 指针 TTL(4 小时)
  • BridgePointer 类型
  • writeBridgePointer() — 写入指针
  • readBridgePointer() — 读取指针
  • readBridgePointerAcrossWorktrees() — 跨 worktree 读earBridgePointer()` — 清除指针

指针结构

type BridgePointer = {
  sessionId: string
  environmentId: string
  source: 'standalone' | 'repl'
}

过期检测

// 通过文件 mtime 检测过期(4 小时 TTL)
const stats = await stat(pointerPath)
const age = Date.now() - stats.mtimeMs
if (age > BRIDGE_POINTER_TTL_MS) return null // 过期

Worktree 扇出

// 跨 git worktree 查找最新指针
// MAX_WORKTREE_FANOUT = 50,限制并行 stat() 调用
async function readBridgePointerAcrossWorktrees() {
  const worktrees = await getGitWorktrees()
  const pointers = await Promise.all(
    worktrees.slice(0, 50).map(wt => readBridgePointer(wt.path))
  )
  return pointers
    .filter(Boolean)
    .sort((a, b) => b.mtime - a.mtime)[0] // 取最新
}

3. bridgeUI.ts — 终端 UI 实现

行数: 531 行

功能概述

桥接状态的终端 UI 显示,包括 QR 码、Spinner、会话列表和工具活动。

导出

  • createBridgeLogger() — 创建桥接日志器

状态机

idle → attached → titled
  ↓        ↓         ↓
  └── reconnecting ──┘
           ↓
        failed

UI 功能

功能说明
QR 码连接/会话 URL 的 QR 码显示
Spinner等待连接时的动画
会话列表多会话模式下的项目符号列表
工具活动显示当前执行的工具(30 秒过期)
容量指示Spawn 模式下的容量显示

ANSI 光标操作

// 追踪 statusLineCount 用于 ANSI 光标操作
function updateDisplay() {
  // 上移 N 行
  process.stdout.write(`\x1b[${statusLineCount}A`)
  // 清除到末尾
  process.stdout.write('\x1b[J')
  // 写入新内容
  process.stdout.write(newContent)
  // 更新行数(考虑终端换行)
  statusLineCount = countVisualLines(newContent, terminalWidth)
}

4. bridgePermissionCallbacks.ts — 权限代理

行数: 44 行

功能概述

定义 CLI 和 Web 应用之间权限请求/响应的回调接口。

type BridgePermissionCallbacks = {
  sendRequest(request: PermissionRequest): void
  sendResponse(response: BridgePermissionResponse): void
  cancelRequest(requestId: string): void
  onResponse(handler: (response: BrPermissionResponse) => void): void
}

type BridgePermissionResponse = {
  behavior: 'allow' | 'deny'
  updatedInput?: unknown
  updatedPermissions?: PermissionUpdate
  message?: string
}

5. bridgeStatusUtil.ts — 状态工具函数

行数: 164 行

导出

  • StatusState 类型 — idle | attached | titled | reconnecting | failed
  • TOOL_DISPLAY_EXPIRY_MS — 工具显示过期时间(30 秒)
  • SHIMMER_INTERVAL_MS — 闪烁动画间隔
  • buildBridgeConnectUrl() — 构建连接 URL
  • buildBridgeSessionUrl() — 构建会话 URL
  • computeShimmerSegments() — 计算闪烁动画段
  • getBridgeStatus() — 获取桥接WithOsc8Link()` — OSC 8 终端超链接

闪烁动画

// 使用 grapheme segmentation 支持多字节字符
function computeShimmerSegments(text: string, index: number) {
  const graphemes = [...new Intl.Segmenter('en', { granularity: 'grapheme' })
    .segment(text)]
  // 计算闪烁位置...
}

OSC 8 超链接

// 终端可点击链接
function wrapWithOsc8Link(text: string, url: string): string {
  return `\x1b]8;;${url}\x07${text}\x1b]8;;\x07`
}

6. bridgeConfig.ts — 桥接配置

管理桥接连接的配置参数,包括 WebSocket URL、认证令牌和重连策略。

7. bridgeMain.ts — 桥接主逻辑

桥接模式的主入口,协调连接建立、消息路由和生命周期管理。

8. remoteBridgeCore.ts — 远程桥接核心

远程桥接的核心实现,处理与远程服务器的持久连接。

9. replBridge.ts — REPL 桥接

将桥接功能集成到 REPL 屏幕中。

10. initReplBridge.ts — REPL 桥接初始化

REPL 模式下桥接的初始化逻辑。

11. sessionRunner.ts — 会话运行器

管理桥接会话的执行生命周期。

12. createSession.ts — 会话创建

创建新的桥接会话。

13. codeSessionApi.ts — 代码会话 API

与后端代码会话 API 的交互。

14. jwtUtils.ts — JWT 工具

JWT 令牌的解析和验证。

15. flushGate.ts — 刷新门控

控制消息刷新的门控机制。

16. capacityWake.ts — 容量唤醒

管理桥接容量和唤醒逻辑。

17. pollConfig.ts / pollConfigDefaults.ts — 轮询配置

桥接轮询的配置和默认值。

18. inboundMessages.ts / inboundAttachments.ts — 入站处理

处理入站消息和附件。

19. types.ts — 类型定义

桥接模块的内部类型定义。


设计亮点

  1. 多传输支持: WebSocket 和 SSE 双传输,自动降级
  2. 崩溃恢复: 指针文件 + TTL 机制确保会话可恢复
  3. 回声去重: BoundedUUIDSet 用 O(1) 操作过滤重复消息
  4. Worktree 感知: 跨 git worktree 查找会话,支持并行开发
  5. 渐进式 UI: 状态机驱动的终端 UI,支持 QR 码和闪烁动画
  6. 权限代理: CLI 和 Web 之间透明的权限请求转发

21 - coordinator 模块源码分析

路径: src/coordinator/ 文件数: 1 个 行数: 369 行 功能: 协调器模式 — 功能标志检测、会话模式匹配和 Worker 上下文构建


模块概述

coordinator/ 模块实现的是协调器模式的功能标志和上下文构建,不是多会话管理或容量控制系统。核心功能是检测当前是否处于协调器模式,匹配会话模式,以及为 Worker 构建工具上下文和系统提示。


coordinatorMode.ts — 唯一文件

核心导出

// 检测是否处于协调器模式
function isCoordinatorMode(): boolean {
  if (feature('COORDINATOR_MODE')) {
    return isEnvTruthy(process.env.CLAUDE_CODE_COORDINATOR_MODE)
  }
  return false
}

// 匹配会话模式(恢复会话时检查模式是否一致)
function matchSessionMode(
  sessionMode: 'coordinator' | 'normal' | undefined
): string | undefined

// 构建 Worker 的用户上下文(工具列表、系统提示等)
function getCoordinatorUserContext(options: {
  scratchpadDir?: string
}): CoordinatorUserContext

// 返回协调器系统提示词
function getCoordinatorSystemPrompt(): string

设计说明

  • 通过 feature('COORDINATOR_MODE') 编译时门控 + CLAUDE_CODE_COORDINATOR_MODE 环境变量双重控制
  • matchSessionMode() 在恢复会话时检查当前模式与会话存储的模式是否一致,不一致时翻转环境变量
  • Worker 工具上下文定义了 Worker 可用的工具集(排除 TeamCreate/TeamDelete/SendMessage/SyntheticOutput 等内部工具)
  • 支持 scratchpad 功能(通过 tengu_scratch Statsig 门控)

内部常量

// Worker 不可用的内部工具
const INTERNAL_WORKER_TOOLS = new Set([
  TEAM_CREATE_TOOL_NAME,
  TEAM_DELETE_TOOL_NAME,
  SEND_MESSAGE_TOOL_NAME,
  SYNTHETIC_OUTPUT_TOOL_NAME,
])

与其他模块的关系

coordinator/
├── ← bootstrap/state.ts (isCoordinatorMode 被全局使用)
├── → tools/ (引用工具名常量)
├── → services/analytics/ (Statsig 门控)
└── → constants/tools.ts (ASYNC_AGENT_ALLOWED_TOOLS)

注意:多会话的 Spawn 模式逻辑在 bridge/bridgeUI.ts 中,不在 coordinator 模块。

22 - remote 模块源码分析

路径: src/remote/ 文件数: 4 个 功能: 远程会话管理 — 云端 Agent 会话的连接、消息收发和状态同步


文件详解

1. RemoteSessionManager.ts — 远程会话管理器

管理远程会话的连接、消息收发和权限处理。

class RemoteSessionManager {
  // 连接管理
  connect(): Promise<void>
  disconnect(): void
  reconnect(): Promise<void>
  isConnected(): boolean
  getSessionId(): string

  // 消息发送
  sendMessage(content: RemoteMessageContent): Promise<void>

  // 权限处理
  respondToPermissionRequest(requestId: string, response: PermissionUpdate): void

  // 会话控制
  cancelSession(): void
}

注意:不存在 createSessiondisconnectSessionresumeSessiongetActiveSession 方法。

2. SessionsWebSocket.ts — 会话 WebSocket

维护与远程服务器的 WebSocket 持久连接。URL 和认证信息在构造函数中传入。

class SessionsWebSocket {
  // 连接管理(无参数,配置在构造函数中)
  connect(): void
  close(): void
  reconnect(): void
  isConnected(): boolean

  // 消息发送
  sendControlResponse(response: SDKControlResponse): void
  sendControlRequest(request: SDKControlRequest): void

  // 重连(私有方法)
  private scheduleReconnect(delay: number, label: string): void
}

注意:connect() 无参数;不存在 onMessagesend 方法;重连方法是 scheduleReconnect(私有),不是 reconnectWithBackoff。消息回调通过构造函数的 SessionsWebSocketCallbacks 参数传入。

3. sdkMessageAdapter.ts — SDK 消息适配器

将远程 SDK 消息转换为本地 REPL 可用的格式。只有单向转换(SDK→REPL),不存在反向转换。

// SDK 消息 → 本地消息
function convertSDKMessage(message: SDKMessage): ConvertedMessage

// 辅助函数
function isSessionEndMessage(message: SDKMessage): boolean
function isSuccessResult(message: SDKMessage): boolean
function getResultText(message: SDKMessage): string

type ConvertedMessage = { ... }

注意:不存在 adaptRemoteToLocaladaptLocalToRemote 函数。

4. remotePermissionBridge.ts — 远程权限工具

提供为远程权限请求创建合成消息和工具存根的工具函数,不是一个代理转发模块。

// 为远程权限请求创建合成的 assistant 消息
function createSyntheticAssistantMessage(
  toolName: string,
  toolInput: Record<string, unknown>,
  toolUseId: string
): Message

// 创建工具存根(用于权限检查)
function createToolStub(toolName: string): Tool

23 - server 模块源码分析

路径: src/server/ 功能: HTTP/WebSocket 服务器 — IDE 扩展和 Web UI 的通信后端


功能概述

提供 HTTP 和 WebSocket 服务器,用于:

  • IDE 扩展通信(VS Code / JetBrains)
  • Web UI 桥接(claude.ai/code)
  • MCP 服务器托管
  • 健康检查端点 (/health)
  • 会话状态查询 (/status)

端点

端点方法说明
/healthGET健康检查,返回 200
/statusGET会话状态(消息数、费用、模型等)
/wsWebSocket双向消息通道
/mcpWebSocket/stdioMCP 协议端点

WebSocket 通信

IDE 扩展 / Web UI
    ↕ WebSocket (/ws)
Server
    ↕ 内部事件
REPL / Query Engine

消息类型

// 服务器 → 客户端
type ServerMessage =
  | { type: 'message'; message: SDKMessage }
  | { type: 'status'; status: SessionStatus }
  | { type: 'permission_request'; request: PermissionRequest }

// 客户端 → 服务器
type ClientMessage =
  | { type: 'user_message'; content: string }
  | { type: 'permission_response'; response: PermissionUpdate }
  | { type: 'control_request'; request: ServerControlRequest }

与其他模块的关系

server/
├── ← bridge/ (桥接通信使用 server 的 WebSocket)
├── ← cli/transports/ (传输层连接到 server)
├── → screens/REPL.tsx (转发用户消息)
└── → services/mcp/ (托管 MCP 服务器)

24 - keybindings 模块源码分析

路径: src/keybindings/ 文件数: 14 个 功能: 快捷键系统 — 上下文感知的键盘绑定管理


模块概述

keybindings/ 实现了一套完整的键盘快捷键系统,支持 17 种上下文、72+ 种动作、和弦序列(chord)、平台特定处理和用户自定义。


架构总览

┌─────────────────────────────────────────────┐
│              快捷键系统架构                    │
├─────────────────────────────────────────────┤
│                                             │
│  用户输入 (按键事件)                          │
│       ↓                                     │
│  KeybindingProviderSetup.tsx (React 组件)    │
│       ↓                                     │
│  resolver.ts (纯函数解析器)                   │
│       ├── 和弦状态管理                        │
│       ├── Escape 取消                        │
│       └── 上下文匹配                         │
│       ↓                                     │
│  match.ts (匹配逻辑)                         │
│       ├── Alt/Meta 等价处理                   │
│       └── Escape 键特殊处理                   │
│       ↓                                     │
│  defaultBindings.ts + loadUserBindings.ts    │
│       ├── 默认绑定                            │
│       ├── 用户自定义 (~/.claude/keybindings.json) │
│       └── 合并策略                            │
│       ↓                                     │
│  useKeybinding.ts (React Hook)              │
│       └── 注册到处理器 Map                    │
│                                             │
└─────────────────────────────────────────────┘

核心文件详解

1. schema.ts — Schema 定义

行数: 237 行

导出

  • KEYBINDING_CONTEXTS — 19 种上下文
  • KEYBINDING_ACTIONS — 72+ 种动作
  • Zod Schema 定义

上下文列表(17 个)

上下文说明
Global全局
Chat聊天输入
Autocomplete自动补全
Confirmation确认对话框
Help帮助页面
Transcript对话记录
HistorySearch历史搜索
Task任务管理
ThemePicker主题选择器
Settings设置页面
Tabs标签页
Attachments附件管理
Footer底部栏
MessageSelector消息选择器
DiffDialogDiff 对话框
ModelPicker模型选择器
Select选择列表
Plugin插件管理

注意:源码中没有 PermissionVoice 这两个 context(语音按键绑定通过 voice:pushToTalk action 在其他 context 中处理)。

动作分类

// 应用级动作
'app:quit', 'app:help', 'app:settings', 'app:theme'

// 聊天动作
'chat:submit', 'chat:newline', 'chat:clear', 'chat:interrupt'
'chat:paste-image', 'chat:history-prev', 'chat:history-next'

// 自动补全动作
'autocomplete:accept', 'autocomplete:dismiss'

// 确认动作
'confirmation:yes', 'confirmation:no', 'confirmation:always'

// 标签页动作
'tabs:next', 'tabs:prev', 'tabs:close'

// 对话记录动作
'transcript:scroll-up', 'transcript:scroll-down'
'transcript:page-up', 'transcript:page-down'
'transcript:top', 'transcript:bottom'

// 更多...

2. parser.ts — 按键解析器

行数: 204 行

功能

解析按键字符串(如 `ctrl+shif化对象,处理修饰键别名和平台特定显示。

修饰键别名

const MODIFIER_ALIASES = {
  'ctrl': 'ctrl',
  'control': 'ctrl',
  'cmd': 'meta',
  'command': 'meta',
  'win': 'meta',
  'super': 'meta',
  'alt': 'alt',
  'option': 'alt',
  'shift': 'shift',
}

平台显示

// macOS: ⌘⇧K
// Windows/Linux: Ctrl+Shift+K
function formatKeystroke(keystroke: Keystroke, platform: Platform): string

3. defaultBindings.ts — 默认绑定

行数: 341 行

功能

定义所有默认快捷键绑定,包含平台特定处理。

平台特定绑定

// 图片粘贴键
const IMAGE_PASTE_KEY = process.platform === 'darwin'
  ? 'cmd+v'      // macOS
  : 'ctrl+shift+v' // Windows/Linux

// Windows Terminal VT 模式检测
if (isWindowsTerminalVTMode()) {
  // 调整某些绑定以适应 VT 模式
}

Feature Flag 集成

某些绑定受 feature flag 控制,仅在特定条件下启用。


4. reservedShortcuts.ts — 保留快捷键

行数: 128 行

不可重绑定的快捷键

const NON_REBINDABLE = new Set([
  'ctrl+c',  // 中断/复制
  'ctrl+d',  // EOF
  'ctrl+m',  // 回车等价
])

终端保留

const TERMINAL_RESERVED = new Set([
  'ctrl+z',   // 挂起
  'ctrl+\\',  // SIGQUIT
])

macOS 保留

const MACOS_RESERVED = new Set([
  'cmd+c',    // 复制
  'cmd+v',    // 粘贴
  'cmd+x',    // 剪切
  'cmd+q',    // 退出
  'cmd+w',    // 关闭窗口
  'cmd+tab',  // 切换应用
  'cmd+space', // Spotlight
])

5. match.ts — 匹配逻辑

行数: 121 行

功能

将 Ink 输入事件与快捷键定义进行匹配。

特殊处理

// Alt 和 Meta 等价处理
// 在某些终端中 Alt 和 Meta 是同一个键
if (binding.alt && event.meta) return true
if (binding.meta && event.alt) return true

// Escape 键特殊处理
// Escape 可能是 Alt 前缀的一部分
if (event.key === 'escape' && !binding.escape) {
  // 等待下一个按键判断是否是 Alt 组合
}

6. resolver.ts — 纯函数解析器

行数: 245 行

功能

纯函数实现的快捷键解析,管理和弦状态和 Escape 取消。

和弦序列

// 和弦示例: ctrl+k ctrl+s
// 第一次按 ctrl+k → 进入和弦等待状态
// 第二次按 ctrl+s → 匹配完成,执行动作
// 按 Escape → 取消和弦

type ChordState = {
  firstKeystroke: Keystroke
  timestamp: number
  timeout: number  // 1000ms 超时
}

7. loadUserBindings.ts — 用户自定义加载

行数: 473 行

功能

~/.claude/keybindings.json 加载用户自定义绑定,支持热重载。

文件监听

// 使用 chokidar 监听文件变化
const watcher = chokidar.watch(keybindingsPath, {
  persistent: true,
  ignoreInitial: true,
})

watcher.on('change', () => {
  // 重新加载并合并绑定
  reloadBindings()
})

合并策略

// 用户绑定覆盖默认绑定
// 如果用户绑定作,替换默认绑定
// 如果用户绑定了一个新的动作,追加
function mergeBindings(defaults, userBindings) {
  const merged = new Map(defaults)
  for (const [action, binding] of userBindings) {
    merged.set(action, binding) // 覆盖或追加
  }
  return merged
}

8. validate.ts — 验证系统

行数: 499 行

功能

全面验证用户自定义绑定的合法性。

验证项目

验证说明
上下文名称必须是 19 种合法上下文之一
动作格式必须匹配 context:action 格式
按键语法修饰键 + 键名的合法组合
命令绑定正则验证命令绑定格式
重复检测同一上下文中的重复绑定警告
保留键检测不可重绑定的快捷键警告
voice:pushToTalk特殊处理语音按键绑定

9. useKeybinding.ts — React Hook

行数: 197 行

功能

React Hook,支持和弦序列和 stopImmediatePropagation 事件控制。

function useKeybinding(
  context: KeybindingContext,
  action: KeybindingAction,
  handler: () => void,
  options?: { enabled?: boolean }
): void {
  // 注册到处理器 Map
  // 支持和弦序列
  // stopImmediatePropagation 防止事件冒泡
}

10. KeybindingProviderSetup.tsx — React 组件

行数: 307 行

功能

React 组件,提供快捷键上下文、热重载和和弦拦截。

核心结构

function KeybindingProviderSetup({ children }) {
  // 处理器注册表 Map
  const handlers = useRef(new Map())

  // 活跃上下文 refs
  const activeContexts = useRef(new Set())

  // 和弦超时: 1000ms
  const CHORD_TIMEOUT = 1000

  return (
    <KeybindingContext.Provider value={{ handlers, activeContexts }}>
      <ChordInterceptor>
        {children}
      </ChordInterceptor>
    </KeybindingContext.Provider>
  )
}

ChordInterceptor 组件

拦截按键事件,管理和弦状态,在超时后自动取消。


11. shortcutFormat.ts / useShortcutDisplay.ts

shortcutFormat.ts (64 行)

非 React 工具函数,格式化快捷键显示字符串,带回退追踪。

useShortcutDisplay.ts (60 行)

React Hook 版本,附带分析日志记录。


12. template.ts — 模板生成

行数: 53 行

生成 keybindings.json 模板文件,包含 JSON Schema URL。

function generateTemplate(): string {
  return JSringify({
    "$schema": "https://...",
    // 空的绑定模板
  }, null, 2)
}

设计亮点

  1. 上下文感知: 19 种上下文确保快捷键不会在错误的场景触发
  2. 和弦支持: 类似 VS Code 的多键序列(ctrl+k ctrl+s)
  3. 平台适配: macOS/Windows/Linux 各有适当的默认绑定
  4. 热重载: 修改 keybindings.json 后立即生效,无需重启
  5. 安全验证: 全面的验证系统防止无效或危险的绑定
  6. 纯函数解析: resolver 是纯函数,易于测试

25 - vim 模块源码分析

路径: src/vim/ 文件数: 5 个 总行数: 1513 行 功能: Vim 模式 — 终端输入框的 Vim 键绑定支持


文件详解

1. types.ts — Vim 状态类型(199 行)

// VimState 是联合类型,只有 INSERT 和 NORMAL 两种模式(大写)
// 不存在 Visual 和 Command 模式
type VimState =
  | { mode: 'INSERT'; insertedText: string }
  | { mode: 'NORMAL'; command: CommandState }

// NORMAL 模式下的命令状态机(11 种状态)
type CommandState =
  | { type: 'idle' }
  | { type: 'count'; digits: string }
  | { type: 'operator'; op: Operator; count: number }
  | { type: 'operatorCount'; op: Operator; count: number; digits: string }
  | { type: 'operatorFind'; op: Operator; count: number; find: FindType }
  | { type: 'operatorTextObj'; op: Operator; count: number; scope: TextObjScope }
  | { type: 'find'; find: FindType; count: number }
  | { type: 'g'; count: number }
  | { type: 'operatorG'; op: Operator; count: number }
  | { type: 'replace'; count: number }
  | { type: 'indent'; dir: '>' | '<'; count: number }

// 持久状态(跨命令保持)
type PersistentState = {
  lastChange: RecordedChange | null  // dot-repeat 记录
  lastFind: { type: FindType; char: string } | null
  register: string                    // 寄存器内容
  registerIsLinewise: boolean
}

function createInitialVimState(): VimState {
  return { mode: 'INSERT', insertedText: '' }
}

2. motions.ts — 光标移动(82 行)

动作说明
h左移字符级
l右移字符级
w下一个词首词级
b上一个词首词级
e当前词尾词级
0行首行级
$行尾行级
^首个非空字符行级
gg文档开头文档级
G文档末尾文档级

3. operators.ts — 操作符(556 行)

操作说明
d删除dw 删除一个词
c修改cw 修改一个词(进入 INSERT)
y复制yw 复制一个词
p粘贴粘贴寄存器内容
x删除字符删除光标下字符

4. textObjects.ts — 文本对象(186 行)

对象说明
iw内部词不含周围空格
aw一个词含周围空格
i"引号内双引号内容
a"含引号含双引号本身
i(括号内圆括号内容
a(含括号含圆括号本身

5. transitions.ts — 状态转换(490 行)

这是一个完整的状态机实现,处理 NORMAL 模式下 11 种 CommandState 之间的转换。

INSERT 模式
  └── Escape → NORMAL (idle)

NORMAL 模式 (CommandState 状态机)
  idle
    ├── i/a/o/A/I/O/s/S/C → INSERT
    ├── 数字 → count
    ├── d/c/y → operator
    ├── f/F/t/T → find
    ├── g → g
    ├── r → replace
    ├── >/<  → indent
    └── h/l/w/b/e/0/$... → 执行 motion

  count
    ├── 数字 → count (追加)
    └── 操作符/motion → 带 count 执行

  operator
    ├── 数字 → operatorCount
    ├── f/F/t/T → operatorFind
    ├── i/a → operatorTextObj
    ├── g → operatorG
    └── motion → 执行 operator+motion

注意:不存在 Visual 模式和 Command 模式。Vim 实现仅覆盖 INSERT 和 NORMAL 两种模式。


设计说明

  • Vim 模式仅作用于 PromptInput 输入框,不影响对话记录的浏览
  • 使用 discriminated union 实现类型安全的状态机
  • CommandState 的 11 种状态确保了 TypeScript 的穷举检查
  • PersistentState 支持 dot-repeat(. 重复上次操作)和寄存器
  • 初始状态为 INSERT 模式(与传统 Vim 不同,因为终端输入框默认需要输入)

26 - voice 模块源码分析

路径: src/voice/ 文件数: 1 个 功能: 语音模式 — 语音输入/输出支持


voiceModeEnabled.ts

行数: 55 行

导出

  • isVoiceGrowthBookEnabled() — GrowthBook kill-switch 检查
  • hasVoiceAuth() — OAuth 认证检查(需要 claude.ai 账户)
  • isVoiceModeEnabled() — 综合启用检查

启用条件

function isVoiceModeEnabled(): boolean {
  // 两个条件都必须满足
  return isVoiceGrowthBookEnabled()  // 1. GrowthBook 特性标志开启
    && hasVoiceAuth()                // 2. 有 claude.ai OAuth 认证
}

语音流连接

  • 端点: claude.ai 的 voice_stream
  • 认证: OAuth Bearer Token
  • 协议: WebSocket 双向流
  • Kill-switch: GrowthBook 可随时关闭

与 REPL 的集成

语音模式在 screens/REPL.tsx 中条件加载:

// REPL.tsx 中
if (isVoiceModeEnabled()) {
  const { VoiceInput } = await import('../voice/VoiceInput')
  // 渲染语音输入组件
}

语音输入转换为文本后,走和键盘输入相同的消息处理流程。

27 - buddy 模块源码分析

路径: src/buddy/ 文件数: 6 个(含 CompanionSprite.tsx) 功能: 伴侣系统 — 虚拟宠物彩蛋(teaser 窗口 2026 年 4 月 1-7 日,命令在之后持续可用)


模块概述

buddy/ 是一个有趣的彩蛋模块,实现了一个虚拟伴侣(宠物)系统。使用种子随机数生成器确保确定性,基于稀有度的抽卡机制,以及 ASCII 艺术精灵动画。仅在 2026 年 4 月 1-7 日期间激活。


文件详解

1. types.ts — 类型定义

行数: 149 行

稀有度权重

const RARITY_WEIGHTS = {
  common:    0.60,  // 60% — 普通
  uncommon:  0.25,  // 25% — 不常见
  rare:      0.10,  // 10% — 稀有
  epic:      0.04,  //  4% — 史诗
  legendary: 0.01,  //  1% — 传说
}

物种列表

// 使用 String.fromCharCode 编码物种名称
// 避免模型代号碰撞(AI 模型可能以动物命名)
const SPECIES = [
  String.fromCharCode(99, 97, 116),        // "cat"
  String.fromCharCode(100, 111, 103),       // "dog"
  String.fromCharCode(102, 111, 120),       // "fox"
  // ... 共 18 种物种
]

设计亮点: 使用 String.fromCharCode 而非字符串字面量,防止代码中出现的动物名称被误认为是 AI 模型代号。


2. companion.ts — 伴侣生成核心

行数: 134 行

Mulberry32 伪随机数生成器

// 种子确定性 PRNG — 相同种子总是生成相同伴侣
function mulberry32(seed: number): () => number {
  return function() {
    seed |= 0
    seed = seed + 0x6D2B79F5 | 0
    let t = Math.imul(seed ^ seed >>> 15, 1 | seed)
    t = t + Math.imul(t ^ t >>> 7, 61 | t) ^ t
    return ((t ^ t >>> 14) >>> 0) / 4294967296
  }
}

稀有度抽卡

// 累积分布函数抽卡
function rollRarity(rng: () => number): Rarity {
  const roll = rng()
  let cumulative = 0
  for (const [rarity, weight] of Object.entries(RARITY_WEIGHTS)) {
    cumulative += weight
    if (roll <= cumulative) return rarity as Rarity
  }
  return 'common' // 兜底
}

伴侣生成

function generateCompanion(sessionId: string): Companion {
  // 用 sessionId 作为种子 → 同一会话总是同一伴侣
  const seed = hashString(sessionId)
  const rng = mulberry32(seed)

  const rarity = rollRarity(rng)
  const species = SPECIES[Math.floor(rng() * SPECIES.length)]
  const name = generateName(rng)

  return { species, rarity, name, seed }
}

3. sprites.ts — ASCII 艺术精灵

行数: 515 行

功能

为 18 种物种提供 ASCII 艺术,每种有 3 帧动画。

精灵格式

// 每个精灵: 5 行 × 12 字符宽 × 3 动画帧
type Sprite = {
  frames: [string[], string[], string[]]  // 3 帧
  // 每帧 5 行
}

// 示例 (cat):
const catSprite = {
  frames: [
    // 帧 1
    [
      '  /\\_/\\    ',
      ' ( o.o )   ',
      '  > ^ <    ',
      ' /|   |\\   ',
      '(_|   |_)  ',
    ],
    // 帧 2 (微动)
    [
      '  /\\_/\\    ',
      ' ( o.o )   ',
      '  > ^ <    ',
      ' /|   |\\   ',
      '(_|   |_)  ',
    ],
    // 帧 3
    // ...
  ]
}

4. prompt.ts — 介绍文本

行数: 37 行

function companionIntroText(companion: Companion): string {
  return `
## 🎉 你获得了一个伴侣!

**${companion.name}** (${companion.species})
稀有度: ${formatRarity(companion.rarity)}

${renderSprite(companion.species, 0)}
  `.trim()
}

5. useBuddyNotification.tsx — React Hook

行数: 97 行

功能

React Hook,区分 teaser 窗口和 live 状态:

  • isBuddyTeaserWindow() — 仅 2026 年 4 月 1-7 日为 true(本地时间,非 UTC)
  • isBuddyLive() — 2026 年 4 月之后持续为 true

useBuddyNotification() 只负责显示 /buddy 彩虹文字 teaser 通知(15 秒超时),不负责直接生成 companion 卡片。Companion 的空闲展示和反应由 CompanionSprite.tsx 处理。

// teaser 窗口: 2026-04-01 到 2026-04-07(本地时间)
export function isBuddyTeaserWindow(): boolean {
  const d = new Date()
  return d.getFullYear() === 2026 && d.getMonth() === 3 && d.getDate() <= 7
}

// live: 2026 年 4 月之后永久生效
export function isBuddyLive(): boolean {
  const d = new Date()
  return d.getFullYear() > 2026 || (d.getFullYear() === 2026 && d.getMonth() >= 3)
}

6. CompanionSprite.tsx — 伴侣精灵组件

React 组件,负责伴侣的空闲展示和动画反应。在 isBuddyLive() 为 true 时渲染。


设计亮点

  1. 确定性随机: Mulberry32 PRNG 确保相同会话总是生成相同伴侣
  2. 反碰撞编码: String.fromCharCode 避免动物名称与 AI 模型代号冲突
  3. 限时彩蛋: 仅在愚人节期间激活,不影响正常使用
  4. 抽卡机制: 累积分布函数实现的稀有度系统,1% 传说概率

28 - utils 模块源码分析

路径: src/utils/ 根级文件数: 280+ 个 .ts/.tsx 文件 子目录数: 31 个 功能: 工具函数库 — 覆盖项目所有基础设施需求


模块概述

utils/ 是 Claude Code 中文件数量最多的模块,包含 280+ 个根级工具文件和 31 个子目录。


根级核心文件(按功能分类,仅列出已验证存在的文件)

Shell 与进程

文件说明
Shell.tsShell 抽象层(exec/execStream/which)
ShellCommand.tsShell 命令封装
execFileNoThrow.ts不抛异常的 execFile
process.ts进程工具
genericProcessUtils.ts通用进程工具
gracefulShutdown.ts优雅关闭
cleanupRegistry.ts清理注册表(进程退出时资源释放)

Git 操作

文件说明
git.tsGit 核心操作(status/branch/commit 等)
gitDiff.tsGit Diff 处理
gitSettings.tsGit 配置
worktree.tsGit Worktree 管理
getWorktreePaths.tsWorktree 路径获取
detectRepository.ts仓库检测
ghPrStatus.tsGitHub PR 状态
commitAttribution.ts提交归因

认证与安全

文件说明
auth.ts认证核心
authFileDescriptor.ts认证文件描述符
authPortable.ts可移植认证
aws.tsAWS 集成
awsAuthStatusManager.tsAWS 认证状态
crypto.ts加密工具
mtls.tsmTLS 配置

文件操作

文件说明
file.ts文件基础操作
fileRead.ts文件读取(多格式支持)
fileReadCache.ts文件读取缓存
fileHistory.ts文件历史追踪
fileStateCache.ts文件状态缓存
fileOperationAnalytics.ts文件操作分析
readFileInRange.ts范围读取
diff.ts差异计算
pdf.ts / pdfUtils.tsPDF 处理
notebook.tsJupyter Notebook 处理

会话管理

文件说明
sessionStorage.ts会话持久化
sessionRestore.ts会话恢复
sessionState.ts会话状态
sessionTitle.ts会话标题生成
sessionStart.ts会话启动
sessionActivity.ts会话活动追踪
sessionUrl.ts会话 URL
listSessionsImpl.ts会话列表实现
crossProjectResume.ts跨项目恢复

Agent 与 AI

文件说明
agentContext.tsAgent 上下文
agentId.tsAgent ID 管理
agenticSessionSearch.tsAgent 会话搜索
teammate.ts队友管理
teammateContext.ts队友上下文
teammateMailbox.ts队友邮箱
sideQuery.ts侧查询(轻量级 LLM 调用)
sideQuestion.ts侧问题
advisor.ts顾问
effort.ts推理努力级别
fastMode.ts快速模式

消息处理

文件说明
messages.ts消息构建工具
messagePredicates.ts消息谓词(类型判断)
messageQueueManager.ts消息队列管理
contentArray.ts内容数组工具

配置与设置

文件说明
config.ts配置管理
configConstants.ts配置常量
envUtils.ts环境变量工具
claudemd.tsCLAUDE.md 处理
cliArgs.tsCLI 参数解析

钩子系统

文件说明
hooks.ts钩子顶层工具(注意:执行引擎在 utils/hooks/ 子目录)

格式化与显示

文件说明
format.ts通用格式化
intl.ts国际化
markdown.tsMarkdown 处理
truncate.ts文本截断
sliceAnsi.tsANSI 切片
stringUtils.ts字符串工具
hyperlink.ts终端超链接

调试与日志

文件说明
debug.ts调试日志
debugFilter.ts调试过滤
diagLogs.ts诊断日志
log.ts日志
errors.ts错误处理
errorLogSink.ts错误日志接收器

Token 与预算

文件说明
tokenBudget.tsToken 预算管理
tokens.tsToken 工具
modelCost.ts模型费用计算

网络

文件说明
http.tsHTTP 请求
proxy.ts代理配置
caCerts.tsCA 证书
peerAddress.ts对端地址

其他重要文件

文件说明
lazySchema.ts懒加载 Schema(打破循环依赖)
memoize.ts缓存/记忆化
frontmatterParser.tsFrontmatter 解析
uuid.tsUUID 生成
hash.ts哈希计算
json.tsJSON 工具
sleep.ts延时
cron.ts / cronScheduler.ts / cronTasks.ts定时任务
glob.tsGlob 匹配
ripgrep.tsRipgrep 搜索
platform.ts平台检测
terminal.ts终端工具
theme.ts主题
zodToJsonSchema.tsZod→JSON Schema 转换
xml.ts / yaml.tsXML/YAML 工具

子目录(31 个)

目录说明
hooks/钩子执行引擎(17 文件:execPromptHook、execHttpHook、execAgentHook 等)
permissions/权限规则引擎
settings/设置读写(三层合并:user/project/local)
shell/Shell 提供者(bash/zsh/fish/powershell)
bash/Bash 特定工具
powershell/PowerShell 特定工具
git/Git 扩展操作
github/GitHub API 集成
model/模型工具(别名解析、能力查询)
mcp/MCP 工具
memory/记忆工具
messages/消息工具
skills/技能工具
plugins/插件工具
todo/待办列表工具
task/任务管理工具
swarm/Swarm 模式(多 Agent 协作)
suggestions/提示建议
ultraplan/Ultraplan 工具
sandbox/沙箱工具
computerUse/计算机使用工具
claudeInChrome/Chrome 中的 Claude
teleport/Teleport API 集成
secureStorage/安全存储
filePersistence/文件持久化
background/后台任务(含 remote/ 子目录)
deepLink/深度链接
telemetry/遥测工具
nativeInstaller/原生安装器
dxt/桌面扩展工具
processUserInput/用户输入处理

之前文档中不存在的文件(已删除)

以下文件在 src/utils/不存在,之前文档错误列出:

  • processManager.tskillProcess.ts
  • ~~gitWorktreeworktree.ts`)、gitBlame.tsgitLog.ts
  • fileWrite.tsfileDiff.ts(实际是 diff.ts
  • messageFormat.tsmessageSearch.ts
  • permissionRules.tspermissionMode.ts(在 utils/permissions/ 子目录中)
  • hookRunner.tshookContext.ts(在 utils/hooks/ 子目录中)
  • logForDebugging.ts(实际是 debug.ts)、profiling.ts
  • tokenCount.tstokenEstimate.ts(实际是 tokens.ts
  • websocket.tsretry.ts(API 重试在 services/api/withRetry.ts

utils 模块 — 31 个工具子目录分类

路径: src/utils/ 子目录数: 31 个 根级文件数: 280+ 总文件数: 500+


子目录清单(按功能分类)

Shell 与进程

目录说明
shell/Shell 提供者(bash/zsh/fish/powershell 多 Shell 支持)
bash/Bash 特定工具(命令解析、安全检查)
powershell/PowerShell 特定工具

Git 与版本控制

目录说明
git/Git 核心操作(status/branch/commit/diff/worktree/blame)
github/GitHub API 集成(PR/Issue/App 安装)

认证与安全

目录说明
teleport/Teleport API 集成(OAuth API 调用)
secureStorage/安全存储(令牌加密存储)
permissions/权限规则引擎

文件与持久化

目录说明
filePersistence/文件持久化(原子写入、锁文件)

消息与对话

目录说明
messages/消息构建、格式化、搜索、压缩辅助
processUserInput/用户输入处理(解析、验证)

AI 与 Agent

目录说明
swarm/Swarm 模式(多 Agent 协作)
memory/记忆工具(记忆文件读写)
suggestions/提示建议生成
ultraplan/Ultraplan 工具(超级计划模式)

配置与设置

目录说明
settings/设置读写(三层合并:user/project/local)
hooks/钩子执行引擎和运行器
skills/技能工具(加载、解析)
plugins/插件工具(加载、验证)

MCP 与工具

目录说明
mcp/MCP 工具(客户端辅助、消息转换)
todo/待办列表工具
task/任务管理工具

网络与通信

目录说明
background/后台任务(含 remote/ 子目录)
deepLink/深度链接处理

遥测与分析

目录说明
telemetry/遥测工具(OpenTelemetry 辅助)

模型与 AI

目录说明
model/模型工具(别名解析、能力查询)

安装与更新

目录说明
nativeInstaller/原生安装器(桌面应用安装)
dxt/DXT 工具(桌面扩展)

特殊功能

目录说明
sandbox/沙箱工具(环境隔离)
computerUse/计算机使用工具(屏幕操作)
claudeInChrome/Chrome 中的 Claude 工具

根级核心文件(精选)

文件说明
Shell.tsShell 抽象层(exec/execStream/which)
ShellCommand.tsShell 命令封装
auth.ts认证核心
config.ts配置管理
envUtils.ts环境变量工具(isEnvTruthy 等)
debug.ts调试日志
format.ts通用格式化
lazySchema.ts懒加载 Schema(打破循环依赖)
memoize.ts缓存/记忆化
retry.ts重试逻辑
frontmatterParser.tsFrontmatter 解析
sessionStorage.ts会话持久化
sessionRestore.ts会话恢复
fileRead.ts文件读取(多格式)
fileHistory.ts文件历史追踪
tokenBudget.tsToken 预算管理
proxy.ts代理配置
mtls.tsmTLS 配置
cleanupRegistry.ts清理注册表(进程退出时资源释放)
agentContext.tsAgent 上下文
teammate.ts队友管理
sideQuery.ts侧查询(轻量级 LLM 调用)

29 - native-ts 模块源码分析

路径: src/native-ts/ 文件数: ~10 个 功能: 纯 TypeScript 原生实现 — 文件索引、Yoga 布局引擎、颜色 Diff


模块概述

native-ts/ 包含三个高性能的纯 TypeScript 实现,替代了原本需要原生 C/C++ 绑定的功能。这种设计选择优先考虑可移植性和零依赖安装体验。


1. file-index/ — 模糊文件搜索引擎

index.ts (370 行)

功能概述

实现 nucleo 风格的模糊文件搜索,使用位图过滤实现 O(1) 快速拒绝,支持边界/驼峰加分和间隔惩罚。

导出

  • FileIndex

核心算法

class FileIndex {
  private files: string[]
  private bitmaps: Uint32Array[]  // 每个文件的字符位图

  constructor(files: string[]) {
    this.files = files
    // 预计算每个文件的字符位图
    this.bitmaps = files.map(f => computeBitmap(f))
  }

  search(query: string, topK: number = 20): SearchResult[] {
    const queryBitmap = computeBitmap(query)

    const results: SearchResult[] = []
    for (let i = 0; i < this.files.length; i++) {
      // Phase 1: 位图快速拒绝 — O(1)
      // 如果查询中的字符不全在文件名中出现,直接跳过
      if ((queryBitmap & ~this.bitmaps[i]) !== 0) continue

      // Phase 2: 融合 indexOf 扫描
      const score = this.computeScore(query, this.files[i])
      if (score > 0) {
        results.push({ file: this.files[i], score })
      }
    }

    // Top-K 堆维护
    return topKHeap(results, topK)
  }
}

评分规则

评分语义:分数越低越好(lower = better)。分数是 position-in-results / result-count,最佳匹配为 0.0。包含 “test” 的路径有 1.05× 惩罚(上限 1.0),使非测试文件排名略高。

内部使用 nucleo 风格的评分常量:

常量说明
SCORE_MATCH16基础匹配分
BONUS_BOUNDARY+8单词边界匹配
BONUS_CAMEL+6驼峰位置匹配
BONUS_CONSECUTIVE+4连续字符匹配
BONUS_FIRST_CHAR+8首字符匹配
PENALTY_GAP_START-3间隔惩罚

智能大小写

// 全小写查询 → 大小写不敏感
// 包含大写 → 大小写敏感
const caseSensitive = query !== query.toLowerCase()

2. color-diff/ — 语法高亮差异

index.ts (999 行)

功能概述

实现带语法高亮的代码差异显示,使用懒加载的 highlight.js 避免 50MB+ 的包体积。

导出

  • ColorDiff

核心架构

ColorDiff
├── 懒加载 highlight.js(避免 50MB 包体积)
├── 词级别差异(word-level diffing)
├── ANSI 颜色渲染
│   ├── truecolor 模式(24-bit)
│   ├── color256 模式(8-bit)
│   └── ansi 模式(16 色)
└── 行级别 + 词级别混合差异

懒加载策略

class ColorDiff {
  private hljs: HighlightJS | null = null

  private async getHighlighter(): Promise<HighlightJS> {
    if (!this.hljs) {
      // 动态导入,避免启动时加载 50MB+
      const { default: hljs } = await import('highlight.js')
      this.hljs = hljs
    }
    return this.hljs
  }
}

词级别差异

// 不是简单的行级别 diff,而是在行内进一步做词级别 diff
// 这样可以精确高亮行内的具体变更
function wordDiff(oldLine: string, newLine: string): DiffSegment[] {
  const oldWords = tokenize(oldLine)
  const newWords = tokenize(newLine)
  return computeLCS(oldWords, newWords) // 最长公共子序列
}

3. yoga-layout/ — Flexbox 布局引擎

enums.ts (134 行)

功能概述

定义 Yoga 布局引擎的枚举常量,使用 const 对象而非 TypeScript enum 以支持 tree-shaking。

// 使用 const 对象而非 enum,支持 tree-shaking
export const Align = {
  Auto: 0,
  FlexStart: 1,
  Center: 2,
  FlexEnd: 3,
  Stretch: 4,
  Baseline: 5,
  SpaceBetween: 6,
  SpaceAround: 7,
  SpaceEvenly: 8,
} as const

export const Edge = {
  Left: 0,
  Top: 1,
  Right: 2,
  Bottom: 3,
  Start: 4,
  End: 5,
  Horizontal: 6,
  Vertical: 7,
  All: 8,
} as const

export const FlexDirection = {
  Column: 0,
  ColumnReverse: 1,
  Row: 2,
  RowReverse: 3,
} as const

// Display, Justify, Overflow, Position, Wrap 等...

index.ts (2578 行)

功能概述

Yoga Flexbox 布局引擎的简化 TypeScript 移植,覆盖 Ink 实际使用的子集,不是完整的 Meta Yoga 全量移植。源码注释明确说明:“simplified single-pass flexbox implementation that covers the subset of features Ink actually uses”。

核心特性

class Node {
  // 脏标志系统 — 只重新计算变更的节点
  private isDirty: boolean = true

  // 4 条目布局缓存 — 避免重复计算
  private layoutCache: LayoutCache = new Array(4)

  // 9 边模型折叠为 4 物理边
  // Edge: Left, Top, Right, Bottom, Start, End, Horizontal, Vertical, All
  // → 物理: left, top, right, bottom
  private resolveEdge(edge: Edge): PhysicalEdge

  // Flexbox 布局计算
  calculateLayout(
    availableWidth: number,
    availableHeight: number,
    direction: Direction
  void
}

Value 类型

type Value = {
  value: number
  unit: 'point' | 'percent' | 'auto' | 'undefined'
}

function resolveValue(value: Value, parentSize: number): number {
  switch (value.unit) {
    case 'point': return value.value
    case 'percent': return value.value / 100 * parentSize
    case 'auto': return NaN  // 由布局算法决定
    case 'undefined': return NaN
  }
}

布局算法核心

calculateLayout(node, availableWidth, availableHeight)
  │
  ├── 检查缓存(4 条目)
  │   └── 命中 → 直接返回
  │
  ├── 解析 margin, padding, border
  │
  ├── 确定主轴和交叉轴
  │   ├── row → 主轴=水平, 交叉轴=垂直
  │   └── column → 主轴=垂直, 交叉轴=水平
  │
  ├── 测量子节点
  │   ├── 固定尺寸子节点 → 直接使用
  │   ├── flex 子节点 → 按 flex-grow/shrink 分配
  │   └── auto 子节点 → 递归计算
  │
  ├── 主轴布局
  │   ├── justify-content 对齐
  │   └── 分配剩余空间
  │
  ├── 交叉轴布局
  │   ├── align-items 对齐
  │   └── align-self 覆盖
  │
  ├── 写入布局结果
  │   ├── left, top, width, height
  │   └── 递归写入子节点
  │
  └── 更新缓存

设计哲学

  1. 零原生依赖: 纯 TypeScript 实现避免了 node-gyp 编译问题和平台兼容性问题
  2. 懒加载: highlight.js 等重依赖按需加载,不影响启动速度
  3. const 对象 vs enum: 使用 as const 对象替代 TypeScript enum,支持 tree-shaking 减小包体积
  4. 位图优化: 文件索引使用位图实现 O(1) 快速拒绝,大幅减少不必要的字符串比较
  5. 缓存策略: Yoga 布局使用 4 条目缓存 + 脏标志,避免重复计算

30 - memdir 模块源码分析

路径: src/memdir/ 文件数: 8 个 功能: 自动记忆系统 — 跨会话的持久化记忆,支持私有记忆和团队记忆


模块概述

memdir/ 实现了 Claude Code 的自动记忆系统,允许 AI 在会话间保持对用户偏好、项目上下文和反馈的记忆。记忆存储在 ~/.claude/projects/<project>/memory/ 目录中。支持双作用域架构(私有 + 团队),AI 驱动的相关记忆检索,以及多层安全防护。


文件详解

1. paths.ts — 路径管理与特性开关

行数: 279 行

导出

  • isAutoMemoryEnabled() — 检查自动记忆是否启用
  • isExtractModeActive() — 检查后台提取 Agent 是否激活
  • getMemoryBaseDir() — 获取记忆基础目录
  • getAutoMemPath() — 获取自动记忆目录路径(memoized)
  • getAutoMemDailyLogPath(date?) — 获取 KAIROS 模式的每日日志路径
  • getAutoMemEntrypoint() — 获取 MEMORY.md 路径
  • isAutoMemPath(absolutePath) — 检查路径是否在记忆目录内
  • hasAutoMemPathOverride() — 检查 Cowork 覆盖是否设置

启用优先级链(5 级)

1. 环境变量 CLAUDE_CODE_DISABLE_AUTO_MEMORY
2. SIMPLE 模式检查
3. CCR 远程环境检查
4. settings.json 中的 autoMemory 设置
5. 默认值: true

路径解析优先级

1. CLAUDE_COWORK_MEMORY_PATH_OVERRIDE 环境变量
2. settings.json 中的 autoMemoryDirectory 设置(支持 ~/ 展开)
3. 计算路径: baseDir + sanitized(git root)

安全验证

function validateMemoryPath(path: string): void {
  // 拒绝: 相对路径、根路径、UNC 路径、null 字节
  if (path.includes('\0')) throw new Error('Null byte in path')
  if (!isAbsolute(path)) throw new Error('Relative path')
  if (path === '/') throw new Error('Root path')
  // ...
}

设计亮点

  • Worktree 共享: 使用 canonical git root,所以 worktree 共享同一份记忆
  • 安全边界: projectSettings 不允许设置路径覆盖(防止恶意项目配置)

2. memoryTypes.ts — 记忆类型分类学

行数: 272 行

四种记忆类型

类型作用域说明示例
user始终私有用户角色、偏好、知识“用户是高级 Go 开发者,React 新手”
feedback默认私有用户对工作方式的反馈“不要在回复末尾总结”
project偏向团队项目进展、目标、截止日期“3月5日起冻结非关键合并”
reference通常团队外部系统资源指针“Bug 追踪在 Linear INGEST 项目”

不应保存的内容

  • 代码模式/架构(可从代码推导)
  • Git 历史(git log 可查)
  • 调试解决方案(修复在代码中)
  • CLAUDE.md 中已有的内容
  • 临时任务详情

导出的提示词模板

  • TYPES_SECTION_COMBINED — 带 <scope> 标签的双目录版本
  • TYPES_SECTION_INDIVIDUAL — 单目录版本
  • WHAT_NOT_TO_SAVE_SECTION — 排除指导
  • MEMORY_DRIFT_CAVEAT — 过期警告文本
  • WHEN_TO_ACCESS_SECTION — 访问时机指导
  • TRUSTING_RECALL_SECTION — 召回信任指导
  • MEMORY_FRONTMATTER_EXAMPLE — frontmatter 格式示例

3. memdir.ts — 记忆系统主编排器

行数: 508 行

导出

  • ENTRYPOINT_NAME = 'MEMORY.md'
  • MAX_ENTRYPOINT_LINES = 200
  • MAX_ENTRYPOINT_BYTES = 25600 (25KB)
  • truncateEntrypointContent() — 强制大小限制
  • ensureMemoryDirExists() — 创建目录结构
  • buildMemoryLines() — 构建提示词行
  • buildMemoryPrompt() — 构建完整提示词
  • loadMemoryPrompt() — 主入口,按特性分发

特性分发逻辑

loadMemoryPrompt()
  ├── KAIROS 模式? → 每日追加日志模式
  ├── TEAMMEM 启用? → 双目录联合提示词
  └── 默认 → 单目录个人提示词

MEMORY.md 截断

function truncateEntrypointContent(content: string, filePath: string) {
  // 强制 200 行 AND 25KB 上限
  // 超出时添加警告横幅
  ifth > MAX_ENTRYPOINT_LINES) {
    return {
      content: lines.slice(0, MAX_ENTRYPOINT_LINES).join('\n'),
      truncation: { originalLines: lines.length, keptLines: MAX_ENTRYPOINT_LINES }
    }
  }
}

遥测日志

  • memory_directory_used — 记忆目录被使用
  • memory_directory_created — 记忆目录被创建
  • memory_entrypoint_truncated — MEMORY.md 被截断

4. memoryScan.ts — 记忆目录扫描

行数: 95 行

导出

  • MemoryHeader 类型 — { filename, filePath, mtimeMs, description, type }
  • scanMemoryFiles(memoryDir, signal) — 扫描记忆文件头
  • formatMemoryManifest(memories) — 格式化为文本清单

扫描优化

async function scanMemoryFiles(memoryDir: string): Promise<MemoryHeader[]> {
  // 递归读取目录
  const entries = await readdir(memoryDir, { recursive: true })

  // 过滤 .md 文件,排除 MEMORY.md
  const mdFiles = entries.filter(e => e.endsWith('.md') && e !== 'MEMORY.md')

  // 只读取每个文件的前 30 行(frontmatter)
  // readFileInRange 内部 stat 返回 mtimeMs,避免二次 stat
  const headers = await Promise.allSettled(
    mdFiles.map(f => readFirstLines(f, 30))
  )

  // 按修改时间降序排序,取前 200 个
  return headers
    .filter(h => h.status === 'fulfilled')
    .sort((a, b) => b.mtimeMs - a.mtimeMs)
    .slice(0, 200)
}

清单格式

- [user] user_role.md (2026-03-15): 数据科学家,关注可观测性
- [feedback] feedback_testing.md (2026-03-10): 集成测试必须用真实数据库

5. findRelevantMemories.ts — AI 驱动的记忆检索

行数: 142 行

导出

  • RelevantMemory 类型 — { filePath, mtimeMs }
  • findRelevantMemories(memoryDir, conversationText, alreadySurfaced, signal) — 检索相关记忆

核心流程

扫描记忆目录 (scanMemoryFiles)
    ↓
过滤已展示的记忆 + 活跃工具的参考文档
    ↓
格式化为文本清单
    ↓
调用 Sonnet 模型 (sideQuery)
    ├── 系统提示: SELECT_MEMORIES_SYSTEM_PROMPT
    ├── 用户消息: 对话文本 + 记忆清单
    └── 输出格式: JSON Schema (最多 5 个文件名)
    ↓
映射文件名回完整路径 + mtime
    ↓
返回 Rey[]

错误处理

  • 失败时返回空数组(不抛异常)
  • 优雅降级,不影响主对话流程

6. memoryAge.ts — 记忆时效性

行数: 54 行

导出

  • memoryAgeDays(mtimeMs) — 计算天数
  • memoryAge(mtimeMs) — 人类可读的年龄(“today”/“yesterday”/“N days ago”)
  • memoryFreshnessText(mtimeMs) — 过期警告文本
  • memoryFreshnessNote(mtimeMs) — 格式化的过期注释

逻辑

// ≤1 天: 无警告
// >1 天: "This memory is from [age] and may be outdated"
// 防止模型将过期的代码引用当作当前事实

7. teamMemPaths.ts — 团队记忆路径(安全加固)

行数: 293 行

导出

  • PathTraversalError — 自定义错误类
  • isTeamMemoryEnabled() — 团队记忆是否启用
  • getTeamMemPath() — 团队记忆目录路径
  • validateTeamMemWritePath(filePath) — 写入路径验证
  • validateTeamMemKey(relativeKey) — 服务器提供的 key 验证
  • isTeamMemFile(filePath) — 综合检查

多层安全防护(PSR M22186)

第 1 层: 字符串级别
  ├── 拒绝 null 字节
  ├── 拒绝 URL 编码遍历 (%2e%2e%2f)
  ├── 拒绝 Unicode 规范化攻击(全角字符)
  ├── 拒绝反斜杠
  └── 拒绝绝对路径

第 2 层: 符号链接解析
  ├── realpathDeepestExisting() 向上遍历解析
  ├── 检测悬空符号链接 (lstat)
  └── 真实路径包含性检查

启用条件

function isTeamMemoryEnabled(): boolean {
  return isAutoMemoryEnabled()                    // 自动记忆已启用
    && checkFeatureFlag('tengu_herring_clock')     // 特性标志
}

8. teamMemPrompts.ts — 团队记忆提示词构建

行数: 101 行

导出

  • buildCombinedMemoryPrompt() — 构建双目录联合提示词

提示词结构

1. 双目录说明(私有 vs 团队)
2. 作用域指导(私有: 用户特定, 团队: 共享)
3. 类型分类(带 <scope> 标签)
4. 排除指导 + 团队记忆安全警告
5. 保存方法(两步: 写文件 + 更新 MEMORY.md 索引)
6. 访问时机
7. 记忆 vs 其他持久化(计划、任务)
8. 搜索过往上下文(grep 指导)

架构总结

memdir/
├── 配置层
│   ├── paths.ts          ← 路径解析 + 特性开关(5 级优先级)
│   └── memoryTypes.ts    ← 类型分类学 + 提示词模板
│
├── 核心层
│   ├── memdir.ts         ← 主编排器(特性分发 + 提示词构建)
│   ├── memoryScan.ts     ← 目录扫描(前 30 行 frontmatter)
│   └── findRelevantMemories.ts ← AI 驱动的相关性检索(Sonnet)
│
├── 安全层
│   ├── teamMemPaths.ts   ← 多层路径遍历防护(PSR M22│   └── memoryAge.ts      ← 时效性警告(防止过期引用)
│
└── 团队层
    └── teamMemPrompts.ts ← 双目录联合提示词构建

关键设计决策

  1. 双作用域: 私有记忆(用户偏好)和团队记忆(项目知识)分离
  2. AI 检索: 使用 Sonnet 模型智能选择相关记忆,而非全量加载
  3. 安全加固: 多层路径遍历防护,防止恶意项目配置攻击
  4. Worktree 共享: 使用 canonical git root,worktree 共享记忆
  5. 优雅降级: 所有错误返回空结果,不影响主流程
  6. 大小限制: MEMORY.md 强制 200 行 / 25KB 上限

31 - migrations 模块源码分析

路径: src/migrations/ 文件数: 11 个 功能: 配置迁移 — 跨版本的配置格式升级,确保向后兼容


模块概述

migrations/ 处理 Claude Code 跨版本升级时的配置格式迁移。每个迁移文件是一个幂等函数,在应用启动时按需执行。迁移覆盖了从权限配置、模型别名到 MCP 服务器审批等多个领域。


迁移文件详解

1. migrateAutoUpdatesToSettings.ts

行数: 62 行

功能

将自动更新偏好从全局配置迁移到 settings.json 环境变量。

迁移逻辑

旧: globalConfig.autoUpdates = false
新: settings.json → env.DISABLE_AUTOUPDATER = '1'

步骤

  1. 检查 autoUpdates 是否显式为 false
  2. 读取用户设置,添加 DISABLE_AUTOUPDATER: '1' 到 env
  3. 立即设置 process.env 使其即时生效
  4. 从全局配置中删除 autoUpdatesautoUpdatesProtectedForNative
  5. 记录分析事件

2. migrateBypassPermissionsAcceptedToSettings.ts

行数: 41 行

功能

将权限绕过接受标志从全局配置迁移到 settings.json。

旧: globalConfig.bypassPermissionsModeAccepted = true
新: settings.json → skipDangerousModePermissionPrompt: true

3. migrateEnableAllProjectMcpServersToSettings.ts

行数: 119 行

功能

将 MCP 服务器审批字段从项目配置迁移到本地设置。

迁移字段

旧字段新位置
enableAllProjectMcpServerslocal settings
enabledMcpjsonServerslocal settings(数组合并去重)
disabledMcpjsonServerslocal settings(数组合并去重)

特殊处理

  • 数组字段使用合并去重策略,避免覆盖已有配置
  • 记录迁移数量到分析事件

4. migrateFennecToOpus.ts

行数: 46 行

功能

将已移除的 fennec 模型别名迁移到 Opus 4.6 别名(仅内部用户)。

映射规则

fennec-latest[1m]     → opus[1m]
fennec-latest         → opus
fennec-fast-latest    → opus[1m] + fastMode: true
opus-4-5-fast         → opus[1m] + fastMode: true

条件

  • USER_TYPE === 'ant'(Anthropic 内部用户)

5. migrateLegacyOpusToCurrent.ts

行数: 58 行

功能

将第一方用户从显式 Opus 4.0/4.1 版本字符串迁移到 ‘opus’ 别名(解析为 4.6)。

匹配的旧值

claude-opus-4-20250514
claude-opus-4-1-20250805
claude-opus-4-0
claude-opus-4-1

迁移结果

所有上述值 → model: 'opus'

条件

  • 仅 firstParty API 提供者
  • 仅启用了 legacy remap 的用户

6. migrateOpusToOpus1m.ts

行数: 44 行

功能

将符合条件的用户(Max/Team Premium)从 ‘opus’ 迁移到 ‘opus[1m]’,用于合并的 Opus 1M 体验。

条件

  • Opus 1M 合并已启用
  • 用户设置的模型恰好是 ‘opus’
  • Pro 订阅者和第三方用户跳过

7. migrateReplBridgeEnabledToRemoteControlAtStartup.ts

行数: 23 行(最小的迁移)

功能

重命名配置键。

旧: globalConfig.replBridgeEnabled
新: globalConfig.remoteControlAtStartup

特殊处理

  • 使用 untyped cast 访问旧键(已从类型定义中移除)
  • 仅在旧键存在且新键不存在时迁移

8. migrateSonnet1mToSonnet45.ts

行数: 49 行

功能

将 ‘sonnet[1m]’ 用户固定到显式版本 ‘sonnet-4-5-20250929[1m]’(因为 ‘sonnet’ 现在解析为 4.6)。

迁移逻辑

sonnet[1m] → sonnet-4-5-20250929[1m]

特殊处理

  • 同时迁移内存中的模型覆盖(getMainLoopModelOverride
  • 使用完成标志 sonnet1m45MigrationComplete 防止重复执行

9. migrateSonnet45ToSonnet46.ts

行数: 68 行

功能

将 Pro/Max/Team Premium 用户从显式 Sonnet 4.5 字符串迁移到 ‘sonnet’ 别名(现在是 4.6)。

匹配的旧值

claude-sonnet-4-5-20250929      → sonnet
claude-sonnet-4-5-20250929[1m]  → sonnet[1m]
sonnet-4-5-20250929             → sonnet
sonnet-4-5-20250929[1m]         → sonnet[1m]

条件

  • 仅 firstParty Pro/Max/Team Premium 订阅者
  • 新用户(numStartups ≤ 1)跳过通知

10. resetAutoModeOptInForDefaultOffer.ts

行数: 52 行

功能

一次性迁移:为接受了旧对话框但默认模式不是 ‘auto’ 的用户清除 skipAutoPermissionPrompt

条件

  • TRANSCRIPT_CLASSIFIER 特性已启用
  • 自动模式状态为 ‘enabled’
  • 用户有 skipAutoPermissionPrompt 但默认模式不是 ‘auto’

11. resetProToOpusDefault.ts

行数: 52 行

功能

自动将 Pro 用户迁移到 Opus 4.5 默认模型。

逻辑

  • 无自定义模型设置 → 保存 opusProMigrationTimestamp(用于通知)
  • 有自定义模型设置 → 仅标记迁移完成

通用模式

1. 幂等性保证

// 大多数迁移使用完成标志
const config = getGlobalConfig()
if (config.migrationXComplete) return  // 已执行过,跳过

// ... 执行迁移 ...

saveGlobalConfig({ ...config, migrationXComplete: true })

2. 条件执行

// 按用户类型、订阅、API 提供者过滤
if (getAPIProvider() !== 'firstParty') return
if (!isProSubscriber()) return

3. 分析追踪

// 所有迁移记录分析事件
logEvent('migration_x_completed', { originalModel, newModel })
logEvent('migration_x_error', { error: e.message })

4. 错误处理

try {
  // 迁移逻辑
} catch (e) {
  logError('Migration failed', e)
  // 不抛出 — 迁移失败不应阻止应用启动
}

迁移执行时机

应用启动 (setup.ts)
    ↓
按顺序检查每个迁移
    ├── 检查完成标志
    ├── 检查前置条件(用户类型、订阅等)
    └── 执行迁移(如需要)
    ↓
所有迁移完成
    ↓
继续正常启动流程

32 - tasks 模块源码分析

路径: src/tasks/ 文件数: 12 个 功能: 后台任务管理 — 7 种任务类型的完整生命周期管理


模块概述

tasks/ 实现了 Claude Code 的后台任务系统,使用 discriminated union 架构统一管理 7 种任务类型。每种任务类型有独立的状态接口、类型守卫、React 组件和生命周期函数。


架构总览

TaskState (discriminated union)
├── LocalShellTask      — 本地 Shell 命令 (type: 'local_bash')
├── LocalAgentTask      — 本地子 Agent (type: 'local_agent')
├── RemoteAgentTask     — 远程 Agent (type: 'remote_agent')
├── InProcessTeammate   — 进程内队友 (type: 'in_process_teammate')
├── LocalMainSession    — 本地主会话后台化 (type: 'local_main_session')
├── DreamTask           — 后台推理/记忆整合 (type: 'dream')
└── MonitorMcpTask      — MCP 监控 (type: 'monitor_mcp')

核心文件

1. types.ts — 类型统一

行数: 47 行

// 所有任务类型的 discriminated union
type TaskState =
  | LocalShellTaskState
  | LocalAgentTaskState
  | RemoteAgentTaskState
  | InProcessTeammateTaskState
  | LocalMainSessionTaskState
  | DreamTaskState
  | MonitorMcpTaskState

// 后台任务(运行中或待处理 + 已后台化)
type BackgroundTaskState = TaskState

function isBackgroundTask(task: TaskState): boolean {
  return (task.status === 'running' || task.status === 'pending')
    && task.isBackgrounded
}

2. stopTask.ts — 任务终止

行数: 101 行

导出

  • StopTaskError — 自定义错误类
  • stopTask(appState, taskId) — 通用任务终止函数

逻辑

async function stopTask(appState: AppState, taskId: string): Promise<void> {
  // 1. 验证任务存在且正在运行
  const task = findTask(appState, taskId)
  if (!task) throw new StopTaskError('Task not found')
  if (task.status !== 'running') throw new StopTaskError('Task not running')

  // 2. 调用任务特定的 kill 实现
  await task.kill()

  // 3. Shell 任务: 抑制 exit code 137 的噪音通知
  if (isLocalShellTask(task) && task.exitCode === 137) {
    suppressNotification(task)
  }

  // 4. 发送 SDK 事件
  emitTaskTerminatedSdk(task)
}

3. pillLabel.ts — 任务标签 UI

行数: 83 行

功能

为底部状态栏的后台任务药丸标签生成紧凑文本。

// 类型特定标签
"1 shell"       // 1 个 Shell 任务
"2 teams"       // 2 个队友任务
"◇ ultraplan"   // ultraplan 阶段(空心钻石 = 等待输入)
"◆ ultraplan"   // ultraplan 阶段(实心钻石 = 计划就绪)

任务类型详解

4. DreamTask — 后台推理/记忆整合

行数: 158 行

功能

在用户不活跃时,AI 在后台进行记忆整合和推理。

状态

interface DreamTaskState extends TaskStateBase {
  type: 'dream'
  phase: DreamPhase        // 'starting' | 'updating'
  turns: DreamTurn[]       // 最近 30 轮(用于实时显示)
  touchedFiles: string[]   // 通过 Edit/Write 触及的文件
}

生命周期

registerDreamTask()
    ↓
phase: 'starting'
    ↓ (首次工具调用)
phase: 'updating'
    ↓ (追踪 EdWrite 的文件)
addDreamTurn(turn)  // 保留最近 30 轮
    ↓
completeDreamTask() 或 failDreamTask()

清理

注册到 cleanup 系统,通过 AbortController 处理中止。


5. LocalMainSessionTask — 主会话后台化

行数: 480 行

功能

支持用户按 Ctrl+B 两次将当前主会话查询后台化,继续在前台进行新对话。

关键设计

// 任务 ID 使用 's' 前缀(vs Agent 的 'a' 前缀)
const taskId = 's' + generateId()

// 隔离的 transcript 文件,防止 /clear 后损坏
const transcriptFile = createIsolatedTranscript()

生命周期

用户按 Ctrl+B 两次
    ↓
registerMainSessionTask()
    ├── 创建隔离 transcript
    ├── 保存当前消息上下文
    └── 启动后台查询
    ↓
后台运行中...
    ↓
foregroundMainSessionTask()  // 用户选择前台化
    ├── 恢复消息到主对话
    └── 继续交互

6. InProcessTeammateTask — 进程内队友

行数: 122 行 (types) + 126 行 (component)

功能

支持多个 AI Agent 在同一进程内协作(Swarm 模式)。

身份系统

interface TeammateIdentity {
  agentId: AgentId
  agentName: string
  teamName: string
  color: string                // UI 区分颜色
  planModeRequired: boolean    // 是否需要计划模式审批
  parentSessionId: string
}

消息上限

const TEAMMATE_MESSAGES_UI_CAP = 50

// 防止 36.8GB 内存膨胀
function appendCappedMessage(messages: Message[], msg: Message): Message[] {
  if (messages.length >= TEAMMATE_MESSAGES_UI_CAP) {
    return [...messages.slice(1), msg]  // FIFO
  }
  return [...messages, msg]
}

隔离机制

  • 使用 AsyncLocalStorage 实现并发 Agent 隔离
  • 邮箱消息系统用于 Agent 间通信
  • 优雅关闭:处理待处理消息后再停止

7. LocalShellTask — Shell 命令执行

行数: 42 行 (guards) + 77 行 (kill) + 522 行 (component)

卡住检测

const STALL_THRESHOLD = 45_000  // 45 秒
const STALL_CHECK_INTERVAL = 5_000  // 每 5 秒检查

function isShellTaskStalled(task: LocalShellTaskState): boolean {
  // 检测交互式提示模式
  const interactivePatterns = [
    /\(y\/n\)/,
    /\[y\/n\]/,
    /Press any key|Enter password/,
  ]
  return task.lastOutputAge > STALL_THRESHOLD
    || interactivePatterns.some(p => p.test(task.lastOutput))
}

任务种类

type BashTaskKind = 'bash' | 'monitor'

// bash: 标准命令,有完成通知
// monitor: 流式输出,无完成通知(如 tail -f)

僵尸进程清理

// 防止 10 天僵尸进程
function killShellTasksForAgent(agentId: AgentId): void {
  // 终止该 Agent 的所有 Shell 任务
  // 清除排队的通知
  // 驱逐任务输出缓存
}

8. LocalAgentTask — 本地子 Agent

行数: 682 行

功能

管理本地子 Agent 执行,包括进度追踪、消息队列和磁盘输出。

进度追踪

interface ProgressTracker {
  inputTokens: number
  outputTokens: number
  cacheReadTokens: number
  toolActivities: ToolActivity[]  // 工具活动列表
  startTime: number
  lastActivityTime: number
}

interface ToolActivity {
  toolName: string
  description: string
  timestamp: number
}

消息队列

// 后台 Agent 的消息队列
function appendMessageToLocalAgent(taskId: string, message: Message): void
function drainPendingMessages(taskId: string): Message[]

磁盘输出

// 输出写入磁盘文件,带驱逐策略
// 防止内存膨胀
const outputFile = createTempFile(`agent-${taskId}.jsonl`)

9. RemoteAgentTask — 远程 Agent

行数: 855 行(最大的任务文件)

远程任务类型

type RemoteTaskType =
  | 'remote-agent'     // 通用远程 Agent
  | 'ultraplan'        // 超级计划
  | 'ultrareview'      // 超级审查
  | 'autofix-pr'       // 自动修复 PR
  | 'background-pr'    // 后台 PR

前置条件检查

registerRemoteAgentTask()
    ↓
前置条件验证:
  ├── 用户已登录?
  ├── 远程环境可用?
  ├── 在 Git 仓库中?
  ├── 有 GitHub 远程?
  └── GitHub App 已安装?
    ↓
全部通过 → 创建远程会话
任一失败 → 显示错误 + 修复指导

Ultraplan 阶段追踪

// Ultraplan 有特殊的阶段状态
type UltraplanPhase =
  | 'needs_input'   // 等待用户输入(◇ 空心钻石)
  | 'plan_ready'    // 计划就绪(◆ 实心钻石)
  | 'executing'     // 执行中

元数据持久化

// 元数据保存到会话 sidecar 文件
// 支持跨会话恢复远程任务状态
persistMetadata(taskId, { remoteSessionId, status, phase })

通用设计模式

1. TaskStateBase 基础接口

interface TaskStateBase {
  id: string
  type: string
  status: 'pending' | 'running' | 'completed' | 'failed' | 'killed'
  isBackgrounded: boolean
  startTime: number
  endTime?: number
  error?: string
}

2. 每种任务类型的标准导出

// 类型守卫
export function isXxxTask(task: TaskState): task is XxxTaskState

// 生命周期函数
export function registerXxxTask(params): void
export function backgroundXxxTask(taskId): void
export function foregroundXxxTask(taskId): void

// React 组件
export function XxxTask(props): JSX.Element

3. AbortController 取消机制

所有长时间运行的任务都使用 AbortController,支持优雅取消。

4. 清理注册

所有任务注册到 cleanup 系统,确保进程退出时资源被正确释放。


模块依赖关系

tasks/
├── types.ts ← 所有任务状态类型
├── stopTask.ts ← 通用终止逻辑
├── pillLabel.ts ← UI 标签
│
├── DreamTask/ ← 后台推理
├── LocalMainSessionTask/ ← 主会话后台化
├── InProcessTeammateTask/ ← 队友协作
│   ├── types.ts
│   └── InProcessTeammateTask.tsx
├── LocalShellTask/ ← Shell 命令
│   ├── guards.ts
│   ├── killShellTasks.ts
│   LocalShellTask.tsx
├── LocalAgentTask/ ← 本地 Agent
│   └── LocalAgentTask.tsx
└── RemoteAgentTask/ ← 远程 Agent
    └── RemoteAgentTask.tsx

tasks 模块 — 5 个任务类型子目录

路径: src/tasks/ 子目录: DreamTask/, InProcessTeammateTask/, LocalAgentTask/, LocalShellTask/, RemoteAgentTask/


1. DreamTask/ — 后台推理/记忆整合

文件: DreamTask.ts (158 行)

interface DreamTaskState extends TaskStateBase {
  type: 'dream'
  phase: 'starting' | 'updating'
  turns: DreamTurn[]       // 最近 30 轮
  touchedFiles: string[]   // Edit/Write 触及的文件
}

生命周期: registerDreamTask() → phase:starting → 首次工具调用 → phase:updating → completeDreamTask()


2. InProcessTeammateTask/ — 进程内队友协作

文件: types.ts (122 行) + InProcessTeammateTask.tsx (126 行)

interface TeammateIdentity {
  agentId: AgentId
  agentName: string       // 如 "reviewer"
  teamName: string        // 如 "code-review-team"
  color: string           // UI 区分颜色
  planModeRequired: boolean
  parentSessionId: string
}
  • 消息上限 50 条(FIFO,防 36.8GB 内存膨胀)
  • AsyncLocalStorage 实现并发 Agent 隔离
  • 邮箱消息系统用于 Agent 间通信

3. LocalShellTask/ — Shell 命令执行

文件: guards.ts (42 行) + killShellTasks.ts (77 行) + LocalShellTask.tsx (522 行)

type BashTaskKind = 'bash' | 'monitor'
// bash: 标准命令,有完成通知
// monitor: 流式输出,无完成通知(如 tail -f)
  • 卡住检测: 45 秒阈值,每 5 秒检查
  • 交互式提示模式检测: (y/n), [y/n], Press any key, Enter password
  • 僵尸进程清理: killShellTasksForAgent() 防止 10 天僵尸

4. LocalAgentTask/ — 本地子 Agent

文件: LocalAgentTask.tsx (682 行)

interface ProgressTracker {
  inputTokens: number
  outputTokens: number
  toolActivities: ToolActivity[]
  startTime: number
  lastActivityTime: number
}
  • Token 计数(input + output,缓存感知)
  • 消息队列(后台 Agent 的 pending messages)
  • 磁盘输出(JSONL 文件,带驱逐策略)
  • AbortController 取消

5. RemoteAgentTask/ — 远程 Agent(最大,855 行)

文件: RemoteAgentTask.tsx (855 行)

type RemoteTaskType =
  | 'remote-agent'     // 通用远程
  | 'ultraplan'        // 超级计划
  | 'ultrareview'      // 超级审查
  | 'autofix-pr'       // 自动修复 PR
  | 'background-pr'    // 后台 PR

前置条件检查链:

登录? → 远程环境? → Git 仓库? → GitHub 远程? → GitHub App?

Ultraplan 阶段: needs_input(◇) → plan_ready(◆) → executing

元数据持久化到会话 sidecar 文件,支持跨会话恢复。

33 - upstreamproxy 模块源码分析

路径: src/upstreamproxy/ 文件数: 2 个 功能: 上游代理 — CCR 环境中的 CONNECT-over-WebSocket 代理隧道


模块概述

upstreamproxy/ 实现了 CCR(Claude Code Remote)环境中的上游代理系统。当 Claude Code 在远程容器中运行时,工具(如 curl、gh、kubectl)的 HTTPS 请求需要通过代理隧道转发,由服务端注入组织配置的凭证(如 DD-API-KEY)。


1. relay.ts — CONNECT-over-WebSocket 中继

行数: 456 行

导出

  • encodeChunk(data) — 编码 protobuf UpstreamProxyChunk 消息
  • decodeChunk(buf) — 解码 protobuf 块
  • UpstreamProxyRelay 类型 — { port: number, stop: () => void }
  • startUpstreamProxyRelay(opts) — 启动中继服务器
  • startNodeRelay(wsUrl, authHeader, wsAuthHeader) — Node.js 特定实现

架构

工具 (curl/gh/kubectl)
    ↓ HTTP CONNECT
本地 TCP 服务器 (localhost:ephemeral)
    ↓ WebSocket 隧道
CCR upstreamproxy 端点
    ↓ MITM TLS + 凭证注入
真实上游服务器

连接状态机

Phase 1: 累积 CONNECT 请求
    ↓ (直到 CRLF CRLF 终止符)
Phase 2: 打开 WebSocket 隧道(带认证头)
    ↓
Phase 3: 双向字节转发
    ├── 客户端 → 服务器: encodeChunk() → WebSocket
    └── 服务器 → 客户端: WebSocket → decodeChunk() → TCP

Protobuf 编码(手写)

// 手写 protobuf wire format,避免引入 protobuf 库
// UpstreamProxyChunk: field 1, wire type 2 (length-delimited)
function encodeChunk(data: Uint8Array): Uint8Array {
  const tag = 0x0a  // field 1, wire type 2
  const len = encodeVarint(data.length)
  return concat([tag], len, data)
}

双运行时支持

if (typeof Bun !== 'undefined') {
  // Bun: 需要显式写缓冲管理(背压处理)
  return startBunRelay(wsUrl, auth)
} else {
  // Node.js: 内部缓冲
  return startNodeRelay(wsUrl, auth)
}

关键参数

  • 最大块大小: 512KB
  • Keepalive: 每 30 秒发送空块
  • 错误处理: 隧道建立前返回 502 Bad Gateway;建立后静默关闭

2. upstreamproxy.ts — 代理系统初始化

行数: 286 行

导出

  • SESSION_TOKEN_PATH = '/run/ccr/session_token'
  • initUpstreamProxy(opts?) — 初始化代理系统
  • getUpstreamProxyEnv() — 获取子进程环境变量
  • resetUpstreamProxyForTests() — 测试重置

初始化流程

initUpstreamProxy()
    ├── 1. 守卫: 仅在 CLAUDE_CODE_REMOTE && CCR_UPSTREAM_PROXY_ENABLED 时执行
    ├── 2. 令牌: 读取 /run/ccr/session_token → 读后即删
    ├── 3. 安全: prctl(PR_SET_DUMPABLE, 0) 阻止 ptrace
    ├── 4. CA 证书: 下载 + 合并到 ~/.ccr/ca-bundle.crt
    ├── 5. 中继: startUpstreamProxyRelay() → 获取本地端口
    └── 6. 环境变量: HTTPS_PROXY, SSL_CERT_FILE, NODE_EXTRA_CA_CERTS 等

NO_PROXY 排除列表

localhost, 127.0.0.1, RFC1918, IMDS, api.anthropic.com, github.com, registry.npmjs.org 等

Fail-Open 设计

任何错误只记录警告,不中断会话。


设计亮点

  1. 零依赖 Protobuf: 手写 wire format,避免引入 protobuf 库
  2. 双运行时: Bun 和 Node.js 各自的背压处理
  3. 安全加固: prctl 防 ptrace、令牌读后即删、CA 证书管理
  4. Fail-Open: 代理失败不阻断会话
  5. 凭证注入: 服务端 MITM 注入组织凭证,客户端无需感知

34 - outputStyles 模块源码分析

路径: src/outputStyles/ 文件数: 1 个 功能: 输出样式加载 — 自定义 AI 响应的格式和风格


loadOutputStylesDir.ts

行数: 99 行

导出

  • getOutputStyleDirStyles(cwd) — 获取输出样式配置(memoized)
  • clearOutputStyleCaches() — 清空缓存

样式文件格式

---
name: concise
description: 简洁直接的回复风格
keep-coding-instructions: true
---

回复时请保持简洁。不要使用 emoji。
避免冗长的解释,直接给出答案。

加载流程

.claude/output-styles/     ← 项目级样式
~/.claude/output-styles/   ← 用户级样式
    ↓
loadMarkdownFilesForSubdir('output-styles', cwd)
    ↓
对每个 .md 文件:
  ├── 提取文件名作为默认样式名
  ├── 解析 frontmatter (name, description, keep-coding-instructions)
  ├── 使用 frontmatter name 或回退到文件名
  ├── 提取描述(frontmatter 或 markdown 内容)
  ├── 解析 keep-coding-instructions 标志
  └── 警告 force-for-plugin(仅插件样式有效)
    ↓
返回 OutputStyleConfig[]

Memoization

结果按 cwd 缓存,避免重复文件系统访问。

OutputStyleConfig 结构

interface OutputStyleConfig {
  name: string                    // 样式名称
  description: string             // 样式描述
  prompt: string                  // 注入到系统提示的内容
  source: 'user' | 'project'     // 来源
  keepCodingInstructions: boolean // 是否保留默认编码指令
}

35 - assistant 模块源码分析

路径: src/assistant/ 文件数: 1 个 功能: 会话历史 API — 从远程 API 分页获取会话事件


sessionHistory.ts

行数: 88 行

导出

  • HISTORY_PAGE_SIZE = 100 — 分页大小
  • HistoryPage 类型 — { events: SDKMessage[], firstId: string, hasMore: boolean }
  • HistoryAuthCtx 类型 — { baseUrl: string, headers: Record<string, string> }
  • createHistoryAuthCtx(sessionId) — 创建认证上下文
  • fetchLatestEvents(ctx, limit?) — 获取最新事件页
  • fetchOlderEvents(ctx, beforeId, limit?) — 获取更早事件页

关键依赖

  • axios — HTTP 客户端
  • getOauthConfig — OAuth 配置
  • SDKMessage — 事件消息类型
  • getOAuthHeaders, prepareApiRequest — API 认证

认证上下文创建

async function createHistoryAuthCtx(sessionId: string): Promise<HistoryAuthCtx> {
  const headers = await getOAuthHeaders()
  const { baseUrl } = await prepareApiRequest()

  return {
    baseUrl: `${baseUrl}/v1/sessions/${sessionId}/events`,
    headers: {
      ...headers,
      'anthropic-beta': 'ccr-byoc-2025-07-29',
      'x-organization-uuid': orgUuid,
    }
  }
}

分页策略

获取最新页:
  GET /v1/sessions/{id}/events?anchor_to_latest=true&limit=100
  → { events: [...], firstId: "cursor_abc", hasMore: true }

获取更早页(游标分页):
  GET /v1/sessions/{id}/events?before_id=cursor_abc&limit=100
  → { events: [...], firstId: "cursor_xyz", hasMore: false }

错误处理

// HTTP 错误或网络故障返回 null(不抛异常)
// 用 logForDebugging 记录状态码
// 15 秒请求超时
try {
  const response = await axios.get(url, { headers, timeout: 15000 })
  return mapToHistoryPage(response.data)
} catch (error) {
  logForDebugging('Failed to fetch events', error.response?.status)
  return null
}

使用场景

主要被 screens/ResumeConversation.tsx 使用,在恢复远程会话时获取历史事件。

用户选择恢复远程会话
    ↓
createHistoryAuthCtx(sessionId)
    ↓
fetchLatestEvents(ctx, 100)
    ↓
显示会话内容
    ↓
用户滚动加载更多 → fetchOlderEvents(ctx, cursor, 100)

从源码角度看:如何避免封号

本文基于 Claude Code 源码中的认证、遥测、指纹、归因等机制,分析 Anthropic 后端可能用于检测异常账号的信号,以及中国用户被封号的常见原因。


封号的本质

Anthropic 封号不是随机的,而是基于多维度信号交叉验证。从源码来看,每次 API 请求都会携带大量元数据,后端可以据此判断你是否是“正常用户“。


一、Claude Code 上报了哪些信息

1. 每次 API 请求必带的 HTTP 头

// services/api/client.ts:106-115
headers = {
  'x-app': 'cli',
  'User-Agent': 'claude-cli/2.1.87 (consumer, cli)',
  'x-claude-remote-container-id': '...',    // 远程容器 ID(如有)
  'x-claude-remote-session-id': '...',      // 远程会话 ID(如有)
  'x-client-app': '...',                    // SDK 客户端标识
  'x-client-request-id': 'uuid',            // 每次请求唯一 ID
}

2. 归因头(Attribution Header)— 最关键的追踪机制

// constants/system.ts:73-91
// 每次请求都带,格式:
// x-anthropic-billing-header: cc_version=2.1.87.a3f; cc_entrypoint=cli; cch=00000;

function getAttributionHeader(fingerprint: string): string {
  const version = `${MACRO.VERSION}.${fingerprint}`  // 版本号 + 指纹
  const entrypoint = process.env.CLAUDE_CODE_ENTRYPOINT ?? 'unknown'
  const cch = feature('NATIVE_CLIENT_ATTESTATION') ? ' cch=00000;' : ''
  // cch=00000 会被 Bun 原生 HTTP 层替换为真实的客户端证明 token
  return `x-anthropic-billing-header: cc_version=${version}; cc_entrypoint=${entrypoint};${cch}`
}

这个头包含三个关键信息:

  • cc_version — 版本号 + 3 字符指纹(证明你用的是真正的 Claude Code)
  • cc_entrypoint — 入口类型(cli/sdk/mcp)
  • cch — 客户端证明 token(Bun 原生层计算,防伪造)

3. 指纹算法

// utils/fingerprint.ts
const FINGERPRINT_SALT = '59cf53e54c78'  // 硬编码盐值,必须和后端匹配

function computeFingerprint(messageText: string, version: string): string {
  // 取用户第一条消息的第 4、7、20 个字符
  const indices = [4, 7, 20]
  const chars = indices.map(i => messageText[i] || '0').join('')
  const input = `${FINGERPRINT_SALT}${chars}${version}`
  return createHash('sha256').update(input).digest('hex').slice(0, 3)
}

后端会验证这个指纹。如果你用第三方客户端伪造请求,指纹对不上就会被标记。

4. 客户端证明(Native Client Attestation)

// constants/system.ts:81-82
// cch=00000 是占位符,Bun 的原生 HTTP 层会在发送前替换为真实 hash
// 实现在 bun-anthropic/src/http/Attestation.zig
const cch = feature('NATIVE_CLIENT_ATTESTATION') ? ' cch=00000;' : ''

这是最难绕过的机制 — 证明 token 由 Bun 运行时的 Zig 原生代码计算,不在 JS 层暴露,第三方客户端几乎无法复现。

5. User-Agent 格式

// utils/http.ts:36
// 格式:claude-cli/{版本} ({用户类型}, {入口点})
return `claude-cli/${MACRO.VERSION} (${process.env.USER_TYPE}, ${process.env.CLAUDE_CODE_ENTRYPOINT ?? 'cli'})`
// 示例:claude-cli/2.1.87 (consumer, cli)

6. 设备 ID(持久化)

// utils/config.ts:1757-1764
function getOrCreateUserID(): string {
  const config = getGlobalConfig()
  if (config.userID) return config.userID
  // 首次运行生成,存储在 ~/.claude/config.json,永久关联
  const userID = randomBytes(32).toString('hex')
  saveGlobalConfig(current => ({ ...current, userID }))
  return userID
}

这个 ID 存在 ~/.claude/config.json 里,一旦生成就永久绑定。如果你的账号被封,换账号但不清理这个文件,新账号也可能被关联。

7. GrowthBook 用户画像

// services/analytics/growthbook.ts — 上报给特性门控系统的属性
attributes = {
  deviceID,              // 设备 ID
  sessionId,             // 会话 ID
  organizationUUID,      // 组织 ID
  accountUUID,           // 账号 ID
  rateLimitTier,         // 限流等级
  subscriptionType,      // 订阅类型(free/pro/team/enterprise)
  platform,              // 操作系统
  email,                 // 邮箱
}

8. 遥测事件

// services/analytics/ — 双通道上报
// 1. Datadog — 实时指标
// 2. 第一方事件日志 — 发送到 /api/event_logging/batch
//    批处理:10 秒间隔,200 条批量,8192 队列

二、后端可能的封号判据

基于源码中上报的信息,后端大概率会检测以下异常:

IP 地址相关

信号风险说明
中国大陆 IP 直连🔴 极高Anthropic 不对中国提供服务,直连 = 违反 ToS
IP 频繁切换🟡 中等短时间内 IP 跳跃,像是共享代理
数据中心 IP🟡 中等机房 IP 而非住宅 IP,可能是批量使用
IP 与注册地不符🟡 中等注册时美国 IP,使用时亚洲 IP

客户端指纹相关

信号风险说明
指纹验证失败🔴 极高第三方客户端伪造请求,指纹对不上
cch 证明缺失/无效🔴 极高非官方 Bun 运行时,无法生成证明 token
User-Agent 异常🟡 中等格式不对或版本号不存在
版本号过旧🟢 低长期不更新,可能是破解版

使用模式相关

信号风险说明
同一设备 ID 多账号🔴 极高一台机器切换多个账号
请求频率异常🟡 中等超出正常人类使用频率
7×24 无间断使用🟡 中等没有人类作息规律
只用 API 不用 UI🟢 低纯 SDK 调用法用途

三、实用建议

1. 网络层面

  • 使用稳定的住宅代理,不要用数据中心 IP
  • 保持 IP 一致性 — 不要频繁切换节点,选一个地区固定用
  • Claude Code 原生支持代理:
// utils/proxy.ts — 支持的环境变量
// HTTPS_PROXY / https_proxy / HTTP_PROXY / http_proxy
// NO_PROXY — 支持通配符、域名后缀、端口、IP

设置方式:export HTTPS_PROXY=http://your-proxy:port

2. 客户端层面

  • 用官方客户端,不要用第三方封装或破解版
  • 官方客户端的 cch 证明 token 是 Zig 原生代码生成的,第三方无法复现
  • 及时更新版本 — 旧版本的指纹算法可能和后端不匹配

3. 账号层面

  • 一机一号~/.claude/config.json 里的 userID 是持久化的设备指纹
  • 如果要换账号,需要清理 ~/.claude/ 目录
  • 不要共享账号 — GrowthBook 会追踪 deviceID + accountUUID 的关联

4. 使用模式

  • 保持正常使用节奏 — 不要写脚本批量调用
  • 不要关闭遥测 — 虽然可以通过 CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1 关闭非必要遥测,但完全没有遥测数据本身就是异常信号

5. 关于 API Key vs OAuth

源码中两种认证方式的追踪力度不同:

// OAuth 用户 — 追踪更多
attributes = { subscriptionType, rateLimitTier, billingType, organizationUUID, accountUUID }

// API Key 用户 — 追踪相对少
// 但 policyLimits 仍然会检查

使用 API Key(Console)比 OAuth(claude.ai 订阅)的追踪维度少一些,但核心的 IP + 指纹 + 设备 ID 检测是一样的。


四、源码中的“后门“和可控开关

可以关闭的

开关环境变量效果
归因头CLAUDE_CODE_ATTRIBUTION_HEADER=0不发送 billing header
非必要遥测CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1关闭分析/遥测
GrowthBook无直接开关6 小时刷新,有磁盘缓存

无法关闭的

机制原因
User-Agent硬编码在请求头中
指纹 (fingerprint)后端验证,不发 = 请求被拒
cch 证明Bun 原生层注入,JS 层无法控制
OAuth token 属性服务端下发,客户端无法修改

策略限制的 Fail-Open 设计

// services/policyLimits/index.ts
// 大多数策略检查在获取失败时默认放行(fail-open)
// 唯一例外:HIPAA 组织的 allow_product_feedback 策略(fail-closed)

这意味着即使策略服务器不可达,Claude Code 仍然可以正常使用 — 但这不代表后端不记录。


五、总结

从源码来看,Anthropic 的检测体系是多层纵深防御

第 1 层:IP 地址(最容易被检测,也最容易解决)
第 2 层:客户端指纹 + cch 证明(确认是官方客户端)
第 3 层:设备 ID + 账号关联(跨会话追踪)
第 4 层:使用模式分析(频率、时间、行为)
第 5 层:GrowthBook 特性门控(服务端动态控制)

中国用户被封号最常见的原因是第 1 层(IP 暴露)和第 3 层(一机多号)。用好代理 + 一机一号 + 官方客户端,基本可以避免大部分风险。

声明:本分析仅基于公开源码的技术解读,不构成任何规避服务条款的建议。使用 Claude Code 请遵守 Anthropic 的使用政策。

快问快答 (FAQ)

基础概念

Q: Claude Code 到底是什么?和 Claude 网页版有什么区别?

Claude Code 是 Anthropic 官方的 CLI 工具,直接在终端里和 Claude 交互,核心区别是它能直接操作你的文件系统 — 读写文件、执行 Shell 命令、搜索代码,本质上是一个 AI 驱动的编程 Agent,不只是聊天。

Q: 用什么语言写的?为什么选 TypeScript + Bun?

全部 TypeScript,1884 个文件。选 Bun 而不是 Node 主要是为了:

  • 更快的启动速度(CLI 工具对冷启动敏感)
  • 内置打包器,不需要额外的 webpack/esbuild
  • 原生支持 TypeScript,不需要编译步骤

Q: 为什么 Fork 了 Ink 而不是直接用 npm 包?

标准 Ink 不够用。Claude Code 需要:

  • 鼠标点击支持(hit-test)
  • 完整终端协议栈(CSI/SGR/OSC/DEC)
  • 声明式光标管理
  • 搜索高亮
  • 纯 TS 的 Yoga 布局(避免 WASM 加载问题)

这些都不是简单的插件能解决的,所以直接 Fork 了整个框架,改了约 80 个文件。


架构设计

Q: main.tsx 4683 行、REPL.tsx 5005 行,为什么不拆分?

这是个好问题。从源码来看:

  • main.tsx 是编排器,负责初始化所有模块(bootstrap、tools、skills、plugins、bridge、server、coordinator),拆开会导致初始化顺序难以管理
  • REPL.tsx 是整个交互的状态中心,消息数组、权限请求、文件状态缓存、后台任务全在这里,拆开会导致状态同步问题

本质上是“God Component“反模式,但在 CLI 场景下,状态集中管理比分散管理更实际。

Q: query.ts 和 query/ 目录是什么关系?

  • query.ts(根级,1729 行)是查询主循环,直接被 REPL.tsx import,负责调用 Claude API、处理流式响应、执行工具
  • query/(目录)是主循环的支撑模块:配置快照(config.ts)、依赖注入(deps.ts)、Token 预算(tokenBudget.ts)、停止钩子(stopHooks.ts)

Q: hooks/ 和 utils/hooks/ 为什么分成两个?

完全不同的东西:

  • src/hooks/(104 个文件)— React Hooks,给 UI 组件用的(useSearchInput、useTerminalSize 等)
  • src/utils/hooks/(17 个文件)— 钩子执行引擎,处理 28 种生命周期事件(Stop、PreToolUse、PostToolUse 等)

前者是 React 的 useState/useEffect 那套,后者是 Claude Code 自己的事件系统。

Q: 工具是怎么注册的?类继承还是工厂模式?

工厂模式。所有 40 个工具都通过 buildTool(def) 构建:

// src/Tool.ts:783-792
export function buildTool<D>(def: D): BuiltTool<D>

传入一个 ToolDef 对象(包含 name、description、inputSchema、execute 等),返回 BuiltTool。没有基类继承。

Q: MCP 工具是怎么集成的?

Claude Code 同时是 MCP Client 和 MCP Server:

  • 作为 Client:启动时动态发现并注册第三方 MCP 工具,和内置工具统一管理
  • 作为 Server:通过 entrypoints/mcp.ts 入口暴露自己的能力给其他 MCP Client

核心流程

Q: 用户输入到 AI 回复的完整链路是什么?

用户输入 → REPL.tsx 解析
  → import { query } from '../query.js' 直接调用
    → microcompact 消息压缩
    → autocompact 检查(上下文太长时自动压缩)
    → callModel() → services/api → Claude API(流式)
         - 文本 → yield 给 REPL → ink/ 渲染到终端
      - 工具调用 → 权限检查 → 执行 → 结果追加到消息 → 继续循环
    → checkTokenBudget()(连续2次 delta<500 且续传≥3 → 停止)
  → 停止钩子(记忆提取、自动推理、提示建议)
  → 会话持久化

Q: 权限系统怎么工作的?

三级权限:

  1. 自动允许 — 只读工具(Read、Glob、Grep)和匹配白名单的命令
  2. 需要确认 — 写文件、执行未知命令,弹出权限对话框
  3. 沙箱执行 — 在受限环境中运行,网络和文件系统访问受控

权限规则在 utils/permissions/ 中定义,检查逻辑在 hooks/useCanUseTool.ts

Q: Token 预算是怎么控制的?

不是硬切断,而是收益递减检测

const COMPLETION_THRESHOLD = 0.9    // 90% 预算使用率
const DIMINISHING_THRESHOLD = 500   // 收益递减阈值

// 连续 2 次 delta < 500 tokens 且续传次数 ≥ 3 → 停止

也就是说,如果 AI 连续两轮只产出很少的新内容,系统会判断它在“原地打转“,主动停止。


连接与扩展

Q: bridge/ 是干什么的?VS Code 扩展怎么和 CLI 通信?

bridge/ 实现了 IDE 桥接协议。VS Code/JetBrains 扩展通过这个桥接层和 Claude Code CLI 进程通信,实现:

  • 文件 diff 同步
  • 编辑器内显示 AI 修改
  • 共享终端上下文

REPL 不直接 import bridge/,而是通过 hooks/useReplBridge.tsx 间接访问。

Q: 多个 Claude Code 实例怎么协调?

coordinator/ 模块负责多实例协调,被 main.tsx 在启动时初始化。主要解决:

  • 同一项目多个终端窗口的会话隔离
  • 文件锁冲突
  • 共享状态同步

Q: 子 Agent 是怎么工作的?

通过 tools/AgentTool/ 实现。用户或 AI 可以启动子 Agent:

  • general-purpose — 通用 Agent,拥有所有工具
  • Explore — 只读代码探索,不能修改文件
  • Plan — 计划模式,只读分析后输出方案

子 Agent 可以选择在 Git Worktree 中隔离运行,避免影响主工作区。


有趣的细节

Q: Task ID 是怎么生成的?

不是 UUID,而是 randomBytes(8) + 单字符类型前缀 + 36 字符字母表编码。比 UUID 短很多,在终端显示更友好。

Q: Buddy 彩蛋是什么?

src/buddy/ 目录(6 个文件)实现了一个隐藏的伴侣系统:

  • isBuddyTeaserWindow:2026 年 4 月 1-7 日显示预告
  • isBuddyLive:2026 年 4 月之后正式上线
  • 包含 CompanionSprite.tsx 精灵动画组件

看起来是个愚人节彩蛋,但代码写得很认真。

Q: 为什么用纯 TS 重写 Yoga 布局而不是用 WASM?

native-ts/yoga-layout/ 是 Meta Yoga 的简化子集移植,不是完整移植。原因:

  • 避免 WASM 加载的兼容性问题(不同平台、不同 Node/Bun 版本)
  • CLI 场景只需要基础 Flexbox(行/列布局、对齐、padding),不需要完整 CSS 规范
  • 纯 TS 更容易调试和定制

Q: 会话数据存在哪里?

utils/sessionStorage.ts 负责持久化,存储在 ~/.claude/ 目录下:

  • 会话消息历史
  • 会话元数据(标题、时间戳、项目路径)
  • 支持跨项目恢复(crossProjectResume.ts
  • 自动定时保存

Q: 快速模式 (Fast Mode) 是什么?

不是切换到更小的模型,而是同一个模型用更快的输出配置。通过 bootstrap/state 中的 fastModeEnabled 标志控制,影响 query/config.ts 中的查询参数。