Selecting a filing system
Taxonomy import/export/merge, bundle import/verify, native export, refile and rescan accept--system CODE. Omission targets original system 1, except a taxonomy file’s
explicit system selects its own destination. A conflicting --system is an error.
These local commands are trusted administrator operations, not token-scoped APIs.
See JD for first-import introduction and immutable system/address identity.
suchi serve
Runs the HTTP server. Blocks until SIGINT/SIGTERM.
- Applies embedded migrations up to the current schema version.
- Creates a neutral System / Inbox baseline until a filing tree is selected.
- Starts the durable-outbox dispatcher.
- Logs the effective egress surface at INFO.
- Listens on
LISTEN_ADDR(default:8000).
suchi healthcheck
Probes LISTEN_ADDR’s /readyz over loopback. Exit 0 if the server
answers 200, non-zero otherwise. Wired as the Docker HEALTHCHECK, so the
image does not depend on wget or curl for readiness checks.
suchi import [flags]
Point --from at your existing DMS’s export bundle. See
importer for the full walkthrough.
Flags
Category-resolution flags (
--flat, --map-jd, --auto-jd) are mutually
exclusive.suchi gc [flags]
Mark-and-sweep the CAS: walks every blob under $DATA_DIR/blobs/
and deletes anything not referenced by a document original, archive,
decrypted copy, thumbnail, or user avatar. Trashed document rows still count.
The blob’s on-disk mtime gates a grace window. It is a retention buffer, not
protection against concurrent writes: an upload can reuse an old blob before
committing its new database reference.
Dry-run by default. Nothing is deleted until you pass --apply.
Before applying, stop Suchi and every other archive writer, including CLI
imports. Keep them stopped until GC finishes. Do not apply GC while a backup
is copying the blob tree.
Flags
Trash and its automatic retention remove document rows and rendered files,
but retain CAS blobs for this offline collection. Run GC during a planned
maintenance window after taking a complete backup.
suchi taxonomy validate <file>
Validate exactly one .huml or .toml suchi-taxonomy/v1 file, offline, using
the same strict parser as imports. Success is silent (exit 0); file/validation
failure exits 1; usage failure exits 2. Reads are limited to 1 MiB. YAML and
unsupported extensions fail. This command runs before server configuration or
database initialization: no data directory, provider or running server is needed,
and even malformed server configuration does not prevent validation.
From a source checkout, validate a bundled unprefixed tree:
suchi taxonomy import <file> [flags]
Preview a suchi-taxonomy/v1 import against the local instance. Dry-run is the
default; the summary identifies the destination, original-archive preservation and
initial access for a newly created system, alongside additions, preserved/skipped
rules and collisions. --apply performs the same preview and transactional freshness
recheck as the HTTP importer. Skipping seeds still validates the whole file.
Flags
Only safe initial unconfigured setup can replace the bootstrap tree. Filed
documents (including recoverable Trash) and dependent user configuration prevent
replacement. Later imports merge: preserve local descriptions, existing rule
names, disabled originals and user forks; require a remap/skip for collisions.
Skipping a category skips its whole dependent starter.
Without
--existing-system-code, first prefixed Apply adopts the original archive
under the file’s code/name, retaining IDs and grants. Newly created systems initially
admit only instance admins. After introduction unprefixed imports cannot remove it.
Apply queues the generated filing-index refresh in the same transaction. If no
server is processing jobs, refresh remains pending until the server runs; command
success does not claim the physical 00.00 archive.huml has updated.
suchi taxonomy export [flags]
Export a validated current snapshot on stdout, with id = "archive" and content
version = 1. Only user structure is serialized; generated System/49 is implicit.
The default includes representable preset-owned keywords/starters with symbolic
references, not user-owned rules/forks or a full archive backup. Disabled or
unrepresentable starters fail rather than being re-enabled or silently lost.
Explicit tree-only export omits both keywords and starters. Legacy incompatible
reserved rows fail export without repairing or hiding database contents.
suchi taxonomy merge [flags]
Admin operation for post-import cleanup: after years of use (or a
big import), taxonomy tables accumulate near-duplicates
(“BESCOM” and “Bescom”, “Tax” and “TAX”). Merge picks one, moves
every reference from the other, deletes the source, and rewrites
any automations that referenced the source name.
Dry-run by default. Reports how many docs would move before you
commit.
Flags
Example:
suchi doctor
One-shot diagnostic report. Prints:
- Managed egress destinations for OIDC, enabled mailboxes, Microsoft OAuth, and the active LLM endpoint, with credentials removed
- Presence of optional pipeline binaries on
PATH; versions are not queried - Database schema version compared with the embedded target
- Imported taxonomy preset, version, and content hash per system when available
$DATA_DIRwritability- Operational indicators: last-backup age (WARN past 2×
BACKUP_INTERVAL), dead-job count, oldest running job (WARN >15m), effective upload cap, last boot’s orphaned-job reclaim count, and theaudit_eventsrow total against the retention window
--scrub-cas for the explicit full CAS hash
walk.
Flags
Non-zero exit only on hard errors. Missing optional binaries print but
don’t fail — the ingest pipeline degrades gracefully. An explicit CAS
scrub also exits non-zero on missing or corrupt content. Useful for air-gap
verification and support tickets.
When
DATA_DIR is unset and the /data default cannot be created, the
doctor falls back to the current user’s OS config directory (for example,
~/Library/Application Support/suchi on macOS). An explicitly configured
DATA_DIR is never replaced by the fallback.
--quarantine-corrupt only while the server and workers are stopped. The
report-only scrub streams files without modifying them; quarantine moves each
bad path out of the live CAS for later inspection or restoration.
suchi mcp [flags]
Start a Model Context Protocol server that adapts the REST
surface into MCP tools. See MCP guide for the client-side
setup + tool reference.
Flags
The binary also responds to
suchi-mcp when invoked via symlink — the
argv[0] dispatcher rewrites the command so command: "suchi-mcp" in a
Claude Desktop config stays clean.
Uses a scoped API token, not an admin token. Every MCP call is attributed to that
token’s owner and stays within its bound filing system; there is no MCP system flag.
suchi demo [flags]
Seed $DATA_DIR from the versioned manifest maintained by
suchi-demo.
Flags
Without a corpus flag,
suchi demo downloads the tested corpus release. A
different manifest version is rejected so showcase images cannot silently run
against an untested data contract. Corpus input is capped at 256 MiB compressed,
1 GiB extracted, and 10,000 archive entries; checksum sidecars are capped at
4 KiB.
The manifest owns fixtures, metadata, saved views, and symbolic automations.
Same-name views and automations are preserved on repeat runs, and existing
documents are reported rather than duplicated. See demo instance
for the runtime and deployment boundaries.
suchi refile [flags]
Rerun document_added automations and enqueue a render/move job for every live
document in the selected system after an automation or path-template change.
Full walkthrough at Refile.
Flags
Safe against a live server — uploads that arrive mid-sweep use the
normal postingest chain and land under the new tree automatically.
suchi rescan [flags]
Re-run the content-extraction pipeline (qpdf → OCR → content write →
automations → render → thumb → post-classify) against
originals for a selected set of docs. Sibling to refile; the
split is:
refile= re-rundocument_addedautomations and enqueue a render job. Cheap, changes filing metadata. Use after preset, path-template, or automation edits.rescan= re-run everything, including OCR against the original blob. Expensive but authoritative — this is the tool for “I swapped tesseract for ocrmypdf” or “I upgraded the LLM classifier model.”
Filters (compose with AND)
Pre-flight
How it works under the hood
Each matching doc gets a freshpost-ingest job in the durable
outbox. When suchi serve is running (or the next boot picks the
job up), those drain through the same chain a fresh upload runs.
Idempotent — re-running against the same doc bumps its
pipeline_version_* markers but doesn’t otherwise diverge. Batched
in groups of 200 so a crash mid-run leaves the outbox consistent.
Signature semantics — each pipeline step reads a version constant
and writes it onto the doc on success:
pipeline_version_contentbumps when the content-extraction chain changes (new format handler, byte-cap change, etc.).pipeline_version_ocrbumps when the OCR engine or its data changes.pipeline_version_llmbumps when the classifier’s prompt or validated result contract changes (constant lives in the plugin package). Operator endpoint, model, key, timeout, and threshold changes use an explicit selected rescan instead of stale detection.
suchi rescan --stale <kind> catches only affected docs — the
selective alternative to a bulldozer.
Examples
Discovery in Approvals
The CLI is the surgical path: you pick filters, run the command, and own the outcome. Approvals discovers older successful pipeline results after a code revision bump. Its proposal offers Rescan all, Try 20 first when more than 20 documents match, and Dismiss. Both surfaces route throughcore/rescan.Enqueue.
Dismiss cleanly closes the run; the card doesn’t come back until
the next version bump. If someone rescans out-of-band and the stale
count hits zero, the detector cancels the pending run on the next
boot.
A kind whose current version reports as 0 is disabled, and any pending
proposal for it is cancelled. Automatic LLM proposals also exclude stored
version 0, which means classification never completed. Enabling a classifier
therefore affects new ingests without turning the existing archive into an
upgrade proposal. An explicit --stale llm command still includes those
documents. See Pipeline versions for the full boundary.
suchi export --out FILE.zip
Portable takeout of live originals and selected metadata from one system.
Manifest version "2" identifies its code/name. The ZIP contains original
bytes, documents/<name>-<id>.json sidecars and selected-system taxonomy-table
dumps, not a database restore graph. Sidecar format stays 1, adding optional
jd_system and jd_address describing the source. Document IDs can change on intake.
sensitivity, mime_type,
and sha256 sidecar fields are currently informational and ignored on ingest.
MIME and SHA-256 are recomputed from the bytes, and sensitivity uses the target
instance default.
An input jd_system must match the watcher’s configured target; it cannot route
or create a system. jd_address is informational source metadata, not a requested
new identity. To retain IDs, memberships, ACLs and relationships exactly, use a
whole-instance backup, not native takeout or Paperless import.
Not included in this version:
- Avatars, thumbnails (derived — regenerate on re-import).
- Document versions history.
- Approvals + audit history.
- Share links + saved views.
- Per-document custom-field values and notes.
version in manifest.json
so importers can gate on it.