Getting started with okf: search a Markdown knowledge base
Getting started with okf: search a Markdown knowledge base
After these five steps you have found a concept with okf find, read it with okf read and run a conformance check with okf check.
The output below comes from okf 0.2.5. It was run against a throwaway copy of the test catalogue of the okf repository (tests/golden/catalogue). Use that copy, or your own catalogue, so that you never run your first experiments on live content. Install okf first: see Installation.
-
Point okf at a catalogue.
okf needs one catalogue root. It finds it in this order:
--global: therootkey of~/.config/okf/config.toml.--root PATH.- The nearest catalogue above the working directory. A directory counts as a catalogue when it holds
.okf.toml, orSPEC.mdtogether withTYPES.md. - The
rootkey of the user config.
Copy the test catalogue and change into it. The copy holds
.okf.toml, so okf finds it from there:Make a throwaway catalogue cp -R tests/golden/catalogue /tmp/okf-try && cd /tmp/okf-tryDetails: Configuration.
-
List the bundles with
okf index.A bundle is a top-level directory of the catalogue.
okf indexprints one line per bundle.okf index $ okf index_ctx: Curated, ordered reading lists per topic — one file per ctx slug, managed by `okf ctx`.handbook: Welcome to the handbook.kc-gov:recipes:[exit 0]Three bundles hold concepts.
_ctxholds context bundles. Bundles with no description print an empty text after the colon. -
Search with
okf build-indexandokf find.Ask first, without an index.
findfalls back to a substring scan and says so on stderr:okf find without an index $ okf find bread --limit 2note: lexical index absent — falling back to substring scan; run `okf build-index` for BM25 ranking------rank: 1title: Breadtype: Recipepath: recipes/breaddescription: Bread with a long risebody-snippet: # Bread ## Steps Mix, rise, bake. Related: [pasta](pasta.md).…provenance: lexical------rank: 2title: cookingtype: Contextpath: _ctx/cookingdescription: Cooking basicsbody-snippet: …comment | |---|---|---|---| | 1 | pflicht | [bread](/okf-cli/recipes/bread.md) | | | 2 | pflicht | [pasta](/okf-cli/recipes/pasta.md) | | | 3 | pflicht |…provenance: lexical------[exit 0]Build the FTS5 index once. It lands in
.fts/fts.sqliteinside the catalogue. Then ask again for BM25 ranking:okf build-index, then okf find $ okf build-indexindexed 25 concept(s) -> <catalogue>/.fts/fts.sqlite[exit 0]$ okf find bread --limit 2note: semantic arm skipped (.tagvec cache/concept embeddings absent) — lexical results only------rank: 1title: Breadtype: Recipepath: recipes/breaddescription: Bread with a long risebody-snippet: # Bread ## Steps Mix, rise, bake. Related: [pasta](pasta.md).…provenance: lexical------rank: 2title: Recipes overviewtype: Conceptpath: recipes/overviewdescription: Overview of the recipesbody-snippet: # Overview See [pasta](pasta.md), [bread](/okf-cli/recipes/bread.md), [soup](soup.md) and [[salad]].…provenance: lexical------[exit 0]Semantic search is optional. See Markdown knowledge base search.
-
Read one concept with
okf read.Pass the
pathvalue from the search result:okf read recipes/bread $ okf read recipes/bread---type: Recipetitle: Breaddescription: Bread with a long risetags:- food- breadtimestamp: 2025-12-02T08:00:00Zstatus: todo---# Bread## StepsMix, rise, bake. Related: [pasta](pasta.md).[exit 0] -
Check the catalogue with
okf check.checkscans against the format rules. Name a bundle to narrow the scan. The test catalogue breaks rules on purpose, so the exit code is 4:okf check recipes $ okf check recipesERROR okf/type/reserved-no-type recipes/readme.md (reserved file must not carry `type`)ERROR kc/supersede/resolves recipes/salad.md (superseded_by target does not resolve: recipes/soup)ERROR kc/asset/placement recipes/shopping.txt (non-md file outside assets/)ERROR kc/supersede/resolves recipes/stew.md (superseded_by target does not resolve: handbook/ops/deploy)WARNING kc/link/crosslink-format recipes/bread.md (non catalogue-absolute link(s) (use /bundle/…): pasta.md)WARNING kc/link/crosslink-format recipes/drafts/ideas.md (non catalogue-absolute link(s) (use /bundle/…): pie.md)WARNING kc/link/crosslink-format recipes/overview.md (non catalogue-absolute link(s) (use /bundle/…): pasta.md, soup.md)WARNING kc/frontmatter/tags-block-form recipes/overview.md (tags field uses inline form — local convention requires YAML block-list)WARNING kc/link/crosslink-format recipes/salad.md (non catalogue-absolute link(s) (use /bundle/…): soup.md)WARNING kc/supersede/scope recipes/salad.md (superseded_by used on non-Decision concept (type=Recipe))WARNING kc/frontmatter/tags-block-form recipes/soup.md (tags field uses inline form — local convention requires YAML block-list)WARNING kc/markup/xml-like-tags recipes/soup.md (angle-bracket placeholder(s) not in code-fence: <size>)WARNING kc/tag/registered recipes/stew.md (tag `misc` not registered in TAGS.md)WARNING kc/frontmatter/english-keys recipes/stew.md (German frontmatter key(s): beschreibung, titel)WARNING kc/supersede/scope recipes/stew.md (superseded_by used on non-Decision concept (type=Recipe))4 VIOLATIONS[exit 4]The summary counts the
ERRORlines. Warnings print but do not count, unless you add--strict. Exit codes: JSON output and exit codes.
Where options go
--root and --global are options of okf itself. Put them before the command. You can then run okf from any directory:
$ cd /tmp$ okf --root /tmp/okf-try index_ctx: Curated, ordered reading lists per topic — one file per ctx slug, managed by `okf ctx`.handbook: Welcome to the handbook.kc-gov:recipes:[exit 0]Without --root, a directory with no catalogue above it and no root in the user config fails:
$ okf indexERROR: no catalogue found in cwd or its ancestors and no root in ~/.config/okf/config.toml; pass --root <path>[exit 3]Result
You have a catalogue root that okf resolves, a lexical index in .fts/fts.sqlite, and one real run each of index, find, read and check.