AI Assistant

Services Overview

The service layer in Claude Code consists of singleton modules that manage global state, API interactions, background tasks, and external integrations. Services are long-lived utilities that persist across queries and operate independently of the REPL loop, providing shared infrastructure to tools, commands, and the query engine.

What Are Services?

Services differ from tools and commands in several ways:

  • Singleton lifecycle: services initialize once at startup and persist for the entire session
  • Global state management: they own module-scoped state (connections, caches, tokens) rather than per-query state
  • Background operations: many services run tasks asynchronously without blocking user interaction
  • Cross-cutting concerns: they provide shared capabilities (auth, analytics, memory) used by multiple tools

Major Services

Service Initialization

Services initialize at different points during startup:

ServiceInitializationBlocking?
OAuth / AuthBefore first API callYes
Analytics (GrowthBook)Early startupNo (cached values)
MCP ConnectionsAfter REPL mountNo (async)
LSP ManagerAfter REPL mountNo (async background)
Session MemoryAfter first query thresholdNo (hook-driven)
Policy LimitsBackground pollingNo (fail-open)

Most services follow a fail-open pattern: if a service fails to initialize (LSP, MCP, policy limits), the CLI continues operating with reduced functionality rather than blocking the user.

Common Patterns

Singleton with Factory Function

Many services use factory functions with closures rather than classes to encapsulate state:

export function createLSPServerManager(): LSPServerManager {
  // Private state via closures
  const servers: Map<string, LSPServerInstance> = new Map()

  async function initialize(): Promise<void> { /* ... */ }
  async function shutdown(): Promise<void> { /* ... */ }

  return { initialize, shutdown, /* ... */ }
}

Forked Agent Pattern

Memory and compact services use forked agents (subagent calls that share the parent's prompt cache) for efficient background processing:

const result = await runForkedAgent({
  messages,
  systemPrompt,
  tools: [FileReadTool, FileEditTool],
  cacheSafeParams,
})

Cached Feature Flags

Services frequently gate behavior behind feature flags using cached (non-blocking) reads:

function isFeatureEnabled(): boolean {
  return getFeatureValue_CACHED_MAY_BE_STALE('feature_key', false)
}

Source Layout

All services live under src/services/:

src/services/
  api/          # Claude API client, retry logic, errors, usage tracking
  mcp/          # MCP client, transports, connection management
  lsp/          # LSP server manager, diagnostics
  compact/      # Context compaction (auto, micro, session memory)
  oauth/        # OAuth 2.0 PKCE flow
  analytics/    # GrowthBook, event logging, Datadog
  plugins/      # Plugin installation manager
  policyLimits/ # Organization policy restrictions
  SessionMemory/# Session-scoped memory extraction
  extractMemories/ # End-of-query auto-memory
  MagicDocs/    # Auto-updating markdown docs
  tips/         # Tip scheduling and display
  toolUseSummary/ # Tool batch summary generation