Skip to main content

forktex-knowledge

Keep documentation as JSON: typed records, rendered to markdown, retrievable within a token budget.

Markdown is a fine thing to read and a poor thing to maintain once there is structure to keep consistent — a rule needs a severity and something that proves it, a document needs typed links to others, and prose cannot be checked. So the source of truth is JSON validated by Pydantic models, and the markdown is generated from it.

pip install forktex-knowledge

Three moves

1. JSON is the source. One record per file. Each names the model it loads into, so a tree nests however suits the material and nothing infers a type from a directory name:

{
  "$model": "Document",
  "id": "practice.python",
  "title": "Writing Python here",
  "updated": "2026-08-24",
  "tags": ["python"],
  "summary": "...",
  "rules": [
    {
      "id": "python:target-314",
      "title": "Target 3.14",
      "statement": "...",
      "severity": "blocker",
      "enforcement": "make lint fails on the wrong target"
    }
  ]
}

id is handcrafted and never derived. Renaming a file or moving it between folders breaks nothing, because everything cites the id and the filesystem only groups.

2. Load it through a repository, never by touching files:

from pathlib import Path
from forktex_knowledge import FileRepository

repo = FileRepository(Path("sources"))
doc = repo.read("engineering/python.json").document
docs = [loaded.document for loaded in repo.read_all() if loaded.ok]

3. Export with to_markdown(), inherited from Renderable, so a whole document and any piece of one render the same way:

doc.to_markdown()             # the page
doc.rules[0].to_markdown()    # just that rule

The CLI, over a Site

Four verbs are the same for any corpus, so they ship here. What varies is the Site. Two fields are required — sources and output — and everything else has a default you can leave alone:

Field Default What it is
banner "" Comment block stamped on every page. Usually a licence header, which is why the library supplies none.
generated_note a DO-NOT-EDIT line Marks a page as generated. Must contain {source}.
build_hint "rebuild" How to rerun the build, quoted in staleness findings — make build, just build, a script.
link_pattern [[id]] The citation syntax. Defaulted because Document renders it.
index_title / index_name / index_intro Knowledge / README.md / a sentence The generated index page.
ungrouped "general" Index section for a record with no folder above it.
# main.py
from pathlib import Path
from forktex_knowledge import Site, run

ROOT = Path(__file__).resolve().parent

raise SystemExit(run(Site(
    sources=ROOT / "sources",
    output=ROOT / "markdown",
    banner="<!-- generated; do not edit -->",
)))
python main.py check --strict --drift   # validate, and fail on a stale page
python main.py build                    # render everything
python main.py ask "how do I add a route?"
python main.py ask --rules --tag python
python main.py new my-doc --updated 2026-08-24

check --drift is the load-bearing one: it regenerates every page and byte-diffs it, so a hand-edited page fails rather than surviving as a second author of the same fact.

Retrieval

Two questions, and only one needs ranking:

from forktex_knowledge import ground, rules

rules(docs)                                  # every rule, worst severity first
ground(docs, "add a route", budget_tokens=4000)

rules has no ranking on purpose — the whole normative set is usually a few thousand tokens, and dropping a blocker to save a few hundred is a bad trade. ground ranks (BM25, length-normalised so the longest document does not win on volume), injects briefs rather than whole pages, and names what it dropped — a silently cut context reads exactly like a complete one.

Storage is a port

The core knows nothing about files. Repository is four methods over an opaque key, so a database or an API adapter needs no change to the models:

class Repository(Protocol):
    def keys(self) -> list[str]: ...
    def read(self, key: str) -> Loaded: ...
    def write(self, key: str, document: Document) -> None: ...
    def delete(self, key: str) -> None: ...

FileRepository is the one implementation shipped. An in-memory one is about ten lines.

Document types

Document is doctrine: rules, worked examples, a principle. Two more ship because they are shaped differently, and forcing them into Document loses what makes them worth keeping:

  • Research — findings true on a date. as_of is required and renders as a warning above the first figure, because prices and measurements decay.
  • Decision — an ADR. alternatives is the field that earns it its own type: a decision without its rejected options gets re-litigated.

Register your own with @known:

from forktex_knowledge import Document, known

@known
class Runbook(Document):
    oncall: str

Licence

Dual-licensed: AGPL-3.0-or-later, or a commercial licence from FORKTEX S.R.L. See LICENSE and NOTICE. For proprietary or SaaS use where the AGPL's obligations cannot be met, contact info@forktex.com.

Metadata

Release files for forktex-knowledge 0.1.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 forktex-knowledge 0.1.0
File Size Uploaded Provenance Actions
forktex_knowledge-0.1.0.tar.gz 26.3 kB Without provenance Details for forktex_knowledge-0.1.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for forktex-knowledge 0.1.0
File Interpreter ABI Platform Actions
forktex_knowledge-0.1.0-py3-none-any.whl Python 3 none any Details for forktex_knowledge-0.1.0-py3-none-any.whl

Total release size: 64.2 kB

Release files / forktex_knowledge-0.1.0.tar.gz

Download URL forktex_knowledge-0.1.0.tar.gz
Size 26.3 kB
Tags Source
SHA-256 checksum
How to use checksums
f159440cfdc0994d220e1102e49a78c148018a87cc3988e2b24fc0e14b467728
BLAKE2b-256 checksum
How to use checksums
ce86b29ed46f86a776ad4bc1518ccabb9892a797e39416ff00ec63eaa9e5fe9b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.6

Release files / forktex_knowledge-0.1.0-py3-none-any.whl

Download URL forktex_knowledge-0.1.0-py3-none-any.whl
Size 37.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
340dae672b87761b1097c8ed24b7fe19fb7fbc4bf9084f6b5ddc6d2333654351
BLAKE2b-256 checksum
How to use checksums
8b774f37c90b8f16725a7e507bea30e7a5010fa8cb9c53b0f6fa4bd87b5fd027
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.6

Security for forktex-knowledge 0.1.0

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.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files No provenance

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