Install the CLI globally:
npm i -g @rotorsh/cli
rotor --versionAuthenticate once, then all commands use your saved key:
rotor login
# Paste your rt_ws_* key. Saved to ~/.rotor/config.json (mode 0600).You can also pass the key inline via ROTOR_API_KEY — this takes precedence over the saved config.
rotor queues
rotor queues create
rotor queues create <name> [options]
Options:
--concurrency <n> Max jobs processed in parallel (default: 1)
--retry-attempts <n> Attempts per job before moving to DLQ (default: 3)
--callback-url <url> HTTPS URL Rotor POSTs each job to
--rotate-callback-secret Generate a new HMAC signing secret (printed once)rotor queues create enrichment \
--concurrency 10 \
--retry-attempts 5 \
--callback-url https://your-app.example.com/rotor/enrichmentrotor queues list
rotor queues list
# NAME CONCURRENCY JOBS (waiting/active/failed)
# enrichment 10 142 / 3 / 1
# outreach 5 0 / 0 / 0rotor queues get
rotor queues get <name>Prints full queue config: callback URL, retry settings, concurrency, metrics.
rotor queues update
rotor queues update <name> [options]
Options:
--concurrency <n>
--retry-attempts <n>
--callback-url <url>
--rotate-callback-secret Rotate the signing secret; new value printed once# Update callback URL and rotate the secret in one command
rotor queues update enrichment \
--callback-url https://new-host.example.com/rotor/enrichment \
--rotate-callback-secretrotor queues delete
rotor queues delete <name>
# Prompts for confirmation. Pass --force to skip.rotor jobs
rotor jobs enqueue
rotor jobs enqueue <queue> --payload <json> [options]
Options:
--payload <json> Job payload as a JSON string (required)
--delay <seconds> Delay before job becomes eligible
--tags <tag,...> Comma-separated list of tags
--concurrency-key <key> Mutual exclusion key (one job per key at a time)
--idempotency-key <key> Deduplicate — same key = same job, not a new onerotor jobs enqueue outreach \
--payload '{"contactId":"cid_123","campaignId":"camp_456"}' \
--tags "campaign:q2-outbound,contact:cid_123" \
--concurrency-key "contact:cid_123"rotor jobs get
rotor jobs get <queue> <jobId>Prints job state, payload, tags, retry count, timestamps, and failure reason if applicable.
rotor jobs list
rotor jobs list <queue> [options]
Options:
--status <state> Filter by state: waiting|active|completed|failed|delayed
--tag <tag> Filter by tag
--limit <n> Results per page (default: 50)rotor jobs list enrichment --status failed
rotor jobs list outreach --tag campaign:q2-outboundrotor jobs retry
rotor jobs retry <queue> <jobId>
# Moves a failed job back to waiting. Resets attempt count.rotor jobs cancel
rotor jobs cancel <queue> <jobId>
# Cancels a waiting or delayed job. Cannot cancel an active job.rotor schedules
rotor schedules create
rotor schedules create [options]
Options:
--queue <name> Queue to enqueue jobs into (required)
--cron <expression> Cron expression (required)
--timezone <tz> IANA timezone (required) — e.g. "America/New_York"
--name <name> Human-readable name for the schedule
--payload <json> Payload for each generated jobrotor schedules create \
--queue enrichment \
--cron "0 9 * * 1-5" \
--timezone "America/New_York" \
--name "weekday-morning-enrichment" \
--payload '{"source":"clearbit"}'rotor schedules list
rotor schedules list
# NAME CRON NEXT FIRE
# weekday-morning-enrichment 0 9 * * 1-5 2026-05-21T09:00:00-04:00rotor schedules pause
rotor schedules pause <name>
# No new jobs fire until resumed. In-flight jobs are not affected.rotor schedules resume
rotor schedules resume <name>rotor schedules delete
rotor schedules delete <name> [--force]rotor secrets
Secrets are workspace-scoped encrypted values. Reference them in callback URLs and job payloads as ${{ secrets.SECRET_NAME }} — Rotor injects the plaintext at dispatch time. The value never appears in your code or logs.
rotor secrets create
rotor secrets create <NAME> --value <value>
# Or pipe the value to avoid shell history:
echo -n "sk_live_abc123" | rotor secrets create STRIPE_KEY --stdinSecret names must be UPPER_SNAKE_CASE. Values are encrypted at rest (AES-256).
rotor secrets list
rotor secrets list
# NAME HINT CREATED
# STRIPE_KEY sk_li… 2026-05-01
# RESEND_KEY re_… 2026-05-10Only the masked hint is shown. Plaintext values are never returned after creation.
rotor secrets delete
rotor secrets delete <NAME> [--force]rotor status
rotor status
# API: ok
# Redis: ok
# Plan: pro
# Quota: 12,450 / 100,000 jobs used this period
# Resets: 2026-06-01Add --watch to poll every 5 seconds:
rotor status --watchrotor template
rotor template add <template-name>Scaffolds a starter workflow into your current directory. Available templates:
| Template | Description |
|---|---|
outbound-with-approvals | Multi-step outbound sequence with human approval gate |
multi-step-outbound | Email sequence with step.waitForEvent reply detection |
event-driven-enrichment | Parallel contact enrichment on campaign.started |
scheduled-with-approval | Weekly cron report requiring approval before delivery |
rotor template add outbound-with-approvalsGlobal flags
All commands accept:
--api-key <key> Override saved key for this command only
--json Output raw JSON instead of formatted table
--quiet Suppress all output except errors
--help Show help for any command