How does Claude Code initialize on first launch end-to-end, from CLI invocation through auth check, settings load, MCP server discovery, telemetry setup, and reaching the first interactive prompt

en
100.0% sentence pass·34/34 cited·51/51 citations valid·112 fn·0 dec·967 sem
Application Bootstrap & EntrypointsAuthentication & Credential StorageSettings & ConfigurationMCP IntegrationAnalytics & Telemetry

Claude Code first-launch initialization

Overview

This scenario traces the cold-start path from the claude CLI binary through fast-path dispatch, config/auth/settings loading, telemetry bootstrap, MCP discovery, and into the first interactive turn . The entry is the bootstrap shim that defers all heavy imports until after version and special-flag fast paths .

Steps

  1. The process starts in the bootstrap shim which sets COREPACK_ENABLE_AUTO_PIN=0 and optional NODE_OPTIONS heap flags at module top-level before any dynamic import runs . It then calls main() with process.argv.slice(2) .
  2. main() short-circuits on --version, then loads the startup profiler and marks cli_entry for later timing analysis . Subsequent branches dispatch fast-paths like --daemon-worker, remote-control, daemon, ps/logs/attach/kill, and environment-runner before the normal Commander program is built .
  3. For a normal launch, Commander's preAction runs enableConfigs() and kicks off managed-settings download, then the settings loader merges plugin base, user, project, local, flag, and policy sources into the session cache . Each source file is parsed and schema-validated with a per-file cache .
  4. Managed/MDM and HKCU layers are layered in, with the remote-managed layer consulted first for policy settings; a cache flush guards against poisoned merged reads from an earlier getSettings_DEPRECATED call . Settings env vars are then applied into process.env so downstream code sees user-configured variables .
  5. Auth is resolved: if CLAUDE_CODE_OAUTH_REFRESH_TOKEN is present the refresh token is exchanged and persisted via installOAuthTokens, otherwise the stored OAuth tokens or API key source are used; subscription type is derived from those stored tokens .
  6. Telemetry is initialized: bootstrapTelemetry copies ANT_OTEL_* vars to their OTEL_* counterparts and defaults metrics temporality to delta . initializeTelemetry then strips console exporters when stdout is the SDK channel, builds resource attributes via getPlatform, and constructs meter/logger/tracer providers registered through state setters .
  7. Telemetry readers are selected: getOtlpReaders/getOtlpLogExporters/getOtlpTraceExporters parse exporter types and protocols; BigQuery metrics are additionally enabled for 1P API, C4E, and Team users . A shutdown hook is registered so providers flush on exit .
  8. MCP server discovery reads project/user/local/enterprise scopes, walking parent directories for .mcp.json project configs . Each configured server may have a headersHelper that is gated on trust-dialog acceptance before being invoked .
  9. Workspace trust is resolved via TrustDialog, which inspects MCP servers, hooks, bash permission sources, apiKeyHelper, OTEL headers helper, and dangerous env var sources to decide whether to prompt . Policy limits are also fetched and cached for gating features like remote control .
  10. In headless/print mode, runHeadless subscribes to settings changes, initializes sandbox, loads initial messages, and dispatches to runHeadlessStreaming which registers a SIGINT handler and drains the command queue . The SDK initialize control request is answered with commands, agents, models, and account info before the first prompt is accepted .
  11. The first turn's run() awaits deferred plugin install, refreshes plugin state, assembles MCP clients from app state plus SDK and dynamic clients, and calls drainCommandQueue which forwards the prompt to QueryEngine.submitMessage for the first interactive response .

State touched

Decisions

(none in whitelist)