Skip to main content

type: ProjectDescription project: okflint updated: 2026-07-08 tags: [python, cli, linter, okf, open-source]

okflint

The Ruff of documentation. A deterministic compliance linter for documentary bases in Open Knowledge Format (OKF).

MIT License Python Documentation


Why

When a project's value migrates into its documentary base, that base must be held to a standard — just as code is by a linter. okflint verifies, in a deterministic, reproducible, LLM-free way, that Markdown documents conform to an OKF standard declared in a YAML manifest.

Four commands:

  • okflint audit — inventory and descriptive diagnostic of a base (statistics, broken links, split candidates). Always exit 0.
  • okflint validate — normative compliance gate. exit 0 if conformant, exit 1 otherwise. Designed for pre-commit hooks and CI.
  • okflint validate-manifest — validates an OKF manifest's structure alone, without scanning the base it declares. exit 0 if valid, exit 2 otherwise.
  • okflint index — generates OKF §6-conformant index.md files. Dry-run (diff only) by default, writes only with --apply.

Installation

# Via uv (recommended)
uv tool install okflint

# Or via pip
pip install okflint

For development:

git clone https://github.com/mattdav/okflint
cd okflint
uv sync --all-extras
uv pip install -e .

Quick start

  1. Copy the example manifest to the root of your documentary base:
cp example/manifest.example.yaml /path/to/my-base/okf-base.yaml
  1. Adapt it to your taxonomy (types, required fields, status vocabulary).

  2. Validate:

okflint validate --manifest /path/to/my-base/okf-base.yaml /path/to/my-base

The manifest

okflint is a generic engine: it knows no type vocabulary in hard code. The okf-base.yaml manifest defines your standard. See manifest.example.yaml for an annotated template.

Each root entry under base.roots accepts an optional exclude_patterns list of fnmatch glob patterns. Files whose path (relative to the root) matches any pattern are skipped during scanning, auditing, and validation:

base:
  roots:
    - path: "."
      exclude_patterns:
        - ".venv/**"        # Python virtual environments
        - "node_modules/**" # JS/TS dependencies
        - "src/**/data/**"  # generated data directories

Each type declares its required/optional fields. Any property may additionally declare a controlled vocabulary via a <prop>_values key (e.g. status_values for a status property) — this only constrains the value when the property is present, orthogonally to whether it is required, optional, or absent from the type:

types:
  Decision:
    required: [type, status, created]
    optional: [updated, tags]
    status_values: [Proposed, Accepted, Deprecated, Superseded]
  Note:
    required: [type, created]
    optional: [updated, tags]

OKF resources — Official Google Cloud spec · openknowledgeformat.com (examples, templates, online validator) · okf.md (annotated guide)


Key concepts

Term Definition
bundle A root folder of the documentary base to audit or validate. All .md files it contains (recursively) are analysed. Multiple bundles can be declared via base.roots in the manifest.
vault The root folder(s) of all your Markdown (may be larger than the bundle). Used only to resolve [[...]] wikilinks. When using --manifest, all roots serve as the vault automatically.
vault manifest An okf-vault.json file listing multiple bundles in a workspace. Passing it to --vault enables audit/validate across all bundles at once, with a shared union wikilink-resolution index.
manifest The okf-base.yaml file you write to describe your standard: which concept types you use, which fields are required, which status vocabulary applies. Declares one or more roots via base.roots. See example/manifest.example.yaml for an annotated template.
target For validate only: one or more paths to folders or .md files to validate. If omitted, all roots declared in the manifest are validated.

Usage

okflint audit — Inventory and diagnostic

audit scans one or more bundle roots and produces a descriptive report: OKF conformance statistics, broken wikilinks, broken Markdown links, split candidates. This command is always exit 0 — it is an observation tool, not a gate.

When a manifest is available (--manifest, or a bundle resolved through a vault entry with its own manifest), audit runs the same checks as validate — core, profile, and hygiene — according to the manifest's declared severities. The JSON report then includes diagnostics per file and a top-level diagnostics_summary (counts by severity, tier, and code). The difference with validate is the exit code, not the checks: audit never fails, it only reports. Without a manifest (--bundle/--vault folder mode), diagnostics stay core-only (F001/F002), with reserved files (index.md, log.md) still routed to R001/R002 instead of F001/F002, exactly as with a manifest.

# Audit every bundle in a vault manifest (recommended)
okflint audit --vault /path/to/okf-vault.json
okflint audit --vault /path/to/okf-vault.json --apply

# Single-root scan (legacy form, backward compatible)
okflint audit --bundle /path/to/my-base --vault /path/to/my-vault

# Vault JSON + --bundle as a sub-filter (scans only files under --bundle)
okflint audit --vault /path/to/okf-vault.json --bundle /path/to/sub-folder

Either --vault pointing to an okf-vault.json file, or both --bundle and --vault (folder) for single-root mode must be provided.

Options:

Option Required Description
--manifest <path> conditional OKF manifest; base.roots defines the bundle and vault roots
--bundle <path> conditional Root folder to audit; acts as a sub-filter when --manifest is also set
--vault <path> conditional Vault folder for wikilink resolution, or an okf-vault.json file for multi-bundle mode
--apply no Writes the full JSON report to .okflint/YYYY-MM-DD_audit_vN.json

When scanning multiple roots, the console output includes per-root file counts. In vault JSON mode, each bundle is printed under its own === name === header, followed by a === Total vault === aggregate.

Concrete example — Obsidian vault:

okflint audit \
  --bundle ~/Obsidian/My-project/docs \
  --vault ~/Obsidian \
  --apply
# Produces: .okflint/2026-06-28_audit_v1.json

Concrete example — multi-bundle workspace:

# okf-vault.json lists several bundles, each with its own okf-base.yaml
okflint audit --vault ./okf-vault.json --apply
# Produces: .okflint/2026-06-28_vault_audit_v1.json

okf-vault.json format:

{
  "okf_vault_version": "0.1",
  "name": "my-workspace",
  "bundles": [
    { "path": "projects/alpha" },
    { "path": "projects/beta", "manifest": "okf-base.yaml" }
  ]
}

Each bundle entry requires a path field (absolute or relative to the vault file). The optional manifest field names the manifest file inside the bundle directory (defaults to okf-base.yaml).


okflint validate — Compliance gate

validate checks the conformance of Markdown files to OKF and to the profile declared in your manifest. Returns exit 0 if no errors, exit 1 otherwise. Designed for pre-commit hooks and CI.

# Validate all roots declared in the manifest (no explicit targets)
okflint validate --manifest okf-base.yaml

# Validate an entire base
okflint validate --manifest okf-base.yaml /path/to/my-base

# Validate a single sub-folder
okflint validate --manifest okf-base.yaml /path/to/my-base/ADR

# Validate specific files
okflint validate --manifest okf-base.yaml concept1.md concept2.md

# Machine-readable JSON output (for CI, scripts)
okflint validate --manifest okf-base.yaml --json /path/to/my-base

# Validate every bundle in a vault (each bundle uses its own manifest)
okflint validate --vault /path/to/okf-vault.json

# Validate with a specific manifest but use the vault's union index
okflint validate --vault /path/to/okf-vault.json --manifest /path/to/okf-base.yaml

Options:

Option Required Default Description
--manifest <path> no okf-base.yaml Path to the OKF manifest
--vault <path> no — okf-vault.json file: without --manifest validates each bundle with its own manifest; with --manifest uses the vault union index
--json no — JSON output instead of human-readable text
<targets...> no all manifest roots One or more paths (folders or .md files) to validate

Exit codes:

Code Meaning
0 No errors (warnings may still be present)
1 At least one conformance error
2 Invalid or unreadable manifest / vault config error

In vault JSON mode without --manifest, errors are prefixed with [bundle_name] and the exit code is the maximum across all bundles.

Concrete example — CI GitHub Actions integration:

- name: Validate docs
  run: |
    pip install okflint
    okflint validate --manifest docs/okf-base.yaml docs/

Concrete example — git pre-commit hook:

# .git/hooks/pre-commit
okflint validate --manifest okf-base.yaml docs/ || exit 1

okflint validate-manifest — Validate a manifest alone

validate-manifest exposes the structural validation load_manifest already performs as a side effect of the other commands, as a standalone command with readable output and a dedicated exit code. It does not scan any file of the base: base.roots need not exist on disk.

# Human-readable
okflint validate-manifest okf-base.yaml

# Machine-readable JSON output
okflint validate-manifest --json okf-base.yaml

Options:

Option Required Default Description
<manifest> yes — Path to the OKF manifest YAML file
--json no — JSON output instead of human-readable text

Exit codes:

Code Meaning
0 The manifest is valid
2 The manifest is invalid or unreadable

There is no exit 1: no base is scanned, so no content non-conformance is possible.


okflint index — Generate index.md files

index generates index.md files conforming to the OKF §6 format: one index.md per directory (progressive disclosure), listing the directory's .md files (title + optional description from frontmatter) and links to sub-directories that have their own index. No frontmatter is emitted, except that a root-level index.md may carry okf_version if you add it by hand (R001).

By default index runs in dry-run mode: it prints a unified diff for each index.md that would change (or "index.md up to date" if none) and writes nothing. Pass --apply to actually write the files.

# Dry-run: show what would change
okflint index --manifest okf-base.yaml

# Write the index.md files
okflint index --manifest okf-base.yaml --apply

# Vault JSON: each bundle uses its own manifest
okflint index --vault ./okf-vault.json --apply

Options:

Option Required Description
--manifest <path> conditional OKF manifest; required unless --vault resolves to an okf-vault.json
--vault <path> conditional okf-vault.json file for multi-bundle mode (each bundle uses its own manifest)
--apply no Write the index.md files whose content differs from the expected one

index is idempotent: running --apply twice in a row writes nothing the second time.


Development

inv lint     # ruff + mypy
inv clean    # clean build artefacts
inv repomix  # pack the codebase for an LLM

See CONTRIBUTING.md for the full contribution guide, the release process, and commit conventions.

The full API documentation (generated from docstrings) is available at mattdav.github.io/okflint.


Architecture

src/okflint/
├── cli.py        ← dispatcher: okflint audit | validate | index
├── scanner.py    ← shared primitives (scan, frontmatter, links)
├── audit.py      ← audit command (descriptive)
├── validate.py   ← validate command (normative gate)
├── cohesion.py   ← S202 semantic-cohesion scorer (TF-IDF, cosine, clustering)
├── index.py      ← index command (OKF §6 index.md generation)
├── vault.py      ← okf-vault.json loading (VaultConfig, load_vault)
├── manifest.py   ← manifest loading + validation (Manifest, load_manifest)
└── __main__.py   ← python -m okflint

Roadmap

Envisioned evolutions beyond v0.1 (verifiable reading-grid expectations, broader invocation surfaces) are described in ROADMAP.md.


What okflint does not do

okflint is a static, deterministic gate. By design, it will never:

  • Execute a reading traversal for an agent — that is the harness's role.
  • Judge the content of a concept via LLM (summarise, classify, rewrite).
  • Decide on a split or reorganisation — it signals, it does not rule.
  • Impose a convention not declared by your manifest — no hardcoded vocabulary, no imposed language.

License

MIT — @mattdav

Metadata

Release files for okflint 0.4.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for okflint 0.4.0
File Size Uploaded
okflint-0.4.0.tar.gz 181.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for okflint 0.4.0
File Interpreter ABI Platform
okflint-0.4.0-py3-none-any.whl Python 3 none any Details

Total release size: 222.6 kB

Release files / okflint-0.4.0.tar.gz

Download URL okflint-0.4.0.tar.gz
Size 181.1 kB
Tags Source
SHA-256 checksum
How to use checksums
8aa75f39326de05ee5c9b9e086285d1a6e91735b91917097c6c4c31370a1b2b8
BLAKE2b-256 checksum
How to use checksums
536f37d6c80282fb98e283251d66ee662962dd0a8114cd6f20709195eef535a6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 29, 2026.

Transparency log

Release files / okflint-0.4.0-py3-none-any.whl

Download URL okflint-0.4.0-py3-none-any.whl
Size 41.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
a0915efe871f996fe78867c35f0c1ec99eba3ac4bf48c2fc7e899830efc0f077
BLAKE2b-256 checksum
How to use checksums
ea0991bd6f782d11818cc842aed3b0129d827942f05b1297de33462bd3bc6f39
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 29, 2026.

Transparency log

Release history Release notifications | RSS feed

0.5.0

2 release files

0.4.1

2 release files

This release

0.4.0 This release

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.0

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page