Skip to content

CLI Overview

The wh CLI is the primary human interface for interacting with WarmHub. It covers all operations — creating repos, writing data, querying state, and bootstrapping agent context.

The CLI requires Node 22+.

Terminal window
npm install -g @warmhub/cli
wh --version

After installing, wh is available everywhere. See the Quickstart for the full walkthrough.

Use wh use to set the repo for a working directory, pass --repo org/name when a script should be explicit, and add --json when another tool needs structured output. Most commands accept a repo from the current .wh file or a flag.

Most commands follow the wh <domain> <verb> pattern. A handful are flat single commands that take no verb — wh use, wh init, wh doctor, wh prime, wh onboard, wh update, wh notifications, and wh channel:

Terminal window
wh org create myorg
wh repo list myorg
wh thing list --shape Location
wh commit submit --ops '[...]'

Domains: org, repo, shape, thing, assertion, commit, sub, auth, token, credential, component, collection

See the full command reference for every domain, verb, flag, and alias.

The easiest way to set a default repo is wh use, which writes a .wh file in the current directory:

Terminal window
wh use myorg/world
wh thing list # targets myorg/world

The CLI resolves the target repo using this priority:

  1. --repo flag (per-command override)
  2. WARMHUB_REPO environment variable
  3. .wh file in the current directory

The CLI reads WH_TOKEN (authentication), WARMHUB_REPO / WARMHUB_ORG (default repo target), WARMHUB_API_URL (backend URL), and WH_PROFILE (auth profile), plus a few behavior toggles. See Environment Variables for the full list, accepted values, and precedence rules.

Terminal window
wh thing list --repo myorg/other-repo

Colored, formatted text output:

Terminal window
wh thing list

Structured output for scripts and agents:

Terminal window
wh thing list --json

Paginated list commands wrap their rows in a page envelope:

{
"items": [ /* rows */ ],
"page": { "limit": 50, "count": 50, "hasMore": true, "nextCursor": "<cursor>" }
}

count is the number of items in this page. When hasMore is true, pass nextCursor back as --cursor to fetch the next page, or use --all to auto-fetch every page.

Failure output. When a command fails under --json, the CLI writes a structured error envelope to stderr:

{
"error": {
"code": "CONFLICT",
"errorCode": "thing_version_conflict",
"backendCode": "thing_version_conflict",
"message": "A newer version of this thing already exists.",
"hint": "Re-fetch the thing and reapply your changes."
}
}

error.code is a high-level bucket your script can branch on. Values are drawn from the ErrorCode enum: UNKNOWN, USER_INPUT, CONFIG, AUTH, BACKEND, CONFLICT, RATE_LIMITED, QUERY_TOO_EXPENSIVE, FIELD_INDEX_UNAVAILABLE, FIELD_NOT_INDEXABLE, and FIELD_TYPE_AMBIGUOUS. error.errorCode carries the service-specific error code when the API returns one; error.backendCode is also present for the same value and is retained for backwards compatibility. message is always present; hint, suggestions, and context are optional and included only when the CLI has additional detail to surface.

Live updates by polling — re-runs the query periodically and auto-refreshes as data changes:

Terminal window
wh thing list --live

--max-updates <n> auto-exits after N updates, and --live-timeout-ms <ms> auto-exits when no update arrives within that window — both useful for scripted, bounded live reads.

Exact flag names. Long flags and declared aliases must match exactly. Use the full --description name:

Terminal window
wh repo create myorg/repo --description "My repo"

Unknown flags may receive a “did you mean?” suggestion, but are never expanded or executed. Typos in domains and verbs receive the same kind of recovery guidance.

Verb aliases. A handful of verbs accept an alias — for example, wh auth whoami resolves to wh auth status. There is no general show/get aliasing; use the canonical verb shown in the command reference. A mistyped verb returns a “did you mean?” suggestion rather than silently resolving.

Terminal window
wh help # full help overview
wh <domain> # list verbs for a domain
wh <domain> <verb> --help # verb details with flags and examples
wh help --format json # full CLI spec as JSON (all domains)
wh help <domain> --format json # spec for a single domain as JSON
wh doctor # verify environment and connectivity

wh help --format json returns the complete CLI spec as JSON: all domains, a compact verb matrix, and the authoritative global flags and controls tables. The payload includes a schemaVersion field — check it before parsing, as a version advance may indicate structural changes. Targeted JSON help (wh help <domain> --format json or wh <domain> <verb> --help --format json) returns only the spec for that domain or verb, without the aggregate tables.

Individual domain specs can carry a globalFlagOverrides map that modifies how inherited flags behave for that domain. For example, the channel domain carries { repo: { multiple: true } }, which signals that the --repo flag accepts multiple values for that domain. When consuming the JSON spec programmatically, apply any globalFlagOverrides entries on top of the top-level global flag definitions to get the effective flag contract for a given domain — entries in globalFlagOverrides take precedence over the inherited global flag definition for that domain only.

NeedPage
Every domain, verb, flag, and aliasCommand Reference
Build and submit a multi-operation writecommit submit deep dive
Install the CLI as part of first-run setupQuickstart