Analyzed: March 31, 2026 leak snapshot
This page is about live in-memory state during an active session. Disk persistence and resume mechanics are covered separately in the persistence page.

Two state layers

Claude Code has two different state layers that are easy to conflate:
  • Bootstrap-global session state in src/bootstrap/state.ts
  • UI and runtime app state in src/state/AppStateStore.ts
The first stores session-wide process facts such as current cwd, session ID, model overrides, telemetry counters, and feature latches. The second stores the mutable session state that the UI and tools read continuously.

What lives in AppState

AppState in src/state/AppStateStore.ts is the main live runtime object. It includes:
  • Current settings snapshot
  • Active model and session model
  • Permission context
  • Tasks and foregrounded task selection
  • MCP clients, tools, commands, and resources
  • Plugin state
  • File history and attribution state
  • Notifications and elicitation queue
  • Thinking toggle state
  • Session hooks state
  • Remote bridge and remote session status
  • Todo state
This is not a tiny view-model. It is effectively the operational state for the whole TUI runtime.

Why there is also bootstrap state

The bootstrap state exists because some data does not belong inside React-style UI state:
  • Global counters and telemetry
  • Session identity
  • Stable project root
  • Model override plumbing
  • Prompt-cache latches
  • Session-only process flags
  • Hook registration
The comments in src/bootstrap/state.ts are explicit: the file is already considered risky global state and should not grow casually.

Session status model

The smaller session-status state machine lives in src/utils/sessionState.ts:
  • idle
  • running
  • requires_action
That status is used for downstream surfaces such as remote clients and notifications. requires_action is not just a boolean. The code also carries structured details:
  • tool name
  • human-readable action description
  • tool use ID
  • request ID
  • optional raw input payload
That lets remote consumers know what the session is blocked on, not just that it is blocked.

State flow

Permission state is central, not peripheral

One of the most important subtrees in AppState is toolPermissionContext. It carries:
  • current permission mode
  • additional working directories
  • allow, deny, and ask rules
  • bypass-permission availability
  • plan-mode restoration state
That matters because permission mode changes are not local implementation details. They affect the query loop, tool execution, dialogs, and remote clients. notifyPermissionModeChanged() in src/utils/sessionState.ts exists specifically so different mutation paths cannot bypass downstream observers.

MCP and plugin state are first-class

AppState keeps external capability surfaces directly in memory:
  • mcp.clients
  • mcp.tools
  • mcp.commands
  • mcp.resources
  • plugins.enabled
  • plugins.disabled
  • plugins.errors
That means Claude Code does not treat extension state as a side cache. It is part of the active runtime model.

Task-oriented state

The app state also contains multiple task-level coordination structures:
  • task map keyed by task ID
  • foregrounded task selection
  • agent name registry
  • todo lists
  • remote-agent task suggestions
This is one reason the TUI can switch between leader and subagent views without rebuilding the whole conversation model from scratch.

Remote and bridge state

The app state tracks remote-control and remote-viewer state explicitly:
  • remote connection status
  • background task count
  • always-on bridge enablement
  • bridge session URL
  • reconnect state
  • error strings
This is a useful architectural clue: remote mode is not bolted on after the fact. It has dedicated state slots throughout the runtime.

Design implications

A few patterns stand out from the state model:
  • Claude Code prefers one authoritative app state over many isolated feature stores
  • External integrations are promoted into first-class state early
  • Permission state is treated as session infrastructure
  • Remote clients depend on the same state transitions as local UI
That design increases central-state complexity, but it avoids a more dangerous failure mode: each subsystem inventing its own incomplete view of session reality.