Docs index
CLI
The eight published files, how to pin them, and how to verify an export with nothing but a download.
What the distribution is
The developer distribution is published on the Developers page and pinned by sha256 in /developer/channel.json. 8 files, each one listed below with what it is for.
| File | What it is for |
|---|---|
| tavonel-cli.mjs | The upload and compile path from a terminal. |
| tavonel-mcp.mjs | The read-only MCP bridge, with a --doctor preflight. |
| tavonel-source-agent.py | Walks a folder or an S3-compatible bucket and pushes what it finds. |
| tavonel-verify-export.mjs | Checks an archive's signature, its file digests and that nothing was added. |
| tavonel-verify-package.mjs | Checks what is inside: relations resolve, regions sit inside their page, the three graph formats agree. |
| tavonel-verify-roundtrip.py | Loads the export into SQLite and queries the ids back, outside our tools. |
| tavonel-public-sample.py | Recipe 2, runnable: reads the public sample World, recomputes its digest and follows every claim to its evidence. |
| tavonel-recipe-smoke.mjs | Runs all three recipes against a deployment. Every request it makes is an unauthenticated GET. |
Note npm and PyPI publishing is pending; install from the digest-pinned files today. No package exists on either registry — npx @tavonel/mcp and pip install tavonel do not resolve, and publishing needs registry credentials that have not been issued. What is here is a distribution rather than a package-manager release: the manifest names the exact bytes and you check them before anything runs. Each file imports nothing — Node 20+ for the .mjs files, Python 3.12+ for the .py ones — so there is no install step, no lockfile and no transitive dependency to audit. Reading a file before you run it is the intended workflow, not a fallback, and it stays the audited path after a package exists.
Fetching and verifying it
# Downloads every published asset and refuses any file whose bytes do not match the
# digest the channel manifest names. Requires curl, jq and sha256sum.
curl -fsS https://tavonel.com/developer/channel.json -o channel.json
jq -r '.assets | to_entries[] | "\(.value.sha256 | sub("^sha256:";"")) *\(.value.url | split("/") | last)"' \
channel.json > channel.sha256
jq -r '.assets[].url' channel.json | xargs -n1 curl -fsS -O
sha256sum --check channel.sha256
# tavonel-cli.mjs: OK ... one OK line per asset. Any FAILED line means do not run that file.
jq -r '"pinned version: \(.version) apiVersion: \(.apiVersion) node>=\(.minimumNode)"' channel.json$channel = Invoke-RestMethod https://tavonel.com/developer/channel.json
foreach ($asset in $channel.assets.PSObject.Properties.Value) {
$name = Split-Path $asset.url -Leaf
Invoke-WebRequest $asset.url -OutFile $name
$actual = "sha256:" + (Get-FileHash $name -Algorithm SHA256).Hash.ToLower()
if ($actual -ne $asset.sha256) { Remove-Item $name; throw "$name does not match $($asset.sha256)" }
"$name OK"
}
"pinned version: $($channel.version)"Pin, update, uninstall
--version prints the immutable distribution version compiled into the file you hold, so pinning is keeping the file and its digest. node tavonel-cli.mjs update-check compares that version with the published channel and prints the difference; it never downloads and never overwrites anything, so updating is deliberately the same act as installing — fetch, check the digest, replace the file. Uninstalling is deleting the file: nothing is written to a registry, a PATH, a profile or a system directory, and the only state the CLI keeps is the connector cursor file you name yourself.
The two verifiers
Two verifiers answer different questions, and both are downloads rather than commands in the CLI. tavonel-verify-export.mjs checks the archive: that the Ed25519 signature was made by the key whose fingerprint you supply, that every file matches the digest we signed, and that nothing was added. tavonel-verify-package.mjs checks what is inside it: that relations resolve to objects that exist, that every region sits inside its page in the 0-1000 coordinate frame, that the Turtle, the JSON-LD and the CSV describe the same graph, and that the package's own report counts what the package holds.
# The trusted fingerprint comes from the trust endpoint, not from the archive.
# An archive that vouches for its own key has proven nothing.
fingerprint=$(curl -fsS https://tavonel.com/api/export/trust | jq -r .publicKeySpkiSha256)
node tavonel-verify-export.mjs --archive world.zip --trusted-fingerprint "$fingerprint"
# {"ok":true,"archive":"world.zip","collectionId":"collection-...","keyId":"...","filesVerified":23}
node tavonel-verify-package.mjs --package world.zip --require-signature
# world.zip: 23 files, 5 documents, ... / PACKAGE VALID
# --package also takes an extracted directory or a candidate artifact JSON.
# --json prints the whole report instead of a summary. Without --require-signature an
# unsigned package is a note rather than an error, which is what a candidate is.Note A tampered archive fails at the signature. A package whose relations point at objects that are not there verifies perfectly and is still wrong, which is why the second check exists. Both exit non-zero on any error, and the package validator exits 2 when its arguments are wrong rather than exiting 0 having checked nothing.
Checking an export outside our tools
Cross-format parity inside the package is what tavonel-verify-package.mjs proves. Whether the ids and the provenance survive being loaded by a tool that has never heard of TAVONEL is a different question, and tavonel-verify-roundtrip.py, the third published verifier, answers it against a package you already hold: it loads graph/nodes.csv and graph/relationships.csv into an in-memory SQLite database and queries the ids back through SQL, parses ontology/knowledge.jsonld as plain JSON, and counts triples and subjects in ontology/knowledge.ttl. Python 3.12 and the standard library, nothing else.
python tavonel-verify-roundtrip.py --package world.zip
# sqlite: 12310 nodes, 7794 relationships loaded and queried back
# jsonld: 12310 subjects
# turtle: 20104 triples, 12310 subjects (minimal parser -- rdflib not installed)
# ROUND TRIP OK
# --json prints the counts as a receipt you can keep beside the package digest.Note The Turtle check has a stated ceiling. Where rdflib is importable the script parses the Turtle with it and says so; where it is not, it falls back to a minimal parser that handles the shapes this compiler emits and prints which strict check it could not run. A skipped check is never reported as a pass, and the counts above are an illustrative shape rather than any particular package's numbers — run it on yours.
API version 2026-09-02.1 · reviewed 11 September 2026
Something here out of date or wrong? Report an issue with this page.