Skip to main content
Configuration comes from HuML or TOML files with environment-variable overrides. See config.

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_DIR writability
  • 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 the audit_events row total against the retention window
It does not test remote connectivity, available disk space, CAS shard capacity, or operator-script egress. Use --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.
Run --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-run document_added automations 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.”
Every rescan is explicit + selectable + previewable. There is no “rescan all” default and no background auto-rescan — the operator picks the set every time.

Filters (compose with AND)

Pre-flight

How it works under the hood

Each matching doc gets a fresh post-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_content bumps when the content-extraction chain changes (new format handler, byte-cap change, etc.).
  • pipeline_version_ocr bumps when the OCR engine or its data changes.
  • pipeline_version_llm bumps 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.
Bumping the constant in code, rebuilding, and running 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 through core/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.
After extracting the zip, placing each original beside its sidecar in an fs-watch staging directory restores title, source date, correspondents, tags, and JD category within the configured target. Follow the takeout reingestion guide for target preparation, safe copy order and verification steps. This is not a full metadata round trip: per-document custom field values and notes are omitted, while exported 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.
Bumps to the export format land a new version in manifest.json so importers can gate on it.

suchi version

Prints the binary version, build revision, and the Go version it was compiled with.