CLI

The curator binary is the whole operational surface. Query commands are thin shells over the same engine the MCP tools ride, so curator search and kp_search cannot drift apart.

curator --help prints the canonical usage text; this page is that text, expanded. Every command exits 0 on success, 1 on failure (message on stderr), 2 on usage errors.

Commands

commanddoes
init [dir]scaffold a vault: curator.toml, .kp/, now.md, first index
ingestrun producer adapters (Curio, vault notes) into the vault/index, incrementally
index rebuildrebuild index.db (blue/green epoch swap); reindex is an alias
zotero synctwo-channel Zotero sync into the vault (delta metadata + fulltext)
searchhybrid retrieval from the terminal
getone note by id (any namespace) — content + metadata
relatedembedding-nearest notes to a note
recentrecently ingested/changed notes
mcp serveserve the MCP surface (stdio default; --http + bearer)
proposecreate a proposals/v1 changeset from a directory of files
review [<id>]interactive TUI — Review · Search · Digest (no id), or render one proposal
apply <id>validate and apply a proposal (stamps applied/rejected)
reject <id>reject an open proposal without applying it (stamps rejected)
proposals listlist stored proposals and their status
digest runrun the deterministic librarian digest (--auto to apply)
doctorconfig / vault / index / cursors health
statusvault + index + proposals snapshot (always succeeds; --json)
-h, --help / -V, --versionusage / version

Shared flag on every command that loads config: --config <path> — config location (default: $CURATOR_CONFIG or $KP_CONFIG, then ./curator.toml, ./kp.tomldiscovery details). Batch and query commands also take --json for machine-readable output on stdout.

curator init

curator init [dir] [--embedder builtin|hash]

Scaffolds dir (default .) as a Curator vault: writes curator.toml from the shipped example pointed at the directory (never overwriting an existing curator.toml or legacy kp.toml), creates the proposals directory and a starter now.md, and builds the first index by running a full ingest.

flagmeaning
--embedder <e>builtin | hash, stamped into the scaffolded config. builtin fetches its pinned ~130 MB ONNX model on first use (one-time, announced); hash is offline and deterministic (no ML)

curator ingest

curator ingest [--config <path>] [--json]

Incremental: full-file hashes mean unchanged notes cost nothing; changed notes are re-chunked and re-embedded; frontmatter-only edits update metadata without re-embedding. Reports counts for ingested/unchanged/skipped/ignored/removed notes and links; with [curio].enabled, also folded/duplicate/malformed event counts.

curator index rebuild

curator index rebuild [--config <path>] [--json]    # alias: curator reindex

Rebuilds the same corpus, identities, and chunks that incremental ingest produces, blue/green-swapped in as a new epoch — see Operations for when and why.

curator zotero sync

curator zotero sync [--config <path>] [--json]
                    [--dir <path>] [--no-fulltext] [--fulltext-cap <n>]
flagmeaning
--dir <path>vault-relative notes dir (default: zotero)
--no-fulltextskip the fulltext pass
--fulltext-cap <n>fulltext truncation cap, characters (default: 20000)

Two-channel sync — how it works.

curator search <query> [--k <n>] [--mode hybrid|vector|fts]
               [--config <path>] [--json]
flagmeaning
--k <n>result count (default 10)
--mode <m>hybrid (default) | vector | fts
--jsonprint the MCP-shaped JSON output (kp_search's shape)

curator get

curator get <id> [--config <path>] [--json]

<id> accepts every identity namespace: curio:…, zotero:…, kp:…, path:<vault-relative-path>.

curator related <id> [--k <n>] [--config <path>] [--json]

Embedding-nearest notes to the anchor note (anchor excluded).

curator recent

curator recent [--days <n>] [--kind curio|zotero|kp|path]
               [--config <path>] [--json]
flagmeaning
--days <n>look-back window in days (default 7)
--kind <ns>identity-namespace filter

curator mcp serve

curator mcp serve [--config <path>] [--http]

Serves MCP surface v1. stdio by default; --http (or [mcp].transport = "http") serves streamable HTTP on [mcp].http_bind and requires the bearer token env named by [mcp].bearer_token_env — the server refuses to start without it.

curator propose

curator propose --title <t> --from <dir>
                [--rationale <r>] [--author <a>]
                [--config <path>] [--json]
flagmeaning
--title <t>proposal title (required)
--from <dir>directory of generated files; every file maps to the same vault-relative path (required)
--rationale <r>why this change (default: empty)
--author <a>proposal author (default: curator-cli)

Generated-content is the only creation mode in v1; a staged-changes mode (diffing working-tree edits) is planned, not yet implemented.

curator review / apply / reject / proposals list

curator review            # the interactive TUI (Review · Search · Digest) — a TTY
curator review <id>       # human-readable render of one changeset (scriptable)
curator apply <id>        # validate -> apply -> stamp status
curator reject <id>       # stamp an open proposal rejected, writing nothing
curator proposals list    # ids, status, titles, file counts

apply runs the deterministic validator (hard-reject list) and stamps applied/rejected. A failed apply also stamps rejected; reject is the reviewer saying "no" up front — same one-way guard (only an open proposal can be rejected), but nothing is written.

The interactive TUI. curator review with no id and a terminal opens a tabbed full-screen app — three screens over your vault. Tab / Shift-Tab or 1 2 3 switch screens, ? toggles a key reference, q quits (Ctrl-C anywhere; Esc is back / cancel / close-preview). The index and embedder load lazily — a review-only session never opens them, so the app starts instantly.

Review

The proposal queue: the selected changeset's metadata and a coloured diff, with a pre-flight banner that checks — non-destructively — whether the patch still applies cleanly against the current vault, so drift is visible before you commit (apply is destructive-on-reject). Apply and reject both confirm.

The Review screen: a proposal queue with status glyphs, the selected proposal's metadata, a green pre-flight banner, and a coloured diff

keyaction
j / k, / move between proposals
Ctrl-d / Ctrl-u, PgDn / PgUpscroll the diff
fcycle the status filter (all → open → applied → rejected)
a / xapply / reject the selected proposal (confirm with y/n)
rrefresh the queue from disk

Interactive hybrid retrieval over the same KpEngine the MCP surface and curator search ride — so it cannot drift from them. Type a query and press ; move through the ranked hits; open a note's full content, or jump to its embedding-nearest neighbours.

The Search screen: a query box, a ranked results list with scores, and the opened note's content in a preview pane

keyaction
type · edit the query · run it
j / kmove through the results
o / open the selected note · ^d/^u scroll it
rrelated — embedding-nearest to the selection
mcycle mode (hybrid → vector → fts) and re-run
/ or ijump to the query box · Esc closes the preview / returns

Digest

A read-only preview of what the deterministic librarian would surface right now — ranked candidates with scores and why-surfaced reasons — and a one-key generate that files today's digest as a proposal (which lands on the Review tab to apply or reject). It writes nothing until you generate.

The Digest screen: ranked candidates with surfaced/quiet glyphs and scores, and a why-surfaced detail pane

keyaction
j / kmove · ^d/^u scroll the preview
fcycle the filter (all → surfaced → quiet)
ggenerate today's digest (confirm with y/n)
rrefresh the preview from the index

Run without a terminal (piped/CI), curator review prints guidance and exits 0 rather than blocking — pass an <id> for the non-interactive render.

curator digest run

curator digest run [--auto] [--now <rfc3339>] [--config <path>] [--json]
flagmeaning
--autoauto-apply the digest proposal when the gate admits it (pure additions under [librarian].digest_dir, kp:<uuidv7> identities)
--now <rfc3339>inject the clock (testing/reproducibility; default: now)

curator doctor

curator doctor [--config <path>] [--json]

Checks config, vault, proposals queue, now.md, index meta + embedder identity match, digest log, Curio cursors, and MCP transport sanity. Levels ok/warn/error; exits nonzero when anything errors — healthcheck-ready (operations guidance).

curator status

curator status [--config <path>] [--json]

A state snapshot — the counterpart to doctor's health checks. Reports the vault note count, the serving index epoch/embedder/note count, the latest librarian digest, the proposal queue (total + open), and the MCP transport. Unlike doctor it never fails: a not-yet-built index is reported as not built, not an error, so status --json is safe to pipe into scripts.