Outcrop — conceptual architecture
A DBMS whose storage layer is a folder of markdown files.
Hover, tap, or tab to any block for its role — or show every
description at once, which is also what printing this page gives you.
Read it like a core sample: surfaces at the top, substrate at the bottom.
Record = one .md file · Table = folder · Git = transaction log · OKF v0.2 in and out
Surfacespeople use these
Canvas (macOS) dashboards & authoring
OutcropCanvas — SwiftUI
Infinite pan/zoom canvas of cards: query, graph, record (edit-in-place).
Explorer sidebar with full-text search; scenario picker re-renders every
card against the chosen scenario. The canvas itself persists as a normal
record (canvases/default.md ) — dashboards diff and merge like data.
outcrop CLI scripting & CI
outcrop-cli
The whole surface from a shell: query, get/set/rm, validate, scenarios,
snapshots, merge with keep-mine/theirs/both, history, adopt/discard.
Embeds the service directly — no server needed for local work.
IDEs via LSP edit with guardrails
VS Code · Neovim · JetBrains · Zed · Helix
One language server, thin clients everywhere. Editing a record gets
schema diagnostics as you type, completion for fields, enums and
[[wikilinks]], hover cards, and go-to-definition across records.
Agents via MCP Claude & friends
Model Context Protocol clients
Agents get the same tools people do: query, upsert, validate, scenario
branch/diff/merge. Transactions make agent writes safe by construction —
propose, review the diff, keep or discard.
Android · Windows stubs, UI later
Generated clients, no UI yet
Kotlin and C# clients generated from the same frozen contract, each with a
smoke test. They exist to prove the contract travels; interfaces come later.
gRPC over a Unix socket · MCP (stdio) · LSP (stdio) — all generated from one frozen proto/outcrop.proto
Rendezvousnobody starts a server
the engine instance shared, on demand, self-terminating
One engine per bundle
The first client that needs it starts it; everyone else adopts it. A kernel
lock on .outcrop/engine.lock is the only authority on who is alive —
engine.json is a hint, and adoption is only granted by a live Hello
answering with the right version and bundle root. Clients hold a lease for
as long as they run; the engine winds itself down about 45s after the last
one leaves. Prior art: LocalDB automatic instances, the Gradle daemon.
Canvas spawns-or-adopts · agents adopt-or-spawn · CLI adopts only if one is already there · unreachable lock ⇒ each client runs solo, which is simply the old behaviour
same process, same answers — adoption is an optimization, never a requirement
Servingthe doorway
outcrop-server gRPC + MCP
One service, two transports
tonic gRPC for native clients and an MCP server for agents, both mapping
1:1 onto the same scenario-aware core. Policy blocks come back as normal
answers, never transport errors. Speaks only user vocabulary:
Scenario, Snapshot, Propose changes, History, Restore.
outcrop-lsp language server
The IDE doorway
Wraps the store and validation engines behind the Language Server
Protocol: diagnostics, completion, hover, navigation. Launched as
outcrop lsp over stdio by any editor.
plain Rust calls — the crates below are the product; servers are thin
Engineask & check
outcrop-query SQL · search · graph
DataFusion + tantivy
Every folder is a SQL table: frontmatter → columns, H2 sections → text
columns, plus _path, _links_in/_links_out, _modified, _flagged. Full-text
via search('…'), link-graph via neighbors(), links_to(), paths(). Engines
capture a snapshot; writes invalidate; pinned snapshots never do.
outcrop-schema validation & policy
Constraint tools, not enforcement
Per-folder _schema.yaml: field types, required, enums, link targets.
Policies ignore / warn / block apply at write and merge time. A violating
file is a valid file and a flagged record — never corruption.
outcrop-txn transactions & scenarios
Git as the write-ahead log
Stage = open transaction; commit = commit; rollback = discard; crash
recovery = pending/resume. Scenarios are branches you can diff and merge
field-by-field (Keep mine / theirs / both); snapshots pin immutable
states you can still query. Survives SIGKILL mid-transaction.
lossless byte-span edits — never parse-and-reserialize
Storagethe contract with your files
outcrop-store files, watcher, index
The only code that touches bytes
Span-aware documents: updating one frontmatter field leaves every other
byte identical (property-tested). Atomic writes (temp → fsync → rename).
A debounced watcher folds in external edits and keeps an incremental
index of records and their link graph.
plain files on disk — yours, readable, diffable
Substratewhat actually exists
the bundle/ folders of markdown · OKF v0.2
A folder you already understand
Each record is a .md file with YAML frontmatter; each folder is a table;
index.md and log.md are reserved bundle furniture. Conforms to the Open
Knowledge Format v0.2 — bundles travel in and out with provenance and
trust fields intact.
.git + .outcrop/ history beneath
Invisible machinery
Git holds every transaction as a readable diff; .outcrop/ holds scenario
worktrees and snapshot caches. Users never see git vocabulary — they see
History, Scenarios, Snapshots, Restore.
External writersfirst-class citizens
Obsidian · any editor · git pull · Finder · other agents
— write the files directly. The watcher detects, reindexes, and conflicting
edits surface as mergeable conflicts against snapshot reads. Never lockout,
never corruption.