Commands
Every command is a thin wrapper over one named GraphQL operation. This page documents each command exactly as the package implements it: synopsis, flags, the operation it maps to, and output examples.
Global flags
Section titled “Global flags”These apply to every command and may appear before or after the command path:
| Flag | Effect |
|---|---|
--json | Emit the GraphQL data payload, pretty-printed. |
--jsonl | Emit one JSON object per line (for the streamable list of a result). |
--human | Force the human table/record view (e.g. into a pipe). |
--no-color | Disable ANSI color. |
--quiet | Suppress non-error stderr chrome. |
--profile <name> | Select the config profile. |
--endpoint <url> | Override the profile’s api_url. |
--help, -h | Print top-level usage. |
--version, -v | Print the CLI version. |
Format precedence is --jsonl > --json > --human; with none given, the CLI emits human at a TTY and json when piped. See Scripting.
login / logout / whoami
Section titled “login / logout / whoami”Covered in full on Install & Authentication. In brief: login stores a token (verifying it via query stats), logout forgets it, and whoami prints identity + corpus size (also via query stats). None maps to a dedicated GraphQL auth operation — auth is Clerk; whoami reuses stats.
The highest-leverage group. Each is --json-capable, and the human view echoes the [doc:ID] handle convention the Core tools use, so output reads like what an agent sees.
search
Section titled “search”trove search <query…> [--source <name|id>] [--source-type <t>] [--author <a>] [--after <date>] [--before <date>] [--type <ct>] [--tag <t>]… [--feed <id>] [--limit <n> | -l <n>]Semantic top-K search → query search. Positional words are joined into the query string. --source accepts a name or id; a name is resolved to its id client-side via sources (an id-shaped value, src_…, is used as-is). --tag is repeatable. --type is upper-cased to the ContentType enum.
$ trove search "database indexing" --source "arXiv Papers" --limit 5SCORE TITLE SOURCE HANDLE0.847 Learned Indexes for Range Queries arXiv Papers [doc:d_8f2a]0.812 B-Tree vs LSM under Write Amplification arXiv Papers [doc:d_31c0]
2 match(es) in 41ms--json emits the SearchResults object ({ totalMatches, queryTimeMs, results[] }); --jsonl emits one results[] entry per line.
discover
Section titled “discover”trove discover <topic…> [--source <name|id>] [--source-type <t>] [--feed <id>] [--limit <n> | -l <n>]Broad thematic browse → query discover. Only source/feed filters take effect — the wider search filters (--author, --after, --type, --tag) are accepted but ignored. Output shape matches search.
recent
Section titled “recent”trove recent [--source <name|id>] [--author <a>] [--since <date>] [--limit <n> | -l <n>]Chronological by indexedAt → query recent. Renders a TITLE / AUTHOR / SOURCE / HANDLE table. --json/--jsonl emit the document array.
trove get <doc-id…> [--offset-words <n>] [--max-words <n>]Fetch one or more documents with full text → query document(id), once per id. A missing document fails with exit code 5. The human view prints a record header (title, author, source, url, handle) followed by the full text — built for piping into $EDITOR/less:
trove get d_8f2a | $EDITOR -In --json, a single id emits one document object; multiple ids emit an array. In --jsonl, each document is one line.
Word paging. --offset-words / --max-words page a long transcript client-side: the CLI fetches the document’s fullText, slices it by words, and prints just that window. The human view writes the slice to stdout plus a continuation hint (the next offset) to stderr; --json returns { id, offsetWords, returnedWords, totalWords, nextOffset, text }. Paging applies to a single document id at a time.
trove get d_8f2a --offset-words 0 --max-words 800 # first 800 wordstrove get d_8f2a --offset-words 800 --max-words 800 # next page (use nextOffset)trove list [--source <name|id>] [--type <ct>] [--tag <t>]… [--search <text>] [--sort <field>] [--order <asc|desc>] [--limit <n> | -l <n>] [--offset <n>]The exhaustive lister with an authoritative totalCount → query documents. This is the right tool for “all X”, counts, and pagination — search is semantic top-K. --sort maps to DocumentSortField and --order to SortOrder (both upper-cased); --type upper-cases to ContentType.
$ trove list --source "The Guardian" --json | jq '.totalCount'675The human view appends a <N> total footer (with (more available) when hasMore). --jsonl emits the nodes[] one per line.
sources
Section titled “sources”trove sources [--type <t>] [--status <s>]List your sources → query sources. --status upper-cases to SourceStatus. Renders an ID / NAME / TYPE / STATUS / DOCS table.
source
Section titled “source”trove source <id|name> [--feeds] [--sync-runs]One source with feeds, top authors, date range, and recent sync runs → query source(id). The name/id argument is resolved via sources. A missing source fails with exit code 5. (--feeds/--sync-runs are accepted; the operation already requests feeds and sync runs.)
trove statsCorpus aggregates → query stats: total documents, total/active sources, breakdowns by source type and content type, and recent sync runs.
Capture
Section titled “Capture”trove save (--text <text> | --text - | --url <url>) [--title <t>] [--tag <t>]… [--source <s>]Manual capture of free text or a URL into the Manual Saves source → mutation saveDocument. One of --text or --url is required. --text - reads the body from stdin, so:
cat notes.md | trove save --text - --title "Meeting notes"trove save --url https://example.com/post --tag reading --tag aiHere --source is free-form attribution text (e.g. "conversation with Claude"), not a source id. On success the human view writes ✓ saved [doc:…] to stderr and the record (id, title, url, tags) to stdout. --json/--jsonl emit the saved Document.
ingest
Section titled “ingest”trove ingest --source <id> --feed <id> --documents <file.jsonl|-> [--cursor <new>] [--cursor-before <expected>]The lower-level ingest boundary for source-adapter authors and bulk scripts → mutation ingestDocuments. --documents accepts a JSONL stream or a JSON array of IngestDocumentInput; - reads from stdin.
It honors the cursor compare-and-swap: pass --cursor (the new cursor) and --cursor-before (the expected current value). On a CAS rejection the CLI exits with code 8 (retryable) so a script can re-read IngestResult.cursor and retry. Re-sent documents are reported as documentsSkipped, not errors.
generate-docs | trove ingest --source src_123 --feed feed_456 --documents -The human view prints indexed, skipped, transcriptions queued, cursor, and errors. --json emits the full IngestResult; --jsonl emits the per-document errors[] one per line.
Source authoring (@ontrove/extend/source)
Section titled “Source authoring (@ontrove/extend/source)”The CLI is the local dev toolchain for source adapters. A source adapter is a folder with extension.ts — one defineSource({ sync }) export against @ontrove/extend/source — plus the manifest.json generated from it. Locally, the CLI runs the adapter on your machine — dev/test run sync(ctx) and never upload; sync runs it then pushes via ingestDocuments. In production, most sources run in Trove’s cloud; the ones that need a browser or local files run on the Mac app.
source init
Section titled “source init”trove source init <name>Scaffold <name>/extension.ts (a defineSource stub with a sample sync) and the manifest.json generated from it. No GraphQL.
source dev
Section titled “source dev”trove source dev [path] [--config <file.json>] [--cursor <json>]Load the source adapter’s extension.ts and hand it to @ontrove/extend/source’s runSource, run sync(ctx), and print the produced documents (human table or --json/--jsonl). --config supplies the source’s preference values; --cursor supplies the starting cursor. Nothing is uploaded.
source test
Section titled “source test”trove source test [path] [--fixtures <file.json>] [--config <file.json>]Run sync(ctx) against a fixtures file (a JSON map of request URL → canned response body, default fixtures/responses.json) so the run is deterministic and offline, then assert the document shape. Exits 2 if assertions fail.
source validate
Section titled “source validate”trove source validate [path]Validate the manifest half of your defineSource declaration with @ontrove/extend/source’s validateSourceManifest — required fields, the id/version patterns, and the credential-key lint (a source’s config must hold preferences only, never credentials). Exits 2 on an invalid manifest.
source sync
Section titled “source sync”trove source sync [path] [--source <name|id>] [--feed <key>] [--create] [--config <file.json>]The real upload: run sync(ctx) locally, then push the documents via mutation ingestDocuments with cursor compare-and-swap. The CLI reads the target feed’s current cursor as cursorBefore and advances it with the cursor sync returns. --source (defaults to the manifest name) and --feed (defaults to default) select the target; --create creates the source/feed (via createSource/addFeed) if they don’t exist yet.
Toolkit authoring & deployment (@ontrove/extend/toolkit)
Section titled “Toolkit authoring & deployment (@ontrove/extend/toolkit)”toolkit init/toolkit dev are the local toolchain for toolkits. A toolkit is a folder with extension.ts — one defineToolkit({ …, tools }) export against @ontrove/extend/toolkit — plus the manifest.json generated from it, and every toolkit runs as a full MCP server on Trove’s cloud. The remaining commands wrap the toolkit control-plane operations. A toolkit argument is a slug or id, resolved via mcpServers.
toolkit init
Section titled “toolkit init”trove toolkit init <name>Scaffold <name>/extension.ts (a defineToolkit stub with a sample tool, annotations, and an output schema) and the manifest.json generated from the same declaration. No GraphQL.
toolkit dev
Section titled “toolkit dev”trove toolkit dev [path] [--port <n>] [--once]Load extension.ts, wrap it in @ontrove/extend/toolkit’s runtime fetch handler, and serve it over http://127.0.0.1:<port> (default 8788) so a client can connect: GET returns tools/list, POST runs a tool. Prints the local URL and the tool list; ctx.secret/ctx.trove resolve against the configured endpoint. Runs until interrupted (--once serves and returns, used in tests).
toolkit ls
Section titled “toolkit ls”trove toolkit lsList your toolkits → query mcpServers. Renders a SLUG / NAME / STATUS / VIS / TOOLS / ACTIVE table (ACTIVE is the active deployment’s version).
toolkit deploy (alias deploy)
Section titled “toolkit deploy (alias deploy)”trove toolkit deploy [--dir <path>] [--name <name>] [--slug <slug>]trove deploy [--dir …] [--name …] [--slug …]Register/version a toolkit → mutation deployServer. Reads manifest.json from --dir (default .), derives name/slug from it (slug falls back to the manifest id) unless overridden by --name/--slug, bundles extension.ts locally (a Bundling extension.ts… line is written to stderr), and registers the deployment. The manifest’s egress, scopes and secrets are read from the file, not from the bundle, and become the deployed toolkit’s policy. On success it prints the namespaced tool names ({slug}__{tool}) to stdout and a ✓ deployed … line to stderr. --json emits the deployment. Missing manifest.json is a usage error (exit 2). See Toolkits — Deploying.
toolkit pause / toolkit resume / toolkit rm
Section titled “toolkit pause / toolkit resume / toolkit rm”trove toolkit pause <toolkit>trove toolkit resume <toolkit>trove toolkit rm <toolkit>Lifecycle, each over a single id → mutation pauseServer, mutation resumeServer, mutation deleteServer (a soft-delete). The human view writes ✓ paused|resumed|deleted <name> to stderr; --json emits the returned McpServer.
toolkit rollback
Section titled “toolkit rollback”trove toolkit rollback <toolkit> <deploymentId>Repoint a toolkit to a prior deployment → mutation rollbackServer. Both positionals are required. The human view writes ✓ rolled back <name> → <version> to stderr.
toolkit logs
Section titled “toolkit logs”trove toolkit logs <toolkit>There is no logs GraphQL operation: per-script logs are produced by the deployed toolkit runtime, not the GraphQL API. Rather than invent a fake op, this command explains where logs live (the deployed endpoint, once the runtime ships) and exits 0. --json returns { server, available: false, reason }.
secret set
Section titled “secret set”trove secret set <toolkit> <name> (--value <v> | --from-file <path> | --from-stdin)Seal a secret into the encrypted vault → mutation setServerSecret. The value comes from --value, --from-file <path>, or --from-stdin so it need never land in argv history; it is stored server-side in the vault, never in D1. The human view writes ✓ secret '<name>' sealed for <toolkit> to stderr.
secret ls
Section titled “secret ls”trove secret ls <toolkit>List a toolkit’s declared secret names → backed by query mcpServers (the secrets field). Values are unreadable by design — only the names are ever returned. The human view prints one name per line (or notes when the toolkit declares none); --json emits { server, secrets } and --jsonl emits one name per line.
Escape hatch
Section titled “Escape hatch”trove gql <file|-> [--variables <json|->]Run a raw, user-supplied GraphQL document over the same endpoint with the same token. The document is read from a file path or stdin (-); --variables takes inline JSON or stdin. Unlike the wrapped commands, gql emits the full { data, errors } envelope (so scripts can branch on .errors) and exits 7 if errors[] is non-empty, 0 otherwise. It is the same authz the server enforces for every client — there is nothing reachable here that the token could not do with curl.
echo '{ stats { totalDocuments } }' | trove gql -trove gql query.graphql --variables '{"id":"d_8f2a"}'Command → GraphQL operation mapping
Section titled “Command → GraphQL operation mapping”This table is the contract: every command resolves to a named operation in schema.graphql (or a marked local step). It is a strict subset of the published GraphQL surface — the CLI never exceeds the API, it only makes a slice of it ergonomic.
| Command | GraphQL operation | Kind |
|---|---|---|
login / logout / whoami | — (Clerk; whoami calls query stats) | Auth |
search <query> | query search | Read |
discover <topic> | query discover | Read |
recent | query recent | Read |
get <id…> | query document(id) (once per id) | Read |
list | query documents | Read |
sources | query sources | Read |
source <id|name> | query source(id) | Read |
stats | query stats | Read |
save | mutation saveDocument | Write |
ingest | mutation ingestDocuments (cursor CAS) | Write |
source init | — (scaffold @ontrove/extend/source project) | Local |
source dev | — (local sync(ctx)) | Local |
source test | — (local fixtures assertion) | Local |
source validate | — (validateSourceManifest) | Local |
source sync | mutation ingestDocuments (+ createSource/addFeed w/ --create) | Write |
toolkit init | — (scaffold @ontrove/extend/toolkit project) | Local |
toolkit dev | — (local server over 127.0.0.1) | Local |
toolkit logs | — (no log op; explains the deployed-runtime gap) | Info |
toolkit ls | query mcpServers | Read · PROPOSED |
toolkit deploy / deploy | mutation deployServer | Write · PROPOSED |
toolkit pause | mutation pauseServer | Write · PROPOSED |
toolkit resume | mutation resumeServer | Write · PROPOSED |
toolkit rollback | mutation rollbackServer | Write · PROPOSED |
toolkit rm | mutation deleteServer (soft-delete) | Write · PROPOSED |
secret set | mutation setServerSecret | Write · PROPOSED |
secret ls | query mcpServers (secrets — names only) | Read · PROPOSED |
gql <file|-> | arbitrary, user-supplied | Escape hatch |