Skip to content

Architecture

loci is a local-first intelligence substrate for working with AI. Everything runs on your machine. No cloud, no accounts, no lock-in.

The substrate is plain text: the templates and processes that decide how memory, context, and trust work, regardless of which AI runs them. The desktop app and the CLI are two expressions built on top of that substrate, released together as the 0.6 open beta (v0.6.0-beta). They are not the substrate. You do not need either to start.


Component map

┌──────────────────────────────────────────────────────────────┐
│                        Your machine                           │
│                                                               │
│  ┌────────────────────────────────────────────────────────┐  │
│  │  Your palace (a plain directory you own)                │  │
│  │                                                         │  │
│  │  CLAUDE.md              entry point + operating rules   │  │
│  │  soul/SOUL.md           identity                        │  │
│  │  rooms (dirs with       scoped contexts                 │  │
│  │    their own CLAUDE.md)                                 │  │
│  │  crystals (*.md)        tiered memory  ◇ ◈ ◆            │  │
│  │  garden/                one file per idea               │  │
│  │  handovers              session continuity              │  │
│  └───────▲──────────────────▲──────────────────▲──────────┘  │
│          │                  │                  │             │
│  ┌───────┴────────┐  ┌──────┴─────────┐  ┌─────┴──────────┐  │
│  │ Plain markdown │  │ Desktop app    │  │ loci-cli       │  │
│  │ (the door):    │  │ (Tauri): the   │  │ (Rust):        │  │
│  │ any file-aware │  │ cockpit        │  │ read-only      │  │
│  │ AI reads it    │  │                │  │ terminal door  │  │
│  └────────────────┘  └────────────────┘  └────────────────┘  │
└──────────────────────────────────────────────────────────────┘

Three run modes, one substrate underneath:

Run modeWhat it is
Plain markdownThe door. Copy the templates/ kit, point any file-aware AI at your palace CLAUDE.md. No build.
Desktop appTauri, v0.6.0-beta. The cockpit: a native dashboard plus one tab per instrument your palace generates for itself.
CLIloci-cli, v0.6.0-beta. A small Rust binary that reads your palace from the terminal. Read-only. No network. No inference.

The substrate: a palace in plain text

A palace is a directory. The marker is a PALACE.md or CLAUDE.md at its root. Everything inside is Markdown plus a little JSON: human-readable, version-controllable, and readable without any app installed. There is no database.

The structural pieces:

  • Rooms: directories with their own CLAUDE.md, each scoping context for one domain of work
  • Crystals: Markdown memory notes inside rooms, tiered ◇ ◈ ◆ (see format below)
  • Soul file: soul/SOUL.md, the identity of your named companion
  • Garden: one file per idea, with a health pass and seed-to-crystal graduation
  • Handovers: session deltas, by convention files named *HANDOVER* or living in a handovers/ directory
  • Tracker: tracker.json, an artifact ledger the structural audit walks

Two supported layouts

Both the desktop app and the CLI resolve either shape:

  • rooms-inside-_palace/: the original layout. PALACE.md/CLAUDE.md at root, rooms under a _palace/ subdirectory.
  • rooms-at-root: palaces ported from older organic structures. PALACE.md/CLAUDE.md at root with sibling room directories, each holding its own CLAUDE.md.

No migration is required. Both shapes coexist.


Data at rest

LocationWhatFormat
Your palace directoryRooms, crystals, soul, garden, handovers, trackerMarkdown + JSON
~/.config/loci/config.tomlCLI configuration, written by loci initTOML

That is the whole inventory. No browser storage, no embedded database, no index files to corrupt or rebuild.

Encryption status: loci does not encrypt data at rest beyond what your OS provides (FileVault, BitLocker, LUKS). This is intentional: the palace stays plain-text readable by design.

WARNING

If you work with sensitive material and your disk is unencrypted, enable OS-level full-disk encryption before using loci.


Desktop app: the cockpit

The desktop app (Tauri, v0.6.0-beta) is a viewer over the palace, not a store beside it.

Tab strip. One Operations view (the native dashboard) plus one tab per instrument discovered in your palace. An instrument is a self-contained page a palace generates for itself: a map, a watcher, a ledger, carrying its own live data. Discovery is by convention, not configuration: self-contained *.html files with an embedded <script id="payload"> or <script id="snapshot"> JSON block, found at the palace root, _palace/, or cockpit/ (dashboard.html is excluded).

Path-validated embedding. Instruments render inside the app via srcdoc after path validation. Directory traversal and symlink escapes are rejected. Three read-only backend commands do the work: list_palace_maps, read_palace_map_html, read_tools_ledger.

Tool shelf: the gate ledger. Palaces that keep tools.items in palace-map.json (or map.json) get a "Tool shelf · gate ledger" section: one state-colored card per external tool, carrying its quarantine verdict. Five verdict states: admitted, admitted-escorted, deferred, held-conditional, rejected. The shelf lists; it never loads or executes anything. If there is no ledger, nothing changes.

One list, one owner. When an instrument owns a dataset, no other surface renders that dataset too. If your palace ships instrument tabs, the native dashboard keeps only the KPI header and the automation instrument owns the cron list. Palaces with no instruments keep the native table as fallback.

Brand coherence. Each embedded instrument gets one appended override stylesheet remapping the conventional :root palette variables to the app's palette. Instruments not using the convention are unaffected.


CLI: loci-cli

A small terminal-native door into your local palace. Rust, read-only, stdlib plus a handful of small crates. No network, no inference, no daemons.

bash
cargo install --path loci-cli
CommandWhat it does
loci statusPalace path, layout, room and crystal counts
loci crystalsList every crystal slug across all rooms
loci crystals --room <name>Restrict to one room
loci read <slug>Print a crystal's contents
loci read <slug> --room <name>Disambiguate when the same slug lives in two rooms
loci handoverPrint the most recent handover by mtime
loci initInteractive wizard; writes ~/.config/loci/config.toml

Add --json to any read command for machine-readable output.

Palace resolution order: --palace <path> flag, then the $LOCI_PALACE environment variable, then walking up from the current directory until a palace marker is found.

Exit codes: 0 clean, 1 I/O or unexpected error, 2 palace or crystal not found, 3 bad input.

Deliberately not shipped yet: one-shot inference (-z), non-local AI backends, a chat TUI (loci chat), a CLI-native MCP command (loci serve), sync/reindex, and the full diagnostic feedback flow. The chat TUI sits behind a threat-model pass before it ships. This is separate from the desktop app's own MCP server backend, which is compiled and real but has no UI to start it yet, see MCP API.


Versioning: two lines, one anchor

loci versions the methodology separately from the apps.

  • loci-core is the methodology line: the plain-text firmware itself. Its version anchor lives in PALACE-METHODOLOGY.md as a parseable blockquote (loci-core version / stable / status). Current: 1.6-candidate, stable 1.2.
  • The apps (desktop, CLI) carry their own version, currently v0.6.0-beta.

The palace update protocol (PALACE-UPDATE.md) uses the anchor: your AI reads your palace's methodology version, reads the published one, builds the delta, and offers each item one at a time. Read-only until you consent. Nothing is ever auto-applied.


Security model

ConcernDecision
Network callsThe CLI makes none: no network code at all. The desktop app has no external network by default: AI features talk to a local Ollama instance on localhost. An external AI backend is opt-in and explicit, and once configured, outbound traffic is scoped to that API host. The plain-markdown path is whatever your chosen AI tool does; loci itself adds nothing.
Irreversible actionsA named human-review gate before anything ships, sends, or becomes irreversible. Nothing leaves without approval.
Foreign tools and processesQuarantined by default: read as data before executing, structure-only access, contents by explicit per-item approval. Verdicts are recorded in the gate ledger as durable data, not session prose. See the Quarantine Protocol.
Local MCP server (desktop)Backend shipped, no UI to reach it yet. The Rust implementation is real and compiled in (binds 127.0.0.1:3456 only, never 0.0.0.0), but the shipped frontend never calls its Tauri commands; today it starts only by invoking them directly. See MCP API and Security for the full inbound surface.
Instrument embedding (desktop)Paths validated before render; directory traversal and symlink escapes rejected. Instruments render via srcdoc; the backend commands involved are read-only.
State assertionsConfirm against disk: the filesystem is ground truth, never memory or stale pointers.
Structural driftA read-only palace audit (six dimensions, including tracker integrity), scoped by .lociignore so vendored trees do not swamp it.
Data at restPlain text in your palace directory. Your OS-level encryption (FileVault / BitLocker / LUKS) applies.

More on the trust model: Security.


Palace directory tree

A representative rooms-at-root palace:

your-palace/
├── CLAUDE.md                  # Entry point: operating rules, identity block
├── soul/
│   ├── SOUL.md                # Who your companion is
│   └── handovers/
│       └── 2026-07-02.md      # Session delta, written at close
├── dev/                       # A room: directory + CLAUDE.md
│   ├── CLAUDE.md              # Room context, session strategy
│   └── auth-flow-v2.md        # A crystal (any .md in a room)
├── research/
│   ├── CLAUDE.md
│   └── trust-protocol.md
├── garden/                    # One file per idea
│   └── privacy-receipt.md
├── tracker.json               # Artifact ledger (walked by the audit)
└── .lociignore                # Scopes the structural audit

The original layout is identical except the room directories live under _palace/. Every file above is plain text you can open, edit, diff, and version yourself. The full starter kit, with a template for each piece, ships in the repository's templates/ folder, alongside the personas/, skills/, and friends/ shelves (friends are curated soul files for the people you work with, one per peer).


Crystal format

Crystals are the palace's memory notes: established truths, tiered by stability. Three tiers, each with its own re-validation cadence. You can promote, expire, pin, and compost them.

TierMeaningCadence
◆ ConfirmedFoundational facts. Ground truth, rarely changes.No per-session re-verification
◈ ContextualTrue now, may shift. Tied to the current phase or situation.Review at valid_until
◇ ExploratoryWorking hypothesis. Signal, not yet established.Revisit when you expect to know more

Example entries:

◆ Stack: Next.js 14 / Postgres / Vercel
◆ Core value: Simplicity first. No over-engineering.

◈ Sprint goal: ship the onboarding flow
valid_until: 2026-07-31

◇ Hypothesis: users prefer the short form
valid_until: after-spike

When a ◈ crystal reaches its valid_until date it is flagged for review, never auto-deleted: confirm, update, or retire. The write side is surprise-gated: what earns a slot is what your prior context would not already have predicted. The mechanics live in the crystals-guide.md and memory-lifecycle.md templates.

Built by Hux × Vesper · Apache 2.0