---
description: Set up exe-os — encryption, sync, and embedding model
allowed-tools: Bash, AskUserQuestion, Write, Read
---

Set up the exe-os memory system. Follow these steps exactly:

## Step 0: tmux check

tmux is required for exe-os multi-agent. Check if it's installed:
```bash
which tmux >/dev/null 2>&1 && echo "TMUX_INSTALLED" || echo "TMUX_NOT_INSTALLED"
```

If `TMUX_NOT_INSTALLED`, tell the user:
> **tmux is required.** exe-os uses tmux for instant cross-session communication between employees.
>
> Install it before continuing:
> - macOS: `brew install tmux`
> - Linux: `apt install tmux`
>
> New to tmux? https://tmuxcheatsheet.com

Wait for the user to install tmux before proceeding. Re-check with `which tmux` when they say it's done.

## Step 1: Encryption Key

Check if a master key already exists:
```bash
ls -la ~/.exe-os/master.key 2>/dev/null && echo "Key exists" || echo "No key found"
```

If no key exists, generate one:
```bash
node --input-type=module -e "
  import crypto from 'node:crypto';
  import { writeFile, mkdir, chmod } from 'node:fs/promises';
  import path from 'node:path';
  import os from 'node:os';
  const dir = path.join(os.homedir(), '.exe-os');
  await mkdir(dir, { recursive: true });
  const key = crypto.randomBytes(32);
  const keyPath = path.join(dir, 'master.key');
  await writeFile(keyPath, key.toString('base64') + '\n');
  await chmod(keyPath, 0o600);
  console.log('Encryption key generated at', keyPath);
"
```

If key already exists, tell the user: "Encryption key already exists — skipping."

## Step 2: Sync Mode

Tell the user:

> **Take your AI employees everywhere.**
>
> exe-os syncs your encrypted memories across all your machines — Mac, VPS, laptop.

Use AskUserQuestion to ask:
- "How do you want to sync your memories?"
  - **Exe Cloud** — Paste your API key from askexe.com. E2EE — we can't read your data.
  - **Local only** — No sync. Memories stay on this machine. Free forever. You can add sync later.

## Step 3a: If Exe Cloud

Use AskUserQuestion to ask for their Exe Cloud API key (exe_sk_...).

Validate the key:
```bash
curl -s "https://api.askexe.com/auth/verify" \
  -H "Authorization: Bearer USER_API_KEY" | cat
```

If valid, save it in the config (Step 4).

## Step 3b: If Local Only

Skip to Step 4.

## Step 4: Write Config

First get the absolute home directory path:
```bash
echo $HOME
```

Then create the config directory:
```bash
mkdir -p ~/.exe-os
```

Use Write tool to create the config file at the ABSOLUTE path (e.g., `/Users/username/.exe-os/config.json`). Use the $HOME value from above — never write `~` in the dbPath.

For **Local only:**
```json
{
  "dbPath": "/Users/USERNAME/.exe-os/memories.db",
  "modelFile": "jina-embeddings-v5-small-q4_k_m.gguf",
  "embeddingDim": 1024,
  "batchSize": 20,
  "flushIntervalMs": 10000,
  "autoIngestion": true,
  "autoRetrieval": true,
  "searchMode": "hybrid",
  "hookSearchMode": "fts"
}
```

For **Self-hosted (Turso):**
```json
{
  "turso": {
    "url": "PROVISIONED_URL",
    "authToken": "PROVISIONED_TOKEN"
  },
  "dbPath": "/Users/USERNAME/.exe-os/memories.db",
  "modelFile": "jina-embeddings-v5-small-q4_k_m.gguf",
  "embeddingDim": 1024,
  "batchSize": 20,
  "flushIntervalMs": 10000,
  "autoIngestion": true,
  "autoRetrieval": true,
  "searchMode": "hybrid",
  "hookSearchMode": "fts"
}
```

Replace `/Users/USERNAME` with the actual $HOME path.

## Step 5: Download Model

Tell the user: "Downloading the Jina v5-small embedding model (397MB). This is required for memory search and runs locally on your machine."

Run with a 600s timeout:
```bash
node --input-type=module -e "
  import https from 'node:https';
  import fs from 'node:fs';
  import path from 'node:path';
  import os from 'node:os';
  const dir = path.join(os.homedir(), '.exe-os', 'models');
  fs.mkdirSync(dir, { recursive: true });
  const dest = path.join(dir, 'jina-embeddings-v5-small-q4_k_m.gguf');
  if (fs.existsSync(dest)) { console.log('Model already exists at', dest); process.exit(0); }
  console.log('Downloading Jina v5-small Q4_K_M GGUF (397MB)...');
  const url = 'https://huggingface.co/jinaai/jina-embeddings-v5-text-small-text-matching-GGUF/resolve/main/v5-small-text-matching-Q4_K_M.gguf';
  const tmp = dest + '.tmp';
  const file = fs.createWriteStream(tmp);
  const follow = (u) => https.get(u, { headers: { 'User-Agent': 'exe-os' } }, (res) => {
    if (res.statusCode === 302 || res.statusCode === 301) { follow(res.headers.location); return; }
    const total = parseInt(res.headers['content-length'] || '0');
    let dl = 0;
    res.on('data', (c) => { dl += c.length; file.write(c); process.stderr.write('  ' + Math.round(dl/1024/1024) + 'MB / ' + Math.round(total/1024/1024) + 'MB\r'); });
    res.on('end', () => { file.end(() => { fs.renameSync(tmp, dest); console.log('\nModel saved to', dest); }); });
  }).on('error', (e) => { console.error('Download failed:', e.message); process.exit(1); });
  follow(url);
"
```

The model download is not optional — exe-os requires it for embedding and search.

## Step 6: Confirm

Tell the user:
- Setup complete
- Encryption: always on (SQLCipher at rest, E2EE for sync when enabled)
- Sync mode: Local only / Self-hosted Turso (whichever they chose)
- They can change sync mode later by running `/exe-setup` again
- They can change settings anytime with `/exe-settings`
- Run `/exe` to boot exe (COO) and start working
