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
API Service
Claude API client with streaming, retries, token estimation, and error handling.
MCP Service
Model Context Protocol client managing transports, server connections, and permissions.
LSP Service
Language Server Protocol integration for diagnostics and code intelligence.
Memory Services
Session memory, auto-memory extraction, and Magic Docs for persistent context.
Compact Service
Context compression via auto-compact, micro-compact, and message grouping.
Authentication
OAuth 2.0 with PKCE flow, token management, and profile fetching.
Analytics & Plugins
Feature flags, analytics tracking, plugin management, and policy limits.
Service Initialization
Services initialize at different points during startup:
| Service | Initialization | Blocking? |
|---|---|---|
| OAuth / Auth | Before first API call | Yes |
| Analytics (GrowthBook) | Early startup | No (cached values) |
| MCP Connections | After REPL mount | No (async) |
| LSP Manager | After REPL mount | No (async background) |
| Session Memory | After first query threshold | No (hook-driven) |
| Policy Limits | Background polling | No (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