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).
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). Alwaysexit 0.okflint validate— normative compliance gate.exit 0if conformant,exit 1otherwise. Designed for pre-commit hooks and CI.okflint validate-manifest— validates an OKF manifest's structure alone, without scanning the base it declares.exit 0if valid,exit 2otherwise.okflint index— generates OKF §6-conformantindex.mdfiles. 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
- Copy the example manifest to the root of your documentary base:
cp example/manifest.example.yaml /path/to/my-base/okf-base.yaml
-
Adapt it to your taxonomy (types, required fields, status vocabulary).
-
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
Metadata
Release files for okflint 0.4.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| okflint-0.4.1.tar.gz | 181.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| okflint-0.4.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 223.0 kB
Release files / okflint-0.4.1.tar.gz
| Download URL | okflint-0.4.1.tar.gz |
|---|---|
| Size | 181.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
ae9984a392a8820bf8904c88b56b521ee20f7fa62450847fa306778001957139
|
|
BLAKE2b-256 checksum How to use checksums |
0d043b16ed4a3a6966e083336dc19d5e096d170a4ee48b609d83831f410c3740
|
| 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 Sep 14, 2026.
Transparency logRelease files / okflint-0.4.1-py3-none-any.whl
| Download URL | okflint-0.4.1-py3-none-any.whl |
|---|---|
| Size | 41.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
837b74a2feb6991cd00171c684b6d16b7621edc4f9e460d24641878d3fa38bbf
|
|
BLAKE2b-256 checksum How to use checksums |
d8e91813d8d6762cb6166a07271d37d762f1cf3dcbc77df8a80b1a717659be95
|
| 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 Sep 14, 2026.
Transparency log