# Passport Bootstrap

> Use when the user installs mnemo-mcp on a fresh machine and wants to restore prior memory state from S3 or Google Drive (Phase 2 passport sync). Triggers on phrases like "set up mnemo on this machine", "restore my memory passport", "import passport", "bootstrap mnemo", or when the user says they got a new laptop / VM and wants their memories back.

- Skill: `n24q02m/passport-bootstrap` (Agent Skill)
- Install (CLI): `npx skillmds@latest add n24q02m/passport-bootstrap`
- Raw SKILL.md: https://api.skillmd.com/api/skills/n24q02m/passport-bootstrap/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- Author: n24q02m (https://skillmd.com/u/n24q02m)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/n24q02m/passport-bootstrap

---


# Passport Bootstrap

Restore an encrypted memory passport from a configured backend so a
fresh mnemo-mcp install picks up the user's full memory history.

## When to Use

Trigger on explicit signals:

- "set up mnemo on this machine"
- "restore my passport" / "import my memory passport"
- "bootstrap mnemo on this laptop / VM"
- New-machine context: "I just installed mnemo on a new device"
- Recovery context: "I lost my memories, can you restore from S3?"

Do NOT trigger when the user is on an already-configured machine
(check `config(action="status")` first - if `total_memories > 0`,
ask before importing because import LWW-merges and may NOT overwrite
local rows newer than the bundle).

## Workflow

### Step 1: Detect configured backend

Call `config(action="status")` and inspect the response. The default
backend is the first entry of `SYNC_BACKEND` env (defaults to
`gdrive`). If both `s3` and `gdrive` are configured, ask the user
which one to import from. If neither is configured, stop and tell the
user they need to run the relay form first
(`config(action="setup_start")` in HTTP mode, or set
`SYNC_S3_BUCKET` + `GOOGLE_DRIVE_CLIENT_ID` env vars in stdio mode).

### Step 2: Confirm passphrase

The bundle is AES-256-GCM-encrypted with an Argon2id-derived key from
the user's passphrase. The MCP server needs the RAW passphrase to
decrypt - the Argon2id hash stored in `config.enc` is verification-
only.

In stdio mode: instruct the user to set `SYNC_PASSPHRASE` env var
before running `mnemo-mcp` (or to relaunch with the env exported).

In HTTP mode: prompt the user to submit the relay form's passphrase
field again (the raw value is held in process memory only and is
cleared on restart - it is NEVER persisted).

### Step 3: Import the bundle

Call `config(action="import_passport", key="<backend>")` where
`<backend>` is `s3` or `gdrive`. The server pulls the latest bundle
from the chosen backend, decrypts with the supplied passphrase, and
applies each row via last-write-wins per row (local rows newer than
the bundle row are preserved + an audit row is written to
`sync_overrides`).

### Step 4: Verify

After the response lands, call `config(action="status")` again and
confirm `total_memories` matches expectations. If the response from
step 3 reports `inserted > 0` but `total_memories` did not move,
something else is wrong (caller should escalate, not silently
proceed).

## Failure Modes

- **"SYNC_PASSPHRASE not set"** -> Step 2 was skipped. Re-prompt for
  the passphrase, do NOT pick a default value.
- **"Passphrase mismatch or tampered bundle"** -> wrong passphrase,
  OR the bundle was modified at rest. Generic message by design (no
  passphrase oracle). Tell the user to double-check the passphrase;
  if confirmed correct, the bundle may need re-upload from a clean
  source.
- **"no_passport"** -> the backend bucket / folder is empty. Either
  the user has never run `config(action="sync_now")` from another
  machine, or the bucket name in the relay form was wrong. Ask them
  to verify on the source machine.
- **`KeyError` on backend name** -> backend isn't registered. Means
  `SYNC_S3_BUCKET` is empty (for s3) or the gdrive token is missing.
  Run the relay form to populate.

## Anti-Patterns

- Do NOT call `config(action="sync_now")` before import - that would
  push the empty local DB on top of the remote, deleting other
  machines' state.
- Do NOT call `memory(action="import", data=...)` - that imports
  Phase 1 JSONL files, NOT Phase 2 encrypted passport bundles.
- Do NOT proceed silently when the user supplied no passphrase.
  Importing yields cryptic "Passphrase mismatch" errors instead of
  the cleaner "passphrase missing" pre-flight check.

