Skip to main content
The Resend CLI works out of the box for AI agents and CI/CD pipelines. This page covers agent-specific behavior — see the CLI reference for installation, commands, and full documentation.

Agent Skills

The Resend CLI includes built-in Agent Skills that help AI agents understand how to use the CLI effectively. Install the skill using the following command:
npx skills add resend/resend-cli

Non-interactive mode

When the CLI detects a non-TTY environment (piped output, CI runner, or the --json flag), it automatically switches to machine-readable mode:
  • Output: JSON to stdout, no progress indicators
  • Exit codes: 0 for success, 1 for errors
  • Errors: Always include message and code fields
{ "error": { "message": "No API key found", "code": "auth_error" } }
All required flags must be provided — interactive prompts are disabled. Missing flags cause an error listing what’s needed.

Piping from stdin

Agents generate content on the fly. Pass - to read from stdin instead of writing temp files:
echo "Your order has shipped." | resend emails send \
  --from "Acme <onboarding@resend.dev>" \
  --to delivered@resend.dev \
  --subject "Order update" \
  --text-file -
This works with --html-file - on send and --file - on batch commands.

Batch sending

Send up to 100 emails in a single request by piping a JSON array into emails batch:
cat emails.json | resend emails batch --file -

Safe retries

Add --idempotency-key to prevent duplicates when your agent retries a failed request:
resend emails send \
  --from "Acme <onboarding@resend.dev>" \
  --to delivered@resend.dev \
  --subject "Welcome" \
  --text "Hello!" \
  --idempotency-key "welcome-user-123"
This flag is available on both emails send and emails batch.

Scheduling

The --scheduled-at flag accepts ISO 8601 timestamps and natural language:
resend emails send \
  --from "Acme <onboarding@resend.dev>" \
  --to delivered@resend.dev \
  --subject "Your trial ends soon" \
  --text "Your free trial expires in 3 days." \
  --scheduled-at "tomorrow at 9am ET"
Cancel or reschedule with resend emails cancel <id> and resend emails update <id> --scheduled-at <datetime>.

Reading inbound emails

Agents can process incoming email as an input source. Stream inbound emails as NDJSON with emails receiving listen:
resend emails receiving listen --json
Or fetch a specific email with full content and attachments:
resend emails receiving get <email-id>
This requires a verified domain with receiving enabled.

Closing the loop with webhooks

When an agent sends an email, it often needs to know what happened next — was it delivered, did it bounce, did the recipient reply? The webhooks listen command gives your agent a real-time feedback loop by streaming webhook events directly to the terminal.
resend webhooks listen \
  --url https://hostname.tailnet-name.ts.net \
  --events email.delivered email.bounced email.received
The CLI registers a temporary webhook, streams matching events as JSON to stdout, and deletes the webhook when you exit (Ctrl+C). Use --forward-to to pipe payloads to a local server for processing:
resend webhooks listen \
  --url https://hostname.tailnet-name.ts.net \
  --forward-to http://localhost:4321/api/webhook
The --url flag takes any public URL that points to the local server port (4318 by default). Use any tunnel — Tailscale Funnel, ngrok, localtunnel, etc.
For a permanent setup, deploy a webhook handler and register it via resend webhooks create pointing to your production URL.