初始化与配置
init() 函数
Source:
src/entrypoints/init.ts:57-238
init() 是整个 CLI 的一次性初始化函数,通过 memoize() 确保只执行一次。它在 Commander.js 的 preAction hook 中被调用。
export const init = memoize(async (): Promise<void> => {
// 20+ 初始化步骤
});初始化步骤详解
1. 启用配置系统
// Source: src/entrypoints/init.ts:63-69
enableConfigs();验证 .claude/settings.json 的合法性。如果配置文件格式错误:
- 非交互模式:写入 stderr 并退出
- 交互模式:显示
InvalidConfigDialog让用户修复
2. 安全环境变量
// Source: src/entrypoints/init.ts:73-84
applySafeConfigEnvironmentVariables();
applyExtraCACertsFromConfig();这里只应用"安全"的环境变量 — 即不需要经过信任对话框确认的变量。
特别注意:applyExtraCACertsFromConfig() 设置 NODE_EXTRA_CA_CERTS,必须在第一次 TLS 握手前完成。Bun 使用 BoringSSL,会缓存 TLS 配置,迟到的修改不会生效。
3. 优雅关闭
// Source: src/entrypoints/init.ts:87
setupGracefulShutdown();注册 SIGINT/SIGTERM 信号处理器,确保退出时刷新缓冲区和关闭连接。
4. 事件日志与 GrowthBook
// Source: src/entrypoints/init.ts:94-106
const [fp, { refreshGrowthBook }] = await Promise.all([
import('./firstPartyEventLogger.js'),
import('./growthbook.js')
]);
fp.initialize1PEventLogging();并行导入两个模块,避免串行加载的延迟。GrowthBook 用于特性标志的远程配置(在反编译版中实际上是空实现)。
5. 异步 Fire-and-Forget 操作
以下操作启动后不等待完成:
// Source: src/entrypoints/init.ts:110-118
void populateOAuthAccountInfoIfNeeded(); // OAuth 账户信息
void initJetBrainsDetection(); // JetBrains IDE 检测
void detectCurrentRepository(); // Git 仓库检测使用 void 前缀表明这些是 fire-and-forget 调用。它们的结果会在后续需要时被查询。
6. 远程设置加载
// Source: src/entrypoints/init.ts:123-128
initializeRemoteManagedSettingsLoadingPromise();
initializePolicyLimitsLoadingPromise();启动远程配置加载的 Promise,但不立即 await。这样后续需要时可以 await 已经开始的加载过程。
7. mTLS 与 HTTP 代理
// Source: src/entrypoints/init.ts:135-150
configureGlobalMTLS();
configureGlobalAgents();配置全局的 mutual TLS 和 HTTP 代理。这对企业环境至关重要。
8. API 预连接
// Source: src/entrypoints/init.ts:159
preconnectAnthropicApi();Fire-and-forget 的 TCP+TLS 握手,与后续初始化并行执行。当真正发送 API 请求时,连接已经建立好了。
性能优化
预连接在以下情况被跳过:使用代理、mTLS、Unix socket 或云供应商(SDK 不会复用全局连接池)。
9. CCR 上游代理
// Source: src/entrypoints/init.ts:167-183
if (process.env.CLAUDE_CODE_REMOTE === "true") {
// 启动本地 CONNECT 中继
// 懒加载以避免非 CCR 启动的模块开销
}仅在远程容器环境(CCR)中启用。
遥测初始化
Source:
src/entrypoints/init.ts:247-340
遥测系统在信任对话框通过后才初始化:
doInitializeTelemetry()
// Source: src/entrypoints/init.ts:288-303
let telemetryInitialized = false;
function doInitializeTelemetry() {
if (telemetryInitialized) return; // 防止重复初始化
telemetryInitialized = true;
// ...
}setMeterState()
// Source: src/entrypoints/init.ts:305-340
async function setMeterState() {
// 延迟加载 OpenTelemetry (~400KB protobuf + SDK)
const { initializeTelemetry } = await import('utils/telemetry/instrumentation.js');
const meter = await initializeTelemetry();
setMeter(meter, createAttributedCounter);
getSessionCounter()?.add(1); // 记录会话计数
}OpenTelemetry 是最重的依赖之一,通过延迟 import() 避免影响启动速度。
配置系统概览
settings.json
用户配置存储在 ~/.claude/settings.json,包含:
| 配置项 | 说明 |
|---|---|
| 环境变量 | 注入到进程环境中 |
| CA 证书 | 自定义 TLS 证书 |
| mTLS | 客户端证书认证 |
| 代理 | HTTP/HTTPS 代理 |
| 权限模式 | 工具权限策略 |
| MCP 服务器 | Model Context Protocol 配置 |
配置加载顺序
- 安全环境变量 —
init.ts中加载,无需用户确认 - 完整环境变量 — 信任对话框通过后加载
- 远程管理设置 — 后台异步加载,可能覆盖本地配置
preAction Hook
init() 不是直接调用的,而是通过 Commander.js 的 preAction hook:
// Source: src/main.tsx:907-967
program.hook('preAction', async thisCommand => {
// 1. 等待异步预取完成
await Promise.all([
ensureMdmSettingsLoaded(),
ensureKeychainPrefetchCompleted()
]);
// 2. 运行 init()
await init();
// 3. 设置进程标题
process.title = 'claude';
// 4. 初始化分析
// 5. 应用 --plugin-dir
// 6. 运行迁移
// 7. 启动远程设置加载(异步)
// 8. 启动策略限制加载(异步)
});这个 hook 在每个 Commander 命令执行前运行(显示帮助时除外)。
下一步
- CLI 命令解析 — Commander.js 的完整命令和选项定义