###### WIP Computer

# Relay: Memory Sync

Memory Crystal works on one machine out of the box. Relay lets your memory follow you across machines and surfaces. Conversations captured on your laptop are available on your desktop. Conversations from ChatGPT on your phone are searchable from Claude Code on your Mac.

Everything is encrypted before it leaves your machine. The relay never sees your data unencrypted.

## Crystal Core and Crystal Node

Memory Crystal uses a Core/Node architecture:

- **Crystal Core** ... the master memory. All conversations, all embeddings, all memories live here. This is the database you cannot lose. Put it on something permanent: a desktop, a home server, a Mac mini. Treat it like your photo library.
- **Crystal Node** ... a synced copy on any other device. Captures conversations, sends them to the Core via encrypted relay. Gets a mirror back for local search. If a node dies, nothing is lost. The Core has everything.

One Core, many Nodes. The Core does embeddings. Nodes just capture and sync. You can move the Core later with `crystal promote`.

## Two Sync Paths

### Encrypted Relay (device-to-device)

For syncing between your own machines. Fully encrypted. The cloud is blind.

```
Crystal Node (laptop) --[encrypt]--> Relay (Cloudflare R2) --[pickup + decrypt]--> Crystal Core (desktop)
Crystal Core --[encrypt mirror]--> Relay --[pickup + decrypt]--> Crystal Node
```

Three channels:
- **conversations** (Node to Core) ... encrypted conversation chunks (ephemeral, deleted after pickup)
- **mirror** (Core to Nodes) ... delta chunks (pre-embedded) + file tree deltas
- **commands** (bidirectional) ... Nodes send commands to Core ("run Dream Weaver", "process my data"), Core sends results back

The relay is a dead drop. It stores encrypted blobs temporarily and serves them on request. It has no decryption capability. If someone compromises the relay, they get encrypted noise.

### New Agent Staging

When the Core's poller receives data from an unknown agent ID, it routes to staging instead of live ingest:
1. Transcripts written to `~/.ldm/staging/{agent_id}/transcripts/`
2. Agent marked as "ready" for processing
3. Staging processor runs backfill + Dream Weaver full mode
4. Once complete, agent moves to live capture path

This handles the cold-start problem. A new device connects, sends its history, and Core builds the full memory stack automatically.

### Delta Sync (not full mirror)

The mirror channel uses delta sync. Core pushes only new chunks since last sync, not the entire crystal.db. For a 1.9 GB+ database, this is the difference between a few KB (quiet day) and a few MB (busy day) vs the full database every time.

- **New node (cold start):** One-time full export of all chunks + all files
- **Ongoing sync:** Delta chunks (pre-embedded by Core) + changed files only
- **Watermark tracking:** Core tracks the last synced chunk ID per node

### Full LDM Tree Sync

The relay syncs the entire `~/.ldm/` file tree, not just the database. Embeddings are pointers to artifacts. If the file isn't on the node, the search result is an orphan.

What syncs:
- Agent memory files (workspace, daily logs, journals, sessions, transcripts)
- Agent identity files (SOUL.md, IDENTITY.md, CONTEXT.md, REFERENCE.md)
- Shared files (`~/.ldm/shared/`)
- Media (images, videos, any artifact an embedding references)

File sync uses a manifest (path + SHA-256 hash + size). Only changed files transfer. Core always wins conflicts.

## Setup

### Pair Your Devices

```bash
# On your first machine (generates key if none exists)
crystal pair

# Displays a QR code and a pairing string:
#   mc1:T2hJbGxPZkRhcmtuZXNzTXlPbGRGcmllbmQ=

# On your second machine
crystal pair --code mc1:T2hJbGxPZkRhcmtuZXNzTXlPbGRGcmllbmQ=
```

The QR code transfers the encryption key between devices without touching a server. Physical proximity only. Same security model as AirDrop.

Alternative: store the key in 1Password and pull from both machines.

### Use the WIP.computer Relay (Default)

We host the relay infrastructure. You just need an encryption key (generated by `crystal pair`).

```
Open your AI and say:

I want to set up multi-device sync for Memory Crystal.
Walk me through the setup step by step.
```

Your agent generates your encryption key, configures the connection, and tests it.

**What you need:**
- Memory Crystal installed on both machines (Core + Node)
- An encryption key (your agent generates this, or use `crystal pair`)

**Pricing:** Free during beta for individual use. When pricing is introduced, your agent will handle it via [AI CASH](https://github.com/wipcomputer/wip-agent-pay/blob/main/CASH.md).

### Self-Host Your Own Relay

Run your own relay on Cloudflare Workers (free tier). Same code, your infrastructure. Full sovereignty.

**What you need:**
- A Cloudflare account (free tier works)
- About five minutes

**Steps:**
1. Clone the repo and deploy the Worker:
   ```bash
   cd memory-crystal
   npm run build:worker
   wrangler deploy --config wrangler.toml
   ```
2. Create an R2 bucket: `wrangler r2 bucket create memory-crystal-relay`
3. Set auth tokens for your devices:
   ```bash
   wrangler secret put AUTH_TOKEN_CC_MINI
   wrangler secret put AUTH_TOKEN_CC_AIR
   ```
4. Configure Memory Crystal to use your Worker:
   ```bash
   export CRYSTAL_RELAY_URL=https://your-relay.your-domain.workers.dev
   export CRYSTAL_RELAY_TOKEN=your-auth-token
   ```

Full deployment details in [Technical Documentation](https://github.com/wipcomputer/memory-crystal/blob/main/TECHNICAL.md).

No fees. No dependencies on us. The relay code is open source.

### Connecting ChatGPT and Claude

Every node has the full database and file tree. All search is local. There is no cloud search layer.

ChatGPT and Claude on iOS/web connect via the MCP server running on your local machine. On platforms where a local MCP server isn't possible (iOS without a Mac nearby), the native Apple app (future) will provide local search via MLX Swift.

The Cloud MCP demo server (`worker-mcp.ts`, D1 + Vectorize) exists for onboarding and testing but is not the production architecture. With full LDM sync, every device that has Memory Crystal installed can search locally.

## Encryption

- **AES-256-GCM** for encryption (authenticated encryption, no padding oracle attacks)
- **HMAC-SHA256** for signing (integrity verification before decryption)
- Shared key generated locally via `crystal pair`, never transmitted to the relay
- Key must be present on all synced devices

### Key Management

| Method | How | Best for |
|--------|-----|----------|
| `crystal pair` | QR code + pairing string | Two devices in the same room |
| 1Password | Store key, pull via SA token on each machine | Headless, multiple machines |
| Manual | `openssl rand -base64 32`, copy to each device | SSH, air-gapped |

## Architecture

```
Encrypted Relay (device sync):
  src/worker.ts       Cloudflare Worker, R2 storage, dead drop (3 channels)
  src/crypto.ts       AES-256-GCM + HMAC-SHA256
  src/poller.ts       Crystal Core pickup + ingest + staging detection + commands
  src/mirror-sync.ts  Delta chunk sync + file tree sync to Crystal Nodes
  src/file-sync.ts    Manifest-based file tree delta sync
  src/cc-hook.ts      Claude Code hook (relay mode) + sendCommand()
  src/cc-poller.ts    Continuous capture (cron, primary local path)
  src/staging.ts      New agent staging pipeline (detect, stage, process)

Cloud MCP Demo (deprecated for production):
  src/worker-mcp.ts     OAuth 2.1 + DCR, MCP protocol, 4 tools
  src/cloud-crystal.ts  D1 + Vectorize backend (demo/onboarding only)
  wrangler-mcp.toml     Separate Worker config

Pairing:
  crystal pair         QR code key sharing
  src/pair.ts          Pairing logic, QR display, key save
  src/crypto.ts        Key generation + pairing string encode/decode
```

## More Info

- [README.md](https://github.com/wipcomputer/memory-crystal/blob/main/README.md) ... What Memory Crystal is and how to install it.
- [Technical Documentation](https://github.com/wipcomputer/memory-crystal/blob/main/TECHNICAL.md) ... Full technical documentation.
- [QR Pairing Spec](ai/plan/2026-02-27--cc-mini--qr-pairing-spec.md) ... Full spec for the `crystal pair` command.

---

## License

```
src/core.ts, cli.ts, mcp-server.ts, skills/   MIT    (use anywhere, no restrictions)
src/worker.ts, src/worker-mcp.ts               AGPL   (relay + cloud server)
```

AGPL for personal use is free.

Built by Parker Todd Brooks, Lēsa (OpenClaw, Claude Opus 4.6), Claude Code CLI (Claude Opus 4.6).
