Cortex Stick
July 13, 2026 · View on GitHub
Your AI doesn't know you. This does. And it fits in your pocket.
You work from two desks — home and the shop, home and the office. Both machines run Mnemo, and they drift: the decision you saved at one desk doesn't exist at the other. The usual fixes put your AI's working memory on somebody else's wire (cloud sync) or need infrastructure you don't want to run (VPN, tailnet).
The Cortex Stick is a USB stick that works as a courier between two full Mnemo installations. It is not a server — there's no database engine, no embedder, nothing running on it. It carries the delta:
- memories — the per-agent memory JSONs (the truth files)
- trajectories — the append-only "how we did it" recipe logs
- brain — optionally, your brain/notes git repo (the stick holds a bare repo both machines push/pull through)
- pad — a free-form folder for dragging in-flight work between desks
Plug it in, sync, pull it out, carry it, plug it in. The other machine catches up. No cloud, no VPN, no account.
Quick start
# once, on any machine, with the stick mounted — YOUR choice of mode:
mnemo-cortex stick init /media/you/USB # plain: readable by eye
mnemo-cortex stick init --encrypt /media/you/USB # encrypted: passphrase
# encrypted sticks only — once, on the OTHER machine, with the stick in:
mnemo-cortex stick unlock # same passphrase — enrolls this host
# then, at each desk, whenever the stick is in:
mnemo-cortex stick sync
# or let it happen automatically while you work:
mnemo-cortex stick watch # syncs on plug-in, re-syncs while present
mnemo-cortex stick watch --notify # + desktop toast per sync / refusal
Zero-terminal courier (recommended)
Run the watcher as a background unit and the stick becomes plug-and-walk-away: insert it, a toast tells you what traveled and that it's safe to remove, pull it out. A refusal (torn generation, guard trip, wrong key) also raises a toast — unattended mode never hides a stick that needs a human.
Linux — systemd user unit (~/.config/systemd/user/cortex-stick-watch.service):
[Unit]
Description=Cortex Stick courier — auto-sync on plug-in
[Service]
ExecStart=%h/.local/bin/mnemo-cortex stick watch --poll 5 --notify
Restart=on-failure
RestartSec=15
[Install]
WantedBy=default.target
systemctl --user daemon-reload
systemctl --user enable --now cortex-stick-watch.service
Windows — Task Scheduler: an At log on task running
mnemo-cortex stick watch --poll 5 --notify (start hidden). The watcher
polls for the stick itself, so no drive-letter trigger plumbing is needed.
Both modes are first-class and stay supported: plain sticks are
human-auditable and zero-dependency; encrypted sticks survive being lost.
A plain stick can upgrade later with stick encrypt; sticks provisioned
by v1.0 keep working unchanged.
stick status shows what would travel in each direction without changing
anything, plus when each machine last synced and whether the stick is
encrypted.
Encrypted sticks need one extra package on each host:
pip install 'mnemo-cortex[stick-crypto]'.
Encryption
A plaintext stick is a notebook full of your AI's working memory — lose it and whoever finds it reads everything. Encrypt it:
- What's protected. Every truth file on the stick — memories, trajectories, pad files, conflict backups — is AES-256-SIV ciphertext, and the brain travels as an encrypted git bundle instead of a readable repo. A found stick leaks structure (file names, sizes, counts, which agents exist) but never content.
- Where the key lives. On each host, at
{data_dir}/stick-keys/(0600) — never on the stick. It derives from your passphrase (scrypt); the stick's passport holds only the salt and a fingerprint, so a wrong passphrase fails loud instead of writing garbage. Enroll each host once withstick unlock; after that sync and watch run unattended. - Losing the passphrase loses the courier, not your data — both machines keep their full installs. Re-init a fresh stick.
- Already have a plaintext stick?
mnemo-cortex stick encryptupgrades it in place (resumable if interrupted — rerun with the same passphrase). One honest caveat: replaced plaintext can linger in the stick's free space (flash wear leveling defeats targeted scrubbing) — if the plaintext era matters, zero-fill the free space afterwards, e.g. fill the stick with a junk file and delete it. - Tampering (or bit rot) is caught twice: the manifest hash check
refuses the generation, and even after a
stick repairthe AEAD tag refuses the decrypt. Tampered content can never reach a host as truth. - Repair works without the key — anyone can make a torn stick consistent again; only key-holders can read it.
stick brain-clone <dest>bootstraps the brain repo on a new machine from the encrypted bundle.
Encryption is in-tool rather than volume-level (BitLocker/VeraCrypt/LUKS) so it behaves identically on Windows, macOS, and Linux with no drivers, no admin rights, and no per-plug-in mount step — but nothing stops you from running the stick on an encrypted volume as well.
How it stays safe
- Only truth files cross. Vector indexes, caches, and sidecar files are derived data — each machine rebuilds its own. New memories are recallable immediately via disk truth; embeddings catch up on the server's next backfill pass.
- Every sync is a 3-way merge. The stick remembers what each machine had at last sync, so it can tell "new on the other side" from "deleted here" — no silent overwrites, no resurrection of deleted memories.
- Conflicts never destroy data. If the same memory was edited at both
desks, one version wins deterministically and the loser is preserved on
the stick under
state/conflicts/. If one desk edited what the other deleted, the edit wins. Trajectory logs union-merge — append-only truth never loses a row. - Nothing moves until every check passes. A sync first plans the whole run — every guard fires before a single byte is copied — so a refusal really does mean nothing was changed, on either machine or the stick.
- Yank-proof commits. Files are hashed into a manifest that is written
last; a stick yanked mid-sync fails verification on the next plug-in and
the sync refuses, loudly, instead of merging from a torn state. "Safe to
remove ✓" prints only after every written file is readback-verified. If a
yank does tear a generation,
mnemo-cortex stick repairrebuilds the manifest from the stick's contents and the next sync merges from there — no manual surgery, nothing deleted by the repair. - Massacre guard. If a sync would delete more than a quarter of a
store (a wiped or replaced machine), it refuses and explains, and only
proceeds with
--force.
Facts travel too
The structured Facts store (facts.sqlite) syncs as its own channel: the
stick carries a canonical JSONL export and each host merges row-wise under
the same promotion-ladder rules the store enforces locally — a verified
fact survives a newer lower-confidence contradiction from the other desk,
a fresh demotion ("this is wrong") propagates, and a stale demotion loses
to a later re-establishment. Every change the courier applies is recorded
in the fact history with changed_by='stick:<id>'. Opt out with
"facts": false in {data_dir}/stick.json.
What it does not do (yet)
- No session logs. Raw session capture stays on each machine; the dreamer digests locally.
- No fact-history sync — the audit log stays local by design; each host's history describes what happened there.
- Two-desk, one-human. Multi-user shared lanes are designed for (the merge machinery is already order-safe) but not shipped.
Files on the stick
<mount>/cortex/
passport.json which stick this is, which machines it has met,
encryption salt + fingerprint (never the key)
manifest.json per-file SHA-256 of the current generation
memories/<agent>/ memory JSONs + trajectory JSONLs, per agent
brain/brain.git bare git repo (plaintext stick)
brain/brain.bundle.enc encrypted git bundle (encrypted stick)
facts/facts.jsonl merged Facts-store export
pad/ yours — drag anything
state/ per-machine inventories, conflict archive, lock
Everything is a plain file. On a plaintext stick your data is sitting right there, readable; on an encrypted stick the same files are there, dark without the passphrase.