Skip to main content
A write in Repost is not a simulation. Replaying an event re-delivers it to the live target; pausing a forwarder stops real traffic; provisioning creates real infrastructure. Every mutating command an agent runs follows the same shape — learn it once here, then each playbook shows its command-specific parts.

What mutates

CommandEffectScopeGuard
replayRe-delivers events to a live targetwrite--dry-run, --yes for bulk, --idempotency-key
forwarder pause / resume / disableStarts, stops, or retires deliverywriteExplicit --bucket + --forwarder (no picker)
bucket create / forwarder createProvisions a new routewritePositional name; re-check before re-creating
initProvisions a bucket + forwarder togetherwrite--idempotency-key (idempotent by design)
Read-only commands (events, forwards, health, whoami, capabilities, docs) never need these guards — this page applies only to the writes above.

The pattern

1

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.
2

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.
3

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.
4

Make it idempotent

Pass --idempotency-key so a retried command re-attaches to the existing work instead of doing it twice.
5

Gate bulk behind --yes

Agents run non-interactively, so bulk mutations refuse to proceed without --yes. Pass it deliberately, not reflexively.
6

Wait, then branch on the exit code

Don’t assume success. Wait for terminal state (replay wait, or re-verify with health) and branch on the exit code — never the status string.

Run non-interactively

A human running forwarder 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:
CommandRequired selectors
replay--forwarder (and --bucket when the forwarder is named)
forwarder pause / resume / disable--bucket (-b) and --forwarder (-f)
bucket create / forwarder createThe 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.
{ "schema": "repost.replay.create/v1", "data": { "job_id": "rpl_01JZ9F2K7M", "status": "IN_PROGRESS", "deduplicated": true } }
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

A conflict 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.