A linter for the docs/ knowledge base. It enforces a minimal OKF-style profile (markdown + YAML frontmatter + cross-links), generates per-folder index.md manifests, checks links, and reports staleness - so docs stay findable by both humans and agents.
Dependency-free at runtime (hand-rolled frontmatter/markdown parsing); run from source via tsx, no build step.
From the repo root:
pnpm okf check [--staged] # validate frontmatter (+ links). --staged: only git-staged docs (the ratchet)
pnpm okf links # dangling cross-links across the whole bundle
pnpm okf index [--check] # regenerate index.md. --check fails on drift, --dry previews
pnpm okf stale [--days=N] # docs older than N days by git last-commit date (default 365)
pnpm okf fix # stamp missing type, add status to archive/ docs, regenerate indexes
pnpm okf precommit # hook entry: regenerate+stage indexes, check staged docs, reverse rename checkAdd --json for machine output (use pnpm -s okf ... --json so pnpm's banner stays off stdout). Exit codes: 0 ok, 1 errors found, 2 usage.
Every concept doc carries frontmatter:
---
type: guide # REQUIRED - routable kind (adr|daily|meeting|person|feature-plan|exec-plan|draft|bug|hypothesis|report|guide)
description: One line. # REQUIRED - what the doc is (exempt under archive/)
status: active # OPTIONAL - active|draft|superseded|archived
tags: [sky, storage] # OPTIONAL
---index.md (one per folder, generated) and README.md are reserved. Chronological logs (daily/, meetings/) and date-shard dirs are not indexed.
| Severity | Rules |
|---|---|
| error (blocks) | frontmatter-missing, type-missing, description-missing, value-yaml-unsafe, duplicate-frontmatter-key, description-multiline, index-stale (in index --check) |
| warning (informs) | link-dangling, type-unknown, status-invalid, filename-type-mismatch, archive-status-missing, adr-superseded-unmarked, multiple-h1, description-too-long, index-not-generated |
link-dangling is a warning in v1 (promote to error after a clean okf links pass). Severities live in src/config.ts (SEVERITY).
grep -rl '^type: adr' docs # every ADR
grep -rl '^tags:.*\bsky\b' docs # by tag
grep '^\* ' docs/sky/index.md # one-line summary of a folder's docs.husky/pre-commit runs okf precommit on docs-touching commits (the hook path is installed by the repo-root prepare script, so a fresh pnpm install wires it up - no husky package needed). It regenerates and stages indexes, enforces type+description on touched docs (errors block), and warns on inbound links a rename/delete would break.
Known limit: the hook only sees staged files, so broken inbound links from untouched files on a rename are caught only by running pnpm okf links (there is no CI). Run it periodically.
src/cli.ts commands + flags + exit codes
src/config.ts paths, taxonomy, severities, the fs walker
src/frontmatter.ts CRLF/BOM-safe parse/serialize, duplicate-key detection
src/markdown.ts code stripping + link extraction
src/links.ts link resolution + dangling rule
src/index-gen.ts manifest generation + write-guard
src/rules/ frontmatter + convention rules
src/{git,doc,stale,fix,precommit,report}.ts
test/ vitest fixtures per area
pnpm test # vitest
pnpm typecheck # tsgo
pnpm lint # oxlint + prettier