Documentation

Step 1: 入口点与启动流程

分析日期: 2026-04-16 核心文件: main.tsx (4,683行), cli.tsx, init.ts, setup.ts (477行), migrations/


1. 调用图: main() -> run() -> [子命令路径]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
cli.tsx::main()                    [启动入口 - 零导入快速路径]
  |
  +-- 快速路径 (提前返回,零/低模块加载):
  |     |--version/-v/-V           -> console.log(MACRO.VERSION) and return
  |     |--dump-system-prompt      -> enableConfigs() -> getSystemPrompt() -> return
  |     |--claude-in-chrome-mcp    -> runClaudeInChromeMcpServer() -> return
  |     |--chrome-native-host      -> runChromeNativeHost() -> return
  |     |--computer-use-mcp        -> runComputerUseMcpServer() -> return  [feature: CHICAGO_MCP]
  |     |--daemon-worker <kind>    -> runDaemonWorker(kind) -> return     [feature: DAEMON]
  |     |remote-control/rc/remote/sync/bridge -> bridgeMain(args)         [feature: BRIDGE_MODE]
  |     |daemon [subcommand]       -> daemonMain(args)                    [feature: DAEMON]
  |     |ps|logs|attach|kill      -> bg.{handler}()                     [feature: BG_SESSIONS]
  |     |--bg/--background         -> bg.handleBgFlag(args)              [feature: BG_SESSIONS]
  |     |new|list|reply            -> templatesMain(args)                [feature: TEMPLATES]
  |     |environment-runner        -> environmentRunnerMain(args)        [feature: BYOC_ENVIRONMENT_RUNNER]
  |     |self-hosted-runner        -> selfHostedRunnerMain(args)         [feature: SELF_HOSTED_RUNNER]
  |     |--worktree --tmux         -> execIntoTmuxWorktree(args)         [条件快速路径]
  |
  +-- --bare 标志: 尽早设置 CLAUDE_CODE_SIMPLE=1
  |
  +-- 回退到完整 CLI:
        startCapturingEarlyInput()
        import('../main.js') -> main()

main.tsx::main()                    [完整 CLI 入口 - ~135ms 模块导入]
  |
  +-- 模块求值时的副作用 (main() 运行前):
  |     profileCheckpoint('main_tsx_entry')
  |     startMdmRawRead()               [并行触发 MDM 子进程]
  |     startKeychainPrefetch()          [并行触发 keychain 读取]
  |
  +-- 安全: set NoDefaultCurrentDirectoryInExePath=1
  +-- initializeWarningHandler()
  +-- cc:// / cc+unix:// URL 重写    [feature: DIRECT_CONNECT]
  +-- --handle-uri 深链接处理         [feature: LODESTONE]
  +-- 'assistant' 子命令重写           [feature: KAIROS]
  +-- 'ssh' 子命令参数重写            [feature: SSH_REMOTE]
  +-- 确定 isNonInteractive (来自 -p/--print, --init-only, --sdk-url, !isTTY)
  +-- setIsInteractive(isInteractive)
  +-- initializeEntrypoint(isNonInteractive)
  +-- 确定 clientType (github-action, sdk-typescript, sdk-python 等)
  +-- setClientType(clientType)
  +-- setQuestionPreviewFormat()
  +-- eagerLoadSettings()
  +-- run()

main.tsx::run()
  |
  +-- 创建 Commander 程序(排序帮助)
  +-- 注册 preAction hook:
  |     await ensureMdmSettingsLoaded() + ensureKeychainPrefetchCompleted()
  |     await init()                         [entrypoints/init.ts]
  |     process.title = 'claude'
  |     initSinks()
  |     setInlinePlugins() / clearPluginCache()
  |     runMigrations()
  |     void loadRemoteManagedSettings()
  |     void loadPolicyLimits()
  |     void uploadUserSettingsInBackground()  [feature: UPLOAD_USER_SETTINGS]
  |
  +-- 注册顶级选项 (150+ 标志)
  +-- 注册默认动作处理器(主要交互/headless 逻辑)
  +-- program.parseAsync(process.argv)

2. 启动序列表

步骤 函数 文件 用途 特性开关/条件
0 COREPACK_ENABLE_AUTO_PIN = '0' cli.tsx (顶层) 防止 corepack 自动固定 始终
0 NODE_OPTIONS --max-old-space-size=8192 cli.tsx (顶层) 设置 CCR 容器堆限制 CLAUDE_CODE_REMOTE=true
0 消融基线环境变量 cli.tsx (顶层) 设置 L0 消融基线环境 feature('ABLATION_BASELINE')
1 profileCheckpoint('cli_entry') cli.tsx:48 标记 CLI 入口时间戳 始终
2 --version 快速路径 cli.tsx:37-42 打印版本并退出 --version
3 enableConfigs() cli.tsx (各种快速路径) 为 bridge/daemon/bg 等启用配置 仅子命令快速路径
4 bridgeMain() cli.tsx:160 启动 bridge 远程控制 feature('BRIDGE_MODE')
5 daemonMain() cli.tsx:178 启动守护进程 feature('DAEMON')
6 bg.{handler}() cli.tsx:192-208 会话管理 feature('BG_SESSIONS')
7 templatesMain() cli.tsx:216 模板命令 feature('TEMPLATES')
8 environmentRunnerMain() cli.tsx:229 BYOC 无头运行器 feature('BYOC_ENVIRONMENT_RUNNER')
9 selfHostedRunnerMain() cli.tsx:241 自托管运行器 feature('SELF_HOSTED_RUNNER')
10 execIntoTmuxWorktree() cli.tsx:261 Tmux worktree 快速路径 --tmux + --worktree
11 --bare -> CLAUDE_CODE_SIMPLE=1 cli.tsx:283 尽早设置极简模式 --bare
12 startCapturingEarlyInput() cli.tsx:291 在完整初始化前捕获 stdin 始终
13 profileCheckpoint('main_tsx_entry') main.tsx:12 模块求值时间戳 始终
14 startMdmRawRead() main.tsx:16 并行触发 MDM 子进程 始终
15 startKeychainPrefetch() main.tsx:20 并行触发 keychain 读取 始终
16 initializeWarningHandler() main.tsx:594 捕获未处理警告 始终
17 cc:// URL 重写 main.tsx:612-641 重写 cc:// 方案 argv feature('DIRECT_CONNECT')
18 --handle-uri 处理 main.tsx:648-676 深链接 URI 处理 feature('LODESTONE')
19 assistant 子命令重写 main.tsx:685-700 暂存 assistant session ID feature('KAIROS')
20 ssh 子命令重写 main.tsx:706-794 暂存 SSH 主机/目录 feature('SSH_REMOTE')
21 确定 isNonInteractive main.tsx:799-803 从 -p, –init-only, –sdk-url, !isTTY 条件
22 initializeEntrypoint() main.tsx:815 设置 CLAUDE_CODE_ENTRYPOINT 环境变量 始终
23 setClientType() main.tsx:834 识别客户端来源 始终
24 eagerLoadSettings() main.tsx:852 早期解析 –settings, –setting-sources 始终
25 run() main.tsx:854 启动 Commander 程序 始终
26 preAction hook main.tsx:907-967 任何命令前初始化 Commander 生命周期
27 ensureMdmSettingsLoaded() main.tsx:914 等待子进程结果 始终
28 init() entrypoints/init.ts:57 核心初始化(记忆化) 始终
29 enableConfigs() init.ts:65 验证和启用配置系统 始终
30 applySafeConfigEnvironmentVariables() init.ts:74 在信任前应用安全环境变量 始终
31 applyExtraCACertsFromConfig() init.ts:79 在 TLS 前应用 CA 证书 始终
32 setupGracefulShutdown() init.ts:87 注册退出处理器 始终
33 initialize1PEventLogging() init.ts:94-106 启动 1P 分析(延迟) 始终
34 populateOAuthAccountInfoIfNeeded() init.ts:110 填充 OAuth 信息缓存 始终
35 initJetBrainsDetection() init.ts:114 检测 JetBrains IDE 始终
36 detectCurrentRepository() init.ts:118 检测 GitHub 仓库 始终
37 initializeRemoteManagedSettingsLoadingPromise() init.ts:124 企业远程设置 有条件
38 initializePolicyLimitsLoadingPromise() init.ts:127 策略限制初始化 有条件
39 configureGlobalMTLS() init.ts:137 mTLS 配置 始终
40 configureGlobalAgents() init.ts:146 HTTP 代理/agent 配置 始终
41 preconnectAnthropicApi() init.ts:159 TCP+TLS 预热 非代理/mTLS
42 initUpstreamProxy() init.ts:168-183 CCR 上游代理 CLAUDE_CODE_REMOTE=true
43 setShellIfWindows() init.ts:186 Windows 上 Git-bash 仅 Windows
44 registerCleanup(shutdownLspServerManager) init.ts:189 退出时 LSP 清理 始终
45 ensureScratchpadDir() init.ts:205 创建 scratchpad 目录 isScratchpadEnabled()
46 initSinks() main.tsx:934 附加分析接收器 始终
47 runMigrations() main.tsx:950 运行所有配置迁移 始终
48 loadRemoteManagedSettings() main.tsx:957 企业远程设置 即发即弃
49 loadPolicyLimits() main.tsx:958 策略限制 即发即弃
50 uploadUserSettingsInBackground() main.tsx:964 设置同步 feature('UPLOAD_USER_SETTINGS')
51 setup() setup.ts:56 完整设置(cwd, worktree, hooks 等) 始终
52 initBuiltinPlugins() + initBundledSkills() main.tsx:1924-1926 注册插件/技能 local-agent
53 showSetupScreens() main.tsx:2241 信任对话框、认证、引导 仅交互
54 initializeTelemetryAfterTrust() init.ts:247 启动 3P 遥测 信任后
55 runHeadless()launchRepl() main.tsx:2829/3798 启动无头或交互会话 模式依赖

3. 入口点清单: CLI 标志 -> 处理器映射

快速路径入口点 (cli.tsx - 零/低导入)

CLI 调用 处理器 特性开关
claude --version / -v console.log(MACRO.VERSION)
claude --dump-system-prompt enableConfigs() -> getSystemPrompt() feature('DUMP_SYSTEM_PROMPT')
claude --claude-in-chrome-mcp runClaudeInChromeMcpServer()
claude --chrome-native-host runChromeNativeHost()
claude --computer-use-mcp runComputerUseMcpServer() feature('CHICAGO_MCP')
claude --daemon-worker <kind> runDaemonWorker(kind) feature('DAEMON')
claude remote-control/rc/remote/sync/bridge bridgeMain(args) feature('BRIDGE_MODE')
claude daemon [subcommand] daemonMain(args) feature('DAEMON')
claude ps/logs/attach/kill bg.{handler}() feature('BG_SESSIONS')
claude --bg/--background bg.handleBgFlag(args) feature('BG_SESSIONS')
claude new/list/reply templatesMain(args) feature('TEMPLATES')
claude environment-runner environmentRunnerMain(args) feature('BYOC_ENVIRONMENT_RUNNER')
claude self-hosted-runner selfHostedRunnerMain(args) feature('SELF_HOSTED_RUNNER')
claude --worktree --tmux execIntoTmuxWorktree(args) isWorktreeModeEnabled()

完整 CLI 入口点 (main.tsx - Commander 子命令)

CLI 调用 处理器 特性开关
claude [prompt] (默认) 交互 REPL: launchRepl()
claude -p/--print 无头: runHeadless()
claude --init-only 处理 hooks -> 退出
claude -c/--continue loadConversationForResume() -> launchRepl()
claude -r/--resume 恢复选择器 -> launchRepl()
claude mcp serve mcpServeHandler() -> startMCPServer()
claude server startServer() feature('DIRECT_CONNECT')
claude open <cc-url> createDirectConnectSession() feature('DIRECT_CONNECT')
claude ssh <host> [dir] createSSHSession() feature('SSH_REMOTE')
claude auth 认证子命令
claude plugin/plugins 插件子命令
claude doctor 健康检查
claude update/upgrade 自动更新
claude assistant [sessionId] 连接 REPL 到 bridge 会话 feature('KAIROS')
claude auto-mode 检查自动模式配置 feature('TRANSCRIPT_CLASSIFIER')

4. 初始化顺序图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
[进程启动]
    |
    v
+-----------------------------------------------------------+
|  cli.tsx: 顶层副作用                                       |
|  - COREPACK_ENABLE_AUTO_PIN = '0'                          |
|  - CLAUDE_CODE_REMOTE -> max-old-space-size=8192           |
|  - ABLATION_BASELINE -> 设置 7 个环境变量                   |
+-----------------------------------------------------------+
    |
    v
+-----------------------------------------------------------+
|  cli.tsx::main()  --  启动入口点                             |
|  所有导入都是 DYNAMIC 以最小化模块求值                          |
+-----------------------------------------------------------+
    |
    +--> 快速路径? (--version, --dump-system-prompt,
    |    --claude-in-chrome-mcp, --chrome-native-host,
    |    --computer-use-mcp, --daemon-worker,
    |    remote-control, daemon, ps/logs/attach/kill,
    |    templates, environment-runner, self-hosted-runner,
    |    --worktree --tmux)
    |      |
    |      +--> 是: 执行处理器并返回
    |
    v  (无快速路径匹配)
+-----------------------------------------------------------+
|  --bare -> CLAUDE_CODE_SIMPLE=1                            |
|  startCapturingEarlyInput()                                |
|  import('../main.js')                                      |
+-----------------------------------------------------------+
    |
    v
+-----------------------------------------------------------+
|  main.tsx: 模块求值副作用                                   |
|  (在 main() 调用前运行)                                     |
|  - profileCheckpoint('main_tsx_entry')                     |
|  - startMdmRawRead()       [异步, 并行]                     |
|  - startKeychainPrefetch() [异步, 并行]                     |
+-----------------------------------------------------------+
    |
    v
+-----------------------------------------------------------+
|  main.tsx::main()                                          |
|  - 安全: NoDefaultCurrentDirectoryInExePath               |
|  - initializeWarningHandler()                              |
|  - cc:// URL 重写           [DIRECT_CONNECT]               |
|  - --handle-uri 深链接      [LODESTONE]                    |
|  - assistant 重写           [KAIROS]                       |
|  - ssh 重写                 [SSH_REMOTE]                   |
|  - 确定 isNonInteractive                                  |
|  - initializeEntrypoint()                                   |
|  - 确定 clientType                                         |
|  - eagerLoadSettings()                                     |
|  - run()                                                   |
+-----------------------------------------------------------+
    |
    v
+-----------------------------------------------------------+
|  main.tsx::run()                                           |
|  - 创建 Commander 程序                                     |
|  - 注册 preAction hook                                     |
|  - 注册 150+ CLI 选项                                      |
|  - 注册默认动作处理器                                       |
|  - 注册子命令 (mcp, auth, plugin 等)                        |
|  - program.parseAsync(process.argv)                        |
+-----------------------------------------------------------+
    |
    v  (Commander preAction hook 触发)
+-----------------------------------------------------------+
|  preAction hook                                            |
|  1. ensureMdmSettingsLoaded() + ensureKeychainPrefetchCompleted()  |
|  2. init() [entrypoints/init.ts]                          |
|     +-- enableConfigs()                                    |
|     +-- applySafeConfigEnvironmentVariables()              |
|     +-- applyExtraCACertsFromConfig()                      |
|     +-- setupGracefulShutdown()                            |
|     +-- initialize1PEventLogging() (异步, 即发即弃)         |
|     +-- populateOAuthAccountInfoIfNeeded() (异步)          |
|     +-- initJetBrainsDetection() (异步)                    |
|     +-- detectCurrentRepository() (异步)                   |
|     +-- initializeRemoteManagedSettingsLoadingPromise()    |
|     +-- initializePolicyLimitsLoadingPromise()              |
|     +-- configureGlobalMTLS()                              |
|     +-- configureGlobalAgents()                            |
|     +-- preconnectAnthropicApi() (异步)                    |
|     +-- initUpstreamProxy() (异步, 仅 CCR)                 |
|     +-- setShellIfWindows()                                |
|     +-- registerCleanup(shutdownLspServerManager)          |
|     +-- ensureScratchpadDir() (如果启用)                   |
|  3. initSinks()                                            |
|  4. setInlinePlugins() + clearPluginCache()               |
|  5. runMigrations()                                        |
|  6. loadRemoteManagedSettings() (即发即弃)                 |
|  7. loadPolicyLimits() (即发即弃)                          |
|  8. uploadUserSettingsInBackground() (条件)                |
+-----------------------------------------------------------+
    |
    v  (Commander 分发到匹配的动作处理器)
+-----------------------------------------------------------+
|  默认动作处理器(主会话逻辑)                               |
|  +-- 解析所有 CLI 选项                                     |
|  +-- Assistant 模式设置 [KAIROS]                           |
|  +-- initializeToolPermissionContext()                     |
|  +-- 解析 MCP 配置                                         |
|  +-- Claude in Chrome 设置                                 |
|  +-- 验证格式                                               |
|  +-- getInputPrompt()                                      |
|  +-- getTools(toolPermissionContext)                       |
|  +-- initBuiltinPlugins() + initBundledSkills()            |
|  +-- setup() [与 getCommands/getAgentDefs 并行]            |
|  +-- [仅交互] showSetupScreens()                           |
|  +-- [信任后] initializeTelemetryAfterTrust()              |
|  +-- [信任后] initializeLspServerManager()                 |
|  +-- MCP 配置解析 + prefetchAllMcpResources               |
|  +-- processSessionStartHooks('startup')                   |
|  +--                                                        |
|  +-- IF --init-only: 处理 hooks -> 退出                   |
|  +-- IF --print 模式: runHeadless(...)                      |
|  +-- IF 交互:                                              |
|       +-- IF --continue: 加载会话 -> launchRepl()          |
|       +-- IF --resume: 恢复选择器 -> launchRepl()          |
|       +-- IF cc://: 创建直接连接 -> launchRepl()           |
|       +-- IF ssh: 创建 SSH 会话 -> launchRepl()           |
|       +-- IF assistant: assistant 会话 -> launchRepl()     |
|       +-- ELSE: launchRepl() (新会话)                       |
+-----------------------------------------------------------+

5. 关键类型定义

PendingConnect (main.tsx:543-547):

1
2
3
4
5
type PendingConnect = {
  url: string | undefined;
  authToken: string | undefined;
  dangerouslySkipPermissions: boolean;
};

PendingAssistantChat (main.tsx:555-558):

1
2
3
4
type PendingAssistantChat = {
  sessionId?: string;
  discover?: boolean;
};

PendingSSH (main.tsx:567-576):

1
2
3
4
5
6
7
8
type PendingSSH = {
  host?: string;
  cwd?: string;
  local?: boolean;
  dangerouslySkipPermissions?: boolean;
  permissionMode?: string;
  extraCliArgs: string[];
};

6. 迁移编目

迁移 文件 用途 特性开关/守卫
migrateAutoUpdatesToSettings() migrateAutoUpdatesToSettings.ts 将 user-disabled autoUpdates 从全局配置移到 settings.json globalConfig.autoUpdates === false
migrateBypassPermissionsAcceptedToSettings() migrateBypassPermissionsAcceptedToSettings.ts bypassPermissionsModeAccepted 移到 settings.json 全局配置中存在该字段
migrateEnableAllProjectMcpServersToSettings() migrateEnableAllProjectMcpServersToSettings.ts 将 MCP 服务器审批字段移到本地设置 项目配置中存在这些字段
resetProToOpusDefault() resetProToOpusDefault.ts 为 Pro 用户设置时间戳以通知默认模型变更 isProSubscriber()
migrateSonnet1mToSonnet45() migrateSonnet1mToSonnet45.ts 固定 sonnet[1m] 用户到显式 4.5 !config.sonnet1m45MigrationComplete
migrateLegacyOpusToCurrent() migrateLegacyOpusToCurrent.ts 将旧 Opus 字符串重映射到 ‘opus’ 别名 isLegacyModelRemapEnabled()
migrateSonnet45ToSonnet46() migrateSonnet45ToSonnet46.ts 将 Pro/Max/Team 用户从 Sonnet 4.5 迁移到 4.6 1P 用户 + 订阅者
migrateOpusToOpus1m() migrateOpusToOpus1m.ts 为 Max/Team 用户将 ‘opus’ 迁移到 ‘opus[1m]’ isOpus1mMergeEnabled()
migrateReplBridgeEnabledToRemoteControlAtStartup() migrateReplBridgeEnabledToRemoteControlAtStartup.ts 复制 replBridgeEnabled -> remoteControlAtStartup 旧键存在且新键未设置
resetAutoModeOptInForDefaultOffer() resetAutoModeOptInForDefaultOffer.ts 清除旧的自动模式选择对话框 feature('TRANSCRIPT_CLASSIFIER')
migrateFennecToOpus() migrateFennecToOpus.ts 将已移除的 fennec 模型别名重映射到 Opus USER_TYPE === 'ant'

所有迁移由 CURRENT_MIGRATION_VERSION = 11 跟踪。当 globalConfig.migrationVersion !== 11 时,所有同步迁移运行并版本号更新。


7. 关键洞察

eagerLoadSettings() (main.tsx:502-516): 在 init() 运行前解析 --settings--setting-sources 标志,使用 eagerParseCliFlag()。这是必要的,因为 init() 调用 applySafeConfigEnvironmentVariables() 读取设置,而那些设置必须已包含标志提供的值。

initializeEntrypoint() (main.tsx:517-540): 如果尚未设置,则设置 CLAUDE_CODE_ENTRYPOINT 环境变量。优先级: (1) 已设置则跳过 (SDK/外部), (2) mcp serve 检测到则设为 'mcp', (3) GitHub Action 则设为 'claude-code-github-action', (4) 非交互则设为 'sdk-cli', (5) 交互则设为 'cli'

init() (entrypoints/init.ts:57-238): 通过 lodash 记忆化。运行一次不再运行。在 ConfigParseError 时,根据 getIsNonInteractiveSession() 显示交互对话框或 stderr 消息。

setup() (setup.ts:56-477): 从动作处理器调用,与 getCommands()getAgentDefinitionsWithOverrides() 并行化。关键职责: Node.js 版本检查 (>=18)、UDS 消息、worktree 创建、hooks 快照、会话记忆初始化、权限安全验证、记录 tengu_started 事件。

两次 Commander parseAsync 调用: (1) 第 3887 行 - 仅 print 模式,在子命令注册前解析(避免 -p 加载子命令模块)。(2) 第 4504 行 - 所有其他路径,在完整子命令注册后解析。