Skip to content

Session persistence, replay, and indexing

This page maps the Copilot CLI session persistence stack end to end: raw JSONL events, SessionFs, workspace sidecar files, SQLite indexing, dynamic context storage, search/reindex, fork, checkpoint, rewind, and cloud sync. It fills the gap between the broad session lifecycle, the SessionFs provider, and session-store SQLite indexing.

The key idea is that the CLI has several persistence layers with different authority levels. events.jsonl is the local replay source of truth; workspace files store human-readable sidecar state; session-store.db is a derived searchable index; remote/cloud state is an optional synchronization/export layer.

Because app.js is bundled/minified, source anchors below are search aids for this extracted package, not stable API names.

Source anchors

LayerSemantic aliasMinified anchor / stringApprox. lineRole
State rootsSessionStatePathsI1(t), _y(t,e), ili="session-state"236, 7449Computes the state root and per-session directory under .copilot/state.
Event log storeSessionEventLogStoreIp=HHr(..., "session", ...), events.jsonl, .jsonl236, 4396Reads, appends, truncates, and lists durable JSONL events.
Filesystem abstractionSessionFsBaseZge, VC extends Zge, i1t extends Zge555, 6096Lets the same session code write local files or SDK/RPC-backed provider files.
Debounced writerDebouncedSessionWriterETt4396-4481Buffers non-ephemeral events and appends them through the active SessionFs.
Runtime replayRuntimeSessionReplayua.fromEvents, processEventForState4471Rebuilds chat, system, tool, compaction, and session state from retained events.
Workspace sidecarsWorkspaceManagerqq, workspace.yaml, plan.md, checkpoints, files, research, session.db3559-3573Stores metadata, plans, checkpoint markdown, persistent files, research artifacts, and session-local DB state.
Plan/file eventsWorkspaceStateEventssession.plan_changed, session.workspace_file_changed4361, 4477-4487Bridges sidecar file changes back into the event stream and UI projections.
Compaction checkpointsCompactionCheckpointStorepersistCompactionCheckpoint(...), qq.addSummary(...), session.compaction_complete3559, 4361, 4479Writes summary checkpoints and links them to compaction events.
Rewind truncationSnapshotRewindtruncate, session.snapshot_rewind, upToEventId, eventsRemoved236, 4361, 4471Rewrites event history to a boundary and rebuilds in-memory state.
Fork copyForkStateCopyforkSession(...), copyForkedSessionState(...)5756Copies/rekeys events and workspace artifacts into a new session branch.
Local SQLite storeSessionStoreDatabasesession-store.db, node:sqlite, DatabaseSync4518, 7449Stores searchable/indexed session history in the CLI state directory.
Store schemaSessionStoreSchemasessions, turns, checkpoints, session_files, session_refs, search_index, dynamic_context_items4569-4582Defines relational and FTS tables derived from events and sidecar files.
Live indexerSessionStoreTrackerJZn(...), post-tool hooks4518-4582Subscribes to live events and tool completions to maintain SQLite rows.
Reindex commandSessionReindexCommand/reindex, Index all session history into the session store.4643-4644Rebuilds local SQLite rows and optionally syncs cloud session state.
SQL query toolSessionStoreSqlToolsession_store_sql, executeReadOnly, SQLITE_READ, SQLITE_SELECT4518Exposes read-only local/global session-store queries.
State migrationCopilotStateMigration.copilot, session-state, session-store.db, command-history-state7449Treats session-state and session-store DB as first-class persistent artifacts.
Cloud syncCloudSessionStoreSyncStarting cloud session sync, eventsUploaded, backfillQueued, analytics/backfill4516, 4643-4644Uploads/indexes events into optional cloud session-store paths when gated.

Layer model

flowchart TD
Session[Runtime session events] --> Writer[ETt debounced writer]
Writer --> Jsonl[events.jsonl]
Session --> Workspace[WorkspaceManager qq]
Workspace --> YAML[workspace.yaml]
Workspace --> Plan[plan.md]
Workspace --> Checkpoints[checkpoints/*.md]
Workspace --> Files[files/ and research/]
Workspace --> LocalDb[session.db]
Session --> LiveIndexer[JZn live tracker]
Jsonl --> Reindex[/reindex scanner]
Workspace --> Reindex
LiveIndexer --> Store[session-store.db]
Reindex --> Store
Store --> FTS[search_index FTS5]
Store --> SQL[session_store_sql]
Store --> Chronicle[/chronicle]
Session --> RemoteExporter[Mission Control exporter]
Jsonl --> CloudSync[cloud session-store sync]
CloudSync --> Cloud[cloud indexed history]

The layers should be read from left to right by authority:

  1. runtime emits events and sidecar changes;
  2. JSONL and workspace files are the local replay and artifact sources;
  3. SQLite indexes selected information for search/query;
  4. cloud sync/export provides optional remote visibility.

Persistence layers and authority

LayerPrimary files/tablesCanonical forRebuildable?Notes
Event logsession-state/<id>/events.jsonlLocal resume, replay, fork, handoff reconstructionNo, except from external backups or remote logsMost important durable session record.
Workspace sidecarsworkspace.yaml, plan.md, checkpoints/, files/, research/, session.dbHuman-readable metadata, plans, checkpoint summaries, session-owned artifactsPartlySome sidecars are derived from events, but user/session artifacts may be unique state.
SessionFs backendLocal VC or RPC i1t providerWhere event/workspace files physically liveDepends on providerEnables SDK-owned persistence without changing session logic.
SQLite storesession-store.db tables and search_indexSearch, Chronicle, refs, SQL/debug queryYes, via /reindex, with possible information loss versus raw eventsDerived index, not the canonical event log.
Dynamic context boarddynamic_context_items tableRepository/branch memory/context board entriesPartlyProduced by memory/context workflows, not all session transcript text.
Cloud store/exportMission Control/cloud session store recordsRemote steering, cloud history, analytics backfillPartlyOptional and gated; schema can differ from local SQLite.

Write paths

1. Event append path

sequenceDiagram
autonumber
participant Runtime as Runtime session
participant Writer as ETt
participant Fs as SessionFs
participant Log as events.jsonl
participant Index as JZn tracker
Runtime->>Runtime: emit durable session event
Runtime-->>Writer: on("*") subscription
Runtime-->>Index: live event subscription
Writer->>Writer: debounce and filter ephemeral events
Writer->>Fs: append serialized JSONL
Fs->>Log: write through local or RPC backend
Index->>Index: update turn/file/ref/checkpoint rows when relevant

Important behavior:

  • ephemeral UI/progress events are not blindly persisted;
  • session.resume and session.shutdown alone do not force meaningful persistence;
  • writer failures emit ephemeral persistence errors and requeue pending events;
  • large/bulky tool payloads can be reduced before appending to the event log.

2. Workspace sidecar path

flowchart TD
SessionAction[Session action] --> Workspace[WorkspaceManager qq]
Workspace --> Metadata[workspace.yaml]
Workspace --> Plan[plan.md]
Workspace --> Checkpoint[checkpoints/index.md and numbered summaries]
Workspace --> Files[files/]
Workspace --> Research[research/]
Workspace --> SessionDb[session.db]
Workspace --> Events[session.plan_changed / session.workspace_file_changed / compaction events]

Sidecar files are used when plain event replay is not the best representation:

ArtifactProducerConsumer
workspace.yamlcreate/resume/update metadata pathsession listing, name lookup, relevance ranking, remote export, cleanup
plan.mdplan APIs and editing/tool detection/session plan, model context, checkpoint/fork copy
checkpoints/*.mdcompaction checkpoint persistence/session checkpoints, rewind/fork truncation, search/indexing
files/session workspace tools and large/session-owned artifactstools, fork copying, session-store file indexing
research/research and memory workflowsfork copying, session-local research artifacts
session.dbsession-local database pathstate that benefits from SQLite-like access inside one session

3. Derived index path

flowchart TD
Live[Live session events] --> Tracker[JZn]
Tracker --> Turns[turns]
Tracker --> Sessions[sessions]
Tracker --> Files[session_files]
Tracker --> Refs[session_refs]
Tracker --> Checkpoints[checkpoints]
Tracker --> Search[search_index]
Existing[Existing session-state dirs] --> Reindex[/reindex]
Reindex --> Turns
Reindex --> Files
Reindex --> Refs
Reindex --> Checkpoints
Reindex --> Search

session-store.db is optimized for query rather than replay. It tracks turns, summaries, checkpoint sections, touched files, refs, full-text search rows, and dynamic context entries. It can be regenerated from available JSONL and workspace files, but it may not preserve every detail from raw event logs.

Read and reconstruction paths

OperationReads fromReconstructs or returns
--resume <id> / server session.resumeevents.jsonl plus workspace metadataua.fromEvents(...) runtime session, then session.resume event.
--continueworkspace.yaml, event metadata, git/repo context, possibly local/remote listingsBest matching previous session for branch/repository/git-root/cwd.
/session infolive session and workspace metadataID, cwd, repo, branch, name, checkpoint count.
/session checkpointscheckpoints/index.md and numbered checkpoint fileslist or checkpoint markdown content.
/forksource event log or in-memory non-ephemeral events plus sidecar filesnew session ID, rewritten session.start, copied/truncated workspace artifacts.
/rewind / /undoevent log boundary and retained event prefixtruncated events.jsonl, replayed in-memory state, ephemeral session.snapshot_rewind.
/reindexall session-state directories and workspace artifactsrebuilt session-store.db and optional cloud sync.
session_store_sqlsession-store.db or cloud prefetch dataread-only query results, capped/truncated for safety.

Fork, rewind, checkpoint, and compaction interactions

These operations are easy to confuse because all touch history boundaries.

OperationMutates current event log?Creates a new session?Touches workspace sidecars?Main event/schema
/compactAppends compaction events; does not remove the existing JSONL prefix by itselfNoWrites checkpoint markdown and updates summary_countsession.compaction_start, session.compaction_complete
/rewind / /undoYes, truncates events.jsonl before the target eventNoCan require checkpoint/workspace state alignmentsession.snapshot_rewind ephemeral update
/forkNo for the source; writes a rewritten prefix to the destinationYesCopies/rekeys workspace.yaml, plan.md, checkpoints/, files/, research/fork-info events and rewritten session.start
/reindexNoNoReads sidecars and checkpoint markdownSQLite rows and optional cloud sync results

Compaction is semantic compression of current conversation state. Rewind is event-log truncation. Fork is branch creation. Reindex is derived-store rebuild. They share inputs but have different authority and safety properties.

SessionFs and provider-owned persistence

The persistence pipeline is filesystem-agnostic. SessionFs abstracts file operations, path conventions, and lock keys:

BackendTypical contextPersistence implication
Local VCTUI, prompt, normal CLI/server without a custom providerFiles live under the local CLI state root.
RPC i1tSDK/server client installed sessionFs.setProviderThe connected SDK client owns the provider filesystem; runtime file operations become reverse calls.

Provider mode matters because the same events.jsonl, checkpoints, plans, and large-output temp files may not be on the CLI host filesystem. Docs and debugging tools should identify the active SessionFs backend before assuming local paths.

Search, Chronicle, and SQL are derived consumers

session-store.db supports:

  • full-text search through search_index;
  • session metadata queries through sessions;
  • turn analysis through turns;
  • file/ref discovery through session_files and session_refs;
  • checkpoint summary retrieval through checkpoints;
  • dynamic context board entries through dynamic_context_items;
  • read-only SQL via session_store_sql;
  • Chronicle standup/tips/improvement flows.

The read-only SQL authorizer permits read/select/function/recursive-style operations and rejects mutation. This makes the query tool suitable for debugging and reports without turning the model into a write-capable database client.

Staleness and recovery

SymptomLikely layerRecovery or interpretation
Session resumes but does not appear in searchSQLite index stale or missingRun /reindex; raw events.jsonl may still be fine.
Search result lacks a detailed tool payloadDerived index intentionally summarized or filteredInspect raw event log or session workspace artifacts if safe.
/session checkpoints missing entries after compaction failureWorkspace checkpoint write failed or compaction failed before persistenceCheck session.compaction_complete status and logs.
Forked session misses later checkpointsFork boundary excluded later compactionsExpected when forking before the later checkpoint event.
Provider-backed session files are not on disk locallyRPC SessionFs activeInspect the SDK provider’s storage, not the CLI host path.
Cloud history differs from local SQLiteCloud sync schema/gating/backfill differencesTreat cloud store as a separate derived/exported view.

Relationship to other docs

Created and maintained by Yingting Huang.