Export & Import

Your Retrace journal is a plain SQLite file. This guide covers backup, restore, and migrating entries between local and cloud modes.

Backing Up Your Local Journal

Your journal lives at ~/.retrace/journal.db by default (or the path set by RETRACE_DB_PATH). Back it up like any file:

# Simple copy
cp ~/.retrace/journal.db ~/Dropbox/retrace-backup.db

# Timestamped backup
cp ~/.retrace/journal.db ~/backups/retrace-$(date +%Y%m%d).db

# SQLite dump (portable text format)
sqlite3 ~/.retrace/journal.db .dump > ~/retrace-dump.sql

Restoring from Backup

# Restore from copy
cp ~/Dropbox/retrace-backup.db ~/.retrace/journal.db

# Restore from SQL dump
sqlite3 ~/.retrace/journal.db < ~/retrace-dump.sql

The server will pick up the restored data automatically on next start.

Exporting to JSONL

Use the built-in export command to dump all entries to newline-delimited JSON:

# Export all entries
npx retrace-mcp@latest export > retrace-export.jsonl

# Export with date range
npx retrace-mcp@latest export --from 2024-01-01 --to 2024-12-31 > retrace-2024.jsonl

# Export a single project
npx retrace-mcp@latest export --project "my-project" > project-export.jsonl

# Custom database path
npx retrace-mcp@latest export --db-path /path/to/journal.db > retrace-export.jsonl

The export writes one JSON object per line to stdout and a summary (entry count) to stderr. Each line is a complete entry object compatible with the cloud import API.

Migrating Local Entries to Cloud

To migrate your local history to cloud mode:

  1. Export your local entries:
    npx retrace-mcp@latest export > retrace-export.jsonl
  2. Convert the JSONL file to a JSON array:
    jq -s '.' retrace-export.jsonl > retrace-import.json
  3. Create an API token at retrace-zeta.vercel.app/tokens.
  4. Upload to the cloud:
    curl -X POST https://retrace-zeta.vercel.app/api/entries/import \
      -H "Authorization: Bearer <your-token>" \
      -H "Content-Type: application/json" \
      -d @retrace-import.json

The import endpoint returns a summary:

{ "imported": 312, "failed": 0, "errors": [] }

Entries with validation errors are counted as failed and reported individually. The batch limit is 1,000 entries per request — split larger exports with split -l 1000 retrace-export.jsonl chunk_ then convert each chunk separately.

Moving Between Machines

To move your local journal to a new machine:

  1. Copy ~/.retrace/journal.db to the new machine (same path).
  2. Install retrace-mcp on the new machine and configure your MCP client.
  3. Start the server — it picks up the existing database automatically.

Switching to Cloud (Keep Local as Archive)

You can run the local server in parallel as a read-only archive while new entries go to cloud. Update your MCP client config:

{
  "mcpServers": {
    "retrace": {
      "url": "https://retrace-zeta.vercel.app/mcp"
    },
    "retrace-archive": {
      "command": "npx",
      "args": ["-y", "retrace-mcp@latest"],
      "env": {
        "RETRACE_DB_PATH": "/path/to/old-journal.db"
      }
    }
  }
}

Tell your agent to log new entries to retrace and query both when doing historical lookups.

Import API Reference

POST /api/entries/import — Bulk import entries into the cloud journal.

Authentication: Bearer token (from retrace-zeta.vercel.app/tokens) or active session cookie.

Body: JSON array of entry objects. Each object supports:

[
  {
    "content":   "string (required)",
    "category":  "coding|debugging|reviewing|deploying|meeting|research|planning|general",
    "project":   "string|null",
    "tags":      ["string"] | "comma,separated" | null,
    "people":    ["string"] | "comma,separated" | null,
    "refs":      ["string"] | "comma,separated" | null,
    "component": "string|null",
    "source":    "string|null",
    "timestamp": "ISO 8601 string|null"
  }
]

Response:

{ "imported": number, "failed": number, "errors": [{ "index": number, "error": string }] }

SQLite Schema

The local database schema (for custom queries or tooling):

-- Journal entries
CREATE TABLE entries (
  id          INTEGER PRIMARY KEY AUTOINCREMENT,
  content     TEXT NOT NULL,
  category    TEXT,
  project_id  INTEGER REFERENCES projects(id),
  component   TEXT,
  people      TEXT,  -- comma-separated: "Alice,Bob"
  refs        TEXT,  -- comma-separated: "JIRA-123,PR #42"
  tags        TEXT,  -- comma-separated: "performance,caching"
  source      TEXT,
  timestamp   TEXT NOT NULL DEFAULT (datetime('now'))
);

-- Projects
CREATE TABLE projects (
  id          INTEGER PRIMARY KEY AUTOINCREMENT,
  name        TEXT NOT NULL UNIQUE,
  description TEXT,
  created_at  TEXT NOT NULL DEFAULT (datetime('now'))
);

-- Full-text search index
CREATE VIRTUAL TABLE entries_fts USING fts5(
  content, project, tags, people, refs, component,
  content_rowid=id
);

-- Schema version
CREATE TABLE _meta (key TEXT PRIMARY KEY, value TEXT);