Lang on Rock is a faster, cheaper document database for AI agents.
Your agent answers the same questions for 45% fewer tokens and thirteen fewer round trips. Over a set of RFCs it saves 98%, and it finds the right concept at least as often as reading the raw files. Instead of crawling your Markdown it reads a compiled index and asks for the one section it needs. No embeddings to generate, no vector database to run. One binary, local or over the network.
$ curl -fsSL https://raw.githubusercontent.com/langonrock/langonrock/main/install.sh | shDetects the platform, verifies the checksum, and drops the binary in ~/.local/bin. x64 and arm64 both covered.
No one-line installer yet. Take windows-x64 or windows-arm64 from the releases page.
$ git clone https://github.com/langonrock/langonrock && cd langonrock && bun installNeeds Bun 1.3 or newer. The bin entry points straight at src/cli.ts, so there is no build step before running it.
Then langonrock --version to check it, or the quickstart to compile your first tenant.
| OKF navigator | 116,357 | |
|---|---|---|
| langonrock | 64,355 |
Against the OKF reference consumption pattern.
| OKF navigator | 30 | |
|---|---|---|
| langonrock | 17 |
Tool calls to answer the same twenty questions, manifest strategy. Ranking first instead trades one extra call per question for tokens.
| reference, catalogue | 70 → 75% | |
|---|---|---|
| handbook, recipes | 90 → 100% | |
| spec, RFCs | 95 → 100% | |
| book, novels | 80 → 80% |
- OKF raw files
- langonrock
The concept that answers, found in the top 8. Named queries, default link expansion, never worse than the raw files.
| spec, 28 RFCs | 98% | |
|---|---|---|
| scripture, by book | 97% | |
| handbook, 1,281 recipes | 84% | |
| book, by chapter | 69% | |
| reference, catalogue | 51% |
Best strategy per corpus, at the grain shown. Structure pays — links, headings, titles — and where prose has none, find fetches a located window instead of the chapter. That is what moved the novels from the 2% they sat at.
Synthetic corpus, chars / 4 token estimate. Method
What you get
Six things that change once the store is compiled, and the mechanism behind each one.
Nothing you already have moves
langonrock compiles your Markdown, it does not take it over. Frontmatter is optional and OKF conformance is what --strict enforces, so okflint and the visualizer keep working on the same folder.
A recompile does not cost you the cache
Identical input produces identical bytes, so syncing after every edit leaves the agent’s cached prompt prefix intact instead of billing you to rebuild it.
Pay for the section, not the document
Ask for the schema of a table by its own Markdown heading, hand find a phrase, or follow a search hit’s pos offset to the densest passage. A catalogue read drops from 594 tokens to 213; a novel chapter from 3,244 to 513.
One call, however many concepts
Pass every id you need at once instead of paying an inference turn per hop. The cost of a batched fetch is flat from 500 concepts to 20,000.
The same query returns the same set
Retrieval is BM25 plus a one-hop expansion over the link graph, capped so a hub concept cannot drag in half the manifest. No model anywhere in the path, so results do not drift under you.
Restore is a file copy
Snapshots are named by their own hash, so a backup is a file copy, a restore is a file copy back, and rollback is a side effect rather than a feature you have to operate.
The whole path, four commands long
Nothing you already have moves. langonrock compiles your directory into a snapshot, opens it wherever the agent runs, and hands back one section at a time.
Compile
Point langonrock at your OKF directory. Every subdirectory is read as a bundle, and the whole tenant is written as one snapshot named by its own hash. The Markdown stays the source of truth and stays conformant, so
okflintand the visualizer keep working on the same folder.$ langonrock sync sources/acme --data ./data --tenant acmeIdentical input produces identical bytes, so syncing after every edit leaves the agent’s cached prompt prefix intact instead of billing you to rebuild it.
Open
The scheme picks the mode. Develop embedded against the files, deploy against a daemon or a host, and change nothing at the call site, because
open(dsn)returns the same interface for all three.- okf:///var/data?tenant=acme
- Embedded, direct file access.
- okf+unix:///tmp/okf.sock?tenant=acme
- Local daemon, warm indexes, no cold start.
- okf+https://host:7777?token=…
- Remote, tenant resolved from the token.
Load the manifest
The agent’s first call is the manifest: one tab-separated row per concept with its id, its one-line summary, what it links to and whether it is still current. It is the map, it goes in the cached prefix, and it comes back byte for byte identical on every rebuild.
$ langonrock manifest --data ./data --tenant acmeGet
Ask for the schema of a table or the rollback step of a runbook, addressed by the concept’s own Markdown headings, rather than for the document that contains it. Pass every id you need in one call instead of paying an inference turn per hop.
$ langonrock get orders --section schema --data ./data --tenant acmeOmit the flag for the whole concept. The cost of a batched fetch is flat from 500 concepts to 20,000.
Search takes the same path. Retrieval is BM25 over each concept’s names, manifest row and body, plus a one-hop expansion across the link graph, capped so that a hub concept cannot drag in half the manifest. There is no model anywhere in it, so the same query returns the same set tomorrow — and it finds the right concept at least as often as running the same ranker over the raw files. A query returns in 1.8 ms at 20,000 concepts.
Three ways to read it
The manifest costs once, amortised over the session. A search costs once per question. A located window replaces the cost of the document it came from. Which one wins depends on your corpus, not on a setting, and the store ships all three behind the same four read verbs.
manifest → getKeep the manifest in the prompt
The whole map goes into the cached prefix once, and every read is one hop off it. That is the fewest round trips of the three: 17 calls against the navigator’s 30 on the warehouse catalogue, and 64,355 tokens against 116,357. The right call while the manifest stays small, which means RFCs, coarse-grained bundles, anything up to a couple of thousand concepts.
17 calls · 64,355 tokens · 500 concepts
search → getRank first, never read the manifest
Ask for the eight rows that matter and fetch what ranked. One extra call per question buys the tokens back. A 20,000-concept tenant answers the same twenty questions for 60,755 tokens against the navigator’s 2.69M. The right call once the manifest stops fitting in the prompt.
36 calls · 60,755 tokens · 20,000 concepts
search → get(pos | find)Locate the passage, skip the document
When the question is where the text says something, get takes a literal phrase. When there is no phrase to quote, every search hit carries pos, the offset of the passage densest in the query’s words. Either way the read is a window of about 500 tokens, whatever the document size. Four novels answer the same twenty questions for 39,862 tokens against 127,077 by whole chapters. The corpus this store used to lose.
40 calls · 39,862 tokens · 4 novels
The crossover is the ratio between the manifest’s size and one search result. Over a twenty-question session it lands near twenty. The RFC corpus sits at 2× and reads cheaper through the manifest. Mrs Beeton’s recipes sit at 102× and read cheaper through search. The MCP server measures the manifest at startup and writes the verdict into the tool description, so you never have to work the ratio out yourself. Narrowing on a large tenant
What it costs, and where it loses
Twenty fixed questions over the same corpus. Both paths pay for delivering the same concepts. The baseline is the OKF reference consumption pattern, running the same BM25 over the raw Markdown with perfect navigation and never a wrong turn.
A session that bills 116,357 tokens against that baseline bills 64,355 here, over 17 tool calls instead of 30. Thirteen fewer round trips is thirteen fewer inference turns you wait through, so the answer lands sooner as well as cheaper. That is the synthetic catalogue. Over real corpora the saving runs from 51% on the warehouse catalogue up to 98% on RFCs. The novels used to bottom out at 2%. Locating a passage instead of fetching the whole chapter moved them to 69%.
None of that is density. The manifest is larger than a well-kept index.md, 20,549 tokens against 16,575. The saving comes from asking for one section instead of a whole document, which takes a read from 594 tokens to 213. The rest comes from narrowing to a bundle instead of reading the whole tenant.
Compiling used to cost ranking. The frontmatter the compiler strips repeated the concept id in its resource and sourcesURLs, which happened to help the ranker. Indexing each concept’s own names gave it back. Its id and its frontmatter title now weigh above the other fields, and hit rate lands at 75% against the baseline’s 70%, mean reciprocal rank at 0.44 against 0.43. Queries that describe a concept instead of naming it move the same way. Mrs Beeton’s recipes go from 55% on the raw files to 80% here. What still loses, narrowly, is ranking on plain prose. The raw files keep a slightly better top position on the novels, 0.72 mean reciprocal rank against 0.69. The session cost no longer follows it, because find gives prose the sub-document addressing its missing headings never could. A 3,244-token chapter read becomes a 513-token window.
Synthetic corpus, a deliberately crude chars / 4 token estimate, one script on one machine. Treat all of it as an order of magnitude and measure your own bundles. The full tables, and the method behind them.
- Whole manifest
- One bundle slice
The tenant grows by adding bundles. The slice a reader asks for does not, so it holds at about 20,500 tokens while the whole manifest reaches 835,922. At 500 concepts there is a single bundle and the two are the same number.
People get an editor, not a manifest
The compiled read model is for agents. langoneditor is the half you look at, a desktop app for macOS, Windows and Linux. Point it at a folder of Markdown and it works, or point it at a langonrock server and it searches that server’s own index. The binary ships inside it, so there is nothing else to install.
It derives no ids, resolves no links and reproduces no lint rules. It writes the source Markdown and lets the watcher recompile, so the editor and the store cannot drift apart.
The bundle tree
Every bundle and concept in the tenant, as they sit on disk.
Markdown, with a form for the frontmatter
Prose stays prose. The fields that have to validate get fields.
The link graph
What a concept points at, and what points back at it.
Archives and spreadsheets
Move a bundle in or out without touching the store by hand.
One binary, server optional
One binary for macOS and Linux on x64 and arm64, a data directory, and an MIT licence. No schema to migrate and nothing that has to stay running between reads. It is written for Bun 1.3, so reading it from source is bun install and a --help.
$ curl -fsSL https://raw.githubusercontent.com/langonrock/langonrock/main/install.sh | shDetects the platform, verifies the checksum, and drops the binary in ~/.local/bin. x64 and arm64 both covered.
No one-line installer yet. Take windows-x64 or windows-arm64 from the releases page.
$ git clone https://github.com/langonrock/langonrock && cd langonrock && bun installNeeds Bun 1.3 or newer. The bin entry points straight at src/cli.ts, so there is no build step before running it.
Then langonrock --version to check it, or the quickstart to compile your first tenant.