okf — a CLI for maintaining an OKF v0.2
knowledge bundle: scaffold stubs catalog docs from the repo sources, index
regenerates progressive-disclosure index.md listings, validate checks
spec/profile conformance and links, migrate rewrites v0.1 docs into the v0.2
shape, and viz renders the bundle as a
self-contained interactive 3D graph (single offline HTML file — Svelte 5 viewer
around Three.js glow spheres, bundled at generation time by Bun.build).
Since minification strips the bundled libraries' copyright headers and their
MIT/zlib terms require notices to accompany redistributed copies, viz embeds
each runtime dependency's LICENSE text (collected from node_modules at build
time) in the page — see the "Licenses" tab in the viewer's About modal, which
also carries okflight's own MIT notice (the embedded viewer app is okflight
code) and links back to this project.
Concept bodies may carry LaTeX — inline $…$ or \(…\), display
$$…$$ or \[…\] (single line or a multi-line block). viz typesets it
with KaTeX, MathML layer included so copy-paste and
screen readers get the formula. Because the renderer plus its inlined woff2
fonts add about 1.3 MB to every viz.html, math is off by default;
turn it on either way:
[display]
math = true # okflight.toml — every build of this workspaceokf viz --math # one run, whatever the TOML saysWith math off the page carries no KaTeX code, stylesheet, fonts or license
notice, and the delimiters stay literal text — nothing is stripped, so a
bundle that later enables math renders the same source. Dollar amounts in
prose ($5 to $10) and anything inside code spans or fences are never
treated as math either way.
okf operates on a workspace: the nearest directory at or above cwd holding
an okflight.toml (the pre-rebrand name okf.toml is still discovered, with a
rename nudge), else the git toplevel (zero-config mode). okf init [--dir=<d>]
bootstraps a fresh workspace — a commented starter okflight.toml plus the
bundle skeleton (<d>/index.md, <d>/log.md); it never overwrites. okf setup
is the guided superset — see "Integrating into a repo" below. Git is optional —
[vcs] provider = "auto"|"git"|"none" selects the version-control adapter
(auto = git when the root is a git toplevel); the none provider walks the
filesystem (minus [vcs] ignore globs), stamps mtime dates, and skips commit
links, so any directory tree — no VCS at all — can host a bundle.
The v0.2 spec makes an agent-maintained corpus self-describing through a few optional frontmatter families, and okflight reads all of them:
generated: { by, at }— who wrote the content and when (supersedes the v0.1timestamp;validatestill reads a legacytimestampand nudges you tookf migrate).byis an actor —human:<id>,process:<id>, or<producer>/<version>.verified— one{ by, at }or a list of them.validateaccepts both; the viewer derives the trust tier (unverified / machine-confirmed / human-reviewed — ahuman:verifier is what lifts it).status(draft|stable|deprecated, default stable) andstale_after(an absolute instant):indexmarks deprecated concepts in listings,validatewarns once content is past due, and the viewer shows a stale badge.sources— the materials a concept derives from (resourcerequired;id,title, and the credibility signalsauthor,usage_count,last_modified, framed by a siblingusage_window). Per-claim attribution is a markdown footnote whose label is asources[].id(…as documented.[^ga4-schema]);validatechecks every footnote keys intosources, and the viewer renders footnotes linked to their source.type: Attested Computation— a sanctioned computation as its own concept:runtime(required), typedparameters, the computation inline under a# Computationfence or in a file named bycomputation, plusexecutor { resource, receipt }andattester { resource }.validatechecks the contract;vizembeds the referenced files and links them from the panel.
viz adds two built-in lenses when a bundle uses them — status and
trust — beside any [facet.*] you define (a workspace facet of the same
name wins). okf migrate (dry run; --write to apply) converts a v0.1
bundle in place: timestamp → generated, a body ## Citations list →
sources (link items only — revision hashes stay put), and bumps the root
index.md okf_version; it stamps generated.by from [scaffold] actor
(else okflight/<version>), as scaffold does for the docs it emits.
All commands read that one optional config file (strict-validated; malformed
config fails the command): [bundle] dir sets the bundle root (default
knowledge/), [profile] tunes validation policy (required-fields,
recommended-fields — default title, description, generated —
reserved-files, rooted-links = "error"|"allow" for body links,
repo-links = "check"|"ignore"|"forbid" — defaults reproduce the stock
OKF-plus-reference-tooling behavior), [vcs] adds url and
commit-url-template = "{url}/commit/{hash}" for forge-agnostic revision
links, and the remaining sections drive the viz viewer. Facet filter lenses
can classify concepts via [facet.<name>.classify] — the built-in
nix-optional-attrs parser or provider = "command" running any repo
script that prints a JSON name→value map.
okf scaffold runs the workspace's own metadata pass: [scaffold] script
(a TS/JS module dynamically imported; its default export receives the
injected ScaffoldContext API from scaffold-api.ts — emit with
idempotence/--force, VCS timestamps, comment extraction, text helpers) or
command (any argv, OKF_* env), plus declarative [[scaffold.collect]]
entries (glob + templates with {name}/{Title}/{path}/… placeholders,
validated at load) for repos with simple needs. It is a bun/TypeScript
project run from source — no compile step.
packages.<system>.okf(=default) — the CLI: sources + vendorednode_modulesin the store, wrapped asbin/okf(bun run --prefer-offline --no-install …with git on PATH). Systems:aarch64-darwin,aarch64-linux,x86_64-linux.checks.<system>.test— the viewer unit tests (bun test) run offline against the vendored deps.devShells.<system>.default— bun + git for hacking on okf standalone.
inputs.okf = {
url = "github:kriswill/okflight";
inputs.nixpkgs.follows = "nixpkgs";
inputs.flake-parts.follows = "flake-parts";
};then re-export inputs.okf.packages.${system}.okf from the parent's packages
module. follows makes the parent build against the parent's nixpkgs; the
lock here only governs standalone builds (nix build .#okf), so drv paths
may legitimately differ between the two. Advance the parent's pin with
nix flake update okf. While this repository is private, either consume it
as git+ssh://git@github.com/kriswill/okflight.git with an SSH key
authorized for the repo (auth rides the SSH agent — e.g. 1Password,
enclave-gated, no token at rest), or keep the github: form and set
access-tokens = github.com=<token> in nix.conf.
A vendored copy (or in-tree checkout) works too via a relative-path input
(url = "./path/to/okflight") — edits then flow through on the next
evaluation, no lock bump needed.
okf setup is the guided wizard that makes a repository receive okflight —
interactive on a TTY (Enter accepts every default), flag-driven for agents
and CI (--yes plus --dir=/--title=/--skills-dir=/--no-skill/
--no-scripts/--no-gitignore). It writes, and never overwrites:
okflight.toml— the commented starter config (asinitdoes), with[scaffold] scriptpre-wired when the scripts starter is chosen;- the bundle skeleton —
<dir>/index.md,<dir>/log.md; .agents/skills/knowledge-bundle/SKILL.md— an agent skill teaching the bundle-maintenance loop (when to scaffold/index/validate, entry quality bar, decision-record template), with the bundle dir substituted in; point--skills-dir=at.claude/skills(or symlink) for Claude Code;<dir>/_okflight/scripts/— the repo-owned metadata pass: a startermain.ts(run byokf scaffoldwith the injectedScaffoldContext) plus the vendoredscaffold-api.d.tstype surface, so the scripts typecheck with no okflight checkout at runtime. The_prefix keeps the directory out of the bundle walk;- a
.gitignoreentry for the generated<dir>/viz.html.
The installed templates live in this repo's templates/; a test keeps the
vendored scaffold-api.d.ts member-for-member in sync with
scaffold-api.ts. If setup finds a flake.nix it prints the
inputs.okf wiring as a next step (it never edits your flake).
okf is published to npm as
@kriswill/okflight —
scoped because the registry's typosquat guard reserves the bare name's
neighborhood for inflight — shipping these TypeScript sources as-is plus
one node-compatible launcher (bin/okf.mjs, the only non-.ts code in the
package):
bunx @kriswill/okflight setup # guided integration (or `init` for the bare skeleton)
npx @kriswill/okflight setup # identical — no bun preinstalled required, see belowokf runs on Bun ≥ 1.3.13 (Bun.TOML, Bun.YAML for frontmatter, Bun.Glob, and okf viz invokes Bun.build +
the Svelte plugin at generation time), so the launcher re-execs through a
bun: first the one on PATH, else the bun npm
package that installs alongside as an
optionalDependency — which is what makes plain npx @kriswill/okflight
work with no prerequisites (--no-optional skips the ~90 MB and the launcher
then explains itself). Under bunx --bun it imports the CLI in-process with
no re-exec at all. Installed commands are unscoped either way: okf and
okflight both land on PATH. Publishing is npm publish from a clean
checkout — there is no build step (publishConfig pins public access).
Working from a clone works the same way (also how nix consumers hack on it):
git clone https://github.com/kriswill/okflight ~/src/okflight
cd ~/src/okflight && bun install # once; vendors the viz viewer deps
cd ~/src/your-project
bun ~/src/okflight/okf.ts setup # guided integration
bun ~/src/okflight/okf.ts validate && bun ~/src/okflight/okf.ts vizAny language, any domain, git or no VCS at all ([vcs] provider = "none").
Wire your own metadata pass via [scaffold] (script with the injected
ScaffoldContext API, any-language command, or declarative
[[scaffold.collect]] globs).
node_modules is a fixed-output derivation running bun install --frozen-lockfile --omit=optional (no bun packaging helper exists in nixpkgs;
this mirrors its opencode/helix-gpt packages). With optionals omitted —
the only one is the bun npm package backing the npx fallback, which the nix
wrapper has no use for — the installed tree is pure JS with no
os/cpu-conditional packages, so one hash serves all platforms. When
bun.lock changes (or a
nixpkgs bump changes bun and the install layout shifts — the failure is a loud
hash mismatch), refresh it:
- In
package.nix, set the FOD'soutputHash = lib.fakeHash; nix build .#okf.node_modules— copy thegot:sha256 back in.
A consuming repo can wrap a checkout of this working tree
(bun path/to/okflight/okf.ts) for live edits with no rebuild; nix
consumers get the pinned store build. Standalone:
nix develop # or any ambient bun
bun install
bun test
bun okf.ts helpDev-tree only (not available from the nix-built package):
okf viz --perf— needs a locally installed Chrome (puppeteer-core).okf viz --check— typechecks with tsgo (@typescript/native-preview) through svelte-check's--tsgo-experimental-api; tsgo's per-platform native binary is an optionalDependency, which the nix package's vendorednode_modulesomits (--omit=optional), so the check needs a dev-treebun install.
Plain-TS iteration is fastest with tsgo directly:
bunx tsgo --noEmit -p tsconfig.json (checks everything but .svelte files).
Known upstream gap: svelte-check 4.7.1's non-API --tsgo flag points at
bin/tsgo.js, which current native-preview builds no longer ship — it exits 0
without checking anything; don't use it.