CLI Reference
The wh CLI is the primary control plane for Wheelhouse — used by human operators and agents alike.
Global flags
Section titled “Global flags”| Flag | Description |
|---|---|
--format json | Output as JSON (all commands) |
--no-color | Strip ANSI colors; Unicode symbols preserved |
--help | Show help (works offline) |
Exit codes
Section titled “Exit codes”| Code | Meaning |
|---|---|
0 | Success |
1 | Error |
2 | Plan change detected (wh topology plan) |
Commands
Section titled “Commands”| Command | Description |
|---|---|
wh topology lint <file> | Validate .wh syntax |
wh topology plan <file> | Preview topology changes |
wh topology apply <file> | Apply a topology |
wh topology destroy <file> | Destroy a topology |
wh ps | List running components (agents + surfaces) |
wh logs <agent> | Stream agent logs |
wh status | Topology health summary |
wh stream create <name> | Create a stream |
wh stream list | List streams |
wh stream delete <name> | Delete a stream |
wh stream tail <name> | Live stream of objects |
wh surface cli --stream <name> | Interactive CLI surface (PUB/SUB to broker) |
wh surface restart <name> | Kill and respawn a surface with its original env |
wh surface stop <name> | Stop a surface without respawning it |
wh secrets init | Initialize credential wizard |
wh memory | Show agent memory (MEMORY.md) |
wh compact | Trigger stream compaction |
wh doctor | Check topology and git health |
wh completion <shell> | Generate shell completion |
Output formats
Section titled “Output formats” NAME STATUS STREAM PROVIDER UPTIME ────────────────────────────────────────────────────────── researcher running main podman 2d 14h summarizer running main podman 2d 14h! watcher stopped alerts podman —
3 agents · 2 running · 1 stopped! prefix + column highlight mark a stopped or degraded agent. Column structure is frozen — builds muscle memory.
With --format json:
{ "components": [ { "name": "researcher", "status": "running", "stream": "main", "provider": "podman", "uptime": "2d 14h" } ], "summary": { "total": 3, "running": 2, "stopped": 1 }}wh topology plan
Section titled “wh topology plan” Changes to apply:
+ agent researcher (new) podman · claude-3-5-sonnet ~ agent summarizer (update) replicas: 1 → 2 ! stream legacy-alerts (destroy)
1 to create · 1 to update · 1 to destroy
Run 'wh topology apply topology.wh' to apply these changes.Prefix legend: + create · ~ update · ! destroy.
With --format json, the response includes has_changes: bool as a top-level field for agent-readable consumption:
{ "has_changes": true, "changes": [ { "op": "create", "kind": "agent", "name": "researcher" }, { "op": "update", "kind": "agent", "name": "summarizer", "diff": { "replicas": [1, 2] } }, { "op": "destroy", "kind": "stream", "name": "legacy-alerts" } ]}wh topology lint errors
Section titled “wh topology lint errors”Lint errors use compiler-style format — file:line: field 'X' — reason:
topology.wh:14: field 'max_replicas' is required — prevents unconstrained autonomous scalingtopology.wh:8: field 'retention' — expected duration string (e.g. "30d"), got integerwh stream tail
Section titled “wh stream tail”Each line: [ISO8601] [TypeName] [publisher] content
[2026-03-12T10:00:01Z] [TextMessage] [donna] Hello — I'm ready.[2026-03-12T10:00:03Z] [SkillInvocation] [researcher] {"skill":"summarize","query":"..."}[2026-03-12T10:00:04Z] [SkillResult] [summarize] {"result":"Summary: ..."}Filter by type with --filter type=<TypeName>:
wh stream tail main --filter type=TextMessageContent is truncated at 120 characters. Use --verbose to disable truncation.
Machine-readable output
Section titled “Machine-readable output”--format json is a first-class output contract, not an afterthought. Every command’s JSON schema is stable — breaking changes require a major version bump.
Designed for agent consumption: wh topology plan --format json gives agents a structured decision context. wh ps --format json gives monitoring pipelines machine-parseable status.
# Check if topology has pending changes (agent use)wh topology plan topology.wh --format json | jq '.has_changes'
# Get running agent nameswh ps --format json | jq '[.components[] | select(.status == "running") | .name]'wh surface cli
Section titled “wh surface cli”Connect to a stream as an interactive terminal surface. Probes broker liveness before connecting; reconnects automatically on transient failures.
wh surface cli --stream mainwh surface cli --stream main --format jsonConnected to stream 'main'. Type a message and press Enter. Ctrl+C to quit.> Hello[donna] Hi! How can I help?With --format json, each incoming message is printed as a JSON object:
{ "publisher": "donna", "type": "TextMessage", "content": "Hi! How can I help?" }Endpoint env vars (defaults match broker defaults):
| Env var | Description |
|---|---|
WH_PUB_ENDPOINT | Override broker PUB socket address |
WH_SUB_ENDPOINT | Override broker SUB socket address |
WH_CONTROL_ENDPOINT | Override broker control socket (used for liveness probe) |
wh surface restart / wh surface stop
Section titled “wh surface restart / wh surface stop”Manage the lifecycle of deployed surface processes without a full wh topology apply cycle.
cd ~/my-agents # must be run from the topology directorywh surface restart telegram # kill + respawn with the same env varswh surface stop telegram # kill without respawningrestart re-reads env vars from the running process (ps eww) so secrets and routing config are preserved automatically. If the surface isn’t running, it starts fresh.
stop kills the process and removes the PID file. Use this before a binary upgrade or to take a surface offline deliberately.
Both commands error if the surface name is not found in the committed topology:
Error: surface 'unknown' not found in deployed topologyShell completion
Section titled “Shell completion”wh completion bash >> ~/.bashrcwh completion zsh >> ~/.zshrcwh completion fish > ~/.config/fish/completions/wh.fish