Resend CLI: Send Production Emails Directly From Your Terminal
If you're building a SaaS product, side project, or automation pipeline, you've probably needed to send transactional emails.
Resend CLI is the official command-line tool from Resend that lets you send emails, manage domains, and automate workflows - all without leaving your terminal.
This guide covers everything from installation to production use cases.

Resend CLI
Why Use Resend CLI Instead of the SDK?
The Resend Node.js SDK is great for application code, but the CLI shines in different scenarios:
Quick testing without writing code
Send test emails instantly to verify templates, check deliverability, or debug formatting.
CI/CD pipeline notifications
Send deployment alerts, build status updates, or error reports directly from GitHub Actions, Jenkins, or CircleCI.
Local development workflows
Test email flows without spinning up your entire application stack.
Script automation
Integrate email sending into bash scripts, cron jobs, or data processing pipelines.
AI agent integrations
Built for machine-readable output — perfect for AI coding assistants like Cursor or Claude Desktop.
The CLI is built for humans and machines — interactive when you need it, scriptable when you don't.
Installation (4 Different Methods)
cURL (Fastest for Linux/macOS)
curl -fsSL https://resend.com/install.sh | bashThis installs the binary to ~/.resend/bin/ and updates your PATH automatically.
Node.js (Cross-platform)
npm install -g resend-cliRequires Node.js 20+. Works everywhere npm does.
Homebrew (macOS/Linux)
brew install resend/cli/resendKeeps the CLI updated through Homebrew's update cycle.
PowerShell (Windows)
irm https://resend.com/install.ps1 | iexOr download the .exe directly from GitHub releases.
Authentication: 3 Ways to Provide Your API Key
The CLI resolves your Resend API key using this priority chain:
-
--api-keyflag (highest priority)resend --api-key re_xxx emails send ... -
RESEND_API_KEYenvironment variableexport RESEND_API_KEY=re_xxxresend emails send ... -
Config file (lowest priority)
resend login
If no key is found, the CLI exits with error code auth_error.
Interactive Login
resend loginThe CLI will:
- Check for an existing key
- Offer to open your Resend dashboard to create one
- Prompt for the key with masked input
- Validate it against the API before saving
Your key is stored at ~/.config/resend/credentials.json with 0600 permissions (owner read/write only).
Non-interactive Login (CI/CD)
resend login --key re_xxxxxxxxxxxxxNo prompts — perfect for CI pipelines.
Sending Your First Email
Basic Text Email
resend emails send \ --from "you@yourdomain.com" \ --to recipient@example.com \ --subject "Hello from the terminal" \ --text "This email was sent using Resend CLI."HTML Email
resend emails send \ --from "you@yourdomain.com" \ --to recipient@example.com \ --subject "Weekly Newsletter" \ --html "<h1>Welcome</h1><p>Your HTML content here.</p>"HTML Email from File
resend emails send \ --from "you@yourdomain.com" \ --to recipient@example.com \ --subject "Newsletter" \ --html-file ./templates/newsletter.htmlThis is powerful for template-based workflows.
Advanced Email Options
Multiple Recipients
resend emails send \ --from "you@yourdomain.com" \ --to alice@example.com bob@example.com charlie@example.com \ --subject "Team update" \ --text "Hello everyone"Space-separated recipient list.
CC, BCC, and Reply-To
resend emails send \ --from "you@yourdomain.com" \ --to recipient@example.com \ --cc manager@example.com \ --bcc archive@example.com \ --reply-to noreply@example.com \ --subject "Meeting notes" \ --text "Attached are the notes from today's meeting."Using a Different API Key for One Command
resend --api-key re_other_key emails send \ --from "staging@yourdomain.com" \ --to test@example.com \ --subject "Staging test" \ --text "Testing with staging credentials"The --api-key flag overrides all other key sources.
Interactive vs Non-Interactive Mode
The CLI automatically detects whether you're running it in a terminal or a script.
Interactive Mode (Terminal)
When run in a TTY (terminal), missing required flags trigger prompts:
resend emails send# CLI will prompt for: from, to, subject, and bodyThis is perfect for quick manual sends.
Non-Interactive Mode (Scripts/CI)
When piped or run in CI, all required flags must be provided:
echo "" | resend emails send --from "you@yourdomain.com"# Error: Missing required flags: --to, --subjectThe CLI will not prompt — it will error with a list of missing fields.
Managing Multiple Accounts with Profiles
If you work across multiple Resend teams or use different API keys for staging/production, profiles make this easy.
Switch Between Profiles
resend auth switchInteractive profile switcher — no need to log out and back in.
Use a Specific Profile for One Command
resend domains list --profile productionresend emails send --profile staging --from ...The --profile (or -p) flag overrides the active profile.
CI/CD Integration Examples
GitHub Actions
name: Send Deployment Notificationon: push: branches: [main]jobs: notify: runs-on: ubuntu-latest env: RESEND_API_KEY: ${{ secrets.RESEND_API_KEY }} steps: - name: Install Resend CLI run: curl -fsSL https://resend.com/install.sh | bash - name: Send email run: | resend emails send \ --from "deploy@yourdomain.com" \ --to "team@yourdomain.com" \ --subject "Deploy complete: ${{ github.sha }}" \ --text "Version ${{ github.sha }} deployed successfully."GitLab CI
deploy_notify: stage: notify variables: RESEND_API_KEY: $RESEND_API_KEY script: - curl -fsSL https://resend.com/install.sh | bash - resend emails send --from "ci@yourdomain.com" --to "team@yourdomain.com" --subject "Build passed" --text "Deployment successful"CircleCI
version: 2.1jobs: notify: docker: - image: cimg/node:20.0 environment: RESEND_API_KEY: $RESEND_API_KEY steps: - run: npm install -g resend-cli - run: resend emails send --from "ci@yourdomain.com" --to "team@yourdomain.com" --subject "Pipeline complete" --text "Build finished"JSON Output for Scripting
The CLI automatically switches to JSON output when:
- Running in a non-TTY environment (pipes, CI)
- Using the
--jsonflag - Using the
--quietflag
Example: Extract Email ID
resend emails send \ --from "you@yourdomain.com" \ --to recipient@example.com \ --subject "Test" \ --text "Testing" \ --json | jq -r '.id'# Output: 49a3999c-0ce1-4ea6-ab68-afcd6dc2e794Example: Error Handling in Scripts
response=$(resend emails send --from ... --to ... --subject ... --text ... --json)if echo "$response" | jq -e '.error' > /dev/null 2>&1; then echo "Email send failed: $(echo "$response" | jq -r '.error.message')" exit 1else echo "Email sent successfully: $(echo "$response" | jq -r '.id')"fiEnvironment Diagnostics with resend doctor
The doctor command runs health checks on your CLI setup.
resend doctorChecks performed:
- CLI version (detects updates)
- API key presence and masking
- Domain verification status
- AI agent detection (Cursor, Claude Desktop, VS Code MCP)
Example Output
Resend Doctor ✔ CLI Version: v1.6.0 (latest) ✔ API Key: re_...xxxx (source: env) ✔ Domains: 2 verified, 0 pending ✔ AI Agents: Detected: Cursor, Claude DesktopJSON Mode for Automation
resend doctor --json | jq '.checks[] | select(.status == "fail")'Practical Use Cases for Solo Developers
1. Send yourself deployment alerts
# In your deploy scriptresend emails send \ --from "deploy@yourdomain.com" \ --to "you@yourdomain.com" \ --subject "Deploy successful: $(git rev-parse --short HEAD)" \ --text "Your changes are live."2. Test email templates locally
# Iterate on template designresend emails send \ --from "test@yourdomain.com" \ --to "you@yourdomain.com" \ --subject "Template preview" \ --html-file ./email-templates/welcome.html3. Send error reports from cron jobs
# In your cron scriptif ! ./backup.sh; then resend emails send \ --from "cron@yourdomain.com" \ --to "you@yourdomain.com" \ --subject "Backup failed" \ --text "Check server logs immediately."fi4. Send weekly analytics summaries
# Weekly report scriptreport=$(python generate_weekly_report.py)resend emails send \ --from "analytics@yourdomain.com" \ --to "you@yourdomain.com" \ --subject "Weekly Analytics: $(date +%Y-%m-%d)" \ --text "$report"Error Codes Reference
When things go wrong, the CLI exits with code 1 and outputs structured JSON.
| Error Code | Cause |
|---|---|
auth_error | No API key found or client creation failed |
missing_key | No --key provided in non-interactive mode |
invalid_key_format | Key does not start with re_ |
validation_failed | Resend API rejected the key |
missing_body | No --text, --html, or --html-file provided |
file_read_error | Could not read the file passed to --html-file |
send_error | Resend API returned an error |
Example error output:
{ "error": { "message": "No API key found", "code": "auth_error" }}Configuration File Locations
The CLI respects platform conventions:
| Platform | Config Directory | Install Directory |
|---|---|---|
| Linux | ~/.config/resend/ (respects $XDG_CONFIG_HOME) | ~/.resend/bin/ |
| macOS | ~/.config/resend/ | ~/.resend/bin/ |
| Windows | %APPDATA%\resend\ | %USERPROFILE%\.resend\bin\ |
Credentials file: credentials.json (0600 permissions)
When NOT to Use Resend CLI
The CLI is not ideal for:
- Application code — Use the Resend Node.js SDK or other SDKs
- Bulk email sends — Use the API's batch endpoint or SDK methods
- Complex templating logic — Better handled in application code with a templating engine
The CLI is for quick sends, testing, automation, and CI/CD — not for replacing your transactional email infrastructure.
Quick Comparison: CLI vs SDK vs API
| Feature | CLI | SDK | API |
|---|---|---|---|
| Install time | 1 command | npm install | No install |
| Auth | Login + profiles | Environment variable | API key in code |
| Use case | Terminal, CI/CD, scripts | Application code | Direct HTTP |
| Interactive | Yes (optional) | No | No |
| JSON output | Yes | Programmatic | JSON response |
| Best for | Testing, automation | Production apps | Custom integrations |
Final Thoughts
Resend CLI bridges the gap between "I need to send a quick email" and "I need to integrate email into my pipeline."
For solo developers and small teams, it's a productivity multiplier:
- No boilerplate code for one-off sends
- CI/CD notifications in 2 lines
- Local template testing without spinning up servers
- Profile switching for multi-account workflows
If you're already using Resend, the CLI is a tool you'll reach for daily.
Quick Reference
# Installcurl -fsSL https://resend.com/install.sh | bash# Authenticateresend login# Send emailresend emails send \ --from "you@yourdomain.com" \ --to recipient@example.com \ --subject "Subject" \ --text "Body"# Check setupresend doctor# Get helpresend --helpresend emails send --helpLinks
License: MIT
Maintained by: Resend
