How context-mode Indexes and Searches Session Events for Resume Functionality
context-mode implements a dual-storage architecture that persists hook-generated events to SQLite tables while simultaneously indexing markdown dumps via FTS5, enabling automatic resume snapshot generation and on-demand retrieval through the ctx_search tool.
The mksglu/context-mode repository provides a session management system designed to maintain context across long-running AI coding sessions without exhausting token limits. By combining structured database storage with full-text search capabilities, the system captures every hook event into durable storage and searchable indexes. This article examines the specific mechanisms—including database schemas, FTS5 indexing, and snapshot generation—that power the resume functionality.
Dual-Storage Architecture
The system employs two complementary persistence layers to balance structured data integrity with searchability.
SQLite Session Tables
Raw events are stored in the session_events table defined in src/session/db.ts. This table maintains a persistent per-project log capturing event types, categories, timestamps, and data payloads. The SessionDB class provides the primary interface through methods including insertEvent, getEvents, upsertResume, getResume, and markResumeConsumed.
FTS5 ContentStore
Simultaneously, events are indexed in an FTS5 SQLite database managed by the ContentStore class in src/store.ts. This full-text search index stores parsed markdown chunks from session events under the source identifier "session-events", enabling BM25-ranked queries. The database resides at ~/.claude/context-mode/content/<hash>.db and persists across tool invocations.
Persisting Hook Events
When platform hooks generate events, the system writes data through two parallel paths to ensure both durability and indexability.
Database Insertion
The executor calls db.insertEvent(sessionId, event, sourceHook) (implemented in src/session/db.ts lines 10-44), which writes rows to session_events and updates session metadata in the session_meta table.
Markdown File Generation
Each platform adapter implements getSessionEventsPath() to return a filesystem path following the pattern:
${hash}${worktreeSuffix}-events.md
For example, the OpenCode adapter in src/adapters/opencode/index.ts (line 274) generates these files, appending event data as markdown sections:
## file_write
/path/to/file.ts
Automatic FTS5 Indexing
The server periodically processes accumulated markdown files to populate the search index.
The maybeIndexSessionEvents Function
Located in src/server.ts (lines 99-103), this function scans the sessions directory for *-events.md files and processes them through the ContentStore:
function maybeIndexSessionEvents(store: ContentStore): void {
const sessionsDir = getSessionDir();
const files = readdirSync(sessionsDir)
.filter(f => f.endsWith("-events.md"));
for (const file of files) {
const filePath = join(sessionsDir, file);
store.index({ path: filePath, source: "session-events" });
unlinkSync(filePath); // Delete after indexing
}
}
ContentStore Processing
The store.index method (line 215 in src/store.ts) parses markdown into semantic chunks and inserts them into the FTS5 content table. This operation runs automatically on every server request, ensuring the search index remains current while removing ephemeral markdown files to prevent duplication.
Building Resume Snapshots
Before session compaction or fresh starts, the system generates concise XML summaries that embed hooks for detailed retrieval.
Snapshot Generation Logic
The buildResumeSnapshot function in src/session/snapshot.ts processes all stored events from SessionDB.getEvents, grouping them by category (files, errors, tasks). For each group, it generates XML containing summary statistics and auto-generated ctx_search calls:
<files count="12">
foo.ts (write×3, read×2)
ctx_search(
queries: ["foo.ts write", "foo.ts read"],
source: "session-events"
)
</files>
Database Persistence
The snapshot is persisted via db.upsertResume(sessionId, snapshot, eventCount) (lines 13-15 in src/session/db.ts). The pi-extension.ts component retrieves this via db.getResume (line 275), injects the XML into the system prompt, and marks it consumed with markResumeConsumed to prevent duplicate injection.
Searching Indexed Events with ctx_search
The ctx_search tool provides on-demand access to the indexed event history without loading complete session logs into context.
Tool Registration
Registered in src/server.ts around line 1180, the tool accepts queries and optional source filtering:
server.registerTool(
"ctx_search",
{
inputSchema: z.object({
queries: z.array(z.string()),
source: z.string().optional(),
})
},
async ({ queries, source }) => {
const results = await store.search(queries, { source });
return trackResponse("ctx_search", { content: results });
}
);
Search Implementation
The store.search method (line 246 in src/store.ts) executes FTS5 queries against the content table. When source: "session-events" is specified, the search restricts results to indexed session history, allowing the model to retrieve original event text on demand rather than maintaining full histories in the active context window.
Complete Resume Workflow
The end-to-end process operates across five distinct phases:
- Event Capture: Hooks trigger
insertEvent, simultaneously writing structured data to SQLite and markdown sections to${hash}-events.mdfiles. - Background Indexing: The server executes
maybeIndexSessionEventson every request, feeding markdown content into the FTS5-backedContentStoreand deleting source files. - Snapshot Injection: Before processing new batches,
pi-extension.tsqueriesgetResumeand injects existing XML snapshots into the system prompt, immediately marking them consumed viamarkResumeConsumed. - Compaction: When sessions exceed configured event limits, the server invokes
buildResumeSnapshot, stores the result viaupsertResume, and truncates old events fromsession_events. - Detail Retrieval: During conversation, the model executes
ctx_searchwithsource: "session-events"to pull specific historical details referenced in the compact snapshot.
Summary
- context-mode maintains dual storage: SQLite tables for structured data (
session_events,session_resume) and FTS5 indexes for full-text search viaContentStore. - Events are written to both database tables and
${hash}${worktreeSuffix}-events.mdfiles bysrc/session/db.tsand platform-specific adapters. - Automatic indexing occurs via
maybeIndexSessionEventsinsrc/server.ts, which populates the FTS5contenttable and cleans up ephemeral markdown files. - Resume snapshots are XML documents generated by
buildResumeSnapshotinsrc/session/snapshot.ts, embedding executablectx_searchcalls for granular detail retrieval. - The
ctx_searchtool queries indexed content throughstore.searchinsrc/store.ts, enabling models to access specific historical events without reloading complete session histories.
Frequently Asked Questions
How does context-mode prevent duplicate resume snapshots from being injected?
The system tracks consumption status through the consumed boolean field in the session_resume table. When pi-extension.ts retrieves a resume via db.getResume, it checks this flag; if false, it injects the snapshot into the prompt and immediately calls markResumeConsumed to update the database record, ensuring the snapshot appears only once in the conversation history.
Can I search session events from specific categories only?
While the ctx_search tool accepts a source parameter to restrict searches to "session-events", category-specific filtering primarily occurs during snapshot generation in src/session/snapshot.ts. The buildResumeSnapshot function groups events by category (files, errors, tasks) when constructing the XML summary, though the underlying FTS5 index stores the raw markdown content without explicit category tags for direct querying.
What happens to the markdown files after indexing?
The maybeIndexSessionEvents function in src/server.ts deletes source markdown files immediately after successful indexing via unlinkSync(filePath). This cleanup prevents duplicate indexing on subsequent requests while the content remains permanently searchable in the FTS5 database stored within the ContentStore file at ~/.claude/context-mode/content/<hash>.db.
Where is the resume snapshot stored between sessions?
Resume snapshots persist in the session_resume table managed by src/session/db.ts. The upsertResume method stores the XML snapshot string alongside metadata including event counts and timestamps, while getResume retrieves it using the session ID, enabling cross-request persistence within the project's SQLite database located in the context-mode configuration directory.
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 →