Claude-Mem Session Import and Export Data Flow: A Complete Technical Guide
Claude-Mem transfers session data through a worker HTTP API pipeline that queries SQLite via TypeScript CLI scripts, never touching database files directly, enabling idempotent backups and cross-machine migrations.
The thedotmack/claude-mem repository persists every conversation as structured SDK sessions linked to observations, summaries, and prompts within a SQLite database. Understanding the data flow for importing and exporting sessions in Claude-Mem is critical for archiving memories or migrating between development environments, as the architecture enforces strict separation between CLI interfaces and storage operations through a local HTTP worker service.
Export Flow: Database to Portable JSON
The export process transforms relational database records into a single portable JSON file through six discrete steps orchestrated by scripts/export-memories.ts.
CLI Initialization and Hybrid Search
The export begins in scripts/export-memories.ts, where the exportMemories() function parses command-line arguments (<query> <output-file> [--project]) and loads the worker port from ~/.claude-mem/settings.json via the SettingsDefaultsManager class. The script initiates a hybrid search by issuing an HTTP GET request to GET /api/search?query=…&format=json&limit=999999.
The format=json parameter instructs the worker's handleSearch() function (compiled in plugin/scripts/worker-service.cjs) to return raw database rows rather than rendered UI data. This returns three collections: observations, sessions, and prompts.
Session Metadata Aggregation
After receiving the search results, the script scans the returned observations and session summaries to build a Set<string> of unique memory_session_id values (lines 53-60 in export-memories.ts). It then fetches full SDK session metadata by POSTing to POST /api/sdk-sessions/batch with a payload containing { sdkSessionIds: [...] }.
The worker route handleBatchSdkSessions() (in plugin/scripts/worker-service.cjs) returns complete rows from the sdk_sessions table, including content-session IDs, project associations, and timestamps.
ExportData Assembly and Serialization
With all data collected, the script assembles an ExportData object (lines 80-92) containing:
- Export timestamp and original query
- Optional project filter
- Record counts
- Four arrays:
observations,sessions,summaries, andprompts
Finally, the object is serialized with two-space indentation and written to disk via fs.writeFileSync (line 95), producing a JSON file suitable for version control or transfer to another machine.
Import Flow: JSON to Database
The import process reverses the pipeline, feeding the exported JSON back into the SQLite database through idempotent insert operations handled by scripts/import-memories.ts.
CLI Validation and Payload Upload
The importMemories() function in scripts/import-memories.ts first validates the worker's health by calling GET /api/stats. It then reads the supplied JSON file and POSTs the four top-level arrays (sessions, summaries, observations, prompts) to POST /api/import (lines 48-58).
Worker Processing and Deduplication
The worker's handleImport function (in plugin/scripts/worker-service.cjs around line 700) receives the payload and delegates each array to specialized SessionStore import helpers in src/services/sqlite/SessionStore.ts:
importSdkSession– Creates or reusessdk_sessionsrowsimportSessionSummary– Adds session summaries if not presentimportObservation– Inserts observations, deduplicating onmemory_session_id,title,subtitle, andtypeimportUserPrompt– Stores prompts only if the(content_session_id, prompt_number)pair is new
Each helper implements idempotent INSERT OR IGNORE logic by first executing a SELECT to detect duplicates, then performing an INSERT only if no existing record is found. The helpers return {imported: true/false, id: <row-id>} objects that the route aggregates into a statistics object.
Database Persistence
All insert operations occur within the same SQLite connection opened in WAL mode (Write-Ahead Logging), as configured in the SessionStore constructor (lines 30-34). This ensures durability and atomicity even if the worker restarts during import. The route responds with { success: true, stats: { … } }, which the CLI renders as human-readable counts of imported versus skipped records.
Practical Implementation Examples
Exporting Specific Memory Sets
Search for memories containing "authentication" and export them to a JSON file:
npx tsx scripts/export-memories.ts "authentication" auth-memories.json
The resulting auth-memories.json contains the four data arrays plus metadata fields (exportedAt, query, and counts).
Importing to a New Instance
Transfer the exported file to another machine running Claude-Mem and import:
# Ensure the worker is running (default port 37777)
npx tsx scripts/import-memories.ts auth-memories.json
Console output displays sessionsImported versus sessionsSkipped statistics based on existing database state.
Programmatic API Access
For custom automation, interact directly with the worker HTTP API:
import fetch from 'node-fetch';
import { readFileSync } from 'fs';
import { join } from 'path';
import { homedir } from 'os';
import { SettingsDefaultsManager } from '../src/shared/SettingsDefaultsManager';
// Resolve worker URL from settings
const settings = SettingsDefaultsManager.loadFromFile(
join(homedir(), '.claude-mem', 'settings.json')
);
const workerUrl = `http://localhost:${settings.CLAUDE_MEM_WORKER_PORT}`;
// Load and import export file
const payload = JSON.parse(readFileSync('my-export.json', 'utf-8'));
const res = await fetch(`${workerUrl}/api/import`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload)
});
const { stats } = await res.json();
console.log('Import statistics:', stats);
Summary
- Export Pipeline: CLI script →
GET /api/search→POST /api/sdk-sessions/batch→ JSON file assembly inscripts/export-memories.ts - Import Pipeline: CLI script →
POST /api/import→handleImport→SessionStorehelpers → SQLiteINSERT OR IGNORE - Idempotency: Running the same import multiple times only inserts new records on the first run, reporting subsequent attempts as skipped
- Architecture: All database access flows through the compiled worker (
plugin/scripts/worker-service.cjs); CLI scripts never touch SQLite files directly - Key Files:
scripts/export-memories.ts,scripts/import-memories.ts,src/services/sqlite/SessionStore.ts, andplugin/scripts/worker-service.cjs
Frequently Asked Questions
Does importing duplicate existing sessions?
No. The import flow is fully idempotent. The SessionStore helpers in src/services/sqlite/SessionStore.ts execute SELECT checks before INSERT OR IGNORE operations, ensuring that duplicate sdk_sessions, observations, or prompts are skipped rather than duplicated. The API response explicitly indicates how many records were imported versus skipped.
Can I bypass the worker and import directly into the SQLite file?
No. According to the thedotmack/claude-mem source code, the CLI scripts are designed to interact exclusively with the worker HTTP API (default port 37777). Direct SQLite manipulation would bypass the deduplication logic in importSdkSession and importObservation, risking data corruption and breaking the application's internal consistency guarantees.
What happens if the worker is not running during export or import?
Both scripts/export-memories.ts and scripts/import-memories.ts validate connectivity before operations. The import script explicitly checks GET /api/stats before attempting to POST data. If the worker is unreachable, the CLI will fail with a connection error rather than attempting direct database access.
Which database tables are affected during import?
The import process modifies four core tables: sdk_sessions (via importSdkSession), session_summaries (via importSessionSummary), observations (via importObservation), and user_prompts (via importUserPrompt). All tables utilize SQLite's WAL mode for transaction safety, ensuring that partial imports can be recovered without data loss.
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 →