· 11 min read · Engineering
A Field Is Not a Process
Twenty-one years ago I was writing wiki engines. In 2005 I worked at Socialtext, one of the first commercial wikis, on the then-radical idea that a team could keep its shared knowledge on a page anyone could edit. That same year, for a running contest on Ward Cunningham’s original wiki, I got a working wiki down to four lines. So when Andrej Karpathy posted his LLM Wiki idea in April, and Google shipped a spec that formalized a slice of it, I didn’t read it as news. I read it as a thread I’d been pulling on for two decades, with the same knot still tied in it.
The Wiki I Fit in an Email Signature
The Shortest Wiki Contest asked for the smallest source code that still ran a real wiki: automatic linking, editable pages, the whole contract. People got it to a few dozen lines. Building on the work done on FleaWi, PeeWee, and mostly PeWi, I got it to four, and called it SigWik because it fit in an email signature, 80 columns wide. Nick Clark named it, for the four lines. Doug Merritt’s reaction on the page is still the best code review I’ve gotten: Ok, now I am amazed. Here it is, 218 characters of Perl and shell, reproduced from the contest page:
#!/usr/bin/perluse CGI':all';path_info=~/\w+/;$_=`grep -l $& *`.h1($&).escapeHTML$t=param(t)||`dd<$&`;open F,">$&";print F$t;s/htt\S+|([A-Z]\w+){2,}/a{href,$&},$&/eg;print header,pre"$_<form>",submit,textarea t,$t,9,70I’m not showing this to brag about a stunt (or maybe I am). I’m showing it because it makes the boundary concrete. SigWik is the format: a folder of files, one file per page, links found by pattern. That part is genuinely small, a clever afternoon. Ok, I’ll be honest, several weeks of iterating. What four lines can’t contain is the part where a human comes back next week, sees the page is wrong now, and fixes it. The format is the easy half. It always was.
What Karpathy Proposed, and What Google Kept
Karpathy’s idea was never “a folder of markdown.” Read the gist and it’s the operations that matter: the model incrementally builds and maintains a persistent, interlinked wiki between you and your raw sources. His framing sticks with me: Obsidian is the IDE; the LLM is the programmer; the wiki is the codebase. Knowledge gets compiled once and kept current, instead of re-derived from scratch on every query the way retrieval-augmented generation does it.
But the pitch has a part that isn’t a folder at all. It describes ongoing upkeep, not just a layout. Karpathy spends a section on it: periodically, ask the model to health-check the wiki, hunting contradictions, stale claims a newer source overtook, and orphans nobody links to. He calls it the lint step. It’s the maintenance loop, and it’s what keeps the wiki from becoming a museum of things that used to be true.
Now Google’s Open Knowledge Format.
OKF is a real, minimal, well-designed spec, version 0.2 as I write this, and
standardizing the container is worth doing: a bundle is a directory, one file is
one concept, the file path is the ID, and links are a plain graph. Two reserved
files, index.md and log.md, do what they did in the gist. The container
Karpathy sketched, Google wrote down.
The spec kept the structure. It left out the recurring check.
A Field Is Not a Process
OKF gives you a modified field. It records a fact: here’s when this concept was
last written. Nothing notices that a source published last
month contradicts a page written last year. You can have a perfectly valid,
fully conformant OKF bundle that’s wrong, or out of date, and the format
won’t say a word. Being wrong is not a validation error.
That’s the knot: a field is not a process. A timestamp is inert.
If you’re reaching for a wiki over a vector database, here’s the trap. RAG re-derives its answer from the chunks on every query, so its staleness is bounded by what it just retrieved. A wiki’s staleness is unbounded: it’s whatever the last curation pass left behind, however long ago that was. And a stale wiki page still reads as authoritative, so it rots faster than RAG because nobody suspects the well-formatted page.
I know this because I run a knowledge base that would have rotted if I hadn’t planned for it.
What okfctl Does
My own corpus is currently 254 curated concepts, the research and method notes my agents read before they do anything, stored as an OKF bundle. For a while it was a bundle with no process behind it, aging one commit at a time.
So I built the check the spec left out. okfctl is an open-source CLI, Apache-2.0, on GitHub. It’s a single static Go binary you install and point at a folder, and the whole thing is designed around one refusal: the core stays pure Go, offline, and model-free, so every command below produces the same answer on your laptop that it produces in my CI. What follows is that binary run against my real 254-node bundle. Every number is its actual output.
Conformance and Health Are Two Different Questions
Start with the most important pair. validate asks whether the
bundle is a legal OKF bundle. lint asks whether it’s holding together as a
body of knowledge. On my corpus, both come back clean:
$ okfctl validate ./bundles/knowledgeOK: bundle conforms to the OKF spec floor
$ okfctl lint ./bundles/knowledgeOK: no lint findingsTwo green checks, two different floors. validate measures the bundle against the OKF specification. lint measures orphans, broken cross-links, and
coverage gaps, the curation hygiene. A
perfectly conformant folder can still be quietly rotting, and only lint catches it.
analyze: Make the Rot Visible
lint gives a pass/fail gate. analyze is the microscope.
It walks the whole bundle and reports where the knowledge is weak, not where
it’s malformed:
$ okfctl analyze ./bundles/knowledge# OKF Corpus Analysis
254 node(s), 4123 internal link(s). Stale threshold: 180d....## Coverage gaps — thin nodes (need expansion) - casey/agentic-efficiency.md (9 lines) - design/spacing-rhythm-and-density.md (13 lines)...## Structure — near-duplicate slugs (rename/merge candidates) - security/authz/abac.md ≈ security/authz/rbac.md...435 actionable signal(s) across all dimensions.Four hundred thirty-five signals on a corpus that just passed both gates. A
nine-line concept that pretends to be a concept. Nine nodes with no citation
behind them. Two access-control pages, abac.md and rbac.md, similar enough
that one of them is probably swallowing the other’s traffic. None of that’s a
spec violation. analyze is the timestamp’s
missing conscience: it does the noticing the frontmatter field can’t.
eval: A Machine Gate on Trust
This is the command I’m proudest of. eval decomposes a node’s trustworthiness along four
dimensions borrowed from the TACA framing: Transparency, Accuracy, Calibration,
and Alignment. Only one of those can be checked without a model.
eval transparency is deterministic. It checks that a node’s provenance is
actually there, that it carries a grade, that its internal citations resolve. Run
against my corpus, it found two real problems:
$ okfctl eval transparency ./bundles/knowledgegrade-vocabulary: design/spacing-rhythm-and-density.md has authority: "DEPRECATED", an off-vocabulary value carried by only 1 node(s) (likely a typo/drift)grade-vocabulary: design/ux-psychology/deceptive-patterns.md has authority: "high", an off-vocabulary value carried by only 1 node(s) (likely a typo/drift)2 transparency finding(s)Two nodes carrying authority grades that aren’t in the vocabulary, DEPRECATED
and high, each the only node in 254 to use its value. That’s drift, the kind of
slow schema erosion that no one notices until a query trusts the wrong page.
okfctl’s own help text calls this “the first machine gate that touches trust
rather than format,” and that’s the right claim, precisely because it’s a narrow
one.
The other three dimensions need a model or the network to judge. Instead of guessing whether a claim matches its source,
eval sample scaffolds an eval-set, one row per node with every extractable field
pre-filled and the judgment slots left empty, and hands it to a human or an
out-of-band LLM judge to complete. The tool computes no truth verdict it can’t
verify on its own.
search: Query the Bundle With No Model and No Index
Search runs against the bundle with no embedding model and no prebuilt index,
which matters if you want a curation check you can run on every commit without a
GPU in the loop. Lexical mode matches title, tag, type, or body. The mode I reach
for more is --neighbors, which walks the link graph instead of the text:
$ okfctl search --neighbors research/a-field-is-not-a-process.md ./bundles/knowledgecasey/usermd-anchor-restructure-decision.md Decision Memo depth=1method/node-worthiness-graph-richness.md Research Brief depth=1research/agentic-harness.md Research Brief depth=1research/breadth-access-capability-layer.md Concept depth=1research/core-instruction-files-and-memory-layering.md Research Brief depth=1research/go-vs-rust-okfctl-cli-spike.md Research Brief depth=1research/llm-wiki.md Concept depth=1research/okf-write-time-curation.md Research Brief depth=1research/rag-vs-write-time-curation.md Concept depth=1research/semantic-recall-store-design.md Research Brief depth=1research/the-invisible-moat.md Concept depth=1The bundle is a graph, so I can ask it graph questions: what sits one hop from this concept? The answer is the neighborhood this very post grew out of, right down to the spike where I argued myself into building the thing in Go. Semantic vector search exists too, but as a separate plugin, deliberately outside the core.
migrate: Two Phases So It Never Learns to Guess
When OKF went from v0.1 to v0.2, two keys got renamed. migrate upgrades a bundle
across that break in two phases.
Phase one is pure read: it computes every mechanical edit and enumerates every
edit that needs a judgment call, then writes a plan file and touches nothing else.
Phase two applies only the mechanical edits, order-preserving and additive, and
re-validates. The judgment items, a prose citation with no resource behind it, a
rename with no recorded actor, are never guessed. They stay in the plan for a
person to resolve.
graph export and serve: The Bundle Is a Graph, So Treat It Like One
graph export hands you the whole link structure as JSON or Graphviz DOT, so the
254 nodes and 4,123 edges become something you can pipe into other tooling.
serve renders the same graph as an interactive page, assets baked into the
binary. A knowledge base is a
network of concepts. It can help to visualize it.
Here’s mine. graph export produces the DOT; a short script colors each node and
its outbound edges by top-level folder and sizes nodes by degree, then Graphviz
lays it out:
$ okfctl graph export --format dot ./bundles/knowledge > kb.dot$ ./scripts/color-graph.py kb.dot | sfdp -Tpng > graph.png
Every dot is a concept (node) and every line is a link (edge). That picture is also the argument: nothing in the folder format keeps a network that dense honest as it grows, which is what the rest of these commands are for.
One More Refusal: Plugins
Everything above is core, and core is pure Go and offline on purpose. The things
that need a model or the network, semantic search, an HTTP API, live outside as
okfctl-<name> plugins that the CLI discovers on your PATH. You can also write your own plugins.
Wire It In, or It Won’t Run
A command you have to remember to run is a command that eventually doesn’t. So the check has to sit inside the loop:
flowchart LR
A[Write or edit a concept] --> B[Commit]
B --> C{"okfctl lint --strict"}
C -->|"orphan · stale link · contradiction"| D[Fail the build]
D --> A
C -->|clean| E[Merge]
E --> F[Corpus stays true]
F --> A
I run it at two points. A pre-commit hook stops a bad concept before it lands, and
CI runs it as a hard gate that fails the whole build on any curation error. The
modified field is still inert. The hook and the gate are what make it mean
something, because now something runs when the folder changes.
There’s a measurable payoff, not just a hygienic one. When I moved the corpus to passage-level search indexing, so a hit points at the paragraph instead of the file, retrieval quality on the real corpus went from 0.545 to 0.909. A maintained bundle earns better answers than a pile of valid-but-unkept files.
Choose the Whole Idea, Not Half of It
If you’re choosing a wiki over RAG for your agents because you read the same gist I did, choose the whole idea. The folder is the part you get for free. The recurring, build-failing check that keeps it true is the part you have to build, or borrow, or you won’t have the thing you actually want. OKF is a good container. Use it, then add the tools and process so your information doesn’t go stale. okfctl is one static binary, and it’s the difference between a knowledge base and a graveyard that validates.