# Claude-Mem Session Import and Export Data Flow: A Complete Technical Guide

> Explore the Claude-Mem session import export data flow. Learn how worker HTTP APIs query SQLite via TypeScript CLI scripts for seamless backups and migrations. Understand the technical process.

- Repository: [Alex Newman/claude-mem](https://github.com/thedotmack/claude-mem)
- Tags: how-to-guide
- Published: 2026-02-19

---

**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`](https://github.com/thedotmack/claude-mem/blob/main/scripts/export-memories.ts).

### CLI Initialization and Hybrid Search

The export begins in [`scripts/export-memories.ts`](https://github.com/thedotmack/claude-mem/blob/main/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`](https://github.com/thedotmack/claude-mem/blob/main/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`](https://github.com/thedotmack/claude-mem/blob/main/scripts/import-memories.ts).

### CLI Validation and Payload Upload

The `importMemories()` function in [`scripts/import-memories.ts`](https://github.com/thedotmack/claude-mem/blob/main/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`](https://github.com/thedotmack/claude-mem/blob/main/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:

```bash
npx tsx scripts/export-memories.ts "authentication" auth-memories.json

```

The resulting [`auth-memories.json`](https://github.com/thedotmack/claude-mem/blob/main/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:

```bash

# 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:

```typescript
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`](https://github.com/thedotmack/claude-mem/blob/main/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`](https://github.com/thedotmack/claude-mem/blob/main/scripts/export-memories.ts), [`scripts/import-memories.ts`](https://github.com/thedotmack/claude-mem/blob/main/scripts/import-memories.ts), [`src/services/sqlite/SessionStore.ts`](https://github.com/thedotmack/claude-mem/blob/main/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`](https://github.com/thedotmack/claude-mem/blob/main/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`](https://github.com/thedotmack/claude-mem/blob/main/scripts/export-memories.ts) and [`scripts/import-memories.ts`](https://github.com/thedotmack/claude-mem/blob/main/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.