A pure-Rust, zero-dependency implementation of the Open Knowledge Format (OKF) v0.2, Google's open, human- and agent-friendly format for representing knowledge as a directory of markdown files with YAML metadata.
Install the CLI from crates.io:
cargo install okf
# Run the cli
okf --version # okf 0.2.1 (OKF spec v0.2)Or add it as a library dependency to your project:
cargo add okfOKF stands for Open Knowledge Format, an open, human- and agent-friendly format from Google for representing knowledge as a directory of markdown files.
The format itself is plain markdown files with a YAML header, in a folder. Nothing to install, no schema registry, no database. If you can read a text file, you can read OKF.
- Concepts: one piece of written knowledge about one thing in a markdown file.
- Bundles: a folder of related concepts.
index.mdis its table of contents, andlog.mdthe changelog. - Provenance:
sourceslists where a concept came from, who wrote it, how often it is used, and when it last changed. OKF stores those facts and leaves the conclusion to you, so there is no trust score. - Trust:
generatedindicates who wrote a concept and when.verifiedsays who or what checked it afterwards and when. A concept nobody checked is unverified, one a machine checked is machine-confirmed, and one a person checked is human-reviewed. - Lifecycle:
statusmarks a concept draft, stable or deprecated, andstale_afteris the date it goes stale and has to be checked again. - Attestation: a concept can also define exactly how a value must be
calculated, so an agent cannot make up its own version. An
Attested Computationnames the runtime and its parameters, what a successful run has to report, and the code that checks that report.
okf validate <bundle> Check a bundle against OKF v0.2 conformance
okf lint <bundle> Opinionated bundle health and hygiene checks
okf info <bundle> Summarize a bundle (concepts, types, trust, links)
okf trust <bundle> Report trust tier, status, and staleness per concept
okf computations <bundle> List Attested Computation contracts
okf index <bundle> (Re)generate every index.md in the bundle
okf graph <bundle> Print the cross-link graph (--format text|mermaid|json)
okf parse <file> Parse one concept document and print its structure
okf fmt <file> Normalize a document by parse + re-serialize (-w writes)
okf diff <a> <b> OKF-semantics diff between two bundles
okf validate exits non-zero when a bundle is not conformant, so it drops
straight into CI:
okf validate ./bundles/finance
okf validate ./bundles/finance --today 2026-07-01 # pin staleness for reproducible runs
okf graph ./bundles/finance --format mermaid --sources # renders inline in GitHubokf lint is the opinionated companion: it goes beyond strict conformance and
flags the hygiene issues a continuously-authored corpus drifts into. Every
finding is tagged with a stable rule code so CI can pin or silence
individual checks. It exits non-zero on warnings, leaving infos advisory:
okf lint ./bundles/finance
okf lint ./bundles/finance --today 2026-07-01okf trust gives the per-concept view the trust families exist for:
computations/profit [stable] machine-confirmed STALE
generated: reference_agent/gemini-2.5-pro at 2026-06-14T14:00:00Z
verified: process:finance-nightly at 2026-06-12T08:00:00Z
stale_after: 2026-06-15
source: [cost-alloc] Cost allocation standard
computations/revenue [stable] human-reviewed
generated: reference_agent/gemini-2.5-pro at 2026-06-28T14:00:00Z
verified: human:ahormati at 2026-06-25T09:00:00Z
stale_after: 2026-12-31
use okf::{Bundle, validate_bundle, ConceptId, Date, TrustTier};
let bundle = Bundle::load("./my_bundle")?;
println!("{} concepts", bundle.len());
// Conformance check
let report = validate_bundle(&bundle);
if report.is_conformant() {
println!("conformant with OKF v{}", okf::OKF_VERSION);
}
// Traverse the cross-link graph
let id = ConceptId::parse("tables/orders")?;
for link in bundle.links_from(&id) {
println!("{} -> {} (exists: {})", id, link.target, link.exists);
}
for backlink in bundle.backlinks(&id) {
println!("cited by {backlink}");
}
// Trust and freshness
let today = Date::today_utc().unwrap();
for concept in bundle.concepts() {
if concept.trust_tier() < TrustTier::HumanReviewed && concept.is_stale_on(today) {
println!("{} needs review", concept.id);
}
}
// Provenance: recurse into sources that are themselves concepts
for source in bundle.derived_from(&id) {
println!("{id} derives from {source}");
}
# Ok::<(), Box<dyn std::error::Error>>(())Reading an Attested Computation contract:
use okf::Document;
let doc = Document::parse(
"---\n\
type: Attested Computation\n\
runtime: bigquery\n\
parameters:\n\
\x20 - { name: year, type: integer, required: true }\n\
executor:\n\
\x20 resource: references/skills/run-on-bq.md\n\
\x20 receipt: [job_id, executed_sql, result]\n\
---\n\n# Computation\n\n\
\x20 SELECT SUM(amount) FROM finance.recognized_revenue WHERE fiscal_year = @year\n",
)?;
let contract = doc.attested_computation().unwrap();
assert_eq!(contract.runtime.as_deref(), Some("bigquery"));
assert_eq!(contract.required_parameters().count(), 1);
assert!(contract.computation.code().unwrap().starts_with("SELECT SUM(amount)"));
# Ok::<(), okf::DocumentError>(())v0.2 assumes a corpus that is continuously written and maintained by agents, and makes the questions such a corpus raises answerable from frontmatter. Every new key is optional, and absence is meaningful rather than invalid, so a v0.1 document is still a conformant v0.2 document.
| Question | Frontmatter | Module |
|---|---|---|
| What was this created from? (provenance) | sources, usage_window (§5.1) |
provenance |
| How much should I trust it? (trust) | generated, verified (§5.2), trust tiers (§5.3) |
trust |
| Is it still true? (freshness) | stale_after (§5.5) |
trust |
| Is it the current version? (lifecycle) | status (§5.4) |
trust |
| Was this number produced the way we said it must be? (attestation) | runtime, parameters, computation, executor, attester (§10) |
computation |
Plus the actor convention shared by every identity field
(<producer>/<version>, human:<id>, process:<id>, §7) in actor, and
per-claim attribution through markdown footnotes keyed to sources[].id (§5.1)
in footnotes.
Two v0.1 constructs are superseded (§13.1) but still readable, since a v0.2 consumer is expected to handle v0.1 bundles:
| v0.1 | v0.2 | Fallback in this crate |
|---|---|---|
timestamp |
generated: { by, at } |
Frontmatter::content_changed_at |
body # Citations |
sources + footnotes |
Document::citations still parses it |
okf validate reports both as warnings so a bundle can be migrated
incrementally, without ever failing conformance for using the old form.
An Attested Computation concept (§10) carries a sanctioned way to compute a
value: a runtime, typed parameters, the computation itself (inline under
# Computation or in a file), an executor that produces a receipt, and a
deterministic attester that turns a receipt into a verdict.
This crate models and checks that contract. It never runs anything: the receipt and verdict are runtime artifacts that §10.5 explicitly keeps out of the bundle. Executing computations and attesting receipts are consumer-side concerns.
| Module | Responsibility |
|---|---|
yaml |
A YAML-subset Value/Mapping, parser, and emitter for frontmatter |
document |
Document = frontmatter + body; parse / serialize / validate (§4) |
frontmatter |
Frontmatter: typed accessors over an order-preserving mapping (§4.1) |
concept_id |
ConceptId to/from path conversion and segment rules (§2) |
provenance |
sources, credibility signals, and footnote attribution (§5.1) |
trust |
generated, verified, trust tiers, status, stale_after (§5.2 to §5.5) |
actor |
The human: / process: / <producer>/<version> convention (§7) |
date |
Date/DateTime parsing and comparison for the date-valued fields |
computation |
The Attested Computation contract and its # Computation block (§10) |
footnotes |
[^label] reference and definition scanning (§5.1) |
links |
Markdown link extraction, classification, path-valued fields (§6) |
bundle |
Bundle::load: walk a tree, build the link and derivation graphs (§3, §5.1, §6) |
index |
Generate index.md directory listings (§8) |
log |
Parse / build log.md update histories (§9) |
validate |
§11 conformance checking with severity-tagged diagnostics |
lint |
Opinionated bundle health checks beyond conformance |
The core split mirrors the reference Python implementation's bundle/ package
(document.py, index.py, paths.py, synthesizer.py) so behaviour stays
compatible: the document parser, validator, and index generator are faithful
ports, verified by tests adapted from the reference test suite. Frontmatter can
also be reordered into the key order the reference writes
(Frontmatter::reorder_preferred, PREFERRED_KEY_ORDER).
Compatibility is checked against the reference's four published bundles
(acme_retail, crypto_bitcoin, ga4, stackoverflow): all 53 concepts load,
every one is conformant, and each document's frontmatter re-serializes to a value
PyYAML reads back identically.
| Spec section | Implemented by |
|---|---|
| §2 Terminology / concept id | concept_id::ConceptId |
| §3 Bundle structure | bundle::Bundle, bundle::RESERVED_FILENAMES |
| §4 Concept documents | document::Document, frontmatter::Frontmatter |
| §5.1 Provenance | provenance::Source, provenance::attributions |
| §5.2 Trust | trust::Generated, trust::Verification |
| §5.3 Trust tiers | trust::TrustTier |
| §5.4 / §5.5 Lifecycle | trust::Status, trust::is_stale_on |
| §6 Cross-linking and paths | links, links::field_path_candidates |
| §7 Actor convention | actor::Actor |
| §8 Index files | index::regenerate_indexes |
| §9 Log files | log::Log |
| §10 Attested computations | computation::AttestedComputation |
| §11 Conformance | validate::validate_bundle |
| §12 Versioning | bundle::Bundle::okf_version, OKF_VERSION |
| §13 Changes from v0.1 | frontmatter::LEGACY_FRONTMATTER_KEYS |
- Frontmatter preserves everything. Rather than deserializing into a fixed
struct (which would drop producer-defined keys),
Frontmatterkeeps the full ordered mapping and layers typed getters (type_(),sources(),trust_tier(), and so on) on top. This satisfies the spec's requirement that consumers preserve unknown keys when round-tripping. - Signals are stored, verdicts are derived. Trust tiers (§5.3) and source credibility (§5.1) are computed on read, never stored, because a stored score is subjective, unportable across consumers, and goes stale.
- Staleness is opt-in.
validate_bundleis deterministic and never consults the clock;validate_bundle_at(&bundle, today)adds thestale_aftercomparison. The CLI passes the system date, or--today YYYY-MM-DD. - Permissive loading.
Bundle::loadnever aborts on a bad concept file; it collects parse failures inparse_errors()and keeps going. Broken cross-links are retained as graph edges to non-existent concepts, and a malformed date is reported rather than dropped (DateFieldkeeps the raw scalar alongside its parse). - Validation rejects only what §11 rejects.
Document::validate()requires a non-emptytypeand nothing more, matching the reference implementation. Everything else the spec asks of a producer is reported, never enforced:Document::missing_recommended()returns the unset recommended keys (title,description,generated, plusruntimeon an Attested Computation), andvalidate_bundlesurfaces them as warnings. - A documented YAML subset. Real OKF frontmatter is scalars, lists, and
shallow maps. The parser handles block/flow collections, quoted/plain
scalars,
|/>block scalars, and comments; it rejects (with a clear error) the YAML features that never appear in frontmatter: anchors, tags, multiple documents. Colons inside flow scalars are content, not separators, so{ by: human:ahormati, at: 2026-06-25T09:00:00Z }parses as v0.2 intends. Scalars may also span lines, folding each break into a space, because PyYAML wraps any value past 80 columns and the reference publishes bundles that way. - Timestamps stay strings. YAML's implicit resolver would type a bare
2026-06-30T14:00:00Zas a datetime; this crate keeps it as text with the parse alongside (DateTimeField), so a malformed date can be reported rather than silently dropped. On the way out a datetime-valued scalar is emitted quoted, because a bare one is not stable even under the reference's own round-trip: PyYAML re-dumps it as2026-06-30 14:00:00+00:00, losing theTandZthat §5.2 asks for. A bareYYYY-MM-DDstays plain.
Licensed under the Apache License, Version 2.0, the same license as the
upstream OKF project.
This crate is a derivative work: its document parser, concept-id conventions,
and index generator are ports of the OKF reference implementation. See
LICENSE for the full terms and NOTICE for attribution.
This is an independent implementation and is not affiliated with or endorsed by Google.