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.

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, and prompts

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 reuses sdk_sessions rows
  • importSessionSummary – Adds session summaries if not present
  • importObservation – Inserts observations, deduplicating on memory_session_id, title, subtitle, and type
  • importUserPrompt – 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 in scripts/export-memories.ts
  • Import Pipeline: CLI script → POST /api/import → handleImport → SessionStore helpers → SQLite INSERT 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, and plugin/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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →