@openwop/cli is the host-agnostic control plane for any OpenWOP-compatible host — a single openwop command that drives the protocol from your terminal. It is a reference client, not an engine: every command surfaces a capability the host advertises at /.well-known/openwop, sends the wire shape the host expects, and renders the host's resolved view. It bundles to a single file with zero runtime dependencies and ships independently of the spec corpus.
Install
npm install -g @openwop/cli
openwop --version
One-off, no install (handy in CI or a scratch shell):
npx -y @openwop/cli@latest --help
Requires Node ≥ 20. Channel adapters for Discord and WhatsApp are optional peer dependencies — install them only if you use those channels.
Point it at a host
The CLI reads OPENWOP_BASE_URL (or --base-url) and OPENWOP_API_KEY (or the interactive onboard flow). Against the reference deployment:
export OPENWOP_BASE_URL=https://app.openwop.dev/api
openwop onboard # interactive auth + key issuance
openwop doctor # connectivity + advertised-capability check
openwop capabilities # read /.well-known/openwop
The in-app command reference — with one-click copyable snippets, rendered against whatever host you're pointed at — lives at app.openwop.dev/cli.
How it behaves — the contract
Three properties hold for every command, so the CLI is safe to script against a shared host:
- Capability-honest, fail closed. A command drives a surface only when the host advertises it. When the host doesn't, the command fails closed with a legible message and a non-zero exit — never a stack trace, never a fabricated success.
- The host is the authority. Policy, RBAC, toggle/variant resolution, consent, approvals, and goal/proposal completion are all decided host-side. The CLI renders the host's decision; it never computes or asserts one locally.
- Secrets are refs, never values. BYOK keys, OAuth client secrets, SAML certs, and SCIM tokens stay host-side. The CLI handles refs and status only, and runs every response through a redactor before output — nothing secret is printed, logged, or written to local config.
Meaningful exit codes make commands scriptable: 0 ok, 3 escalated / pending, 1 failed (with per-group nuances documented in --help).
Command groups
Point at a host and run openwop --help for the live list. The groups cluster by area:
| Area | Groups |
|---|---|
| Setup & health | onboard · doctor · capabilities · config |
| Run lifecycle | runs · chat · interrupts · workflows · catalog · media |
| Agents & orchestration | agents · roster · workforces (fleet) · a2a |
| Governance & safety | approvals · governance (policy) · consent · toggles |
| Identity & access | users · profiles · auth (sso) |
| Extensibility & connections | packs · mcp · connections (conn) · providers · byok |
| Memory & workspace | memory · workspace · prompts |
| Automation & messaging | cron · webhooks · triggers · messaging · relay · notifications |
| Observability | analytics (usage) |
Agent-platform capabilities
Three higher-level capabilities for driving an agent platform — each capability-gated, so the group activates only when the host advertises it.
Reviewable learning — proposals
An agent's learned change is stored as an inert proposal. It does nothing until a human reviews it and applies it through the host's activation gate (which may route through an approval). The CLI renders the host's verdict and never activates locally.
openwop proposals list --state pending
openwop proposals revise prop_123 --artifact-json '{"systemPrompt":"…"}'
openwop proposals apply prop_123 # host materializes + routes through its activation mode
Standing goals — goals
A durable objective the host pursues across runs until a judge verdicts it satisfied or a bound stops it. Completion is the judge's verdict — there is no satisfy verb, and the CLI never declares victory from the client. A bounds-less goal is refused when the host requires bounds, so unattended continuation always terminates.
openwop goals create --objective "Keep the triage backlog under 20" \
--judge verifier --continuation schedule --max-iterations 50
openwop goals pause goal_123
Portability — export / import
Move reusable estate — agents, packs, schedules, rosters, templates — between hosts as a refs-only bundle. Secrets never travel as values; the bundle reports secretsToRebind references you bind at the destination. Always dry-run first; apply is idempotent and re-owns every entity to you.
openwop export --kinds agent --kinds schedule --out estate.json
openwop import estate.json --dry-run # preview creates/updates/skips/conflicts (no writes)
openwop import estate.json # apply
Trigger bridge — triggers
Bind an external webhook / email / form source to a workflow, then let a verified inbound event start a run with the payload as ctx.triggerData. The host verifies the source, dedups, and runs the durable delivery state machine (active | paused | failed | dead-lettered) — the CLI registers the subscription and renders the host's resolved state. A webhook binding secret is returned once at creation; the CLI prints the fingerprint and never persists the value.
openwop triggers register --source webhook --workflow wf_intake --dedup --verification required
openwop triggers list --state active
openwop triggers get tgsub_123 # exit code reflects state: 0 active · 3 paused · 1 failed
Durable A2A tasks — a2a
When a host advertises a2a.durableTasks, every backing run carries a persisted A2ATaskState (taskId === runId) that survives caller disconnect, host restart, and HITL pauses. status shows what the host advertises; task reads one durable task's live state. The record is content-free — no run inputs, outputs, artifacts, or credentials — and the CLI renders the host's projection rather than deriving a state locally.
openwop a2a status
openwop a2a task <taskId> # exit: 0 completed · 3 in-progress/needs-input · 1 failed
Channel relay (optional)
The messaging and relay commands are a non-normative host extension: the CLI can run a local adapter that bridges a chat channel (Signal, iMessage, WhatsApp, Discord) into a workflow or agent on the host. The CLI pairs with the host over an authenticated session via a short code; channel-side auth lives only in the local adapter process and never reaches the host as a primary credential.
Source
@openwop/cli is on npm; source, docs, and the issue tracker are at github.com/openwop/openwop-cli. The CLI evolves additively through v1.x.
Next steps
- Install the demo app — stand up a host for the CLI to drive.
- Host implementers — the capability advertisement contract every command checks against.
- Run the quickstart — your first workflow against any host.