124 KiB
kind, title, status, topics, domains, applies-when, siblings, prerequisite-reads, last-verified-against-source, last-updated
| kind | title | status | topics | domains | applies-when | siblings | prerequisite-reads | last-verified-against-source | last-updated | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| as-built | OpenRig CLI Reference — Full rig Command Surface | active |
|
|
Need the exact rig CLI surface — command groups, subcommands, flags, JSON output, cross-host, coordination primitives. |
|
|
b13a8e4c7 | 2026-06-20 |
OpenRig CLI Reference
Verified against the shipped CLI on 2026-06-15 (v0.3.4) using:
packages/cli/src/index.tspackages/cli/src/commands/*.tspackages/cli/src/mcp-server.ts- live help from
node packages/cli/dist/index.js ... --help
This document reflects the current rig surface as shipped. Where live help text is narrower than the implementation, notes call that out explicitly.
Terminal dashboard entry
rig tui opens an independent TUI through the same front door as bare rig.
rig tui --shared requires interactive input/output and a loopback daemon
connection. It resolves the kernel's bound operator.human terminal and
attaches a local tmux client without starting a seat or another TUI. Ctrl-b,
then d detaches; reattaching preserves navigation. A missing or ambiguous
binding fails with inspection guidance instead of creating another kernel.
Fresh kernel terminals start rig tui automatically. Older terminals, or a
terminal where the TUI was quit, retain their shell: run rig tui there once.
The kernel view uses TUI instance kernel; standalone uses its ordinary
instance. rig tui commands --json exposes the command registry for agent
control. See the first-use journey.
Daemon shutdown
rig daemon stop sends at most one SIGTERM to a live daemon identified by its
local state.
An explicit OPENRIG_URL that disagrees with that target refuses before signaling.
The daemon has one referenced 10-second budget covering asynchronous service
shutdown, connections and recorder drain; repeated SIGINT/SIGTERM joins that stop.
The CLI allows 12 seconds for process exit, then verifies the original PID and
listener even if daemon.json was removed. A refused listener, a responding
listener and an unavailable probe are different outcomes.
$OPENRIG_HOME/daemon-shutdown.json records the PID, shutdown start/completion,
phase, failures and clean|failed|timed-out outcome. Only successful drains mark
the lifecycle record clean. A failed/timed-out drain returns nonzero, including
after the process exits. For a recorded target, missing or stale receipt evidence
is unverified and also returns nonzero. Failed/unverified stops retain target
state for retries; status reads only clean it after a matching clean receipt.
An already-exited target uses the same receipt judgment without another signal.
With no recorded target and a refused listener, the CLI reports a distinct
no-target no-op, not a clean-drain verdict. Unbound incomplete or unreadable
local shutdown evidence remains nonzero/unverified rather than being attributed
to an unrelated listener.
Older daemons without the receipt can therefore be proven stopped without their
graceful drain being certified. Inspect the receipt and daemon.log;
do not infer that pending external work completed or was rolled back, or retry it
blindly. The bound covers asynchronous waits, not a synchronous event-loop wedge.
Human delivery
rig gateway human list --json discovers registered <entityId>@external
addresses. rig gateway human show <entityId> --json includes primary-connector
readiness, reason and next inspection. Project policy decides when to contact a
human; messaging-the-human supplies the transport mechanics.
Create a human request with rig queue create --destination <address> --summary "<decision>" --body-file <file> --evidence-ref <ref> --verify --json. It persists
one row before checking the delivery receipt. posted proves connector
acceptance, never readership; transport-failed, never-posted, still-pending
and indeterminate preserve the request and name the next inspection. Do not
blindly repeat the create. rig send is for agent seats.
rig slack enable [--reason <reason>] seeds existing backlog only on a disabled
to enabled transition. Repeating enable does not reseed or restart. rig slack disable --reason <reason> requires a shutdown reason. Both return attributed
lifecycle receipts; direct requests can name actor when no managed-session
header exists. Header-derived and claimed identities remain distinct.
Configuration, verification and human-binding edits also record actor, reason,
prior/result state and effect in
$OPENRIG_HOME/state/human-channel-operations.jsonl. Each operation has a start
and a completion receipt with one ID; a missing completion is indeterminate.
Snapshots retain state/digests rather than credentials or message bodies. Local
CLI configuration/verification/binding receipts are explicitly claimed:v1.
rig host pair <url> [--human <address>] selects the sole registered target
human, or requires an explicit selection when several exist. A missing registry
or ambiguous recipient refuses before creating an approval. An unset
workspace.operator_seat_name no longer invents a username-derived kernel
seat: Mission Control discovers a single registered human or shows identity
uncertainty. Explicit existing seat selections remain supported. Legacy aliases
resolve only when their entity is registered; old failed rows are preserved,
not implicitly delivered or replayed by registration.
Overview
System Health diagnosis, policy, checkpoints, and dispositions are documented in Agent-operated System Health diagnosis.
- Binary:
rig - Top-level command groups:
64 - Output mode: human-readable by default; many commands also support
--json - Daemon-backed commands fail when the daemon is stopped or unhealthy;
daemon,config,preflight, anddoctoralso have local responsibilities - Managed apps are launched through the normal spec/library surfaces; the canonical shipped example is
rig up secrets-manager - Legacy surface still shipped:
package
Top-Level Commands
| Command | Description |
|---|---|
daemon |
Manage the OpenRig daemon |
start |
Recovery entrypoint — daemon + kernel + per-rig restore (interactive or headless) |
status |
Show rig status |
snapshot |
Manage rig snapshots |
restore |
Restore a rig from a snapshot |
export |
Export a rig spec as YAML |
import |
Import a rig spec from YAML |
ui |
UI commands |
package |
Manage agent packages (legacy) |
bootstrap |
Bootstrap a rig from a spec file |
requirements |
Check requirements for a rig spec |
discover |
Scan for unmanaged tmux sessions |
attach |
Attach the current shell or agent into a rig node |
bind |
Bind a discovered session to a rig node |
adopt |
Materialize topology and bind discovered live sessions |
reconcile-session |
No-launch, no-input adopt of a hand-resumed session |
bundle |
Manage rig bundles |
up |
Bootstrap a rig from a spec or bundle |
down |
Tear down a rig |
archive |
Archive a rig (soft + reversible: hides it from the default view, retains all data) |
unarchive |
Unarchive a rig (reverse of rig archive): returns it to the default view |
add |
Add a member to an existing pod in a running rig (add_member converge op) |
env |
Inspect and control rig environment services |
file |
Cross-host file movement over ssh/rsync (v0.4.4; one explicit verb: copy) |
ps |
List rigs and their status |
mcp |
MCP server for agent integration |
agent |
Manage agent specs |
spec |
Manage rig specs |
transcript |
Read agent transcript output |
send |
Send a message to an agent's terminal |
capture |
Capture terminal output from agent sessions |
broadcast |
Send a message to multiple agent sessions |
ask |
Query rig evidence from transcript/chat history |
chatroom |
Chat room for rig communication |
specs |
Browse, preview, and manage the spec library |
whoami |
Show current managed identity in an OpenRig topology |
auth |
Manage agent auth profiles per runtime (CLI-local; tokens never printed) |
config |
Inspect and change OpenRig configuration |
preflight |
Check system readiness for OpenRig |
doctor |
Verify OpenRig install health |
destroy |
Destroy OpenRig local state for recovery |
expand |
Add a pod to a running rig |
unclaim |
Release an adopted session without killing tmux |
release |
Release claimed sessions from a rig |
launch |
Launch or relaunch a node in a running rig |
remove |
Remove a node from a running rig |
shrink |
Remove an entire pod from a running rig |
setup |
Prepare the machine for OpenRig |
stream |
Coordination L1 — append-only intake stream |
queue |
Coordination L3 — owned-work queue + inbox/outbox |
project |
Coordination L2 — agent-backed classifier with daemon-enforced lease + idempotency + reclaim |
view |
Coordination L5 — daemon-backed views over coordination state |
watchdog |
Coordination Watchdog — daemon-native scheduler |
workflow |
Daemon-native Workflow Runtime — declarative spec + transactional-scribe step projection |
restore-packet |
Generate, read, and validate cross-runtime restore packets |
restore-check |
Check restore readiness across running rigs |
context |
Browse, preview, compose, and manage operator-authored context packs (never delivers) |
walk |
Walk a seat through a paced sequence of context pieces |
compact-plan |
Plan Claude compact-in-place candidates without compacting anything |
heartbeat |
Show workflow execution proof state from queue files |
seat |
Inspect OpenRig seat observability state |
agent-image |
Browse, snapshot, and manage agent images |
workspace |
Workspace primitive — typed-kind tooling (frontmatter validation) |
plugin |
Inspect plugins (read-only) — list, show, used-by, validate |
scope |
Scope tree primitive — missions, slices, sub-slices |
policy |
Operator context-mode bindings (sleep/desk/mobile/away/focus/debug) |
Core Daemon and System Commands
rig daemon
Usage: rig daemon <subcommand>
Subcommands:
start [--port <port>] [--host <host>] [--db <path>]stopstatuslogs [--follow]
Notes:
startadditively reconciles the canonical instance layout before launching the daemon process, then accepts runtime overrides for port, host, and DB path. Direct daemon first start uses the same initializer. Existing files are preserved and wrong-type managed paths are refused before any write. Seedocs/reference/instance-layout.md.logsreads daemon log output and can follow it.- Deploy identity (v0.4.4, OPR.0.4.4.11 FR-6/7): a PACKAGED build (built via
scripts/build-package.sh) is stamped with{semver, commit, dirty, builtAt}; the daemon's/healthzpayload carries the four stamp fields additively andrig --versionrenders<semver> (<commit8>[, dirty]). A source/dev run has NO stamp and adds NOTHING (never an invented SHA) —/healthzkeeps its legacy body and--versionprints the plain semver. This is the 30-second stale-deploy diagnostic: an unstamped or old-commit/healthzon a long-running host means you are looking at an older deployed build, not the source tree. Source:packages/{daemon,cli}/src/build-info.ts(stampFields),packages/daemon/src/server.ts(/healthz),packages/cli/src/version.ts.
rig status
Usage: rig status
Notes:
- Human-oriented summary command.
- Prints daemon state, rig summary, and cmux availability.
- Does not support
--json.
rig ui
Usage: rig ui open
The OpenRig UI is experimental and in maintenance mode. It is not under active development; support is best-effort. The CLI is the primary supported interface. Contributions welcome.
Subcommands:
open
rig config
Usage:
rig config [--json] [--with-source]rig config get <key> [--show-source]rig config set <key> <value>rig config reset [<key>]rig config init-workspace [--root <path>] [--force] [--dry-run] [--json]
Supported keys:
daemon.portdaemon.hostdb.pathtranscripts.enabledtranscripts.pathworkspace.root(and other workspace-rooted paths used byinit-workspace)context.root(default$OPENRIG_HOME/context; envOPENRIG_CONTEXT_ROOT) — the single writable addressable context library. The removedcontext.packs_root, config fieldcontext.packsRoot, and envOPENRIG_CONTEXT_PACKS_ROOTare refused with replacement guidance.context.system_world(defaultdefault; envOPENRIG_CONTEXT_SYSTEM_WORLD) — selects$OPENRIG_HOME/context/system/system-world.yaml, an explicit replacement manifest path, or the explicitdisabledstate.rig context work-installreports the resolved state and provenance.skills.root(default$OPENRIG_HOME/skills; envOPENRIG_SKILLS_ROOT) — the one authoritative Git-versioned managed skill catalog. An override replaces the default; it does not add an overlay root.snapshots.periodic.enabled(defaulttrue) — daemon-side periodic snapshot scheduler on/off (v0.3.4)snapshots.periodic.interval_seconds(default300) — interval between periodic snapshotssnapshots.periodic.retention_keep(default10) — number of periodic snapshots to retain per rigfeed.subscriptions.{action_required|approvals|shipped|progress|audit_log}(booleans) — the For-You feed's five flat lens toggles (OPENRIG_FEED_SUBSCRIPTIONS_*env mapping)feed.subscriptions.<hostId>.enabled(boolean; v0.4.4, OPR.0.4.4.15) — ONE registered dynamic key CLASS (not a general dynamic-key mechanism): per-host feed subscription toggles for the aggregated multi-host For-You feed.hostIdsegment charset[A-Za-z0-9_-]+(dotted host ids are inexpressible in dotted keys and reject as unknown); the flat toggle tails +enabledare RESERVED segments in both spellings, so a host id can never shadow a flat key. No env-var mapping for the dynamic class in v1 — file/API only. The CLI config store carries the same class (parity-pinned against the daemon store).
Precedence:
- CLI flag
- environment variable
- config file
- default
Notes:
--with-source(top-level) and--show-source(get) report per-key source/default for honest provenance.init-workspaceadditively scaffoldsmissions/,exhaust/,SPEC.md,project.yaml,workspace.yaml, and.gitignoreat~/.openrig/workspace/(or the--rootoverride).--dry-runpreviews without writing.--forceis deprecated compatibility and preserves existing files. New in v0.3.0.snapshots.periodic.*(v0.3.4): the daemon-side scheduler takes periodic snapshots per rig atinterval_secondsand retains the newestretention_keep. At restore time, newest-wins betweenauto-periodicandauto-pre-downsnapshots.
Legacy env compatibility: the original runtime keys still accept deprecated
RIGGED_* aliases. New typed config keys use OPENRIG_* only.
rig auth
Manage agent auth profiles. The command is CLI-local — it never touches the daemon, so a token
value never enters the daemon queue, stream, database, or logs. The runtime is an orthogonal axis via
--runtime (MVP: codex, also the default), modeled on gh auth switch/status and aws --profile /
kubectl config use-context. It is deliberately NOT rig codex-auth and NOT a rig codex vendor-noun
family — the harness is a flag, not a command noun (see conventions/cli-read-command-grammar).
Usage:
rig auth status [--runtime codex]— auth-file presence, file mode, saved-profile count, and login state. No secrets: login state is derived from the runtime CLI's exit code only, never its output.rig auth list [--runtime codex]— saved profile names.rig auth save <profile> [--runtime codex]— snapshot the active auth file into a named profile (a mode-guarded byte copy; contents are never read into or echoed by the command).rig auth switch <profile> [--runtime codex]— activate a saved profile (copy it onto the active auth file at0600).rig auth validate <profile> [--runtime codex]— check a profile's file mode + JSON parseability. This is not a live-auth check; a parse failure reports a fixed reason, never the file content.rig auth seats list|show <seat>|set …|report [--runtime codex]— a per-operator seat → profile metadata registry.
Profile storage:
CODEX_HOME(default$HOME/.codex, env-overridable) holds the activeauth.json, theauth-profiles/directory (profiles0600, directory0700), andauth-seat-registry.tsv.- Ships empty: no example or bundled profiles/registry. Profile names use a strict whitelist
(alnum-led
[A-Za-z0-9._-], ≤64 chars); symlinked or out-of-tree profile paths are refused.
Secret + honesty invariants:
- No token value is ever printed, logged, queued, streamed, or committed.
status/validatereport presence/mode/parseability/login-state only. - Seat-registry labels are metadata, not proof of a live account. A seat labeled with profile "X"
does not prove a running session is actually using that account; the command output states this. The
registry stores no token/resume secret — its columns are
seat / rig / runtime / cwd / auth_profile / updated_ts.
Note: live runtime sessions do not switch accounts in place — restart the affected seats to pick up a newly switched profile.
rig preflight
Usage: rig preflight [--json]
Notes:
- Runs system readiness checks from local configuration.
- On failure, prints what failed, why it matters, and how to fix it.
rig doctor
Usage: rig doctor [--json]
Notes:
- Verifies install health for packaged/local CLI usage.
- Checks daemon dist, UI dist, Node version,
tmux, optionalcmuxcontrol health, writable state paths, and daemon port availability. - On macOS, also warns when tmux mouse mode appears disabled, gives the current-server fix (
tmux set -g mouse on), and points to the persistent fix in~/.tmux.conf. cmuxissues are warnings, not hard failures. OpenRig still works withoutcmux; onlyOpen CMUXworkflows are unavailable.--jsonis suitable for agent use and only exits non-zero on real failures, not warnings.
rig destroy
Usage:
rig destroy --state [--backup] --yes --confirm destroy-openrig-staterig destroy --all [--backup] --yes --confirm destroy-openrig-state
Notes:
- This is the destructive recovery surface for polluted local OpenRig state.
--statestops the daemon, clears the active OpenRig listener on the configured port if needed, rotates or deletes the effective state root, and recreates an empty state root.--allincludes--stateplus managed tmux session cleanup for sessions that are discoverable from the current OpenRig database.--backupmoves the state root aside to a collision-safe timestamped path such as~/.openrig.backup-YYYYMMDD-HHMMSS.- Managed tmux cleanup is intentionally conservative. It only removes sessions that are present in current DB state; unrelated tmux sessions are left alone.
- Human output prints a compact destroy plan followed by the destroy result.
rig start
Usage:
rig start(interactive: daemon + kernel + pick-and-restore)rig start --last [--json](headless: restore rigs that were last running)rig start --all [--json](headless: restore all rigs with restore-usable snapshots)rig start --rigs <name> [<name>...] [--json](headless: restore only the named rigs)
Notes:
- Recovery entrypoint introduced in v0.3.4 (slice 01). Sequencing-only: composes daemon start + kernel auto-boot wait + per-rig restore primitives; re-codes nothing.
- NOT the getting-started boot hero — that remains
rig up <starter>.rig startis for post-reboot/crash recovery. - TTY interactive flow lists last-running candidates with a readiness summary (
[ready to resume],[will ask before fresh],[fresh start],[mixed]), then offers restore-all or a spacebar multi-select picker. - Headless modes (
--last,--all,--rigs) take zero prompts; if a node returnsawaiting-decision, the CLI reports it honestly and prints therig up --existing <rig> --fresh <logicalId>command to take action. - Surface source-verified against
packages/cli/src/commands/start.tsat03a5f915(v0.3.4).
rig mcp
Usage: rig mcp serve [--port <port>]
Subcommands:
serve
Shipped MCP tools:
rig_uprig_downrig_psrig_statusrig_snapshot_createrig_snapshot_listrig_restorerig_discoverrig_bindrig_bundle_inspectrig_agent_validaterig_rig_validaterig_rig_nodesrig_sendrig_capturerig_chatroom_sendrig_chatroom_watch
Rig Lifecycle and Specs
rig bootstrap
Usage: rig bootstrap <spec> [--plan] [--yes] [--json]
Arguments:
spec: path to a rig spec YAML file or a library name
Notes:
- Bare names resolve through the spec library before falling back to the raw source value.
rig requirements
Usage: rig requirements <spec> [--json]
Arguments:
spec: path to a rig spec YAML file
Notes:
rig requirementsis the spec/app-specific dependency surface.- Use
rig doctorfor host-level install health, thenrig requirements <spec>for rig-specific requirements.
rig up
Usage: rig up <source> [--plan] [--yes] [--cwd <path>] [--target <root>] [--existing] [--fresh <seats...>] [--json]
Arguments:
source: path to.yamlor.rigbundle, or a bare name
Actual source resolution:
- Absolute/relative YAML path: boot from that spec
.rigbundlepath: install/bootstrap from that bundle- Bare name without slash/extension:
- first checks the spec library
- if no library match, treats it as an existing rig restore/power-on target
- if both a library spec and existing rig share the same name, exits with an ambiguity error
Current behavior notes:
--cwd <path>overrides launch working directory for all members for this run only. For path-formrig up <install-internal-spec>invocations the CLI defaultscwdto the caller's directory (slice-22 Bug 3) so library specs match path-form behavior.--target <root>is only for bundle/package installation. It does not override agent working directories.--existingskips the library-spec name resolution and treats<source>as an existing rig name directly (disambiguates when a library spec and a stopped rig share the same name).--planpreviews the restore without executing (read-only). The preview honors an honest async timeout and reports per-node intended action.--fresh <seats...>deliberately fresh-primes the named seats (logical ids) instead of resuming their original sessions (operation B); reported in the per-node status vocabulary asfresh-primed. Repeatable:--fresh seat-a --fresh seat-bor--fresh seat-a seat-b.local:agent_refvalues resolve relative to the rig spec directory, not the caller shell cwd.- If you copy a built-in spec to a new directory, keep its
agents/tree beside it or rewrite those refs topath:/absolute/path. - Managed apps are first-class
uptargets.rig up secrets-managerlaunches the shipped Vault example from the library. rig up factory-rsi(OPR.0.4.6.FAC2) launches the single-rig recursive-self-improvement factory MVP starter — seven seats (plan/build/check/review/dogfood/release/orch) that run thefactory-rsibuiltin workflow (inner loop plan→build→check→review→release); the dogfood seat runs out-of-band against the shipped product and feeds its findings back into the next plan. Workspace-agnostic:rig up factory-rsi --cwd <repo>points the loop at the repo to improve.- v0.3.2 paper-cut fix-round (slice-22): pre-launch failures now return structured HTTP 4xx (
cycle_error/preflight_failed/validation_failed/service_boot_failed) instead of bare 500; failed boots no longer leave orphan rig records on disk. - v0.4.4 (OPR.0.4.4.11) — whole-topology sources: a
.rigtopologymanifest (or a YAML file whose body declares the topology form) boots MULTIPLE rigs in one staged spin-up. v0 manifest entries are spec paths only (a closed-key manifest:.rigbundleand bare library-name entries are rejected at parse time with per-entry what/why/fix naming the v0 boundary). Per-entryhost: <id>is the ONLY placement mechanism for topology entries —rig up --host <id> <topology>is REJECTED pre-dispatch (two placement mechanisms must not coexist). The launcher acquires per-rig launch locks route-side and reports a CLOSED per-entry aggregate{ok | failed | skipped}(skipped is explicit — a lock conflict or upstream failure never reads as silent success). Source:packages/cli/src/commands/up.ts(.rigtopologysniff +--hostrejection),packages/daemon/src/domain/topology/{topology-manifest,multi-rig-launcher,remote-up-leaf}.ts,packages/daemon/src/routes/up.ts. - v0.3.4:
rig upis resume-original-by-default for existing rigs. Per-seat opt-in to deliberate fresh-prime is via--fresh <seats...>. The five-term restore status vocabulary surfaced per-node isresumed/fresh-primed/awaiting-decision/attention_required/failed. On TTY,awaiting-decisionnodes trigger an interactive [y/N] ASK; in headless mode they are reported honestly with the exactrig up --existing <rig> --fresh <logicalId>follow-up command.
Success modes:
- fresh boot
- restored existing rig
- partial boot (non-zero exit)
rig down
Usage: rig down <rig> [--delete] [--force] [--snapshot] [--json]
<rig> accepts a rig name or id, symmetric with rig up. A name is
resolved to its id via the active (non-archived) rig summary before teardown.
Flags:
--delete: delete the rig record after teardown--force: kill sessions immediately--snapshot: take a snapshot before teardown
Notes:
- When
--snapshotsucceeds, human output includes the restore command. - If the rig name is uniquely reusable, the handoff prefers
rig up <rigName>. - Destructive-op safety: if a name matches more than one rig,
rig downrefuses to tear down any of them and lists the matching ids - re-run withrig down <id>. An id always resolves directly (ids are never ambiguous).
rig archive
Usage: rig archive <rigId> [--force] [--json]
Flags:
--force: archive even if the rig is running or degraded--json: JSON output for agents
Notes:
- Soft, reversible archive: hides the rig from the default explorer and
rig ps, while retaining the rig record, topology, and snapshots. - Different from
rig down --delete(delete is destructive; archive is recoverable). - Archived rigs are hidden from default
rig ps; userig ps --include-archivedto see them. - Archiving a running or degraded rig requires
--force; without it the call returns HTTP409with a three-part honest error and exits2. - Reverse with
rig unarchive <rigId>. - Emits
rig.archivedSSE event. - Surface source-verified against
packages/cli/src/commands/archive.tsat53794fbe(v0.3.3).
rig unarchive
Usage: rig unarchive <rigId> [--json]
Notes:
- Reverse of
rig archive: clears thearchived_atflag so the rig returns to the default explorer andrig psview. - Always non-destructive (the row and snapshots were retained while archived); no
--forceand no running-rig guard. - Emits
rig.unarchivedSSE event. - Surface source-verified against
packages/cli/src/commands/unarchive.tsat53794fbe(v0.3.3).
rig env
Usage:
rig env status <rig> [--json]rig env logs <rig> [service] [--tail <n>]rig env down <rig> [--volumes]
Notes:
- This surface is only meaningful for service-backed rigs and managed apps.
statusresolves rig names or IDs and returns the env receipt with an honest freshness probe. The response includesprobeStatus(fresh/stale/no_orchestrator) so operators can distinguish current truth from cached state.logsproxies compose-backed service logs;[service]is optional.downtears down the rig environment.--volumesoverrides the stored down policy to force volume removal viadocker compose down --volumes.- Note:
rig psdoes not yet surface env health. Runtime env truth is available throughrig env statusand the rig drawerEnvtab.
rig ps
Usage:
rig ps [--json] [--full] [--rig <name>] [-A | --all-rigs] [--session <sess>] [--limit <n>] [--fields <list>] [--summary] [--filter <key=value>] [--host <id>]rig ps --nodes [--json] [--full] [--rig <name>] [-A | --all-rigs] [--session <sess>] [--limit <n>] [--fields <list>] [--summary] [--filter <key=value>] [--active] [--host <id>]
Notes:
- v0.4.4 — consolidated all-rigs default + disclosure ladder (OPR.0.4.4.21): the default is every ACTIVE rig, one compact row each — O(rigs), never a fleet node fan-out — plus three load-bearing display elements: the host rollup line ("N rigs · M seats · K need attention"), the archived/stopped count line (history folds to ONE line), and the affordance footer teaching the drill ladder. The v0.4.0 current-rig default is RETIRED (it hid running rigs from the operator's field of view); the session-rig default now applies ONLY to
--nodes, and only locally — implicit scope defaults don't cross host boundaries (remote--nodesrequires explicit--rigor-A).-A/--all-rigskeeps exactly ONE meaning: the--nodesfleet widener; bare-Ais a structured teaching error naming--include-archivedfor history. STATED contract: default--jsonis a bare array of ALL non-archived rigs INCLUDING stopped ones (existing keys preserved; additiveattentionCount); only the human table folds stopped rigs. Fan-out (--all-hosts/--hosts) emits the intra-P4 sharedAggregatedPayload(hostId-stampeditems+ closed-enum per-hosthosts[]statuses) and is rollup-only by default; the full explicit ladder (--all-hosts --nodes -A,--fullfor complete records) fans out per-node with hostId-stamped projected rows. Migration from the old firehose:rig ps --nodes -A --full. The default--jsonoutput is a compact TL;DR projection per node:session,rig(to disambiguate under-A),activity(state + reason),assigned/pendingcounts, resume summary asresumeType+resumeTokenPresent(boolean — NOT the token value, per the slice-34 security correction).--fullreturns the complete per-node record (raw byte-equivalent passthrough — preserves the prior shape includingtmuxAttachCommand,resumeCommand,contextUsage,agentActivityfull,restoreOutcome, etc.;resumeTokenvalue is still part of--fullfor downstream consumers that need it). All-states stays the default (per the orch-lead-grounded ruling: ps surfaces topology/readiness, where stopped/recoverable/attention IS the actionable signal — unlike queue-list which defaults to active items only).--active/--runningis the opt-in active-filter (already existed). Closes a ~77,000-token status-glance incident at root + a fleet-scale unbounded-default-output bomb. - Daemon node-list payload trimmed at source (slice 26):
recoveryGuidanceis no longer serialized as near-identical templated prose on every node — relocated to a guidance-by-reference map at the top level so the 4 current consumers still resolve it.contextUsageis a compact summary in the list payload (full telemetry remains retrievable per-node viarig whoami/ detail queries). Even--fulland the UI consumers stop paying for the redundant per-node blobs. rig pslists rig summaries. Default human columns (v0.4.4):RIG,NODES,RUNNING,ACTIVE,WORK,ATTN,STATUS,LIFECYCLE,UPTIME,SNAPSHOT. TheLIFECYCLEcolumn shows the rig-level fold of per-node lifecycle states with codesrun/rec/stp/deg/att;ATTNis the additive attention count.rig ps --nodesexpands into the current (or--rig-named) rig's node inventory —--nodes -Afor the cross-rig inventory (v0.4.4 scoping). Default human columns includeSTATUS,STARTUP,LIFECYCLE,ACTIVITY,RESTORE,ERRORso startup-time and live runtime state can be compared side-by-side without composing a separate diagnostic command.- JSON output for both rig and node tiers includes a
rigNamealias (equal toname) for forward compatibility; agent code should preferrigName. Default--jsonis a bare array (back-compat); the envelope shape{entries, totalRigs|totalNodes, truncated, hint?}is only used when--limit,--fields,--summary, or--filteris set. - Default human output is bounded for context-window safety: rigs truncate at 50 with a footer naming the total +
--fullopt-out, nodes truncate at 100 with the same shape.--fulldisables truncation.--limit <n>sets an explicit bound. --summaryemits aggregate counts only (byStatus,byLifecyclefor rigs;bySessionStatus,byLifecyclefor nodes); useful for quick fleet checks without per-entry detail. Cross-facet disagreement (e.g. arunningrig withattention_requirednodes) is not directly visible in summary mode — narrow with--filter lifecycleState=attention_requiredinstead.--fields <list>projects JSON output to a comma-separated allow-list of top-level fields. Unknown keys are rejected before any HTTP call with an error naming the unknown key(s) and the sorted supported list. Exit code on rejection is1. Accepted (rig-level):rigId,name,rigName,nodeCount,runningCount,activeCount,hasWorkCount,attentionCount,status,lifecycleState,uptime,latestSnapshot. Accepted (node-level, with--nodes):rigId,rigName,logicalId,podId,podNamespace,canonicalSessionName,nodeKind,runtime,sessionStatus,startupStatus,restoreOutcome,oriented,lifecycleState,tmuxAttachCommand,resumeCommand,latestError,terminalActive,hasAssignedWork,pendingWorkCount,agentActivity,contextUsage,heldReason.nameis rig-level only; for node entries userigName(the rejection error includes a hint). Nested fields (e.g.agentActivity.state) are not drilled; pass the whole object name (e.g.agentActivity) and read the nested value downstream.--filter <key=value>acceptsstatus,lifecycleState,name-prefix,name, andagentActivity.state(PL-019; node-level — use with--nodes). Unknown keys are rejected before any HTTP call with a clear error naming the supported list. ForagentActivity.state, allowed values arerunning,needs_input,idle,unknown; invalid values fail fast with a three-part error (what failed / what's allowed / what to do).--active(PL-019; node-level) is sugar for--filter agentActivity.state=running. Combining--activewith--filteris rejected — pick one explicit form. Output is identical to the explicit-filter form on the same fixture.--host <id>routes the same command to a remote host declared in~/.openrig/hosts.yamlvia single-hop ssh (CLI-side shell-out; daemon untouched). Forwards every shaping flag (--nodes,--full,--limit,--fields,--summary,--filter,--json) to the remoterig ps. The remote rig's output is verbatim passthrough on success; failure is distinguished intossh-unreachable/permission-gate/remote-daemon-unreachable/remote-command-failedper the closed cross-host execution contract.- Exit codes:
0success1daemon not running, or invalid--filter/--limit/--fields2daemon fetch failure
rig snapshot
Usage:
rig snapshot <rigId> [--intended-seats <ids>]rig snapshot list <rigId>
Subcommands:
list <rigId>
rig restore
Usage:
rig restore <snapshotId> --rig <rigId>rig restore status <attemptId> --rig <rigId> [--json]
Important:
--rig <rigId>is required by the source code, even though the help text does not visually mark it as required.
Notes:
- Human output prints each restored node and any failed node error.
- Non-zero exit if any restored node fails.
- A started asynchronous restore prints its attempt id.
statusderives the original and current intended-set verdict, snapshot selection, historical exclusions, and unresolved intended seats from that durable attempt.
rig restore-check
Usage: rig restore-check [--rig <name>] [--as <session>] [--full] [--no-queue] [--no-hooks] [--json]
Notes:
- Checks restore readiness across running rigs (or one rig with
--rig/ one seat with--as). - v0.4.0 — summary + not-ready default (slice 29): default output is a summary block (total seats / ready / not-ready / error-degraded counts) PLUS only the not-ready seats listed compactly (seat + readiness reason).
--full(or--json --full) returns today's complete per-seat readiness across the fleet. The daemon skips per-seat detail assembly for ready seats when compact (computes verdict, omits detail). Closes the largest measured token bomb on the read-command surface (~79,000 tokens → low thousands). - The summary default correctly identifies EVERY not-ready seat (no false-ready omission) — the actionable signal is lossless even though detail is dropped for ready seats.
--no-queueskips queue file checks;--no-hooksskips hook checks.- Exit codes:
0restorable (or restorable with caveats),1not restorable (red blockers found),2unknown / probe error.
rig restore-packet
Usage: rig restore-packet <subcommand>
Subcommands:
write [options]— generate a restore packet from a source session or JSONL file.read <packet-dir> [--json]— render a restore packet's contents (human or JSON).validate <packet-dir> [--json]— validate a restore packet against the v0 schema.
Notes:
- Packet shape is the cross-runtime v0 standard (Claude Code and Codex transcripts both supported via runtime parsers + redaction).
writeemits a packet directory with the canonical schema files plusomitted-recordsaccounting.readandvalidateoperate on existing packet directories and do not mutate them.
rig export
Usage: rig export <rigId> [-o|--output <path>]
Default output path:
rig.yaml
rig import
Usage:
rig import <path> [--instantiate] [--materialize-only] [--preflight] [--target-rig <rigId>] [--rig-root <root>]
Notes:
- Accepts YAML rig specs.
--target-rigis additive materialization into an existing rig.--rig-rootis used for pod-aware resolution.
rig bundle
Usage: rig bundle <subcommand>
Subcommands:
create <spec> -o <path> [--name <name>] [--bundle-version <ver>] [--include-packages <refs...>] [--rig-root <root>] [--notes <text>] [--min-daemon-version <ver>] [--min-cli-version <ver>] [--json]— pack a rig spec + its declared content into a.rigbundle. v0.3.2 slice-05 ships first-class cross-primitive bundling: skills + plugins (hybrid) + workflow_specs + context_packs + agent_images vendor end-to-end with both-sides path containment, symlink escape protection, and integrity hashing.inspect <path> [--json]— inspect a.rigbundlemanifest. v0.3.2 surfaces the cross-primitive content fields as first-class.install <path> [--plan] [--yes] [--target <root>] [--skip-version-check] [--force] [--json]— install a.rigbundle. Routes each declared content kind to its canonical library under$OPENRIG_HOME.--skip-version-checkis an operator-explicit override of the install-time daemon/CLI compatibility gate (NOT recommended).--forceis an operator-explicit override of the install-time conflict check (NOT recommended; conflicts may produce partial install state).history [--rig <name>] [--since <iso>] [--json]— list bundle install audit records from~/.openrig/bundle-audit.jsonl. Filters by target rig name and earliestinstalledAt.
Important:
bundle createrequires-o, --output <path>by source definition.- v0.3.2 install timeout bumped (was 5s — too short for tmux-session-bootstrapping installs).
- Deferred to 0.3.3 (per release packet): agent/port/managed-app collision detection (Item 4.3), broader install-into-existing-rig pathway acceptance (Item 4.4), and the
--target-nameCLI flag (slice-05 Item-3 sub-scopes; design-contingent on CLI surface decision).
rig package (legacy)
Usage: rig package <subcommand>
Subcommands:
validate <path>plan <path> [--target <dir>] [--runtime <runtime>] [--role <name>]install <path> [--target <dir>] [--runtime <runtime>] [--role <name>] [--allow-merge]rollback <installId>list
Notes:
- The package surface is explicitly marked legacy in the shipped CLI.
rig spec
Usage: rig spec <subcommand>
Subcommands:
validate <path> [--json]preflight <path> [--rig-root <root>] [--json]
rig agent
Usage: rig agent validate <path> [--json]
Subcommands:
validate <path>
rig specs
Usage: rig specs <subcommand>
Subcommands:
ls [--kind <kind>] [--json]show <name-or-id> [--json]preview <name-or-id> [--json]add <path> [--json]sync [--json]remove <name-or-id> [--json]rename <name-or-id> <new-name> [--json]
Notes:
specsis the library surface for rigs, agents, and managed apps.previewreturns structured review data from the daemon.addaccepts either a YAML spec file or a full spec directory containingrig.yamloragent.yaml.- Directory adds copy the whole tree into the user library so adjacent agents, guidance, skills, and docs remain available.
preview secrets-manageris the canonical managed-app review example.
Discovery and Topology Mutation
rig discover
Usage: rig discover [--json] [--draft]
Notes:
- Scans unmanaged tmux sessions.
--draftgenerates a candidate rig spec from the discovery set.
rig attach
Usage:
rig attach --self --rig <rigId> --node <logicalId> [--cwd <path>] [--display-name <name>] [--print-env] [--json]rig attach --self --rig <rigId> --pod <namespace> --member <name> --runtime <runtime> [--cwd <path>] [--display-name <name>] [--print-env] [--json]
Notes:
--selfis currently required.- Node attach and pod-create attach are exclusive modes.
- In tmux-backed shells, the command records tmux attachment metadata; otherwise it records an
external_cliattachment. --print-envprints shell exports forOPENRIG_NODE_IDandOPENRIG_SESSION_NAME.
rig bind
Usage: rig bind <discoveredId> --rig <rigId> (--node <logicalId> | --pod <namespace> --member <name>)
Important:
--rig <rigId>is required.- Binding mode is exclusive:
- existing node:
--node <logicalId> - create new node:
--pod <namespace> --member <name>
- existing node:
rig adopt
Usage:
rig adopt <path> --bind <logicalId=tmuxSessionOrDiscoveryId> [--bind ...] [--target-rig <rigId>] [--rig-root <root>] [--json]
Important:
--bindis required and repeatable.- The input file must be a pod-aware RigSpec with
pods.
Notes:
- Materializes the topology first, then resolves/binds discovered sessions.
- In JSON mode, emits the materialized nodes plus binding results.
rig reconcile-session
Usage:
rig reconcile-session <session> [--rig <rigId>] [--node <logicalId>] [--no-launch] [--json]
Arguments:
session: canonical session name (e.g.dev-impl@my-rig) of the LIVE session to adopt.
Flags:
--rigand--nodeare paired disambiguators (both required together) when the session resolves ambiguously.--no-launchis the only mode this command has; accepted for explicitness.
Notes:
- No-launch, no-input adopt of a hand-resumed canonical session (slice 03 / v0.3.4). The operator already resumed the session externally (e.g.
claude --resume,codex resume) inside its canonical tmux session; the daemon still shows the seat down. - Binds the live process to its OWN persisted node (same node id, no re-key) and updates the projection so
rig ps/ topology / send / capture / queue routing work again. - NEVER launches, relaunches, kills, replays startup, presses resume menus, compacts, or types into the pane.
- Anything that could not be proven is reported as projection drift; conversation continuity is never claimed.
- Surface source-verified against
packages/cli/src/commands/reconcile-session.tsat03a5f915(v0.3.4).
rig expand
Usage: rig expand <rig-id> <pod-fragment-path> [--json] [--rig-root <path>]
Notes:
- Adds a pod fragment to a running rig.
--rig-rootcontrols agent resolution.- Member YAML may carry
session_source(see "Session source declaration" below) to start the new seat from a prior native conversation (mode: fork) or from operator-declared artifacts (mode: rebuild).
rig add
Usage: rig add <rig-id> <pod-namespace> <member-fragment-path> [--json] [--rig-root <path>]
Arguments:
<rig-id>: id of the target rig<pod-namespace>: namespace of the existing pod to add the member to<member-fragment-path>: path to a YAML/JSON member-fragment file (spec snake_case fields)
Notes:
- The
add_memberconverge op verb: adds a member to an existing pod in a running rig from a YAML/JSON member-fragment file. - Member fragment accepts both the bare form (top-level member fields) and the wrapper form (
{ member: {...}, edges?: [...] }). A top-leveledges:field in the bare form is lifted as pod-local edges and is NOT silently dropped. - OPR.0.4.6.FAC1: the fragment accepts an optional
role: <name>(charsetA-Za-z0-9_.-; rejected onruntime: terminal). A role-declared seat becomes eligible for workflow role→seat capability resolution on this rig — scale-out = add a member under the role (this verb IS the growth path). Role is opt-in per seat: a role-less member stays reachable only via explicitpreferred_targets; a PROVIDED role is validated, never silently dropped. - A present-but-non-array
edgesfield is rejected with an honest error (no silent drop). --rig-root <path>controls agent resolution.- HTTP outcomes:
201on success (with the new node + persisted edges + optional warnings);409 member_conflict;400 validation_failed/preflight_failed;404 pod_not_found(lists existing pods). - Exit code is non-zero if the HTTP call failed OR the new node did not fully launch (
status !== "launched"). - Surface source-verified against
packages/cli/src/commands/add.tsat53794fbe(v0.3.3).
Session source declaration (session_source)
Member YAML in a rig spec or rig expand payload may declare a launch-time session_source to control how the new managed seat derives its starting context. Two modes are supported in v1:
# Fork from a prior native runtime conversation. Captures and persists a NEW
# post-fork token; the parent token is NEVER persisted onto the new seat.
members:
- id: reviewer-2
runtime: claude-code # or "codex"; not valid on terminal
session_source:
mode: fork
ref:
kind: native_id # v1 fork mode supports "native_id" only
value: "0b0165d7-cb4d-4650-90de-15c0a1ede9e6"
# Rebuild from operator-declared artifacts (CULTURE, role doc, handover packet,
# queue files, session logs). Fresh-launches the harness and seeds the running
# TUI with the artifacts in the operator-declared trust-precedence order.
# The seat's continuityOutcome is `rebuilt` (NEVER `fresh`/`resumed`/`forked`)
# and NO `resumeToken` is persisted.
members:
- id: writer-2
runtime: claude-code # or "codex"; not valid on terminal
session_source:
mode: rebuild
ref:
kind: artifact_set # v1 rebuild mode supports "artifact_set" only
value: # ordered list, highest-trust first
- <substrate-shared-docs>/rigs/<rig>/CULTURE.md
- <substrate-shared-docs>/specs/agents/<role>.md
- /path/to/handover-packet.md
- /path/to/state/<pod>/<member>.queue.md
- /path/to/state/<pod>/shared.session.log
- /path/to/state/<pod>/<member>.session.log
Notes:
terminalruntime rejectssession_source(no native fork primitive; no agent context to rebuild).mode: forkrequiresref.kind: native_idand a non-emptyref.valuestring. Other ref kinds (artifact_path,name,last) are reserved shapes for follow-up slices and are refused in v1 fork mode.mode: rebuildrequiresref.kind: artifact_setand a non-emptyref.valuearray of paths. Missing paths are recorded as gaps and the launch proceeds with what resolved; if NO declared paths resolve, the launch fails with a clear error.- The two modes are mutually exclusive on a given member; mixing is a schema error.
rig unclaim
Usage: rig unclaim <sessionRef> [--json]
Notes:
- Releases an adopted session without killing its tmux session.
rig release
Usage: rig release <rigId> [--delete] [--json]
Notes:
- Releases all claimed/adopted sessions from a rig without killing their tmux sessions.
--deleteremoves the rig record after a clean release.- OpenRig-launched nodes still require
rig down.
rig launch
Usage: rig launch <rigId> [nodeRef] [--seats <ids>] [--hold-reason <reason>] [--snapshot-id <id>] [--plan] [--json]
Notes:
- Launches or relaunches a node in a running rig.
nodeRef(optional) can be a logical ID or node ID for the single-target form.--seats <ids>(v0.3.4, slice 11) takes a comma-separated list of logical IDs for node-granular managed partial restore — launch a named subset of seats while holding the rest. Retires the priorpod_aware_launch_unsupporteddead-end.--hold-reason <reason>records the reason non-target seats are being held; surfaced via observability so the held state is auditable.--snapshot-id <id>selects one exact restore-usable snapshot instead of applying the automatic choice.--planpreviews a multi-seat subset and its non-target effects without mutation.
rig remove
Usage: rig remove <rigId> <nodeRef> [--json]
Notes:
- Removes a single node from a running rig.
rig shrink
Usage: rig shrink <rigId> <podRef> [--json]
Notes:
- Removes an entire pod from a running rig.
podRefcan be a pod namespace or pod ID.
Identity, Communication, and Context
rig whoami
Usage: rig whoami [--node-id <id>] [--session <name>] [--host <id>] [--full | --verbose] [--json]
Identity resolution order:
--node-id--sessionOPENRIG_NODE_ID/RIGGED_NODE_IDOPENRIG_SESSION_NAME/RIGGED_SESSION_NAME- tmux pane metadata
@rigged_node_id - tmux pane metadata
@rigged_session_name - raw tmux session name
Notes:
- v0.4.0 — compact-by-default (slice 27):
rig whoamiandrig whoami --jsondefault to identity-recovery essentials only —identity(rig / pod / member / sessionName / runtime / cwd / logicalId / ids),peers(names only: logicalId + sessionName per peer),edges(directionalkind+to.sessionName),transcriptPath. Daemon skips thecontextUsageStorelookup andruntimeContextbuild when compact is requested (also saves daemon work). The first command every agent runs on boot + every compaction-restore now costs ~192 tokens instead of ~909. --full(alias--verbose) returns today's complete payload includingcontextUsage,commands,peersNote,runtimeContext— byte / shape parity with the v0.3.4 default (back-compat for any consumer that reads those fields).- The compact-default is an ALLOWLIST projection (not a denylist) — future payload fields default to
--fulland cannot silently re-bloat the every-boot path. - If the daemon is unreachable but an identity source can still be resolved,
--jsonreturns a partial result instead of crashing. - Human-readable output (compact default) shows identity + peers + edges + transcript path.
--fulladds context usage block, commands list, peersNote prose, runtimeContext. peers[]is this rig's roster excluding self (no edge filter); useedges{}for directional relationships andrig ps --nodesfor node inventory including self + live state.- In Claude Code projects, unattended
rig whoamion boot may require the local permissions allow list to includeBash(rig:*). --host <id>routes the same command to a remote host declared in~/.openrig/hosts.yamlvia single-hop ssh (CLI-side shell-out; daemon untouched). Identity resolution happens on the REMOTE rig (each host has its own daemon + tmux + identity context); local--node-id/--session/--fullflags are forwarded to the remoterig whoamiinvocation. The remote rig's output is verbatim passthrough on success; failure is distinguished into the samessh-unreachable/permission-gate/remote-daemon-unreachable/remote-command-failedenum asrig ps --hostandrig send --host.
rig transcript
Usage: rig transcript <session> [--tail <lines>] [--grep <pattern>] [--host <id>] [--json]
Defaults:
--tail 50
Notes:
- Reads transcript files, not pane scrollback.
--greptreats the pattern as regex.- v0.4.6 (OPR.0.4.6.MH4) —
--host <id>/ theagent@rig@hostsession form reads the transcript from a remote host, CLI-direct against that daemon's shippedGET /api/transcripts/:session/tail|greproutes (http-registered hosts only — an ssh-declared host is a structured transport-requirement error; there is no ssh path for this verb). Output shape is the origin's, verbatim, under the[via host=…]banner. Precedence: explicit--host> target sugar > the persisted host selection. See "Cross-host execution".
rig send
Usage: rig send <session> [<text>] [--context <ref>] [--verify] [--force] [--raw] [--dangerously-interact --reason <text>] [--wait-for-idle <s>] [--from <session>] [--host <id>] [--json]
Notes:
- Uses the two-step send pattern automatically: paste text, wait, submit Enter.
--verifyrequests delivery verification.- The default path refuses to send ONLY on positive evidence that the target is at an interactive prompt / permission block. This closes the footgun where a peer message blindly submits another agent's open prompt. When the target's activity cannot be determined (unknown, missing, or stale telemetry), the send PROCEEDS with an advisory note — telemetry is advisory, not authority over whether agents can communicate. Use
--wait-for-idleto send only after explicit idle evidence. - A mid-task/busy target sends-with-advisory by default (busy is not a block).
--forceis a back-compat no-op and never bypasses the interactive-prompt/permission guard. --rawsends exact text/keystrokes without the From/To messaging envelope; still guarded against interactive prompts.--context <ref>resolves one path-like context ref and delivers its whole content on a local single-seat send. Missing members abort before delivery; oversized content emits arig walkadvisory. It is not supported with--host, cross-host target sugar, or fan-out targeting.--dangerously-interactis the ONLY override of the prompt/permission guard — it deliberately drives an interactive prompt/permission block (e.g. selects an option). It implies--raw, requires--reason <text>, and is recorded in the audit log. Cannot be combined with--wait-for-idle.--reason <text>records why the prompt is being driven (required with--dangerously-interact).--host <id>sends on a remote host declared in~/.openrig/hosts.yaml; see "Cross-host execution" below. v0.4.6 (OPR.0.4.6.MH4) — the host entry's transport decides the path: ssh hosts keep the single-hop ssh shell-out byte-verbatim (SSH success is NOT verify success — the remote rig'sVerified: yes/nois what counts and is surfaced verbatim); http hosts (e.g. pair-registered) go CLI-direct to the remote daemon'sPOST /api/transport/sendwith the same body a local send posts (wrap parity by construction) —--verifyprints the REMOTE route'sverified/outcomeverbatim, never a locally synthesized verdict. Theagent@rig@hosttarget form is sugar for--hostwhen the suffix is a REGISTERED host id (explicit--host> sugar > persisted selection; a conflict between--hostand the sugar is a structured error).
rig capture
Usage:
rig capture <session> [--lines <n>] [--host <id>] [--json]rig capture --rig <name> [--lines <n>] [--host <id>] [--json]rig capture --pod <name> --rig <name> [--lines <n>] [--host <id>] [--json]
Default:
--lines 20
Notes:
--host <id>captures on a remote host declared in~/.openrig/hosts.yaml; see "Cross-host execution" below. v0.4.6 (OPR.0.4.6.MH4) — ssh hosts keep the shell-out verbatim; http hosts go CLI-direct to the remote daemon'sPOST /api/transport/capturewith the local body shape (lines/rig/pod/session), rendering single/multi results exactly as a local capture under the[via host=…]banner. Theagent@rig@hostsession form is sugar for--hostwhen the suffix is a REGISTERED host id (--rig/--podvalues are names, never sugar-parsed).
rig walk
Usage: rig walk <seat> --through <ref | files...> [--pace <duration>] [--json]
Notes:
--throughaccepts either one path-like context ref or an ordered list of existing local files; mixing the two forms is rejected.- Sends one piece at a time through the normal transport and waits
--pacebetween pieces (default10s; duration overrides require an explicitmsorssuffix). The same explicit-unit grammar applies to--consume-timeout,--consume-poll, and--turn-timeout; bare numbers are refused. There is no trailing delay. - A missing local file or missing/unreadable ref member aborts before the first send, so a walk delivers every piece or none.
- Where a generation record resolves, each piece must appear as a complete user message in the newly appended record and its corresponding native turn must close before the next piece. Only CRLF line endings and surrounding whitespace are normalized; internal whitespace, missing middles, shared prefixes, and tails do not qualify.
- Claude closure follows the message's UUID ancestry through an assistant response to
turn_duration. Codex uses aresponse_itemuser message within a namedtask_started/task_completeturn; queued input or a different turn's completion is insufficient. These receipts prove delivery and turn completion, not semantic comprehension. - Codex generation lookup joins the bound process's post-start log thread IDs to retained native CLI conversations. Auxiliary title threads cannot replace that identity; zero or multiple matching conversations remain unverified instead of being selected by recency.
- Codex records resolve through the verified current pane/process and native thread table, including before token telemetry exists. The rollout header must identify that thread. Missing or ambiguous identity is reported as unverified. A generation/file replacement or unreadable record during a verified walk aborts it; it never silently continues into a replacement occupant.
--jsonreportsconsumptionVerified. If the initial generation-record probe is unavailable, legacy delivery remains possible with an explicit unverified advisory andconsumptionVerified: false.
Cross-host execution (--host <id>)
Cross-host commands route to a remote host declared by id. SSH-transport
commands use single-hop SSH CLI-side shell-out; HTTP-transport commands talk to
the remote daemon API. The local daemon is not involved in SSH routing. The
remote host is expected to have its own managed rig available on $PATH.
Hosts are declared by the operator in ~/.openrig/hosts.yaml:
hosts:
- id: vm-claude-test
transport: ssh
target: vm-claude-test.local
user: your-username # optional
notes: "test VM" # optional
- id: factory-http
transport: http
url: http://100.64.1.2:7433
bearer_env: FACTORY_HTTP_TOKEN
Validation rules:
hostsis required and must be a non-null array.- Each entry:
idrequired (non-empty, unique),transportrequired (sshorhttp). - SSH entries require
target(non-empty — DNS name, SSH config alias, or IP);userandnotesare optional. - HTTP entries require
url; a bearer pointer (bearer_envorbearer_file) is OPTIONAL — omit both for an anonymous/tokenless daemon (noAuthorizationheader is sent; host+VM are one founder-owned trust domain and the mesh is the auth boundary). At most one bearer pointer may be set, never both. Pointers are config names/paths, never resolved token values; a configured-but-unresolvable pointer is a permission failure before any request. rig host add/list/doctorcovers the standard path; hand-editing remains the path for exotica.- A missing or invalid file returns a clear error pointing at the canonical path.
The CLI distinguishes four structured failure modes (operators get an
actionable error per mode; JSON output preserves the failedStep enum):
ssh-unreachable— SSH itself failed (connection refused, host key mismatch, etc.). Verify SSH access and the registry entry.permission-gate— SSH hit an auth/permission gate (Permission denied, Keychain). The error includes a hint to the keychain-over-SSH field note.remote-daemon-unreachable— SSH succeeded but the remoterigreported the remote daemon was not reachable. Start it withssh <target> rig daemon start.remote-command-failed— SSH succeeded but the remoterigexited non-zero for some other reason; the remote stderr is surfaced.
The transport posture (OPR.0.4.4.13 FR-4 — DECIDED, pm-ruled: document, no parity). The
partition is the intended posture, not an accident of history: ssh carries interactive pane
ops, http carries daemon REST ops, ps/whoami follow the host's DECLARED transport.
There is NO cross-transport fallback, and NO http parity for send/capture ships in 0.4.4
(parity would be new attack surface with no scope-locked need). v0.4.6 UPDATE (OPR.0.4.6.MH4,
pm-RULED IN as fulfilling-confirmed-intent): send/capture gain the http branch — the
founder's pair front door registers HTTP hosts, and without the branch a pair-registered demo
host could not receive send/capture at all. The mechanism is CLI-DIRECT via the shipped
runRemoteHttpOp to the remote daemon's EXISTING transport routes (zero daemon-side changes;
the ssh path is kept byte-verbatim for ssh hosts — coverage, not a rewrite, and still no
cross-transport fallback: the host entry's declared transport dictates the path). transcript
and broadcast gain their first cross-host affordance the same way (http-only — there is no
ssh path for them). Per-command:
| Command | ssh transport | http transport | Fan-out (--all-hosts/--hosts) |
|---|---|---|---|
rig send |
✓ (shell-out, byte-verbatim) | ✓ (v0.4.6 MH-4 — CLI-direct POST /api/transport/send) |
✗ |
rig capture |
✓ (shell-out, byte-verbatim) | ✓ (v0.4.6 MH-4 — CLI-direct POST /api/transport/capture) |
✗ |
rig transcript --host (v0.4.6, OPR.0.4.6.MH4) |
✗ (structured transport error) | ✓ (CLI-direct GET /api/transcripts/:session/tail|grep) |
✗ |
rig broadcast --host (v0.4.6, OPR.0.4.6.MH4) |
✗ (structured transport error) | ✓ (CLI-direct POST /api/transport/broadcast; remote fan-out, per-target passthrough) |
✗ |
rig up / rig down / rig launch |
✗ | ✓ (http-ONLY) | ✗ |
rig file copy (v0.4.4) |
✓ (ssh-ONLY, rsync-over-ssh) | ✗ | ✗ |
rig ps --host |
✓ (declared) | ✓ (declared) | http-only; non-http hosts appear as STRUCTURED unsupported-transport statuses in hosts[] |
rig whoami --host |
✓ (declared) | ✓ (declared) | http-only; non-http hosts are currently SILENTLY FILTERED from the fan-out (a shipped gap, routed for 0.4.5 triage — differs from ps's structured status) |
rig host doctor |
✓ | ✓ | n/a (single host) |
rig queue create/handoff/handoff-and-complete --host (v0.4.6, OPR.0.4.6.MH3) |
✗ | ✓ (http-ONLY, daemon→daemon forward — an ssh-declared host is a structured unsupported-transport error) |
✗ |
Out of scope in 0.4.4: cross-transport fallback; http parity for send/capture (shipped in
0.4.6 — OPR.0.4.6.MH4, pm-ruled fulfilling-confirmed-intent; see the v0.4.6 update above);
connection pooling; multi-hop SSH; cross-host queue routing (shipped in 0.4.6 — OPR.0.4.6.MH3;
see rig queue § Cross-host queue routing); cross-host seat handover.
The http branch's failure taxonomy (v0.4.6 — OPR.0.4.6.MH4). The http branch names its OWN
steps (never the ssh enum, never a generic "failed"): registry-load-failed / unknown-host (the
same class across all four verbs) / permission-gate (bearer resolution failed locally, or the
remote returned 401/403 — including the terminal-bearer posture below) / remote-daemon-unreachable
(network/timeout) / remote-command-failed (remote 4xx/5xx, with the remote route's own error
text surfaced beside the step). Terminal-bearer posture (named, v0 — applies to
/api/transport/* ONLY, i.e. send/capture/broadcast): the remote's transport routes gate on
ITS terminal bearer class, while the CLI presents the host's REGISTRY bearer when one is
configured; for a URL-only anonymous host the Authorization header is omitted. Default (no
terminal bearer) + tailnet binds = pass-through by design (the mesh is the auth boundary); a
remote enforcing a DIFFERENT terminal bearer surfaces as the structured permission-gate step —
remedy: set the remote's terminal bearer equal to the paired registry bearer, or rely on the
tailnet boundary. rig transcript --host is NOT in this class (arch n2): the remote's
/api/transcripts/* routes are the shipped UNGATED transcript-read posture (open route,
daemon-local trust boundary, route-level credential redaction as the protective primitive) — a
wrong terminal bearer that permission-gates a cross-host send does NOT gate a cross-host
transcript read; transcript keeps succeeding. A coherent transcript-read auth policy across
tail/grep/full is a named future slice per the route's own comment
(routes/transcripts.ts, orch decision approved-option-a), out of scope here. No new auth
machinery ships with this slice.
Destination parse rules — the two-family contract (OPR.0.4.6.MH3, arch-ruled). The
agent@rig@host three-part form is INPUT SUGAR at the CLI edge, never grammar: session strings
stay member@rig everywhere (BR-1), and the host always travels out-of-band. TWO parse rules
ship, per verb family, BY DESIGN — one canonical rule would either break adopted targets or
degrade queue error honesty:
| Verb family | 3-part trailing segment | Why |
|---|---|---|
Queue coordination writes (rig queue create/handoff/handoff-and-complete) |
Always stripped into the out-of-band hostId envelope (after the human-seat classifier) |
Queue destinations are canonical-only by construction (the daemon's validateRig rejects any non-canonical parse), so the unconditional strip loses nothing — and a mistyped host dies loud as an unknown-HOST error instead of a misleading rig-shaped unknown_destination_rig. |
Session-target interactive/observe verbs (rig send/capture/transcript) |
Stripped only if the segment matches a REGISTERED host id | Interactive verbs legitimately target raw/adopted tmux session names that may contain @; strip-iff-registered preserves them, with the unregistered-suffix host hint keeping mistypes loud. |
rig broadcast |
No sugar — the positional is MESSAGE TEXT, never parsed as a target | Sugar-parsing a message body would corrupt text containing @; cross-host broadcast routes on --host or the persisted selection only (v0.4.6 — OPR.0.4.6.MH4). |
Both families converge on the same outcome: a mistyped host dies loud with the host named. The
RESERVED_HOST_IDS set (kernel, host, local — rejected at rig host add) guarantees no
registered host can ever shadow the human-seat @kernel/@host classification family.
rig file (v0.4.4 — OPR.0.4.4.18)
Usage: rig file copy <src> <dst> [--dry-run] [--json]
Cross-host file movement over ssh/rsync — v0 ships ONE explicit verb, copy,
for a single file.
Operand grammar (parsed, never guessed):
<hostId>:<absolute-path>= remote (the<hostId>must resolve in the ssh hosts registry; remote paths must be absolute).- Bare path = local. A LOCAL file whose name contains a colon needs the
./prefix (./weird:name.txt) — the grammar refuses the ambiguous form with a structured error instead of guessing. - Valid shapes: local→remote, remote→local, local→local. remote→remote is not a v0 shape.
Semantics + safety wall (source: packages/cli/src/lib/file-transfer.ts):
- An existing destination is OVERWRITTEN (v0 copy semantics, stated) —
preview with
--dry-run, which prints the exact planned transfer (src, dst, host, files/bytes) and moves nothing. - Default-deny wall over live agent/credential state: paths resolving into
the closed deny set
~/.openrig,~/.ssh,~/.codex,~/.claude— plus the ACTIVEOPENRIG_HOMEand the active hosts registry file — are refused with a named what/why error (extension of the deny set requires a ruling, never a silent widening). - Traversal is rejected on the RAW operand: a
..path segment refuses BEFORE any normalization (normalization collapses.., so a post-normalize check would be dead code); remote paths are additionally restricted to a shell-inert charset (A-Za-z0-9._/-— restriction over escaping, because both rsync implementations in the fleet differ on quoting flags), and every rsync invocation pins operands behind--and spawns argv-style with no shell. - Transport is ssh-only (see the transport-posture table above); the remote
side uses the same ssh registry entries
rig send/captureuse.
rig host
Usage: rig host <add|list|doctor> — the multi-host registry verbs (OPR.0.4.4.13; capped at
exactly these three — no edit/remove/tunnel/bootstrap verbs; hand-editing hosts.yaml remains
the path for exotica, and the factory bootstrap ships as
scripts/bootstrap-product-factory-vps.sh).
add --id <id> --transport <ssh|http> [--target <t> --user <u> | --url <u> [--bearer-env <n>|--bearer-file <p>]] [--notes <text>] [--json]— writes the entry validated by the registry loader's OWN rules (add-time errors are load-time errors, verbatim; duplicate ids refused; the http bearer pointer is optional — omit both for a tokenless daemon, never both). Rewriteshosts.yamlcanonically (hand-authored comments are not preserved).list [--json]— id/transport/target plus AUTH as a config POINTER (env:NAME/file:PATH/ssh-key); never a resolved secret value.doctor <id> [--posture product-factory-vps] [--public-addr <ip>] [--json]— stepwise, honest verification: transport reachability → remoterigbinary (+version) → remote daemon health → remote identity; each failing step is a DISTINCT actionable error, and unknown host ids surface as the registry error class.--postureruns the ONE built-in baseline (product-factory-vps): every item reports pass/fail/unknown individually with a fix per non-pass — UNKNOWN is never pass; the public:7433/:22probes need--public-addr(outside vantage) and a reachable public daemon port FAILS loudly. Exit1on any fail.
rig broadcast
Usage: rig broadcast [<text>] [--context <ref>] [--rig <name>] [--pod <name>] [--force] [--host <id>] [--json]
Notes:
- Without
--rigor--pod, broadcasts across all running sessions in all rigs. --context <ref>resolves one path-like context ref and fans out its whole content. Missing members abort before fan-out; oversized content emits arig walkadvisory. It is not supported with--host.- v0.4.6 (OPR.0.4.6.MH4) —
--host <id>broadcasts on a remote host, CLI-direct to that daemon's shippedPOST /api/transport/broadcast(http-registered hosts only; an ssh-declared host is a structured transport-requirement error). The REMOTE daemon resolves--rig/--podon ITS topology; its per-target results print verbatim and a partial fan-out exits non-zero exactly as a local one. The remote call carries its own named fan-out deadline (BROADCAST_REMOTE_TIMEOUT_MS, 30s — a full per-target loop outlives the 5s read default). The<text>positional is message text and is NEVER parsed as a target, so broadcast takes--hostor the persisted host selection — not theagent@rig@hostsugar.
rig ask
Usage: rig ask <rig> <question> [--json]
Current implementation:
- Queries
/api/ask - Returns:
- the original question
- a rig summary (
name,status,nodeCount,runningCount,uptime) - evidence excerpts from transcripts
- optional chat excerpts
insufficientflag- optional guidance text
Important:
- The live help description says “Search rig transcript history with a natural language question,” but the shipped behavior is broader than plain transcript grep and narrower than a topology/lifecycle synthesis layer.
- This command is a daemon-backed evidence query, not a second LLM invocation.
rig chatroom
Usage: rig chatroom <subcommand>
Subcommands:
send <rig> <message> [--sender <name>]history <rig> [--topic <name>] [--after <id>] [--since <ts>] [--sender <name>] [--limit <n>] [--json]wait <rig> [--after <id>] [--topic <name>] [--sender <name>] [--timeout <seconds>] [--json]clear <rig>topic <rig> <topic-name> [--body <text>] [--sender <name>]watch <rig> [--tmux]
Notes:
- All chatroom subcommands take the rig name as a positional argument.
historyfilters are composable:--sender,--since,--after,--topiccan be combined.waitblocks until new matching messages arrive or times out (exit 1). Same filter semantics ashistory.clearis destructive and rig-scoped. Removes all messages for that rig.watch --tmuxstarts a dedicated tmux watcher session.
Coordination Primitive (PL-004 Phase A)
Two top-level commands back the SQLite-canonical coordination layer. They speak only to the daemon HTTP API; they do NOT touch the POC rigx-stream-proto / rigx-queue-proto filesystem state. POC and daemon coexist at OPERATOR level only.
rig stream
Usage: rig stream <subcommand> — L1 append-only intake stream.
Subcommands:
emit --source <session> --body <text> [--format <fmt>] [--hint-destination <session>] [--hint-type <type>] [--hint-urgency <urgency>] [--hint-tags <csv>] [--interrupt] [--id <streamItemId>] [--json]list [--source <session>] [--hint-destination <session>] [--tag <tag>] [--since <iso>] [--until <iso>] [--limit <n>] [--after <sortKey>] [--include-archived] [--json]watch [--json]show <streamItemId> [--json]archive <streamItemId> [--json]
Notes:
--idis for idempotency; same id returns the same row, body of subsequent calls is ignored.--tagis exact membership inhint_tags, not substring matching.--sinceand--untilare inclusive ISO timestamp bounds normalized to UTC by the daemon; list order and cursor semantics remain chronological.watchconsumes the existing/api/stream/ssecontract: the daemon's initial replay followed by live items. Human output shows timestamp, source, and body;--jsonemits oneStreamItemobject per line. It makes one connection and does not reconnect automatically.archiveis soft — the row remains for audit and is excluded fromlistunless--include-archivedis passed.
rig queue
Usage: rig queue <subcommand> — L3 owned-work queue plus inbox/outbox.
Subcommands:
create --source <session> --destination <session> (--body <text> | --body-file <path> | --body-context <ref>) [--mission <id>] [--slice <id>] [--priority <p>] [--tier <t>] [--tags <csv>] [--target-repo <name>] [--host <id>] [--no-nudge] [--expires-at <iso>] [--id <qitemId>] [--json]—--body-context <ref>resolves a complete context pack, snapshots that content into the qitem body, and adds abody-context:<ref>provenance tag; it is mutually exclusive with--body/--body-file, and missing members abort before qitem creation. v0.3.2 slice-21 FR-4 adds--body-file <path>(use-for stdin) which kills the backtick-shell-corruption class for multiline bodies, and first-class--mission <id>/--slice <id>flags that translate tomission:<id>/slice:<id>tags (compose with--tags). v0.4.6 (OPR.0.4.6.MH3) adds--host <id>/ theagent@rig@hostdestination form — see § Cross-host queue routing below.claim <qitemId> --destination <session> [--json]— pending → in-progress; computes closure_required_at from tierunclaim <qitemId> --destination <session> [--reason <text>] [--json]— in-progress → pendingupdate <qitemId> --actor <session> --state <state> [--closure-reason <r>] [--closure-target <t>] [--note <text>] [--json]handoff <qitemId> --from <session> --to <session> [--body <text> | --body-file <path>] [--note <text>] [--priority <p>] [--tier <t>] [--tags <csv>] [--host <id>] [--json]— transactional close-as-handed-off + create-new; v0.4.6 (OPR.0.4.6.MH3) adds--host <id>/ theagent@rig@host--toform (§ Cross-host queue routing)handoff-and-complete <qitemId> --from <session> --to <session> [--body <text> | --body-file <path>] [--note <text>] [--priority <p>] [--tier <t>] [--tags <csv>] [--host <id>] [--json]— variant ofhandoffthat closes the source asdone(terminal) instead ofhanded-off; same atomic close+create, chain_of_record, default-nudge, and cross-host contractsfallback <qitemId> --destination <session> [--reason <text>] [--json]— reroute to fallback seatshow <qitemId> [--json]transitions <qitemId> [--json]— append-only transition loglist [--destination <session>] [--source <session>] [--owned] [--mine] [--state <csv>] [-a | --all] [-A | --all-rigs] [--full] [-o <json|wide>] [--limit <n>] [--json]— v0.4.0 grammar (slices 28 + 32, docker / kubectl-aligned):rig queue list(no flags) → active states only (pending/in-progress/claimed/blocked/handed-off; NOTdone/canceled), current-rig breadth, compact rows:qitemId,state,source→destination(orcurrent-owner),closure_reason/closure_target(when handed-off / blocked),mission,slice,tier/priority,age/updated_at, short title, capped tags. Excludes: full body, chain_of_record, transition history, proof / artifact blobs.-a/--all→ include closed / done history within the current breadth (docker-aaxis: history).-A/--all-rigs→ cross-rig breadth (kubectl-Aaxis: breadth). Composable with-a,--owned,--mine,--full.--full→ add body + chain-of-record + full tags + transition history to whichever scope is selected (field-breadth axis).-o json|wide→ encoding, compact-by-default.-o jsondoes NOT imply full body (compact JSON is token-safe + machine-parseable);--full -o jsonreturns the full JSON.--owned→ obligations assigned to the caller (destination_sessiononly).--mine→ the caller's source-or-destination union, including rows the caller authored but does not own.- Pipeline use must enable
set -o pipefail; otherwise the shell reports only the downstream formatter's status and can mask a nonzerorigread such as a timeout. --destination <s>/--source <s>/--state <csv>keep working and compose with the new flags.- The four axes (scope × history × field-breadth × encoding) are orthogonal and composable. The bare unscoped firehose that aggregated cross-rig + full-history (~64,000 tokens on the live host) is retired as a default — opt-in via
-A -a --full. - Use
rig queue show <qitemId>for the full single-item view (kubectldescribe/ dockerinspectpattern).
overdue [--json]— in-progress qitems past closure_required_atinbox-drop <destinationSession> --sender <session> (--body <text> | --body-file <path>) [--tags <csv>] [--urgency <u>] [--audit <pointer>] [--id <inboxId>] [--json]inbox-absorb <inboxId> --receiver <session> [--json]— promote a pending inbox entry to a queue_iteminbox-deny <inboxId> --receiver <session> --reason <text> [--json]inbox-pending <destinationSession> [--json]outbox-record --sender <session> --destination <session> (--body <text> | --body-file <path>) [--tags <csv>] [--urgency <u>] [--audit <pointer>] [--id <outboxId>] [--json]outbox-list <senderSession> [--limit <n>] [--json]
Hot-potato strict-rejection (load-bearing API contract):
update --state doneREQUIRES--closure-reasonfrom one of:handed_off_to,blocked_on,denied,canceled,no-follow-on,escalation. Missing or invalid reason → exit 1 with structured error naming the 6 valid values.closure-reasonofhanded_off_to,blocked_on, orescalationadditionally requires--closure-target.- All hot-potato enforcement happens at the daemon domain layer; every surface (CLI, future MCP, future UI) inherits the same guarantee.
Closure-reason semantics:
handed_off_to— work continues at a different seat (target = new owner).handoffsubcommand is the preferred path;updateaccepts it for non-handoff terminal closures.blocked_on— parked pending another qitem (target = blocker qitem_id).denied— receiver rejected the work.canceled— sender or receiver withdrew.no-follow-on— terminal completion, nothing else needed.escalation— kicked up to a higher tier (target = escalation target).
Cross-host queue routing (v0.4.6 — OPR.0.4.6.MH3)
rig queue create, handoff, and handoff-and-complete can target a destination on ANOTHER
registered host: --host <id> or the host-qualified destination form member@rig@<host> (both
resolve to the same out-of-band hostId request envelope; naming both with DIFFERENT hosts is a
structured ambiguity error). The mechanism generalizes the shipped mission-control
forward-then-strip WRITE: the local daemon resolves the host registry server-side (bearers never
reach the caller), strips the host at the edge, and forwards the WHOLE body over HTTP to the
target daemon — see docs/as-built/architecture/coordination-primitive.md § Cross-host queue
routing for the full model. Load-bearing contract points:
- Explicit-only (no selection follow). Queue verbs route cross-host ONLY on
--host/ the 3-part form — they NEVER consult the persistedrig host selectselection (a durable write and a hot-potato close must not silently re-home on yesterday's sticky selection). This is a deliberate asymmetry with the observe/interactive verbs, which do follow selection. - Origin-owns-the-record. The qitem lives in the TARGET host's DB; that row is THE record.
No local ghost row is ever written, and the target daemon's OWN nudge fires on ITS local tmux
(the whole body — including the
nudgeflag — is forwarded). - At-least-once + idempotent, never exactly-once. The forwarding daemon MINTS the qitem id
before the first forward (a retry carries the same id by construction); a cross-host handoff's
successor id is DERIVED deterministically from (source qitem, destination, host) — namespaced
qitem-xh-…, so a re-driven forward absorbs on the target's primary key. Retrying is safe; a same-id create whose identity fields differ is a structuredqitem_id_reuseerror. - Never-drop ordering. A cross-host handoff creates the successor on the target host FIRST
and closes the local source SECOND. A crash between the two leaves a live duplicate that the
idempotent re-drive converges — never a source closed toward a successor that doesn't exist.
Re-drives: an already-closed source with the MATCHING
closure_targetabsorbs as success; a MISMATCH is a structuredcross_host_close_conflict(409) — surfaced, never overwritten. (Named residual, inherent to at-least-once/no-2PC: a re-drive naming a DIFFERENT destination is a NEW handoff decision and can leave the earlier successor live on the target host — visible via the chain + provenance tags, not a dedup bug.) - Closure fields. The cross-host source close records
closure_reason=handed_off_toandclosure_target=member@rig@<host>—closure_targetis OPAQUE audit/display metadata, presence-checked and NEVER parsed for routing (any PR parsing it as a session string is a spec violation). Session-string carriers (destination_session,source_session,blocked_on,handed_off_to) stay 2-partmember@rig(BR-1). The forwarded successor carries the continuedchain_of_record; those A-side ids are OPAQUE lineage identifiers on the target host (they do not dereference in the target's DB). Provenance: the forwarded item is taggedcross-host+from-host:<sender's self-declared name>(honest best-effort, not authenticated identity). - Failure honesty. Unknown host / ssh-declared host / unreachable / auth-failed each surface
as a distinct structured
remote_queue_write_failederror naming the host — nothing is written on either side. Transport is http-ONLY (the daemon→daemon path is what fires the remote nudge; therig send --hostssh shell-out is a different mechanism, untouched). - Local zero-regression. No
--host(orlocal) = today's local path, byte-identical. Claim / update / inbox verbs stay local-by-principle: after a cross-host handoff the successor lives on the target host where its worker lives. Sender-side operations on an already-forwarded item (cancel/update from the sending host) are a named follow-up, out of v1.
Coordination Project / Classifier and View (PL-004 Phase B)
Two top-level commands extend the coordination layer with L2 (project / classifier) and L5 (views).
rig project
Usage: rig project <subcommand> — L2 agent-backed classifier with daemon-enforced lease + idempotency + reclaim.
Subcommands:
lease-acquire [options]— acquire the active classifier lease for the caller.lease-heartbeat [options]— send a heartbeat for an active classifier lease (extends TTL).lease-show [options]— show the currently-active classifier lease.reclaim-classifier [options]— operator verb to reclaim the active classifier lease. Use--if-deadto refuse if holder is still alive.classify <streamItemId> [options]— project a stream item with classification fields. Idempotent onstream_item_id; requires an active lease.list [options]— list project classifications with filters.show <projectId> [options]— show one project classification.
Notes:
- Lease semantics: only one classifier holds the active lease at a time. Heartbeats extend TTL; lease expiry frees the slot for the next acquirer.
classifyenforces L1→L2 foreign-key existence: the referencedstream_itemsrow must exist or the call is rejected before any state mutation.reclaim-classifieris the operator-side verb to recover from a hung classifier;--if-deadadds a liveness guard so a still-heartbeating classifier is not stolen from.
rig view
Usage: rig view <subcommand> — L5 daemon-backed views over coordination state.
Subcommands:
list [options]— list built-in + custom views.show <viewName> [options]— run a view (built-in or custom).register [options]— register or update a custom view.
Built-in views:
recently-active,founder,pod-load,escalations,held,activity.
Notes:
- Views emit a
view.changedSSE event on every state mutation that affects them. Queue update mutations bridge toqueue.updatedand then toview.changedfor all six built-in views (Phase B R2). - Custom view registration writes to the
views_customtable; the daemon hot-reloads on registration.
Coordination Watchdog (PL-004 Phase C)
rig watchdog registers, lists, inspects, and stops daemon-native scheduler jobs. The scheduler runs inside the daemon supervision tree and persists state in SQLite (watchdog_jobs/watchdog_history); jobs survive daemon restarts. Three policies are available at v1: periodic-reminder, artifact-pool-ready, and edge-artifact-required. The fourth POC policy workflow-keepalive is rejected with policy_deferred_to_phase_d and ships in Phase D.
rig watchdog
register --spec <path> --policy <name> --target-session <s> --interval-seconds <n> --registered-by <s>— register a job from a YAML spec;--active-wake-interval-secondsand--scan-interval-secondsare pool-ready-specific opt-ins.list— list all jobs (active + stopped + terminal).show <job_id>— show one job.status <job_id>— show job + recent evaluation history (last 20 entries).stop <job_id> [--reason <text>]— operator stop; scheduler skips the job thereafter.
History records only loud evaluations: sent (delivery executed) or terminal (policy declared the job done). Quiet skip reasons (not_due, no_actionable_artifacts, no_missing_edge_artifacts, active_wake_not_due) are NOT recorded — POC parity so agents are not woken about scheduler polls. Loud skipped rows are recorded only if a policy returns a non-quiet reason.
Phase D extends the policy enum with workflow-keepalive (the policy deferred from Phase C). It reads workflow_instances directly via SQLite, requires status: active|waiting, and resolves frontier qitem owners from queue_items.
Workflow Runtime (PL-004 Phase D)
rig workflow operates on the daemon-native Workflow Runtime: declarative spec validation, instance creation, step projection (transactional-scribe), trace, and idempotent continue. Workflow specs are markdown/YAML files on disk (workspace-surface); the daemon caches them in SQLite for fast lookup.
rig workflow
validate <specPath>— validate a workflow spec file; returns structured ok/error report (role resolution, step uniqueness, allowed-exits consistency, optional seat liveness). Spec-only: it takes no rig context (OPR.0.4.6.FAC1 arch ruling — rig-coverage checks happen at instantiate).compile <missionPath> [--operation-key <key>]— readproject.yaml→mission.yaml→slice.yamlinto an inspectable lifecycle graph without creating a cached spec, workflow instance, or qitem.instantiate-lifecycle <missionPath> --operation-key <key> --root-objective <text> --created-by <session>— compile and start an eligible lifecycle;--entry-ownerand--rigretain their normal workflow meanings. The opaque operation key makes exact replay idempotent and conflicting reuse refuses.instantiate <specPath> --root-objective <text> --created-by <session>— create a new instance + entry-step qitem in the same daemon transaction;--entry-owner <session>overrides the default entry owner. OPR.0.4.6.FAC1:--rig <name>binds the instance to a rig (overrides the spec'starget.rigDEFAULT; persists asboundRigon the instance, rendered byshow/traceand carried in--json). On a bound instance, a role with nopreferred_targetsresolves to a live capable SEAT on that rig by the pure capability policy (running agents declaring the role, managed seats only, required runtime, least pending backlog, deterministic coordinate tiebreak). Unknown rig = structuredbound_rig_unknown; a bound-rig role no seat structurally declares =bound_rig_role_uncovered(existence at any lifecycle state satisfies it — liveness is checked when the step projects). No--rigand no spec default = unbound, byte-identical pre-FAC-1 behavior.run <specPath> …— accepts the same--rig <name>binding (run instantiates too).project --instance <id> --current-packet <qitem-id> --exit <handoff|waiting|done|failed> --actor-session <session>— close the current packet AND project the next-step packet IN THE SAME daemon transaction (transactional-scribe; lost handoffs impossible by design).--result-note <text>,--blocked-on <ref>,--next-owner <session>modify behavior.list [--status <s>]— list instances; optionally filter by status (active/waiting/completed/failed).show <instanceId>— show one instance.trace <instanceId>— show the instance + its append-only step trail (audit-only).continue <instanceId>— idempotent inspector; in v1 returns the current state.
The owner-as-author + workflow-as-transactional-scribe contract is enforced by the daemon. The owner of a packet decides when it closes; the workflow runtime atomically records the closure AND creates/projects the next qitem per the workflow spec, in a single daemon transaction.
Project-owned release profiles
project.lifecycle.profile selects a key in project.lifecycle.profiles. Each
selected entry contains required_steps (a nonempty list of stable obligation
IDs) and workflow (the ordinary workflow language). The reusable example at
project-release-profile.yaml
names nine release-ceremony stages followed by one release-boundary judgment.
That final judgment covers the seven areas of the canonical
release-boundary.md checklist in one
agent-authored record. It does not create seven automatic gates.
Put the profile in project.yaml once; release missions need only their ordinary
composition. Customize the example's project ID, roles, and policy for the
project. Every profile step declares depends_on (including [] on roots);
conditional next_hop.on jumps are refused so required stages cannot be bypassed.
Missing required IDs refuse with lifecycle_required_step_missing.
Prerequisite cycles make compilation ineligible with dependency_cycle, even
when loop_guards.max_hops is set. That guard bounds routing loops; it cannot
make mutually dependent steps ready.
Precedence is explicit:
- With a selected project graph and no mission workflow, the mission inherits it.
mission.lifecycle: {profile: <same-profile>, mode: extend, workflow: ...}adds new steps, merges roles by name, and appends context references. An extension cannot replace a step ID; its workflow accepts onlysteps,roles, andcontext_refs.mode: overridesupplies a replacement workflow. All required project step IDs and the prerequisite relationships between them must remain. Additional intermediate stages are allowed. An omitted or unknown mode with competing workflows refuses withlifecycle_override_ambiguous.- Without
project.lifecycle.profiles, the existing mission-authored workflow takes precedence over slice execution declarations. This legacy path remains supported and reports an advisory that no project graph is selected. Adding a project graph to an existing copied mission workflow requires explicit mode selection or removal of the copy. Project lifecycle fields such as an inertworkfloworworkflow_refare refused rather than silently ignored.
An authored, ready successor may be a mission extension step depending on
release-boundary. Without that extension, release-boundary exits done and
finishes the current lifecycle. The runtime creates the continuation packet;
the agent judges readiness and performs any authorized activation. It does not
infer readiness from a folder or activate future scope automatically.
Compilation exposes graphSource (selection mode, project/mission addresses,
required IDs), the complete workflowSpec, dependencies, and source digests.
These are bound into the compiled input digest and persisted at instantiation.
Changing source bytes under an existing operation key refuses. Relative paths
passed to both CLI compile and instantiate-lifecycle are resolved against the
caller cwd before HTTP, so daemon cwd cannot change their meaning.
workflow show/JSON and the TUI execution view show every named obligation with
its state and receipt state. Required steps need project --evidence-ref <ref>
on a successful done/handoff exit; missing references refuse before mutation
with lifecycle_receipt_required. Waiting and failed exits remain available.
The projection records who supplied the reference and when. recorded means an
attributed workflow receipt exists, not that the daemon verified its substance.
An ordinary terminal queue row never supplies that receipt. Agents inspect the
actual evidence, including reasoned not-applicable or deferred boundary areas.
Existing typed acceptance contracts remain separate and retain their checks.
Authored mission boundary (legacy)
Without a project-owned graph, when a mission declares lifecycle.workflow, compile uses that explicit
workflow instead of deriving steps from active slices. Slice membership and
backlinks are still validated and included in provenance; slice SDLC selections
do not add workflow steps or gates. lifecycle.profile must match the profile
selected in project.yaml:
# Add to mission.yaml; project.yaml already selects release-boundary-v0.
lifecycle:
profile: release-boundary-v0
workflow:
context_refs: [SPEC.md, PROGRESS.md, NOTES.md]
entry: {role: orchestrator}
roles:
orchestrator: {preferred_targets: [orch@my-rig]}
steps:
- id: mission-boundary
actor_role: orchestrator
objective: Inspect current evidence and decide the next authored exit.
allowed_exits: [waiting, done, failed]
re_present_after_seconds: 300
re_present_max_seconds: 3600
The nested workflow uses the ordinary workflow language; its ID defaults to
lifecycle-<project>-<mission>, and its compiled version is derived from source
digests. Boundary steps explicitly allowing waiting default to a five-minute
initial reminder and a one-hour cap; both fields in the example override those
defaults. Missing operation identity leaves compilation ineligible. Instantiation
with one opaque --operation-key persists the compiled input digest and lifecycle
binding; exact replay returns the same instance/entry packet, and changed input
under that key refuses. Authoring alone never starts an instance.
context_refs carries addresses in entry, successor, route/resume, and reminder
packets. The lifecycle compiler also includes the project/mission manifests and
project.install.context. Relative project references resolve from the project
root; profile workflow references resolve from the project root and mission workflow
references from the mission directory. References
are not evidence verdicts: the receiving agent opens current context, may inspect
beyond it, and chooses the exit. The daemon neither interprets receipts nor
activates a mission. rigx project remains a separate manual shadow.
Outside mission-boundary compilation, an unmapped waiting exit with
re_present_after_seconds alone remains one-shot.
Adding re_present_max_seconds opts into an existing queue/watchdog timer that
repeats with exponential backoff: the example waits 5, 10, 20, 40, then 60 minutes
between reminders. The cap must be an integer at least as large as the initial
delay. No new packet is created. Repeated waiting acknowledgments retain the
schedule; changed structured closureEvidence or a new blocker resets it.
rig workflow project --evidence-ref <ref> records an attributed reference as
closure evidence, without interpreting it or substituting for typed acceptance. Omitted
evidence preserves the prior evidence, and object key order is immaterial.
A transition on the exact qitem blocker makes the reminder due on the next
scheduler tick (normally within one second), resetting the initial delay.
Wake delivery receipts do not count as progress. The workflow's own waiting
acknowledgments are on its frontier packet, not its upstream blocker; a repeating
wait cannot name itself as its blocker. Blocker completion retains native
queue unpark/wake behavior. Terminal or rerouted packets retire their timer.
Restart reconciles blocker transition identity and resumes the persisted delay;
replaying the same transition does not create another wake. A live repeating
timer can have an unconsumed wake: these are separate facts in park status.
Hard human gates are authored using the existing gate field; a reminder does
not manufacture a gate or satisfy one.
Operational Inspection
Read-only inspection commands for compaction planning, workflow heartbeat, and seat handover observability. Default mode is read-only across this section.
rig compact-plan
Usage: rig compact-plan [--rig <name>] [--refresh] [--threshold-tokens <n>] [--threshold-percent <0-100>] [--json]
Notes:
- Plans Claude compact-in-place candidates without compacting anything (read-only triage).
--threshold-tokens <n>is the estimated used-token threshold;--threshold-percent <0-100>is the used-percent threshold when the context window size is missing.- Output identifies seats that are candidates for compaction by current heuristics; the operator decides what (if anything) to compact.
rig heartbeat
Usage: rig heartbeat [--rig <name>] [--nudge] [--include-done] [--json]
Notes:
- Shows workflow execution proof state from queue files.
- Default mode is read-only.
--nudgesends informational proof instructions to stalled or unproven owners; it does not modify queue files or reroute work. --include-doneincludes done/handed-off queue items in the output (excluded by default).
rig seat
Usage: rig seat <subcommand>
Subcommands:
status <seat> [options]— show read-only seat handover observability status.handover <seat> [options]— plan a safe two-phase seat handover.launch <seat> --fresh --reason <text> [--stop] [--operator <address>] [--json]— create a deliberate blank occupant for exactly one existing seat. No continuity source is used; a live managed occupant requires--stop, while adopted or unmanaged ambiguity refuses.clear-attention <session> [--reason <text>] [--json]— evidence-gated, operator-attested, audited reconcile of a stuckattention_requiredseat.
Notes:
statusreads the seat-handover observability tables (migration021); it does not mutate anything.handoverplans the two-phase sequence; actual execution happens through the existing seat-launch surfaces under operator gating.clear-attention(v0.3.4) clears a stuckattention_requiredstartup status using captured evidence;--reason <text>is an operator attestation override that skips the evidence gate (audited). Replaces SQLite hand-edit workarounds.
Mission Control / Queue Observability (PL-005 Phase A)
Mission Control is an integrated product UI inside the existing shell, NOT a new rig command. PL-005 originally named the read-only node surface as rig ps --nodes --json; under the v0.4.4 disclosure ladder, the fleet-wide projected node source is rig ps --nodes -A --json.
Mission Control is reached via the product UI at the /mission-control route. The HTTP API surface (/api/mission-control/*) is documented in docs/as-built/architecture/mission-control.md. The 7 verbs (approve, deny, route, annotate, hold, drop, handoff) execute via POST /api/mission-control/action; the 7 views are read via GET /api/mission-control/views/:view-name.
Mission Control consumes rig ps --nodes -A --json for fleet roll-up where the canonical CLI source is preferred. Cross-CLI-version drift is handled per the 4 sub-clauses of PRD § Runtime/Source Drift Acceptance: missing fields surface as honest "field unavailable on this rig's daemon version" placeholders; once-per-session-per-rig logging avoids spam; the fleet view shows a top-level "rigs running stale CLI" indicator.
Agent Images, Context Packs, and Workspace (v0.3.0)
Three top-level commands shipped in v0.3.0 for operator-authored library content (agent images and context packs) and the workspace primitive.
rig agent-image
Usage: rig agent-image <subcommand> — browse, snapshot, and manage agent images (PL-016).
Subcommands:
list [options]— list all agent images in the library.show <name-or-id> [options]— show image manifest + statistics.preview <name-or-id> [options]— show manifest + sized supplementary file metadata + starter snippet.create <source-session> [options]— capture a productive seat's resumable state into a new agent image.delete <name-or-id> [options]— delete an agent image (subject to evidence-preservation guard).pin <name-or-id> [options]— pin an image so prune cannot delete it.unpin <name-or-id> [options]— unpin an image.prune [options]— delete evictable images (protected by evidence-preservation guard).sync [options]— re-walk discovery roots and refresh the library index.
Notes:
- Images are an operator-authored library form; deletion is gated by an evidence-preservation guard so productive seat snapshots are not lost accidentally.
pin/unpinare the operator levers for explicit retention;prunehonours them.
rig context
Usage: rig context <subcommand> — browse, preview, compose, and manage operator-authored context packs. This noun never delivers; delivery belongs to send, broadcast, walk, and queue create.
Subcommands:
work-install [--project <id>] [--mission <id>] [--slice <id>] [--deliver] [--runtime <claude-code|claude|codex>] [--cwd <agent-working-directory>] [--topology <ids>] [--apply-skills] [--json]— resolve project/mission/slice Markdown plusproject.yaml install.skillsin one plan. With--runtime, composes system, topology, and project selectors and reports per-skill provenance/status;--apply-skillssafely reconciles the owned harness projection into--cwd(default: the caller's current working directory), not the workspace metadata directory. Omitting--runtimeskips skill inspection regardless ofOPENRIG_RUNTIME; applying skills requires an explicit runtime.profile <name-or-ref> --situation <fresh|handover|post-compaction> [--runtime <claude-code|claude|codex>] [--profile <id>] [--budget <tokens>] [--rig <rig> --seat <seat>] [--mission <mission>] [--slice <slice>] [--json]— compose the selected atom graph and explicitly granted context. Runtime defaults toOPENRIG_RUNTIME, otherwise Claude; an unknown nonempty environment value warns and falls back to Claude. An explicit flag overrides the environment.list [options]— list all context packs in the library.show <name-or-ref> [options]— show pack manifest + per-file metadata.preview <name-or-ref> [options]— show the assembled bundle without delivering it.compose --out <ref> --from <files...>— compose ordered files into a durable context ref without delivering it.sync [options]— re-walk discovery roots and refresh the library index.add <source-dir> [options]— install a context pack from a local directory into the configured context store.rm <ref> [options]— remove a context pack by its path-like ref.
Notes:
- Context packs are operator-authored bundles of context (manifest + files) intended to prime a managed seat with a coherent starting context.
- Both
profileandwork-installacceptclaude-code, its aliasclaude, andcodex. Invalid explicit values fail during CLI argument parsing, before context lookup or projection. JSON metadata retains the consumer's existing keys:profile.runtimeisclaudeorcodex;skillProjection.runtimeisclaude-codeorcodex. Both Claude spellings produce the same selection and metadata within each command; manifest runtime keys remain unchanged. - For example,
rig context profile world-public --situation fresh --runtime claude-codeandrig context work-install --runtime claude-codeuse the same runtime spelling. Profile atoms that read seat context still require both--rigand--seat. previewis the canonical read-only way to inspect the assembled content.- This command family is delivery-free; context-window inspection is not part of this noun.
rig workspace
Usage: rig workspace <subcommand> — Workspace Primitive (PL-007), v0 typed-kind tooling.
Subcommands:
validate [root] [--kind <kind>] [--no-recursive] [--require-frontmatter] [--max-files <n>] [--json]— walk a workspace root, parse each.mdfile's YAML frontmatter, and emit a structured gap report. Advisory only — never modifies files. Default root:cwd.--kindvalidates against a specific workspace kind (user | project | knowledge | lab | delivery).--max-files(default10000) hard-caps the walk; v0.3.2 slice-01 GA enforces strict-int regex on this flag.doctor [--workspace <path>] [--strict] [--json]— run an 8-check workspace-readiness diagnostic against the daemon's resolved workspace (workspace root, missions folder, file allowlist, daemon alignment, daemon reload, optional slice docs, currentNOTES.mdor readable legacy notes, and SDLC convention sections). Read-only. Default exit-code: non-zero only onfail;--strictmakes warn-or-fail non-zero.
Notes:
- v0 surface was intentionally narrow (
validateonly); v0.3.2 addeddoctoras the operator-facing readiness diagnostic. - Future versions will add typed-kind authoring/refactor tooling on the same root walker.
- See
rig config init-workspaceto scaffold a fresh default workspace.
Plugin Inspection (v0.3.1)
One read-only top-level command added in v0.3.1 to inspect plugins
discovered from $OPENRIG_HOME/plugins/ (default ~/.openrig/plugins/).
No install verb at v0 — installation is explicit operator copy or
symlink per each plugin's OPENRIG-INSTALL.md.
rig plugin
Usage: rig plugin <subcommand> — read-only plugin inspection.
Subcommands:
list [options]— list discoverable plugins (aggregated across vendored + runtime caches).show <id> [options]— show plugin manifest + skills + hooks + mcp servers.used-by <id> [options]— list agents referencing this plugin in theirprofile.uses.plugins[].validate <path> [options]— validate plugin manifest + skill frontmatter against the agentskills.io spec.
Notes:
- Plugin discovery aggregates
$OPENRIG_HOME/plugins/(vendored at runtime by the operator) with the daemon's bundled plugin cache. openrig-coreships bundled with the daemon (11 skills). Additional plugins (gstack— 45 skills;obra-superpowers— 14 skills) ship as substrate references for plugin authors to copy-install per theOPENRIG-INSTALL.mdworkflow inside each plugin's source tree.- A first-class
rig plugin install <substrate-path>verb is deferred to 0.3.2.
Scope Tree Primitive (v0.3.2)
One top-level command first shipped in v0.3.2 (scopeCommand,
packages/cli/src/index.ts:20,187; defined in
packages/cli/src/commands/scope.ts; release-0.3.2 slice 12). Operates
the scope tree (missions, slices, sub-slices) per
conventions/scope-and-versioning.
rig scope
Usage: rig scope <subcommand> — scope tree primitive: missions, slices, sub-slices.
Top-level option:
--workspace <path>— override workspace root (otherwise use the typedworkspace.slices_rootsetting;$OPENRIG_WORK_ROOTremains a legacy override).
Two subcommand groups: slice and mission.
rig scope slice <subcommand> — slice-tier commands:
ls [--mission <name>] [--state <state>] [--json]— list slices in a mission (or across all missions).--statefilter:active | closed | shipped | all(defaultactive).show <slice-path> [--mission <name>] [--json]— inspect a single slice (frontmatter + README + children).slice-pathis absolute, relative-to-substrate, orNN-slug;--missionhints the mission when path is justNN-slug.create <mission> <slug> [--template <kind>] [--title <text>] [--intent <text>] [--depends-on <dot-id...>] [--json]— create a mode-neutral slice scaffold: one intent-bearingSPEC.mdwith the three convention sections,PROGRESS.md,PROOF.md, andproof/.depends_onaccepts same-mission sibling slice dot-IDs and is advisory build-order data. Every template kind emits the same file set; mode richness composes through the template seam.progress <slice-path> [--mission <name>] [--status <state>] [--milestone <text>] [--owner <session>] [--note <text>] [--json]— v0.4.0 (slice 33) new verb: append / set / update progress entries deterministically. Writes the canonical structure the OpenRig PROGRESS UI page reads. Replaces hand-editingPROGRESS.mdwith markdown.stage <slice-path> <new-stage> [--mission <name>] [--successor <id>] [--json]— v0.4.0 (slice 35) new verb: set the slice'sstagefrontmatter (wip / provisional / established / canonical / superseded / retired) deterministically.supersededREQUIRES--successor <id>(rejected otherwise + records the successor);retiredwarns "do not use"; invalid stages rejected with the valid set named.verified <slice-path> --against "<source>" [--mission <name>] [--json]— v0.4.0 (slice 35) new verb: stamp the slice'sverifiedline withverified: <today> against <source>.--againstis MANDATORY (bare timestamps rejected — the anti-stale keystone perconventions/scope-and-versioning§2). Overwrites the prior verified line.reconcile <slice-path> [--mission <name>] [--json]— v0.4.0 (slice 35) new verb: idempotent repair. Backfills missingPROGRESS.md, conforms mandatory frontmatter (id/stage/verified), and repairs id-registration ghosts (id:null/ doubled-prefix). Safe to re-run.ship <slice-path> <release-mission> [--mission <name>] [--json]— ship a slice to a release mission (preserves git history).close <slice-path> [--note <text>] [--mission <name>] [--json]— close a slice (move to<mission>/closed/, update status).--noteis an optional closure note.move <slice-path> <dest-mission> [--mission <name>] [--json]— move a slice between missions (re-numbers in destination).
rig scope mission <subcommand> — mission-tier commands:
ls [--json]— list missions (top-level folders withREADME.md).show <mission> [--json]— inspect a single mission.create <name> [--template <kind>] [--id <dot-id>] [--title <text>] [--intent <text>] [--depends-on <dot-id...>] [--no-notes] [--json]— create a mission with an intent-bearingSPEC.md,NOTES.md,PROGRESS.md, andslices/.depends_onaccepts same-project sibling mission dot-IDs and is advisory build-order data.--no-mission-notesremains a deprecated alias for--no-notes; the old notes-template environment variable remains readable with an advisory.graph <mission> [--json]— show slice dependency nodes, the current ready/waiting sets, and advisories for malformed, cross-parent, or absent dependencies. Stale edges never block or crash the reader.progress <mission> [--status <state>] [--milestone <text>] [--owner <session>] [--note <text>] [--json]— v0.4.0 (slice 33) new verb: append / set / update progress entries on a mission'sPROGRESS.mddeterministically. UI-valid by construction.stage <mission> <new-stage> [--successor <id>] [--json]— v0.4.0 (slice 35) new verb: set the mission'sstagefrontmatter deterministically. Same enum +--successor-required-for-superseded rules as the slice variant.verified <mission> --against "<source>" [--json]— v0.4.0 (slice 35) new verb: stamp the mission'sverifiedline.--againstMANDATORY.reconcile <mission> [--json]— v0.4.0 (slice 35) new verb: idempotent mission-tier repair (backfillsPROGRESS.md, conforms frontmatter, repairs ghosts).
Convention compliance: rig scope together with slice 33 (PROGRESS.md + scaffolding) and slice 35 (stage / verified / reconcile) makes rig scope the deterministic enforcer of conventions/scope-and-versioning (§1 dot-IDs, §2 maturity vocabulary). Agents update the convention through commands rather than hand-editing markdown.
SDLC control plane verbs (v0.4.4)
The conventions these verbs operate live in ONE shipped document: docs/reference/sdlc-conventions.md (copied into the assembled CLI package); the operating procedure is the packaged mission-slice-sop skill.
rig scope slice|mission approve <target> [--scope spec|delivery] [--actor <session>] [--on-behalf-of <human>] [--json]— the two staged-approval locks, one daemon-side write path.--scope specplan-locks the node'sSPEC.md;--scope delivery(default) is terminal sign-off. Approval is freeze/sign-off, never proven-green.rig proof add <slice-path> --artifact-type <guard|qa|rev1-r1|rev1-r2|adjudication> --verdict <CLEAR|BLOCKING|CONCERNING|PASS|NOT-CLEAR> --candidate-sha <sha> --money-evidence "<line>" [--file <path>|--body <text>] [--evidences <refs>] [--media <refs>] [--self-check <text>] [--json]— v0.4.4 (slice 19 FR-8;--mediavia the corrective §3.4) drop a proof artifact into<slice>/proof/with the machine-readable C1 header, validated at drop time (closed sets above).--evidences(item text or 1-based index) joins the drop to the slice's## Proof contractitems — the pairing the Living Notes DELIVERED section renders;--media(proof/-relative refs, containment-checked, never absolute) names the curated media the drop stands behind, projected into the DELIVERED items' proof set. Contract/self-check outputs are advisories (exit 0), never gates.rig scope audit <mission> [--json]— checks C1 headers and the one-SPEC convention (frontmatterintent:or a readable legacy Intent section, Mini-requirements, Proof contract, and current NOTES). It never requires a second PRD. All convention findings are advisory/fail-open.
Notes:
- Surface source-verified against
packages/cli/src/commands/scope.tsat51554eee(v0.4.0 post-slice-35); SDLC control-plane verbs source-verified againstscope.ts/proof.ts/scope-audit.tsin OPR.0.4.4.23.
Skill Cascade Audit (v0.4.0)
One top-level command first shipped in v0.4.0 (slice 10 — skill / knowledge lifecycle curation, Hermes-informed). Defined in packages/cli/src/commands/skill.ts. Pairs with the daemon-side audit surface at packages/daemon/src/routes/skills/audit.ts + mirror-drift detection.
rig skill
Usage: rig skill <subcommand>
Subcommands:
loadout --runtime <claude-code|codex> [--cwd <path>] [--project-root <path>] [--topology <ids>] [--apply] [--json]— inspect the deterministic managed loadout selected bycatalog.yamlsystem selectors, topology/profile selectors, andproject.yaml install.skills. Reports selector reasons, catalog Git revision/content digest, target, and current/missing/shadowed/conflicting status.--applywrites exact bytes plus an ownership manifest, is idempotent, and refuses to overwrite or remove locally modified/unowned content.audit [--json] [--include-cache] [--severity <level>] [--rig <name>]— read-only audit of the skill cascade. Detects provenance + freshness issues across the canonical → product mirror → hub cwd → installed plugin chain.
Audit categories surfaced:
missing— a skill location in the cascade lacks a SKILL.md file but a sibling location has one (declares the cascade-relative gap).stale— a SKILL.md file exists but is older than the canonical or has a content-hash mismatch.self-referential— a SKILL.md provenance pointer references its own location instead of an upstream source.invalid-date— frontmatterlast-verified/last-updatedis malformed or in the future.mirror-drift— a downstream mirror copy diverges from canonical with no documented intentional fork.
Notes:
- Read-only: the audit does NOT mutate any skill file. Findings are routed back to the lifecycle (curation-steward) for shaped propagation runs.
- False-green prevention: when mirror-drift evidence is unavailable for any reason (daemon offline, filesystem inaccessible), the CLI emits a clear
unable-to-auditoutcome with exit code2rather than reportingclean. This closes the failure mode the v0.3.4 wrap-gate AC-3 almost shipped ("Mirror sync verified vianpm run mirror-skillsclean" — that sync did not touch substrate canonical or hub cwd). --include-cacheincludes packaged-installer cache copies in the audit (default skips because those are immutable post-ship).--severity <level>filters output:info(default; everything),warn(stale + mirror-drift only),error(invalid-date + self-referential only).--rig <name>narrows the audit to a single rig's embedded skill copies.--jsonemits structured findings:{cascade: [...locations...], findings: [{category, path, evidence, suggested-action}]}.- Exit codes:
0clean,1findings present,2unable to audit.
Composes with the existing scripts/mirror-skills.mjs guardrails — the audit detects what mirror-skills would also catch, plus the canonical / hub cwd layers that script doesn't touch.
Operator Context-Mode Bindings (v0.3.2)
One top-level command first shipped in v0.3.2 as rig policy
(release-0.3.2 slice 09), renamed to rig mode in 0.5.2 per the PM
ruling RULING-rig-mode-rig-policy-naming (clean rename, no alias —
zero adoption confirmed; rig policy is being reintroduced as the
permission-policy verb). Defined in rigModeCommand
(packages/cli/src/commands/rig-mode.ts). Pairs with the daemon's
typed-primitive store at
packages/daemon/src/db/migrations/041_rig_policy.ts (DB artifact
names keep their shipped forms). Operates the operator context-mode
binding surface (sleep / desk / mobile / away / focus / debug) used by
mode-aware agent posture.
rig mode
Usage: rig mode <subcommand>
Subcommands:
set <mode> [--scope <scope>] [--qualifier <id>] [--<field> ...] [--evidence <citation>] [--confirm] [--bearer <token>] [--json]— propose a binding. Without--confirmthe CLI echoes the proposed binding and exits withexit 2so scripts cannot accidentally apply;--confirmis the explicit operator action.<scope>is one ofglobal_host | rig | workstream | qitem(defaults to the per-mode recommendation).--qualifier <id>is required forrig | workstream | qitemscopes and rejected forglobal_host. Per-field tuning flags:--autonomy-scope,--heartbeat-cadence,--inspection-depth,--update-detail,--escalation-threshold,--concurrency-limit,--permission-prompt-posture(one ofnormal | batch_for_human | do_not_prompt_unless_blocked;auto_acceptis FORBIDDEN by convention),--expiry-or-stale-rule.--evidencecarries a free-text operator citation (message id, file pointer, chatroom topic, etc.).show [--json]— list all operator-context-mode bindings.effective [--rig <id>] [--workstream <id>] [--qitem <id>] [--json]— resolve the effective mode for a (rig, workstream, qitem) read context. Surfacesunknown_posturewhen no binding matches.cite [--rig <id>] [--workstream <id>] [--qitem <id>]— emit the short-prose citation line for the effective mode at the read context (per convention §Citation Rules).unset <scope> [qualifier] [--bearer <token>] [--json]— delete one binding (operator-only).defaults [--json]— print the recommended per-mode 6×7 field defaults + default-scope mapping + stale rule.
Notes:
- The 6 modes are
sleep | desk | mobile | away | focus | debug. Bare-word invocation is accepted (set desk);mode:<word>is the disambiguated prefix form. - Restate-and-confirm posture (HG-4):
setis restate-only until--confirmis passed. This prevents accidental script application. --qualifierstrict reject forglobal_host(HG-7 guard finding): operators who type--scope global_host --qualifier <id>get an error and the daemon is never contacted. The CLI does NOT silently drop the qualifier.- Operator-edit mutations (
set --confirm,unset) require an operator bearer token (--bearerorOPENRIG_AUTH_BEARER_TOKENenv). - Surface source-verified against
packages/cli/src/commands/rig-mode.tsatb13a8e4c7(0.5.2 rename).
rig policy
Usage: rig policy <subcommand> — the top-level PERMISSION-POLICY verb, introduced in 0.5.2 after
the context-mode verb moved to rig mode (RULING-rig-mode-rig-policy-naming). OpenRig bakes NO
allow/ask/deny permission policy — the harness-native permissions are the control surface. This verb
TEACHES and RECORDS into RigSpec (permission_policy: builtin:<name> | none); it never enforces at
runtime.
Subcommands:
list [--json]— the built-in templates (locked | standard | open | yolo) plus the reserved deliberate-nonechoice, each with its ref form.show <name> [--json]— one choice: its ref form and what recording it means.current --spec <path> [--json]— thepermission_policyvalue recorded in a rig spec and how it classifies (absent = the floor;none= deliberate;builtin:<name>; custom relative path).apply <name> --spec <path> [--json]— record the choice into an EXISTING spec via the same comment-preserving flow asrig setup --policy(which stays as the setup-step composition, not an alias). A new install has no spec; nothing is written and the floor holds by absence.
Commands Not Present
These are not current top-level rig commands:
rig claimrig blamerig replay
If older docs or habits mention them, treat those references as stale.