Architecture overview
Phone owns. Laptop helps. Shared packages stay platform-free.
Monorepo. Apps in apps/. Domain in packages/. Hard rule: packages that run on both
phone and laptop import zero platform APIs. Adapters only.
Big picture
┌─────────────────────────────┐ USB link ┌──────────────────────────┐
│ Android phone (apps/native)│◄──────────────────►│ Laptop companion (cli) │
│ • Expo / React Native │ tools + compute │ • TUI │
│ • expo-sqlite + sqlite-vec │ │ • Node adapters │
│ • Secure keys │ │ • Runs scripts/ │
│ • Owns Twig root │ │ • Never owns state │
└──────────────┬──────────────┘ └───────────┬──────────────┘
│ │
│ same domain packages │
▼ ▼
packages/core packages/memory packages/harness*
(agents, dreams, (fs + journal + (models + tools)
skills, paths) index + recall)* harness and link planned. Domain types already in @twig/core. Memory engine in
@twig/memory.
Source of truth
| Layer | Role |
|---|---|
| Files under Twig root | Law |
.twig/journal.ndjson | Intent before each mutation |
SQLite (db/twig.db) | Rebuildable index |
blobs/ | Attachments by sha |
DB wrong? Drop. Reindex. Write interrupted? Journal remembers intent. Replay reconciles.
Adapters
@twig/memory defines interfaces. That is it:
- FileStore — atomic write, flush-on-append, list, stat
- Sqlite — query + optional vector flag
- Embedder — optional; missing = lexical deep only
- sha256 — injected hash, no crypto lock-in
Expo bindings → native app. Node bindings → cli. Neither pollutes the other package graph.
Constraints that shape everything
- Android only — WorkManager budgets, OEM background murder, speech packages
- No on-device models — remote APIs, your key
- Voice first-class — fast recall offline, millisecond cheap
- MIT — read every path, every schema