Skip to main content

JidoSeal CLI

Run JidoSeal's Self-Check over a folder of markdown, from your terminal, on your own machine.

Exactly what leaves your machine: nothing — 100% local, zero content egress.
Your files, their names, and their contents never leave your device.

That is not a slogan bolted onto the docs — it is the first thing the command prints, on every run, before it reads a single file. The rest of this page explains exactly what the tool does, and just as importantly what it does not do.


Install

One-liner:

pipx install jidoseal && jidoseal --root .

pipx is the recommended install because it puts JidoSeal in its own isolated environment, so it can neither shadow nor be shadowed by anything else on your system. If you would rather use pip, a virtual environment does the same job:

python3 -m venv ~/.venvs/jidoseal
~/.venvs/jidoseal/bin/pip install jidoseal
~/.venvs/jidoseal/bin/jidoseal --root /path/to/your/notes

From a local wheel:

python3 -m pip wheel . --no-deps -w dist-cli      # from a checkout of this repo
pipx install ./dist-cli/jidoseal-0.1.3-py3-none-any.whl

From a checkout, with no install at all:

python3 engine/local_runner.py --root /path/to/your/notes

Requires Python 3.9 or newer. Developed and exercised on 3.14.


Usage

jidoseal --root /path/to/your/notes
Exactly what leaves your machine: nothing — 100% local, zero content egress.
Your files, their names, and their contents never leave your device.

scanned 747 files in 1.42s — $0 · 100% local · nothing left this machine
  Bronze  coverage: 98.1%
  Silver  coverage: 84.3%
  Gold    coverage: 61.0%
manifest: /path/to/your/notes/.jidoseal/manifest.json
progress: /path/to/your/notes/.jidoseal/progress.ndjson (run scan-20260918-143012-a1b2c3)
Flag What it does
--root <dir> Required. The folder to scan. Every *.md beneath it, recursively.
--include-machine Ignore the machine/transient excludes your .jidoseal/config.yaml declares, and scan every *.md under --root. With no config file there is nothing to ignore, so the flag changes nothing.
--version Print the version and exit.
--help Print usage and exit.

python3 -m jidoseal --root <dir> is identical to jidoseal --root <dir> — same entry point, same output, same banner.

A caution about --include-machine

The certified path does not use it. When you buy a certificate, JidoSeal scans with your configured machine excludes applied — that is the corpus definition a certificate is issued against. --include-machine is a diagnostic: useful for seeing your whole tree, but the coverage percentages it prints are not the percentages your certificate would be based on. For a number that matches, run without the flag.

What it writes

Two files, both inside <root>/.jidoseal/, both on your machine:

  • manifest.json — per file: a content hash, its current tier, which governance fields are present, and exactly what is missing for Silver and Gold. This is the same artifact, in the same format, that the certified engine path produces.
  • progress.ndjson — an append-only progress log, one JSON object per line, flushed to disk as each file is scanned. Append-only on purpose: a new run adds to it rather than erasing the history of previous ones.

Nothing else is written, and nothing in your corpus is modified. This command reads only.


Telling JidoSeal about your corpus — .jidoseal/config.yaml

Out of the box, nothing is excluded and nothing is assumed. Every *.md file under --root is scanned, apart from OKF v0.2's two reserved filenames (index.md and log.md), which the standard itself puts outside a concept corpus. No folder name is special, no owner is invented, and no document type is inferred from a directory JidoSeal has never seen.

That is deliberate. A scanner that silently drops files because their path matched somebody else's folder convention is reporting coverage over a corpus you did not choose — and the number it shows you would be wrong in a way you cannot see.

If your corpus does have conventions, tell JidoSeal about them in an optional <root>/.jidoseal/config.yaml. Every key is optional; leaving the file out is exactly the default above. The config file itself is never part of the corpus (JidoSeal only ever reads *.md), and it is read by the scan engine itself — so the CLI, the local UI and the certificate-issuing path all see the same corpus definition.

# Paths excluded as machine-generated or synced mirrors. Python regexes, matched against the
# path relative to --root. `--include-machine` ignores this list for one run.
machine_extra_excludes:
  - "^Scratch/"          # transient working notes
  - "/_drive/"           # a sync mirror — remediating it just fights the sync
  - "(?i)-autogen-"      # generated files, by filename

# Who owns a file when its frontmatter does not say. First match wins.
owner_map:
  - pattern: "^Accounts/"
    owner: "dept:finance"

# The owner for everything no rule above claims. With no `default_owner`, JidoSeal will not
# invent one — and an apply refuses rather than writing an audit line it cannot attribute.
default_owner: "human:jane-doe"

# Optional: the identity recorded on each audit-log line. Defaults to `default_owner`.
authority: "self:jane-doe"

# Extra `type` inference for your own folders, applied AFTER JidoSeal's built-in conventions
# (so a more specific built-in rule always still wins). Suggested at MEDIUM confidence, and
# never written without your explicit Apply.
propose_type_rules:
  - pattern: "^Accounts/"
    type: "finance-reference"

A malformed config is an error, not a shrug: an unknown key or a bad regex stops the run with a message naming the file, rather than quietly scanning a different corpus than you described.

Your config is recorded with the scan — and on the certificate

Every scan prints one more line:

config:   sha256:9f2c…c41d

That is a SHA-256 of your .jidoseal/config.yaml, exactly as sha256sum computes it — check it yourself:

sha256sum .jidoseal/config.yaml

With no config file, the line reads config: absent:no-config-file: running on the shipped neutral defaults is recorded as such, rather than left blank.

Why it exists: this file decides which documents are in your corpus at all, so it is part of what a tier means. A certificate is bound to a Merkle root of your files, which says WHICH files were certified but not which definition selected them — so the same digest travels onto the certificate, inside its signature. It records your corpus definition; it does not restrict it. Nothing here leaves your machine on the free path, and the digest is one-way: it carries no folder name, no path and no rule text.


If your vault is not written in English

JidoSeal reads a vault in any of twelve languages — English, Chinese (Simplified and Traditional), Spanish, Japanese, German, French, Portuguese (Brazil and Portugal), Korean, Russian and Hindi — and every scan prints which one it decided on:

language: ja  (i18n table 1.0.0 sha256:711f2ff…6f3d1)

That digest is a SHA-256 of i18n/frontmatter-i18n.json, the table this build read, checkable the same way the config digest is. It travels with the scan so a certificate can record which table scored the corpus. It is not part of config_hash: that value stays the plain digest of your own .jidoseal/config.yaml and nothing else, so sha256sum still verifies it.

Keys stay English. Values are yours. JidoSeal writes title, description, status and the rest in English, because Obsidian's own search and every static-site generator expect them there — renaming tags to 标签 is documented to break tag search. But it READS a key you have already renamed: 標題, descripción, Beschreibung, заголовок and the rest all count as the fields they mean, so a vault that is complete is scored as complete instead of as empty. If a field already exists under a name you chose, a value JidoSeal fills in goes under your key, never a second English one beside it. tags, aliases and cssclasses are never touched at all, renamed or not.

Anything JidoSeal invents is in your language; anything it read from you is left alone. A title taken from your heading or your filename stays exactly as you wrote it. The fallback used when there is nothing to read does not: it is Untitled in English and タイトルなし in Japanese. Dates are the exception in every locale — always ISO 8601 with ordinary digits, never localised, because that is the one format every tool downstream can read.

Two things it cannot do, said plainly. Script tells Japanese, Korean, Chinese, Russian and Hindi apart; it cannot tell English, Spanish, German, French and Portuguese apart, because they share an alphabet. For those five, JidoSeal only knows your language if a key is in it. And a Chinese file with no character unique to Simplified or Traditional is read as Simplified unless the rest of the vault says otherwise. Either can be settled outright by putting lang: pt-PT (or any locale above) in a file's frontmatter — a declaration beats every inference.

An IME's full-width colon (状態:安定) is repaired before parsing rather than failing the file, as is a colon left inside a quoted key ("status:").


What the tiers mean

Tiers are objective, deterministic and pass/fail. There is no judgement call and no model involved anywhere in this path — a file either has a populated field or it does not, and the same corpus scanned twice gives the same answer.

Tier Requires
Bronze type
Silver Bronze, plus title, description, timestamp, owner
Gold Silver, plus status, review_policy, reviewed_at, next_review_at

"Populated" means carrying real content. A bare title: with nothing after it earns nothing.

A file whose frontmatter fence exists but whose YAML will not parse is reported with frontmatter_ok: false. Those gaps cannot be closed by adding fields — the block has to be fixed by hand first.


Honest scope — what JidoSeal does and does not certify

It does:

  • Certify presence and integrity of governance fields — that the metadata your documents are supposed to carry is actually there and actually populated, measured the same way every time.
  • Provide hash provenance — every file's content is hashed, so the manifest is bound to the exact bytes on disk at scan time, and a later change is detectable.

It does not:

  • Attribute which change broke a spec. JidoSeal will tell you that a document's governance state is what it is now, and that its content hash differs from before. It does not diff your documents or identify which edit — by you, by an agent, by anything else — was responsible.
  • Judge whether your content is any good. Tiers measure governance-field presence, not quality, accuracy or usefulness of what you wrote.
  • Read your prose. The scan reads frontmatter to determine fields, and hashes file bytes. No content is sent anywhere, because nothing is sent anywhere at all.

Exactly what leaves your machine

Nothing.

Exactly what leaves your machine: nothing — 100% local, zero content egress.
Your files, their names, and their contents never leave your device.

This is enforced structurally, not by policy:

  • The installed package does not contain networking code. The wheel ships seven Python modules — the complete set the scan needs and nothing more. The engine's network-capable modules are not merely unused by this command; they are not in the distribution. You can confirm that yourself with unzip -l on the wheel, or by listing the installed files.
  • Its one dependency is PyYAML, a YAML parser, used to read frontmatter. It has no network capability. See "Dependencies" below.
  • Static analysis enforces it in the test suite — the modules on this path are AST-inspected for any import of socket, ssl, http, urllib, requests, httpx, aiohttp and friends, and the check fails the build if one appears.
  • A runtime guard proves it on a real scan — a full scan is executed inside a harness that raises on any outbound connection or DNS lookup to a non-loopback address. It does not raise.

If you would rather trust your own eyes than our test suite: run it with a network monitor on. That is the point of a local tool.

Buying a certificate is a separate step that happens on jidoseal.com, not through this command. This CLI has no purchase path, no account, no telemetry, and no way to send anything anywhere.


Dependencies

One: PyYAML.

We would rather it were zero, and it is worth being precise about why it is not. JidoSeal's frontmatter parser has always used PyYAML — it is the engine's single hard requirement, and the certified engine path uses the very same parser. Replacing it would mean writing a second YAML implementation, and a second implementation is a second set of edge cases: the day it disagrees with the first about a quoted date or a multi-line string, the CLI and your certificate disagree about your corpus. A pure parser with no network capability is a much better trade than a parity risk in the thing being certified.

Everything else on the path is the Python standard library.


Same engine as the certificate

This is the point of the CLI, so it is worth stating plainly: jidoseal --root <dir> runs the same code the certified issuance path runs. Both call okf_manifest.build_manifest(); both tier files through the same tier_of(); both hash content the same way. The CLI is not a preview, a re-implementation or an approximation of the certified scoring — it is that scoring, invoked locally.

The practical consequence: the tiers you see in your terminal are the tiers a certificate would attest to, for the same corpus, scanned the same way (that is, without --include-machine).


Using JidoSeal from Claude Code, Cursor, or another AI tool

If you work inside an AI coding tool, there is a second package that lets it run this same scan for you — without you leaving the tool, and without your files leaving your machine:

pip install jidoseal-mcp

That installs a server speaking the Model Context Protocol, the standard those tools use to call local programs. Point your host at the jidoseal-mcp command:

claude mcp add jidoseal -- jidoseal-mcp

…or, for Cursor and most other hosts, in their MCP config file:

{
  "mcpServers": {
    "jidoseal": {
      "command": "jidoseal-mcp"
    }
  }
}

Your assistant can then run the free Self-Check over a folder, explain which fields each file is missing for the next tier, and — only if you ask it to — start a certification checkout. The scan is the same local scan this CLI runs, on the same engine, producing the same tier and the same Merkle root.

The egress promise is unchanged and is worth repeating, because an AI tool making the call does not change who holds the data:

Exactly what leaves your machine: nothing — 100% local, zero content egress.
Your files, their names, and their contents never leave your device.

The one exception is the same one as here: if you choose to buy a certificate, the purchase step sends your company name, your name, your email, the tier, a 0–100 score and the corpus's Merkle root — never file contents, file names or paths.

Release files for jidoseal 0.1.3

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

Source distribution (sdist)

Source distribution for jidoseal 0.1.3
File Size Uploaded
jidoseal-0.1.3.tar.gz 70.0 kB Details

Built distribution (wheel)

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

Total release size: 137.8 kB

Release files / jidoseal-0.1.3.tar.gz

Download URL jidoseal-0.1.3.tar.gz
Size 70.0 kB
Tags Source
SHA-256 checksum
How to use checksums
bb172632786b690f7b7330acbd788dede4ab09768fa206765d14fe7bf8ec3f13
BLAKE2b-256 checksum
How to use checksums
2cb457d527804c458e3b3773c4f49340ce9534e13140b097a02625fb425c681e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.4

Release files / jidoseal-0.1.3-py3-none-any.whl

Download URL jidoseal-0.1.3-py3-none-any.whl
Size 67.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
5d2ed7d6b3b8136a4624aa30621f30d9714b8d9a61814e5ca5ee02c76d28164f
BLAKE2b-256 checksum
How to use checksums
eb5e67dabd46b8ad9d326a977f8ab798fc1791b64988cad1185bb87e0b79bb2f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.4

Release history Release notifications | RSS feed

This release

0.1.3 This release

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

1 release file

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