Skip to content

Commit 059ffa1

Browse files
author
alvinttang
committed
feat: one-shot device sync setup script (scripts/setup-device-sync.sh)
Installs/builds cortex-mcp-server, waits for iCloud to deliver the cortex-sync folder (with brctl download nudge), joins the encrypted sync (passphrase via prompt or CORTEX_SYNC_PASSPHRASE env — never argv), writes a deny-by-default capability policy, and prints the Claude Code MCP registration command. Verified live against a real iCloud sync dir: fresh DB restored 6/6 memories on join.
1 parent b58df6b commit 059ffa1

1 file changed

Lines changed: 93 additions & 0 deletions

File tree

scripts/setup-device-sync.sh

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
#!/usr/bin/env bash
2+
# Cortex — one-shot encrypted iCloud sync setup for a new device (macOS).
3+
#
4+
# What it does:
5+
# 1. Installs cortex-mcp-server (builds from this repo if not already installed).
6+
# 2. Waits for the iCloud `cortex-sync` folder to come down from iCloud Drive.
7+
# 3. Joins the encrypted sync with your passphrase — full restore happens on join,
8+
# the passphrase goes into this device's login Keychain, and sync auto-resumes
9+
# on every restart from then on.
10+
#
11+
# Usage:
12+
# ./scripts/setup-device-sync.sh
13+
# CORTEX_SYNC_PASSPHRASE=... ./scripts/setup-device-sync.sh # non-interactive
14+
#
15+
# Privacy notes: only memories you explicitly mark `shared` ever leave a device;
16+
# everything is AES-256-GCM encrypted client-side before it touches iCloud.
17+
18+
set -euo pipefail
19+
20+
BOLD=$'\033[1m'; GREEN=$'\033[32m'; YELLOW=$'\033[33m'; RESET=$'\033[0m'
21+
say() { printf '%s\n' "${BOLD}${1}${RESET}"; }
22+
ok() { printf '%s\n' "${GREEN}${1}${RESET}"; }
23+
warn() { printf '%s\n' "${YELLOW}! ${1}${RESET}"; }
24+
die() { printf '%s\n' "${YELLOW}${1}${RESET}" >&2; exit 1; }
25+
26+
[ "$(uname)" = "Darwin" ] || die "This script targets macOS (iCloud Drive). For Linux, use a synced folder + 'sync enable' manually."
27+
28+
DB_PATH="${CORTEX_DB_PATH:-$HOME/.cortex/memory.db}"
29+
BIN="$HOME/.local/bin/cortex-mcp-server"
30+
ICLOUD_DIR="$HOME/Library/Mobile Documents/com~apple~CloudDocs"
31+
SYNC_DIR="$ICLOUD_DIR/cortex-sync"
32+
33+
# ── 1. Binary ────────────────────────────────────────────────────────────────
34+
say "[1/3] cortex-mcp-server binary"
35+
if command -v cortex-mcp-server >/dev/null 2>&1; then
36+
BIN="$(command -v cortex-mcp-server)"
37+
ok "found: $BIN ($($BIN --version))"
38+
elif [ -x "$BIN" ]; then
39+
ok "found: $BIN ($($BIN --version))"
40+
else
41+
REPO_DIR="$(cd "$(dirname "$0")/.." && pwd)"
42+
[ -f "$REPO_DIR/Cargo.toml" ] || die "binary not installed and no repo found — clone github.com/gambletan/cortex first"
43+
command -v cargo >/dev/null 2>&1 || die "cargo not found — install Rust (https://rustup.rs) and re-run"
44+
say " building from $REPO_DIR (one-time, ~2 min)..."
45+
(cd "$REPO_DIR" && cargo build --release -p cortex-mcp-server)
46+
mkdir -p "$HOME/.local/bin"
47+
rm -f "$BIN" # fresh inode: avoids macOS code-sign cache SIGKILL on overwrite
48+
cp "$REPO_DIR/target/release/cortex-mcp-server" "$BIN"
49+
ok "installed: $BIN ($($BIN --version))"
50+
fi
51+
52+
# ── 2. iCloud sync folder ────────────────────────────────────────────────────
53+
say "[2/3] waiting for iCloud Drive to deliver cortex-sync"
54+
[ -d "$ICLOUD_DIR" ] || die "iCloud Drive folder not found — sign into iCloud and enable iCloud Drive first"
55+
56+
WAIT=120
57+
while [ ! -f "$SYNC_DIR/manifest.json" ] && [ "$WAIT" -gt 0 ]; do
58+
# Nudge iCloud to download if it is still a placeholder
59+
brctl download "$SYNC_DIR" >/dev/null 2>&1 || true
60+
sleep 3; WAIT=$((WAIT - 3))
61+
printf '.'
62+
done
63+
printf '\n'
64+
[ -f "$SYNC_DIR/manifest.json" ] || die "cortex-sync/manifest.json never appeared. Is sync enabled on your other device, and has iCloud finished syncing?"
65+
ok "sync folder present: $SYNC_DIR"
66+
67+
# ── 3. Join (full restore) ───────────────────────────────────────────────────
68+
say "[3/3] joining encrypted sync"
69+
PASS="${CORTEX_SYNC_PASSPHRASE:-}"
70+
if [ -z "$PASS" ]; then
71+
printf 'Sync passphrase (input hidden): '
72+
read -rs PASS; printf '\n'
73+
fi
74+
[ -n "$PASS" ] || die "empty passphrase"
75+
76+
mkdir -p "$(dirname "$DB_PATH")"
77+
"$BIN" "$DB_PATH" sync enable --provider icloud --passphrase "$PASS"
78+
79+
# Deny-by-default capability policy (read+write+sync) if none exists yet
80+
CAPS="$(dirname "$DB_PATH")/capabilities.json"
81+
if [ ! -f "$CAPS" ]; then
82+
printf '{\n "version": 1,\n "grants": ["read", "write", "sync"]\n}\n' > "$CAPS"
83+
ok "capability policy created: $CAPS"
84+
fi
85+
86+
echo
87+
"$BIN" "$DB_PATH" stats
88+
echo
89+
ok "Done. Shared memories now flow both ways automatically (~30s)."
90+
ok "Passphrase is in this device's login Keychain — sync auto-resumes on restart."
91+
echo
92+
say "To use with Claude Code, register the MCP server:"
93+
printf ' claude mcp add cortex-memory -- %s %s\n' "$BIN" "$DB_PATH"

0 commit comments

Comments
 (0)