How the Kimi Code Session Management System Works: A Three-Layer Architecture
The Kimi Code session management system implements a robust three-layer architecture separating filesystem persistence, RPC service logic, and protocol definitions to enable atomic session operations, real-time status tracking, and consistent cross-platform behavior across the MoonshotAI/kimi-code repository.
The session management system in MoonshotAI/kimi-code coordinates complex AI agent interactions through a sophisticated design that spans on-disk storage, real-time event streaming, and workspace isolation. This architecture ensures that sessions remain consistent across multiple front-ends including the CLI, web UI, and VS Code extension, while providing atomic operations for creation, forking, and archival.
Three-Layer Architecture Overview
The system organizes functionality into three tightly coupled layers:
| Layer | Responsibility | Core Files |
|---|---|---|
| Persistence | Stores sessions on disk, maintains a global index, and handles creation, forking, renaming, archiving, and deletion. | packages/agent-core/src/session/store/session-store.ts |
| Service | Exposes a high-level RPC-style API used by the engine, translates RPC calls into persistence actions, and publishes status events. | packages/agent-core/src/services/session/sessionService.ts |
| Protocol | Defines the wire-format types (Session, SessionSummary, SessionUpdate, etc.) that client SDKs and servers exchange. |
packages/protocol/src/session.ts |
Session Persistence Layer (SessionStore)
The persistence layer implements durable storage through the SessionStore class in packages/agent-core/src/session/store/session-store.ts.
Directory Layout and Workspace Buckets
All sessions live under the path <home>/sessions/<bucket>/<session-id>/. The workspace bucket derives from a hash of the normalized workDir computed by encodeWorkDirKey, unless a workspace registry resolves the physical root to a predefined workspace ID. This design prevents duplicate buckets on case-variant Windows paths by canonicalizing directory strings before hashing.
The Append-Only Index
Session lookup relies on an append-only index stored at sessions/index.jsonl, which contains SessionIndexEntry records mapping session IDs to their directories and work-directories. The index enables fast lookups without filesystem scanning and can be rebuilt via SessionStore.reindex() if corrupted, which scans the filesystem, recovers work-dirs from each state.json, and repairs missing entries without overwriting valid data.
Atomic Operations and Error Handling
Core operations—including create, fork, rename, archive, delete, and list—manipulate both the index and on-disk files atomically. Each session directory contains a state.json for metadata and wire.jsonl for recorded agent events. Failures such as "session already exists" or "invalid title" raise strongly-typed KimiError instances with appropriate ErrorCodes.
Forking Sessions
The SessionStore.fork() method implements session branching by copying the source directory, optionally truncating history at a specific turn, dropping unneeded files like upcoming-goals.json, and updating state.json with fork metadata including forkedFrom and timestamps. Forking also appends a "forked" record to each agent's wire.jsonl to maintain audit trails.
Session Service Layer (SessionService)
The service layer acts as the bridge between RPC surface and persistence, implemented in packages/agent-core/src/services/session/sessionService.ts.
Event-Driven Status Management
SessionService maintains per-session work facts (busy, main_turn_active, pending_interaction, last_turn_reason) by listening to bus events such as turn.started, turn.ended, prompt.submitted, and event.approval.requested. These facts are recomputed via _computeWorkFacts and published as event.session.work_changed events through the IEventService defined in packages/agent-core/src/services/event/event.ts.
CRUD Operations and RPC Integration
Public methods including create, list, get, update, fork, createChild, and archive forward to the core RPC service (this.core.rpc.*). After each mutation, _patchSessionStatus augments the protocol session with live facts before emitting creation events. The service throws strongly-typed errors like SessionNotFoundError and SessionUndoUnavailableError to client SDKs.
Undo and Compaction Support
The undo method validates user input history via canUndoHistory before issuing undoHistory on the core RPC. The compact operation triggers beginCompaction after resuming the session in memory, allowing the system to condense event logs while preserving semantic state.
Protocol Layer and Type Definitions
The protocol layer defined in packages/protocol/src/session.ts establishes the contract between clients and server.
Core Session Types
Key types include:
Session– The full session object exposed to UIs, containingid,title,busy,main_turn_active, and metadata.SessionSummary– Lightweight records for listing sessions, containing timestamps,archivedflags, and optionallastPrompt.SessionCreate,SessionUpdate,SessionFork– Input shapes accepted by the service layer for mutations.
Wire Format Stability
These TypeScript definitions ensure a stable contract across the TUI, web UI, VS Code extension, and Node SDK, preventing breaking changes in serialized session data.
Event Flow and Real-Time Updates
Session changes propagate through a four-stage pipeline:
- Client requests arrive at REST/WebSocket endpoints (
/api/v1/sessions) and route toSessionServicemethods. - Service updates
SessionStoreor calls core RPC, triggering disk mutations and index updates. - Service patches sessions with live facts via
_computeWorkFactsand firesevent.session.createdorevent.session.work_changed. - UI components subscribe via
IEventServiceand refresh session lists, status badges, or transcript views.
Integration with Subsystems
Session management interacts with several supporting services:
- Workspace Registry – Located in
packages/agent-core/src/session/store/workdir-key.ts, providesresolveWorkspaceIdto mapworkDirto stable buckets and handle Windows path canonicalization. - Prompt Service – Supplies current prompt IDs to determine
mainTurnActivestatus. - Approval and Question Services – Contribute to the
busyflag by exposing pending user interactions.
Working with the Session API
The following examples demonstrate common operations using the Node SDK.
Creating a new session:
import { Klient } from '@moonshot-ai/klient';
async function newSession() {
const client = new Klient({ baseUrl: 'http://localhost:58627' });
const session = await client.global.sessions.create({
metadata: { cwd: '/home/alice/project' },
title: 'Exploring Kimi',
});
console.log('Created session:', session.id);
}
Forking a session at turn 2:
const forked = await client.global.sessions.fork('session-abc123', {
title: 'Fork of Exploration',
turnIndex: 2, // truncate after the 2nd user turn
});
console.log('Forked session ID:', forked.id);
Listing non-archived sessions:
const list = await client.global.sessions.list({
workspaceId: 'workspace-my-repo',
excludeEmpty: true,
});
list.items.forEach(s => console.log(`${s.title} (${s.id})`));
Subscribing to status changes via WebSocket:
const ws = new WebSocket('ws://localhost:58627/api/v1/ws');
ws.onmessage = ev => {
const event = JSON.parse(ev.data);
if (event.type === 'event.session.work_changed') {
console.log(`Session ${event.sessionId} busy=${event.busy}`);
}
};
Summary
- Three-layer design separates filesystem persistence (
SessionStore), RPC service logic (SessionService), and protocol types (@moonshot-ai/protocol). - Atomic storage uses workspace buckets, an append-only index at
sessions/index.jsonl, and per-sessionstate.jsonandwire.jsonlfiles. - Real-time status propagates via event-driven work facts and the
event.session.work_changedevent. - Robust forking copies directories, truncates history, and maintains audit trails in
wire.jsonl. - Cross-platform safety relies on workspace registry canonicalization in
workdir-key.tsto handle case-sensitivity issues.
Frequently Asked Questions
How does Kimi Code store session data on disk?
Sessions are stored under <home>/sessions/<bucket>/<session-id>/ as defined in packages/agent-core/src/session/store/session-store.ts. Each session contains a state.json file for metadata and a wire.jsonl file for recorded agent events, organized into workspace buckets derived from normalized directory paths.
What happens when I fork a session in Kimi Code?
The SessionStore.fork() method copies the source directory to a new location, optionally truncates the history at a specified turn index, removes temporary files like upcoming-goals.json, updates state.json with forkedFrom metadata, and appends a fork record to wire.jsonl to preserve the audit trail.
How does the session service track real-time activity status?
SessionService computes work facts (busy, main_turn_active, pending_interaction) by listening to internal bus events such as turn.started and prompt.submitted. It publishes these status changes via event.session.work_changed through the event bus defined in packages/agent-core/src/services/event/event.ts, allowing UI components to react instantly.
Can session data be recovered if the index becomes corrupted?
Yes. The SessionStore.reindex() method scans the filesystem, recovers work-directories from each session's state.json, and reconstructs the append-only index at sessions/index.jsonl without overwriting existing valid data, effectively repairing the catalog while preserving session integrity.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →