What mutates
| Command | Effect | Scope | Guard |
|---|---|---|---|
replay | Re-delivers events to a live target | write | --dry-run, --yes for bulk, --idempotency-key |
forwarder pause / resume / disable | Starts, stops, or retires delivery | write | Explicit --bucket + --forwarder (no picker) |
bucket create / forwarder create | Provisions a new route | write | Positional name; re-check before re-creating |
init | Provisions a bucket + forwarder together | write | --idempotency-key (idempotent by design) |
events, forwards, health, whoami, capabilities, docs) never need these guards — this page applies only to the writes above.
The pattern
Confirm the write scope
Mutations need a
write token. A missing scope fails cleanly with forbidden_scope (exit 3) before anything changes — check repost auth status --json up front. See Authentication.Resolve stable IDs first
Act on concrete IDs or a bounded selector you got from a search — never a vague or open-ended one. Arrive at a mutation from Diagnose webhooks, not a guess.
Preview the blast radius
Where a command supports it (
replay --dry-run), read the predicted count and gate on it before executing. If it is larger than expected, tighten the selector instead of proceeding.Make it idempotent
Pass
--idempotency-key so a retried command re-attaches to the existing work instead of doing it twice.Gate bulk behind --yes
Agents run non-interactively, so bulk mutations refuse to proceed without
--yes. Pass it deliberately, not reflexively.Run non-interactively
A human runningforwarder pause with no arguments gets an interactive picker. An agent must never reach it — it blocks forever. Always pass the selectors each mutating command needs:
| Command | Required selectors |
|---|---|
replay | --forwarder (and --bucket when the forwarder is named) |
forwarder pause / resume / disable | --bucket (-b) and --forwarder (-f) |
bucket create / forwarder create | The positional name, plus --target for an external forwarder |
--bucket is the canonical selector for agents. --bucket-slug remains accepted as a compatibility alias, but new automation should use --bucket or -b.Idempotency
--idempotency-key makes a write safe to retry. If a command times out or the connection drops, re-run the identical command with the same key: the API re-attaches to the original work instead of starting a second one.
deduplicated: true means the work is already running — treat it as success. init is idempotent the same way: re-running with the same key (or the same name and target) returns the existing bucket and forwarder rather than creating duplicates.
Recover from conflict
Aconflict error (exit 1, HTTP 409/412) means the state changed under you between read and write — a forwarder was paused by someone else, or a job already moved on. Don’t retry blindly: re-read the current state, reconcile, then retry the mutation. The full error contract is in Output & errors.
Continue
Replay deliveries
The full replay flow: dry-run, selectors, idempotency, and exit-code waiting.
Guard a deployment
Pause forwarders around a deploy and gate on health.
Provision a target
Create a bucket and forwarder idempotently.