Reference
The Residents Guide.
Lifted from ~/GRID THEORY/grids/Residents-Guide.grid. Read it against itself with `grid -g Residents-Guide.grid "study: @/guide/**"`.
01 · What is a grid
A grid is an append-only store of addressed cells in a single file.
Three rules:
- Every cell has an address (
@/like/this), a type, a body, and metadata. - Writes never destroy. A second write at an existing address supersedes the first; the first remains in the chain.
- The chain is verifiable. Each cell links to the previous by hash; tampering with any prior cell breaks every cell after it.
A grid is one file on disk. Many grids can exist; they reference each other by coordinate. The substrate is bytes; the meaning is the protocol on top.
There is no schema. There is no separate index. The address space is the schema; the chain is the index.
02 · Cells
A cell is the atomic unit.
Fields the kernel records:
address, where it lives, e.g.@/notes/firsttype, a free-form label (note, doc, key-entry, tombstone, ...)written-by, the authoring identitywritten-at, ISO 8601 timestampsensitivity, public | team | private | sealedbody, UTF-8 textchain, hash linking to the previous cell in this grid
Type is convention, not enforcement. The kernel does not validate "is this a valid note body", that is the application's job. Protocols emerge from agreements between residents about what type names mean.
Slots are first-class metadata. A cell body may carry slot: name = value lines that the query language can filter on. Slots are a structured handle into the body without forcing a schema on every cell.
03 · Addresses
Addresses follow a path-like scheme rooted at @/.
@/notes/first a leaf
@/notes/ a namespace
@/system/genesis kernel-reserved
@/findings/2026-05-18/x date-namespaced recordsGlobs in queries:
@/** every cell
@/notes/** a subtree
** matches anything within or across segmentsAddresses are opaque to the kernel. Conventions emerge from how applications partition the namespace: @/system/* is the kernel's, @/keys/* is the keychain protocol's, @/findings/* is one application's record-of-record. Choose a prefix and own it.
The ampersand-at form (&@/path) inside a cell body is a reference. The kernel maintains a reverse index at @/system/refs so you can ask "what points at X".
04 · Genesis
Every grid has @/system/genesis.
It is written exactly once when the grid is created. The kernel refuses to rewrite it. Genesis carries the grid's origin record, author, timestamp, intent, as a public cell.
Genesis matters because the grid's identity is derived from it. GHA-1024 over the genesis cell produces three 48-bit integers, the grid's master coordinate. Same genesis → same coordinate, forever. Changing genesis would change the grid's identity, which is why the kernel makes it immutable.
If genesis is missing, queries that derive identity fail. If genesis is somehow rewritten (only possible via a buggy migration), every cell downstream becomes misanchored because the chain hash for the first cell shifts. Protect genesis.
05 · History and tombstones
Grids never forget.
Writing @/notes/x a second time does not replace the first write, it supersedes it. The first write remains in the chain. A normal study returns the latest; history-of returns every version, oldest first:
study: @/notes/x
study: history-of: @/notes/xDeletion is the same: it writes a cell of type tombstone at the address. Live queries skip tombstoned addresses. History still shows the tombstone alongside everything else.
Consequence: a grid grows monotonically. There is no compaction, no garbage collection. If your application produces high write volume, partition into rolling grids (e.g. one per day) and reference across.
Audit comes free. Every state change is a cell. Every cell carries who and when. There is nothing else to log.
06 · Sensitivity
Every cell has a sensitivity level.
public, readable by anyone with the grid openteam, requires team clearanceprivate, requires private clearancesealed, requires sealed clearance, the highest
Sensitivity is a band, not a per-identity ACL. Capabilities grant clearance up to a level. A cell at sensitivity=team is invisible to a reader whose clearance is public.
Sensitivity is enforced on read. The body is also encrypted at rest when the grid is locked, keyed per-level, losing the team key loses access to that band without affecting public, private, or sealed bands.
Set sensitivity on write:
write @/notes/x type: note sensitivity: team body: ...The default is public.
07 · Identity and capabilities
A grid is multi-tenant. Many identities can write to it.
The identity model:
- Each cell records
written-by, the authoring identity. - Capability cells at
@/system/capabilities/<name>declare what an identity can do. - A capability cell's body lists a clearance and one or more
allow:lines. Eachallow:line is itself a grid expression naming the slice of the grid the identity may study or write:
clearance: team
allow: study: @/notes/**
allow: write: @/notes/<name>/**- The kernel reads capability cells when processing reads, writes, deletes. No matching capability = no access.
Identity resolution at the CLI follows this order:
-i / --identityflagGRID_IDENTITYenvironment variable@/system/cli-identitycell in the target grid$USERfrom the host shell
There is no anonymous mode. There is no root mode. Every operation runs under an identity, and the capability cell decides what that identity sees.
Two operational principles:
Permissive default: a grid with NO @/system/capabilities subtree is open. As soon as any capability cell is written, the grid becomes strict for everyone, including the identity that wrote the cell. Set up admin capabilities first.
Invisibility of denial: a write that fails because the identity lacks capability returns empty, not an error. A read that filters out cells returns the survivors. The grid does not announce what it hides, error messages would leak existence.
The __kernel__ identity sees all addresses regardless of capability cells. It exists for migrations and integrity checks, not for normal operation.
08 · Expressions
The expression language is the query and write interface.
Primary verbs:
study, read cellswrite, add a celldelete, tombstone an address (sugar for writing a tombstone cell)move, write a copy at a new addresswatch, follow new writes matching a pattern (a streaming verb)
Study with filters:
study: @/**
study: @/** where: type=note
study: @/** where: written_by=somebody and sensitivity=public
study: @/** where: slot: priority = high
study: history-of: @/addrProjections control the shape of the result:
as: count, integeras: addresses, list of@/...as: types,@/...<type>as: line,@/...<type>first-body-line(default)as: summary,@/...[type]first body lineas: full, every fieldas: json, machine-parseable
Write:
write @/addr type: note body: hello
write @/addr type: doc sensitivity: team body: ...Delete and move:
delete @/addr
move @/src to @/dstSugar: fetch @/addr is study: @/addr as: full.
The kernel parses expressions into a pipeline of stages and executes them in order. There is no procedural escape hatch, every operation is a pipeline of declarative stages.
09 · Pipelines
Stages chain with |.
study: @/** where: type=note | study: @/** where: written_by=somebody as: countThe first stage produces a candidate set. The second stage filters within that set, not across the full grid. Pipelines let you compose without materializing intermediate lists.
In-grammar pipes (|) compose at the expression layer, the kernel handles the data flow without serializing through stdout. Shell pipes also work but require careful quoting. When both forms are available, the in-grammar form is preferred.
Write and delete stages don't accept pipelined input, they are terminal. A pipeline that ends in delete will tombstone what survived the upstream filters.
This is the unit of query composition. Build complexity by composing simple stages, not by escaping into code.
Two patterns worth knowing:
Existence test:
study: @/notes/x as: count
→ 0 or 1; treat anything > 0 as "exists"Set difference:
study: @/a/** | ... (only matches inside @/a)Use two passes if you need true set difference, there is no minus.
10 · Ticks
A tick is one cell written.
Time in a grid is not wall-clock. The grid's clock is the chain, each cell is the next tick, linked to the prior by hash. written-at is an annotation, not a guarantee; chain order is the truth.
A backend that wants to advance state writes a tick. A frontend that wants to observe progress watches the chain. Between ticks, the grid is still, no daemons, no implicit advancement, no background work.
The watch verb is the resident's heartbeat:
watch study: @/events/** where: slot:status = pendingA watch expression streams new matching cells as they are written. This is how a resident loop reacts to ticks from other residents without polling manually.
To process ticks since a known point: scan all cells from that index forward in the chain. The chain hash at each cell tells you where in the sequence you are. The combination of (grid coordinate, chain index, chain hash) is a durable pointer into history.
A grid's tick rate is set by its writers. A grid with two residents writing once per second has a 2 Hz tick rate. A grid that hasn't been written to in a year has had zero ticks in that year. There is no internal clock.
11 · Co-residence
A grid can have many co-residents.
A resident is any identity that writes to the grid. Two residents sharing a grid is the simplest case. They take turns ticking, each write is one resident's move. The grid is the shared substrate; the chain serializes their actions.
Conventions for co-residence:
Owned namespaces. Each resident writes under a namespace it owns: resident A writes under @/A/**, resident B under @/B/**. The capability system enforces this, A's capability cell does not include write:@/B/**.
Shared spaces. Joint state lives under a neutral prefix (e.g. @/shared/**). Capabilities can grant multiple residents write access to the shared space; the chain still records who wrote each cell.
Reading is how coordination happens. Resident A watches @/B/** to know what B has done; B watches @/A/**. There is no message bus, no event queue, no pub/sub layer, there is the chain, and you watch it.
There is no locking, no transactions, no consensus protocol inside a single grid, the append-only chain is the consensus. Last-writer-wins per address, with full history preserved. If two residents race to write the same address, both writes land in the chain; the later one supersedes for live queries, and history-of shows the contention.
For cross-grid coordination, residents in different grids reference each other by coordinate. That is a higher protocol; the kernel only knows about one grid at a time. A resident can have capabilities to read many grids and write to one, that pattern is the basis for read-only mirroring, aggregation, and federated views.
12 · Lock vs Seal
Two encryption modes. Pick deliberately. Full detail on Encryption.
LOCK (CLE, Cell-Level Encryption)
Encrypts cell bodies whose sensitivity > public. The grid file remains a valid binary grid. Addresses, types, written-by, written-at, sensitivity labels are still visible. Only the bodies are ciphertext.
Keys are per-level (team / private / sealed). Sharing the team key lets a reader see team-level cells without seeing private ones.
Reversible with the same passphrase: grid lock / grid unlock.
SEAL (GLE, Grid-Level Encryption)
Encrypts the entire file as one opaque blob. The file is no longer a parseable grid, no addresses, no metadata, nothing visible without the key. One key per grid. All-or-nothing access.
Reversible with the same passphrase: grid seal / grid unseal.
Layering:
- Neither, plaintext grid. Development mode.
- CLE only, structure visible, bodies encrypted per level.
- GLE only, entire file encrypted, nothing visible.
- CLE + GLE, lock first, then seal. Maximum protection. To read: unseal first, then unlock.
Both modes use grid-bound key derivation: the SHA-512 of the genesis body is mixed into the key, so the same passphrase on different grids produces different keys. The derivation is deterministic; the encryption itself uses AES-256-GCM with a fresh random nonce per operation. The keychain at ~/.grid/keychain.grid stores public anchors (coordinates + genesis GHA hex + body digest), not private keys. See Encryption for the full key-derivation, keychain shape, and recovery story.
13 · GHA and coordinates
GHA-1024 is Grid Hash Algorithm.
Input: a cell's address, body bytes, sensitivity. Output: 1024 bits, 512 bits content hash, 512 bits coordinate material.
Run on the genesis cell, GHA produces the grid's identity. The coordinate material is split into three 21-byte slices, each reduced modulo 2^48 to yield (x, y, z), the grid's master coordinate, 144 bits of entropy total.
Two grids with byte-identical genesis cells produce identical coordinates. Two grids that differ in any genesis byte (one character of the body, one second of timestamp, a different author) produce different coordinates. This is by design: a grid's coordinate is the stable name for its content history.
Consequences:
- Move the file, the coordinate is unchanged. Coordinates are content-addressed, not location-addressed.
- Cross-grid references travel by coordinate. A cell can refer to "the grid at [x, y, z]" without naming a file path. The lookup is the resident's problem; the kernel only provides the coordinate.
- Two parties who construct genesis cells from the same recipe (same address, same body, same sensitivity, same written-by-and-at) end up with the same coordinate. This is intentional, it enables deterministic grid identity for shared protocols.
GHA is also computed per-cell, not only for genesis. Per-cell GHAs feed the chain hash and verifiable history. grid hash -g <file> @/addr shows the GHA of any cell.
14 · Building backends
A grid IS a backend.
What you do not need:
- A database server
- Schema migration tooling
- A separate query language
- A separate auth layer
- A separate audit log
What the grid provides:
- Append-only storage with per-address history
- Capability-based access control
- A query language
- Per-level encryption
- A verifiable chain
Patterns:
Use addresses as the schema. @/users/<id>, @/orders/<id>, @/orders/<id>/items/<n>. Addresses model your data. Globs query your data.
Use types to discriminate cells at the same address depth. @/orders/<id> with type: order, type: order-update, type: order-shipped. study: history-of: @/orders/<id> gives you the lifecycle.
Use slots for queryable structured fields inside bodies. slot: status = shipped → filter with where: slot: status = shipped.
Use capabilities for tenancy. Multi-tenant systems give each tenant a capability cell scoped to @/<tenant>/**. The tenant identity simply cannot see other tenants.
Use sensitivity for compliance bands. PII at sensitivity=private. Audit metadata at sensitivity=public. Lock the grid; the PII band is encrypted at rest without affecting public reads.
Use sealed grids for archival. When a record is closed (a year, a project), seal the grid and store the recovery anchor (coordinate + genesis GHA) somewhere durable.
Avoid:
- High-frequency telemetry. The chain is forever. Partition into rolling grids (one per hour, day) or use a different tool for fire-and-forget logs.
- Wide secondary indexes. Globs scan. If you need O(1) lookup by an arbitrary field, materialize a secondary address that encodes the field:
@/index/by-email/<email-hash>→ body:&@/users/<id>. - Long-running transactions. There aren't any. Compose state via successive cells, not via held locks.
15 · Building frontends
A frontend over a grid is a reader + a writer.
The reader pattern:
Open the grid. Run study expressions. Render results. Refresh on a tick: re-open after every known write, or poll mtime, or use the watch verb if you can sustain a long-lived process. Project cells through the projection of your choice (full, summary, count), let the kernel do the shape work.
The writer pattern:
Collect input. Build a write expression. Hand it to the kernel. On capability denial: surface the empty result as "denied", never as an error, never as a crash. The kernel does not tell you why; the UI should not either. After a successful write, re-read. Don't cache the cell list across writes; the chain may have moved.
UI affordances that map naturally:
- A filter bar = where-clause inputs
- A cell card = a single cell rendered with metadata and body
- A history view =
study: history-of: @/addr, reversed - A keychain view =
study: @/keys/**on the keychain grid - A lock/seal modal = passphrase + confirm, then call the kernel
- A search bar = address glob + free-text against bodies
The principle: the UI does not invent state. Everything visible should map back to a cell or a query. If you find yourself caching, queuing, or reconciling, you are fighting the grid, not building on it.
Two architectural notes:
Direct integration beats subprocess. If your frontend is in a language that can link the kernel, link it. Calling out to the CLI works but adds serialization overhead and loses error fidelity.
Co-residence in the frontend. Many UIs run as a resident themselves, writing UI-state cells (focus, selection, scroll position) to a private namespace that other co-residents can observe. This is how the UI becomes legible to automation without bolting on a separate protocol.
16 · Grid Theory
Grid Theory is the philosophy behind this substrate.
Core claims:
- Append-only history is the right default. Reversibility through replay, not through mutation. Deletion is a record, not an erasure.
- Address is identity. A cell at
@/notes/firstis the same cell across rewrites; its history is one chain. This is more honest than UUIDs. - Content-addressing scales further than name-addressing. A grid's coordinate is derived from what is in it, not from where it lives. Move the file; the coordinate is unchanged.
- Capabilities beat ACLs. A capability cell is itself a cell, visible, auditable, supersedable. Permissions live in the data plane, not in a side channel. The mechanism that decides who-can-do-what is the same mechanism that does everything else.
- Invisibility is the right denial model. A denied operation should leave no trace for the unauthorized party. Error messages leak existence; the grid does not advertise what it hides.
- Encryption is layered. Per-cell, per-level, per-grid. Pick the granularity your threat model needs, not the granularity your storage engine forces.
- The chain is the clock. Wall-clock is annotation; the sequence is truth. Two residents on two machines with skewed clocks still produce a well-ordered history when their writes serialize through the same chain.
- The CLI is the grammar, not a wrapper. The CLI does not invent verbs. The expression language is the same whether you type at a terminal, call the kernel from a library, or send expressions over a wire.
The aim: a substrate where storage, query, access control, history, encryption, and identity are not separate systems wired together, but one coherent thing.
17 · Conventions
Patterns that pay off.
Date-namespace volatile content. @/findings/YYYY-MM-DD/topic, @/logs/YYYY-MM-DD/HH/event-<n>. Lets you scope queries by time without parsing written-at.
Reserve @/system/** for kernel and protocol use. Don't write application data there. The @/system/* subtree is where the kernel and a small set of protocols (capabilities, refs, cli-identity) live. Pollution there breaks tooling.
One grid, one purpose. Mixing a project's data with a user's keychain in one grid creates capability tangles. Open many grids; cross-reference by coordinate.
A capability cell is data, version it like data. When a capability changes, you'll see the change in history-of: @/system/capabilities/<name>. Treat capability churn as a reviewable thing.
Test with __kernel__. When you suspect a capability is hiding cells, study under the kernel identity to see ground truth. Compare to the projected view.
Treat tombstones as records. They mean something happened. Don't filter them out of audit views.
Compute coordinates lazily. The GHA is expensive; cache it. The kernel does. If you build a tool that scans many grids, cache by file mtime.
Seal what you ship. Any grid leaving the device should be sealed. Any grid at rest in an untrusted location should be sealed. Local working grids stay open.
Don't manufacture grids. There is no grid create command. Touch a .grid file or start writing cells to a path; the CLI auto-creates on first write. The CLI inhabits grids, it does not manufacture them.
Default to public sensitivity for everything that isn't actually sensitive. Locking only encrypts non-public bands. If everything is private, locking does much more work than necessary on each save.
18 · CLI reference
The CLI is named grid. This is the short reference; for the full surface see CLI.
USAGE
grid -g <path> <expression> # explicit grid file
grid -g <path> <subcommand> # file-level operationOPTIONS
-g, --grid <path> Path to the .grid file
-i, --identity <id> Override GRID_IDENTITY for this invocation
--body-file - Read cell body from stdin (multi-line writes)
--version, -V Print version
--help, -h Show usageEXPRESSIONS
study: @/** all cells
study: @/path/** where: type=note filtered
study: history-of: @/addr version log
study: @/** as: count integer
fetch @/addr sugar for study + as: full
write @/addr type: <t> [sensitivity: <s>] body: <text>
move @/src to @/dst
<stage> | <stage> pipelineSUBCOMMANDS
Inspection / integrity:
status, format, cell count, sealed/locked, genesis presenceverify, walk the chain and verify SHA-256 integritycoordinate, print master coordinate (derives from genesis on demand)hash, print GHA-1024 of the genesis cell + master coordinatedump, export human-readable textmigrate, rebuild grid; add genesis if missing
Cryptographic (see Encryption):
lock/unlock, CLE: encrypt/decrypt bodies above publicseal/unseal, GLE: encrypt/decrypt the whole file
Writing a multi-line body (heredoc + body-file):
cat <<EOF | grid -g <file> --body-file - \
"write @/addr type: doc body: x"
multi-line content
goes here
EOF(The dummy body: x satisfies the parser; --body-file - overrides.)
ENVIRONMENT
GRID_IDENTITY, identity for this invocation (default:unknown)GRID_PASSPHRASE, passphrase for lock/unlock/seal/unseal
There is no --watch flag. watch is a verb in the expression grammar. There is no --secure flag, security is the capability projection, not a CLI mode. There is no grid create, write a cell to a non-existent path and the file is created.
Where this cell and grid --help disagree, grid --help wins.
19 · Getting started
A first session.
1. Pick a grid file path. It does not exist yet.
touch mygrid.grid(Optional, grid write will auto-create. The touch is a habit.)
2. Export your identity:
export GRID_IDENTITY=<your-name>3. The first write becomes the genesis cell. Make it descriptive:
grid -g mygrid.grid "write @/system/genesis type: genesis body: <what this grid is for>"4. Inspect the grid's identity:
grid -g mygrid.grid status
grid -g mygrid.grid hash
grid -g mygrid.grid coordinateNote the coordinate, that is this grid's permanent identity.
5. Write some cells. Read them.
grid -g mygrid.grid "write @/notes/first type: note body: hello"
grid -g mygrid.grid "study: @/**"
grid -g mygrid.grid "study: @/** as: count"6. Try a where-clause and history-of:
grid -g mygrid.grid "study: @/** where: type=note"
grid -g mygrid.grid "write @/notes/first type: note body: updated"
grid -g mygrid.grid "study: history-of: @/notes/first"7. Add a capability cell so a second resident can join:
grid -g mygrid.grid "write @/system/capabilities/resident-b type: capability body: clearance: public
study: @/**
write: @/b/**"8. Lock. Inspect. Unlock.
grid -g mygrid.grid lock
grid -g mygrid.grid status
grid -g mygrid.grid unlock9. Seal. Inspect. Unseal.
grid -g mygrid.grid seal
grid -g mygrid.grid unseal10. Read this guide grid against itself:
grid -g <path-to-Residents-Guide.grid> "study: @/guide/** as: addresses"
grid -g <path-to-Residents-Guide.grid> "study: @/guide/01-what-is-grid"If any of these surprise you, study the relevant cell in this guide. If the kernel surprises you, that is a bug, file it as a cell in your findings grid (e.g. @/findings/<today>/<topic>) so the next resident sees it.
Welcome.
20 · The resident binary
grid-resident is a sibling binary to grid, grid-console, and grid-core. It runs deterministic, identity-bound resident loops over grid files. Each subcommand is one cross-grid flow.
grid-resident mirror Copy cells of a chosen sensitivity from a
source grid to a destination grid under
@/mirror/<original-address>. Cursor state
persists in the destination so restart
resumes without duplicates.
grid-resident digest Write one-line summary cells to a digest
grid. Body format: <type> | <first-line>.
Same cursor model as mirror.
grid-resident auto-seal Scan a directory for grid files; seal each
grid whose live cell count exceeds a
threshold. Each sealed grid receives a
key-entry anchor cell in a specified
keychain grid. Already-sealed files and the
keychain itself are skipped automatically.All three flows support --once for deterministic one-shot runs (used in tests and cron) and a polling loop with --interval seconds for live operation. Each resident writes under its own synthetic identity (mirror-resident, digest-resident, seal-resident) so the chain records which loop produced each cell.
Library API exposed by grid_resident:
run_mirror_once(&MirrorConfig) -> Result<MirrorReport, String>
run_digest_once(&DigestConfig) -> Result<DigestReport, String>
run_seal_once(&SealConfig) -> Result<SealReport, String>In-process embedding works the same way: any program that links grid-core can also link grid-resident and call these directly.
A resident is not the kernel. The kernel (grid-core) stays narrow. grid-resident is one layer up, alongside grid-cli and grid-console, depending inward. Future resident flows are sibling subcommands; the boundary does not move.