Skip to content

The Trove CLI

@ontrove/cli ships a single binary, trove: a scriptable command-line tool for all of Trove. It queries your knowledge base, captures documents, and manages your toolkits (trove mcp deploy) — all over the one GraphQL API at https://api.ontrove.sh/graphql.

GraphQL is the API; the CLI is a convenience layer

Section titled “GraphQL is the API; the CLI is a convenience layer”

There is exactly one data-access contract in Trove: the GraphQL Open Host Service. The Core tools are clients of it. The web app is a client of it. The Mac app is a client of it. trove is one more peer client — with no privileged access and no private endpoint.

Every trove command is a thin wrapper over a documented GraphQL operation (plus, for deploy, a local build step). If a command needs a capability the GraphQL API does not expose, that is a GraphQL gap to close first — never a side-channel bolted onto the CLI.

This is the same discipline that makes the Core tools safe: the surface is wide, the privilege is narrow, and the business logic lives in the resolvers. Concretely:

  • The CLI’s trove search and the trove_search core tool wrap the same search resolver. They differ only in presentation — a table versus an MCP content block.
  • The CLI’s trove ingest and the Mac app’s scheduled sync hit the same ingestDocuments boundary, with the same compare-and-swap idempotency contract.
  • The CLI’s trove mcp deploy wraps the same deployServer control-plane mutation the web management surface uses.

Because the CLI is just another JWT-bearing client, it is indistinguishable from the web app at the wire. Authorization is enforced server-side in the resolvers, never by the CLI.

  • Human by default at a TTY — aligned tables, key/value records, [doc:ID] handles that echo the MCP output convention, and color.
  • --json / --jsonl emit exactly the GraphQL data shape for jq/fzf pipelines. When stdout is not a TTY, the CLI auto-selects --json.
  • Data on stdout, diagnostics on stderr, so trove search … --json | jq is never polluted by progress or chrome.
  • Honest exit codes let pipelines branch on failure class without parsing stderr.

See Scripting & Automation for the full story.

No daemon, no local database, no cache of corpus data. The only local state is a Clerk token in ~/.trove/config.toml, organized into named profiles (e.g. prod, dev) so you can target production and a local dev Worker without re-authenticating. See Install & Authentication.

trove
├── login · logout · whoami Auth
├── search <query> query search
├── discover <topic> query discover
├── recent query recent
├── get <doc-id…> query document(id)
├── list query documents
├── sources query sources
├── source <id|name> query source(id)
├── stats query stats
├── save mutation saveDocument
├── ingest mutation ingestDocuments
├── source init·dev·test·validate @ontrove/sdk toolchain (local)
├── source sync → mutation ingestDocuments
├── mcp init · dev @ontrove/mcp toolchain (local)
├── mcp logs deployed-runtime logs (info)
├── mcp ls query mcpServers
├── mcp deploy (alias: trove deploy) mutation deployServer
├── mcp pause · resume · rollback · rm lifecycle mutations
├── secret set · ls mutation setServerSecret / query mcpServers
└── gql <file|-> raw GraphQL escape hatch

The full reference — every flag, the GraphQL operation each command maps to, and output examples — is in Commands.

The query/capture commands, the source init/dev/test/validate/sync and mcp init/dev local toolchains, login’s loopback OAuth flow, OS-keychain token storage, get word-paging, and secret ls are all implemented. One surface remains genuinely deferred:

  • The toolkit deployed runtime (per-toolkit isolates) is PROPOSED. The control-plane commands that drive it (mcp deploy, secret set, lifecycle) wrap the corresponding mutations and ship the day the control plane does. Because per-script logs come from that runtime — not the GraphQL API — mcp logs has no operation to call: it explains where logs will live rather than inventing a fake op.