Skip to content

Rooms and crystals

The two working units of a palace: where context lives, and what persists.

Naming update

Earlier versions of this page described rooms backed by .room.json metadata files, a fixed six-room roster with glow colors, a "locus" file format, and a desktop app called Wizard. All of that is retired. The shipped model (0.6 open beta, v0.6.0-beta) is simpler: a room is a folder containing a CLAUDE.md, and the unit of permanent memory is a crystal. The project name keeps the memory-palace metaphor (loci are the places). The thing you actually create and retrieve is called a crystal.


What is a room

A room is a domain of work: your job, a creative project, research, ideas. Rooms keep a large palace legible. When you enter one, exactly its context loads, and nothing else.

A room is not a single conversation. Conversations are the activity; the room is the place the work accumulates. You return to a room across sessions, and it already has ground truth, behaviour rules, and open work waiting.

Structurally, the definition is one line: a room is a directory containing a CLAUDE.md. No registry, no separate metadata file, no hidden state. If a folder has a CLAUDE.md, the tools see a room. Rename the folder, the room is renamed. Delete it, the room is gone.

You choose your rooms. There is no default roster. Start tight (two or three rooms); you can always add more later.


The room file

Each room's CLAUDE.md is its context. The template lives in the repo at templates/room-template.md and covers:

  • What this room is for: 1-3 sentences on the kind of work that happens here
  • Ground truth: established facts the AI should never re-derive in this room
  • Behaviour rules: how the AI should act here (some rooms are exploratory, others careful)
  • Active projects: a small table of live work and next steps
  • State summary: a 2-line "where we left off" updated each session
  • Session strategy: when this room's context should load (below)
  • Pinned crystals: facts protected from health-check passes
  • Corridors: connections to other rooms ("Research feeds Writing: confirm facts there before using them here")

Keep room files room-scoped. Behavioural constants belong in your global layer, living project state in the project layer, room specifics here. That separation is what makes room-switching cheap.


Session strategy

Every room declares how it loads, in a session_strategy block inside its CLAUDE.md:

yaml
session_strategy:
  scope: on-demand            # always-load | on-demand | per-session
  auto_detect: true           # read first message for room signals before asking
  crystals_to_load: global    # global | room-only | [specific names]
  handover_depth: 1           # recent handovers to surface at session start (0 = none)
  • always-load: loads every session. Use for identity and master context.
  • on-demand: loads when you enter the room or the topic clearly matches. The default.
  • per-session: loads once, not reloaded mid-session.

This is the room's slot in the L0-L3 retrieval hierarchy: soul identity (L0) and active state (L1) always load, room context (L2) loads on room entry, deep history (L3) only on explicit request. The template is templates/retrieval-hierarchy.md.


Two palace layouts

The desktop app and the CLI both accept two layouts (since v0.6.0-beta):

LayoutShape
Rooms at rootPALACE.md or CLAUDE.md at the root, sibling directories each holding a CLAUDE.md
Legacy _palace/ subdirPALACE.md or CLAUDE.md at the root, rooms inside a _palace/ folder

The marker for "this folder is a palace" is a PALACE.md or CLAUDE.md at the root. Hidden folders and build directories (node_modules, target, cron) are skipped during room discovery. Palaces that grew organically with rooms at the root work without restructuring.


Build a room

The full tutorial is in the repo at tutorials/build-a-room.md. The short version:

  1. Decide your rooms. Copy templates/room-template.md to rooms/<name>/CLAUDE.md for each.
  2. Set the session_strategy in each room file.
  3. Add the room to the room table in your main CLAUDE.md, so your AI can state the room at session open.
  4. Keep the room file room-scoped only.
  5. Optional: draw a local map of how rooms connect (templates/local-map-template.md) and track open work in tracker.json.

You are done when you open a session, name a room, and only that room's context loads. The palace stops dumping everything at once.

There is no room create command. A room is a folder and a markdown file; mkdir and the template are the whole interface.


What is a crystal

A crystal is the palace's unit of permanent memory: a fact established once, never re-derived. Crystals carry a tier marker that signals how much to trust them:

TierSymbolMeaning
ConfirmedFoundational. Ground truth. Rarely changes; if it does, note why.
ContextualTrue now, tied to the current phase. Carries a valid_until for review.
ExploratoryHypothesis. Promote once validated, or retire with a note.

The lifecycle is promote, expire, pin, compost. Exploratory facts get promoted as they harden. Contextual facts expire on their valid_until date and get reviewed, not auto-deleted. Pinned crystals are protected from garden health passes. Retired crystals are composted with a note, not silently dropped.

Where they live: crystal entries sit in your palace and room CLAUDE.md files, so they load at session start. Standalone notes work too. To the CLI, every markdown file inside a room counts as a crystal, addressed by its filename stem (the slug). There is no special file extension and no separate crystal store.

The full guide is Crystals and, in the repo, templates/crystals-guide.md.

Creating one

In a session, say "Add this as a crystal" and your AI writes the fact into context with the right tier. Or write the markdown yourself; the file is the format. There is no crystallise command, and nothing is created automatically. A crystal is a deliberate act.

The test stays the same as it always was: would I want this fact available in a future session without re-deriving it? If yes, crystallise. If not, let it stay in the session's handover.


Rooms from the terminal

The CLI (loci-cli, Rust, v0.6.0-beta) is a small read-only door into the palace. No network, no inference, no daemons. Five commands:

CommandWhat it does
loci statusPalace path, layout, room and crystal counts
loci crystals [--room <name>]List crystal slugs, optionally scoped to one room
loci read <slug> [--room <name>]Print a crystal. --room disambiguates duplicate slugs.
loci handoverPrint the most recent handover
loci initInteractive wizard; writes ~/.config/loci/config.toml

Example:

$ loci status
palace : /home/you/palace
layout : rooms-at-root
rooms  : 3
         dev                      (12 crystals)
         research                 (8 crystals)
         writing                  (5 crystals)
total  : 25 crystals

The palace is resolved in order: the --palace <path> flag, then the $LOCI_PALACE environment variable, then walking up from the current directory looking for a palace marker. Every command takes --json for machine-readable output. Setup details: the terminal path.


Rooms in the desktop app

The desktop app (Tauri, v0.6.0-beta) is a cockpit over the same folder:

  • Operations: a native dashboard tab with room and palace state.
  • Instrument tabs: one tab per instrument your palace generates for itself (self-contained HTML pages, discovered by convention at the palace root, _palace/, or cockpit/).
  • Tool shelf, gate ledger: cards for foreign tooling with a quarantine verdict each (admitted, admitted-escorted, deferred, held-conditional, rejected). The shelf lists; it never loads.

The app reads the palace; it does not own it. Everything it shows is the same plain text the CLI and any file-aware AI read.


Rooms vs projects

Rooms are domains; projects are bounded work inside them. A project is a row in the room's Active projects table, tracked to completion, while the room persists. Open work across rooms can live in tracker.json. When a project ends, its crystals remain in the room.

Connections between rooms are corridors, noted in each room file. A local map (an ASCII diagram of the whole palace) keeps the shape legible once you have more than a few rooms.


What is not shipped

To be plain about the current surface:

  • No room create or room archive commands. Rooms are folders.
  • No conversation indexing or search. The palace stores distilled context, not transcripts.
  • No loci serve CLI command yet (deferred behind a threat-model pass; the desktop app's own MCP server is separate and already shipped, see MCP API), no sync, no team rooms. Nothing leaves your machine.

The substrate does not wait on any of this. A folder, a CLAUDE.md, and a file-aware AI are the whole requirement.

Built by Hux × Vesper · Apache 2.0