resend-cli 1.8.0 → 1.9.0-preview-automations.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +278 -92
- package/dist/cli.cjs +307 -245
- package/package.json +9 -11
- package/skills/resend-cli/SKILL.md +49 -7
- package/skills/resend-cli/references/automations.md +166 -0
- package/skills/resend-cli/references/workflows.md +50 -2
package/README.md
CHANGED
|
@@ -41,9 +41,26 @@ irm https://resend.com/install.ps1 | iex
|
|
|
41
41
|
|
|
42
42
|
Or download the `.exe` directly from the [GitHub releases page](https://github.com/resend/resend-cli/releases/latest).
|
|
43
43
|
|
|
44
|
+
## Quickstart
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
# Authenticate
|
|
48
|
+
resend login
|
|
49
|
+
|
|
50
|
+
# Send an email
|
|
51
|
+
resend emails send \
|
|
52
|
+
--from "you@yourdomain.com" \
|
|
53
|
+
--to delivered@resend.dev \
|
|
54
|
+
--subject "Hello from Resend CLI" \
|
|
55
|
+
--text "Sent from my terminal."
|
|
56
|
+
|
|
57
|
+
# Check your environment
|
|
58
|
+
resend doctor
|
|
59
|
+
```
|
|
60
|
+
|
|
44
61
|
## Agent skills
|
|
45
62
|
|
|
46
|
-
This CLI ships with an [agent skill](skills/resend-cli/SKILL.md) that teaches AI coding agents (Cursor, Claude Code, Windsurf, etc.) how to use the Resend CLI effectively
|
|
63
|
+
This CLI ships with an [agent skill](skills/resend-cli/SKILL.md) that teaches AI coding agents (Cursor, Claude Code, Windsurf, etc.) how to use the Resend CLI effectively, including non-interactive flags, output formats, and common pitfalls.
|
|
47
64
|
|
|
48
65
|
To install skills for Resend's full platform (API, CLI, React Email, email best practices) from the [central skills repository](https://github.com/resend/resend-skills):
|
|
49
66
|
|
|
@@ -82,7 +99,7 @@ Use this when you want to change the CLI and run your build locally.
|
|
|
82
99
|
|
|
83
100
|
Output: `./dist/cli.cjs`
|
|
84
101
|
|
|
85
|
-
|
|
102
|
+
## Running the CLI locally
|
|
86
103
|
|
|
87
104
|
Use the dev script:
|
|
88
105
|
|
|
@@ -114,34 +131,17 @@ pnpm build:bin
|
|
|
114
131
|
|
|
115
132
|
Output: `./dist/resend`
|
|
116
133
|
|
|
117
|
-
## Quick start
|
|
118
|
-
|
|
119
|
-
```bash
|
|
120
|
-
# Authenticate
|
|
121
|
-
resend login
|
|
122
|
-
|
|
123
|
-
# Send an email
|
|
124
|
-
resend emails send \
|
|
125
|
-
--from "you@yourdomain.com" \
|
|
126
|
-
--to recipient@example.com \
|
|
127
|
-
--subject "Hello from Resend CLI" \
|
|
128
|
-
--text "Sent from my terminal."
|
|
129
|
-
|
|
130
|
-
# Check your environment
|
|
131
|
-
resend doctor
|
|
132
|
-
```
|
|
133
|
-
|
|
134
134
|
---
|
|
135
135
|
|
|
136
136
|
## Authentication
|
|
137
137
|
|
|
138
138
|
The CLI resolves your API key using the following priority chain:
|
|
139
139
|
|
|
140
|
-
| Priority
|
|
141
|
-
|
|
142
|
-
| 1 (highest) | `--api-key` flag
|
|
143
|
-
| 2
|
|
144
|
-
| 3 (lowest)
|
|
140
|
+
| Priority | Source | How to set |
|
|
141
|
+
| ----------- | ------------------------ | ----------------------------------------- |
|
|
142
|
+
| 1 (highest) | `--api-key` flag | `resend --api-key re_xxx emails send ...` |
|
|
143
|
+
| 2 | `RESEND_API_KEY` env var | `export RESEND_API_KEY=re_xxx` |
|
|
144
|
+
| 3 (lowest) | Config file | `resend login` |
|
|
145
145
|
|
|
146
146
|
If no key is found from any source, the CLI errors with code `auth_error`.
|
|
147
147
|
|
|
@@ -161,10 +161,10 @@ resend login
|
|
|
161
161
|
|
|
162
162
|
When run in a terminal, the command checks for an existing key:
|
|
163
163
|
|
|
164
|
-
- **No key found
|
|
165
|
-
- **Existing key found
|
|
164
|
+
- **No key found**: Offers to open the [Resend API keys dashboard](https://resend.com/api-keys) in your browser so you can create one, then prompts for the key.
|
|
165
|
+
- **Existing key found**: Shows the key source (`env`, `config`) and prompts for a new key to replace it.
|
|
166
166
|
|
|
167
|
-
|
|
167
|
+
Enter the key via a masked password input. Your key must start with `re_`.
|
|
168
168
|
|
|
169
169
|
#### Non-interactive mode (CI, pipes, scripts)
|
|
170
170
|
|
|
@@ -178,8 +178,8 @@ Omitting `--key` in non-interactive mode exits with error code `missing_key`.
|
|
|
178
178
|
|
|
179
179
|
#### Options
|
|
180
180
|
|
|
181
|
-
| Flag
|
|
182
|
-
|
|
181
|
+
| Flag | Description |
|
|
182
|
+
| ------------- | --------------------------------------------------- |
|
|
183
183
|
| `--key <key>` | API key to store (required in non-interactive mode) |
|
|
184
184
|
|
|
185
185
|
#### Output
|
|
@@ -194,15 +194,15 @@ resend login --key re_xxx --json
|
|
|
194
194
|
|
|
195
195
|
#### Error codes
|
|
196
196
|
|
|
197
|
-
| Code
|
|
198
|
-
|
|
199
|
-
| `missing_key`
|
|
200
|
-
| `invalid_key_format` | Key does not start with `re_`
|
|
201
|
-
| `validation_failed`
|
|
197
|
+
| Code | Cause |
|
|
198
|
+
| -------------------- | ------------------------------------------- |
|
|
199
|
+
| `missing_key` | No `--key` provided in non-interactive mode |
|
|
200
|
+
| `invalid_key_format` | Key does not start with `re_` |
|
|
201
|
+
| `validation_failed` | Resend API rejected the key |
|
|
202
202
|
|
|
203
203
|
#### Switch between teams and accounts
|
|
204
204
|
|
|
205
|
-
If you work across multiple Resend teams or accounts, the CLI handles that too.
|
|
205
|
+
If you work across multiple Resend teams or accounts, the CLI handles that, too.
|
|
206
206
|
|
|
207
207
|
Switch between profiles without logging in and out:
|
|
208
208
|
|
|
@@ -220,29 +220,31 @@ resend domains list --profile production
|
|
|
220
220
|
|
|
221
221
|
### `resend emails send`
|
|
222
222
|
|
|
223
|
-
Send an email via the Resend API.
|
|
223
|
+
Send an email via the Resend API.
|
|
224
|
+
|
|
225
|
+
Provide all options via flags for scripting, or let the CLI prompt interactively for missing fields.
|
|
224
226
|
|
|
225
227
|
```bash
|
|
226
228
|
resend emails send \
|
|
227
229
|
--from "Name <sender@yourdomain.com>" \
|
|
228
|
-
--to
|
|
230
|
+
--to delivered@resend.dev \
|
|
229
231
|
--subject "Subject line" \
|
|
230
232
|
--text "Plain text body"
|
|
231
233
|
```
|
|
232
234
|
|
|
233
235
|
#### Options
|
|
234
236
|
|
|
235
|
-
| Flag
|
|
236
|
-
|
|
237
|
-
| `--from <address>`
|
|
238
|
-
| `--to <addresses...>`
|
|
239
|
-
| `--subject <subject>`
|
|
240
|
-
| `--text <text>`
|
|
241
|
-
| `--html <html>`
|
|
242
|
-
| `--html-file <path>`
|
|
243
|
-
| `--cc <addresses...>`
|
|
244
|
-
| `--bcc <addresses...>` | No
|
|
245
|
-
| `--reply-to <address>` | No
|
|
237
|
+
| Flag | Required | Description |
|
|
238
|
+
| ---------------------- | -------------------------- | ------------------------------------------------------- |
|
|
239
|
+
| `--from <address>` | Yes | Sender email address (must be from a verified domain) |
|
|
240
|
+
| `--to <addresses...>` | Yes | One or more recipient email addresses (space-separated) |
|
|
241
|
+
| `--subject <subject>` | Yes | Email subject line |
|
|
242
|
+
| `--text <text>` | One of text/html/html-file | Plain text body |
|
|
243
|
+
| `--html <html>` | One of text/html/html-file | HTML body as a string |
|
|
244
|
+
| `--html-file <path>` | One of text/html/html-file | Path to an HTML file to use as body |
|
|
245
|
+
| `--cc <addresses...>` | No | CC recipients (space-separated) |
|
|
246
|
+
| `--bcc <addresses...>` | No | BCC recipients (space-separated) |
|
|
247
|
+
| `--reply-to <address>` | No | Reply-to email address |
|
|
246
248
|
|
|
247
249
|
#### Interactive mode
|
|
248
250
|
|
|
@@ -274,7 +276,7 @@ A body (`--text`, `--html`, or `--html-file`) is also required — omitting all
|
|
|
274
276
|
```bash
|
|
275
277
|
resend emails send \
|
|
276
278
|
--from "you@yourdomain.com" \
|
|
277
|
-
--to
|
|
279
|
+
--to delivered@resend.dev bounced@resend.dev \
|
|
278
280
|
--subject "Team update" \
|
|
279
281
|
--text "Hello everyone"
|
|
280
282
|
```
|
|
@@ -284,7 +286,7 @@ resend emails send \
|
|
|
284
286
|
```bash
|
|
285
287
|
resend emails send \
|
|
286
288
|
--from "you@yourdomain.com" \
|
|
287
|
-
--to
|
|
289
|
+
--to delivered@resend.dev \
|
|
288
290
|
--subject "Newsletter" \
|
|
289
291
|
--html-file ./newsletter.html
|
|
290
292
|
```
|
|
@@ -294,11 +296,11 @@ resend emails send \
|
|
|
294
296
|
```bash
|
|
295
297
|
resend emails send \
|
|
296
298
|
--from "you@yourdomain.com" \
|
|
297
|
-
--to
|
|
299
|
+
--to delivered@resend.dev \
|
|
298
300
|
--subject "Meeting notes" \
|
|
299
301
|
--text "See attached." \
|
|
300
302
|
--cc manager@example.com \
|
|
301
|
-
--bcc
|
|
303
|
+
--bcc delivered+1@resend.dev \
|
|
302
304
|
--reply-to noreply@example.com
|
|
303
305
|
```
|
|
304
306
|
|
|
@@ -307,7 +309,7 @@ resend emails send \
|
|
|
307
309
|
```bash
|
|
308
310
|
resend --api-key re_other_key emails send \
|
|
309
311
|
--from "you@yourdomain.com" \
|
|
310
|
-
--to
|
|
312
|
+
--to delivered@resend.dev \
|
|
311
313
|
--subject "Test" \
|
|
312
314
|
--text "Using a different key"
|
|
313
315
|
```
|
|
@@ -322,12 +324,12 @@ Returns the email ID on success:
|
|
|
322
324
|
|
|
323
325
|
#### Error codes
|
|
324
326
|
|
|
325
|
-
| Code
|
|
326
|
-
|
|
327
|
-
| `auth_error`
|
|
328
|
-
| `missing_body`
|
|
329
|
-
| `file_read_error` | Could not read the file passed to `--html-file`
|
|
330
|
-
| `send_error`
|
|
327
|
+
| Code | Cause |
|
|
328
|
+
| ----------------- | ------------------------------------------------ |
|
|
329
|
+
| `auth_error` | No API key found or client creation failed |
|
|
330
|
+
| `missing_body` | No `--text`, `--html`, or `--html-file` provided |
|
|
331
|
+
| `file_read_error` | Could not read the file passed to `--html-file` |
|
|
332
|
+
| `send_error` | Resend API returned an error |
|
|
331
333
|
|
|
332
334
|
---
|
|
333
335
|
|
|
@@ -341,12 +343,12 @@ resend doctor
|
|
|
341
343
|
|
|
342
344
|
#### Checks performed
|
|
343
345
|
|
|
344
|
-
| Check
|
|
345
|
-
|
|
346
|
-
| **CLI Version** | Running latest
|
|
347
|
-
| **API Key**
|
|
348
|
-
| **Domains**
|
|
349
|
-
| **AI Agents**
|
|
346
|
+
| Check | Pass | Warn | Fail |
|
|
347
|
+
| --------------- | --------------------------------------- | ---------------------------------------- | --------------- |
|
|
348
|
+
| **CLI Version** | Running latest | Update available or registry unreachable | — |
|
|
349
|
+
| **API Key** | Key found (shows masked key and source) | — | No key found |
|
|
350
|
+
| **Domains** | Verified domains exist | No domains or all pending verification | API key invalid |
|
|
351
|
+
| **AI Agents** | Lists detected agents (or none) | — | — |
|
|
350
352
|
|
|
351
353
|
The API key is always masked in output (e.g. `re_...xxxx`).
|
|
352
354
|
|
|
@@ -374,7 +376,11 @@ resend doctor --json
|
|
|
374
376
|
"ok": true,
|
|
375
377
|
"checks": [
|
|
376
378
|
{ "name": "CLI Version", "status": "pass", "message": "v0.1.0 (latest)" },
|
|
377
|
-
{
|
|
379
|
+
{
|
|
380
|
+
"name": "API Key",
|
|
381
|
+
"status": "pass",
|
|
382
|
+
"message": "re_...xxxx (source: env)"
|
|
383
|
+
},
|
|
378
384
|
{ "name": "Domains", "status": "pass", "message": "2 verified, 0 pending" },
|
|
379
385
|
{ "name": "AI Agents", "status": "pass", "message": "Detected: Cursor" }
|
|
380
386
|
]
|
|
@@ -385,12 +391,12 @@ Each check has a `status` of `pass`, `warn`, or `fail`. The top-level `ok` is `f
|
|
|
385
391
|
|
|
386
392
|
#### Detected AI agents
|
|
387
393
|
|
|
388
|
-
| Agent
|
|
389
|
-
|
|
390
|
-
| OpenClaw
|
|
391
|
-
| Cursor
|
|
392
|
-
| Claude Desktop | Platform-specific config file exists
|
|
393
|
-
| VS Code
|
|
394
|
+
| Agent | Detection method |
|
|
395
|
+
| -------------- | --------------------------------------- |
|
|
396
|
+
| OpenClaw | `~/clawd/skills` directory exists |
|
|
397
|
+
| Cursor | `~/.cursor` directory exists |
|
|
398
|
+
| Claude Desktop | Platform-specific config file exists |
|
|
399
|
+
| VS Code | `.vscode/mcp.json` in current directory |
|
|
394
400
|
|
|
395
401
|
#### Exit code
|
|
396
402
|
|
|
@@ -398,6 +404,166 @@ Exits `0` when all checks pass or warn. Exits `1` if any check fails.
|
|
|
398
404
|
|
|
399
405
|
---
|
|
400
406
|
|
|
407
|
+
### Webhooks
|
|
408
|
+
|
|
409
|
+
With the Resend CLI, you can manage webhook endpoints so your app receives real-time event notifications.
|
|
410
|
+
|
|
411
|
+
Payloads are signed with [Svix](https://docs.svix.com/receiving/verifying-payloads/how) headers (`svix-id`, `svix-timestamp`, `svix-signature`). Verify them in your app with the Resend SDK.
|
|
412
|
+
|
|
413
|
+
For example: `resend.webhooks.verify({ payload, headers, webhookSecret })`
|
|
414
|
+
|
|
415
|
+
There are many events that you can listen for in your application.
|
|
416
|
+
|
|
417
|
+
For example, you can:
|
|
418
|
+
|
|
419
|
+
- Set up a POST endpoint to unsubscribe users when an email bounces or they mark your email as spam.
|
|
420
|
+
- Notify yourself when you get a new subscriber using the `contact.created` event.
|
|
421
|
+
- Use an `email.received` webhook to set up an inbox for your agent and notify it when a new email is received.
|
|
422
|
+
|
|
423
|
+
#### Event types
|
|
424
|
+
|
|
425
|
+
| Category | Events |
|
|
426
|
+
| -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
427
|
+
| Email | `email.sent`, `email.delivered`, `email.delivery_delayed`, `email.bounced`, `email.complained`, `email.opened`, `email.clicked`, `email.failed`, `email.scheduled`, `email.suppressed`, `email.received` |
|
|
428
|
+
| Contact | `contact.created`, `contact.updated`, `contact.deleted` |
|
|
429
|
+
| Domain | `domain.created`, `domain.updated`, `domain.deleted` |
|
|
430
|
+
|
|
431
|
+
Use `all` with `--events` to subscribe to every event.
|
|
432
|
+
|
|
433
|
+
#### Subcommands
|
|
434
|
+
|
|
435
|
+
- `list`
|
|
436
|
+
- `create`
|
|
437
|
+
- `get`
|
|
438
|
+
- `update`
|
|
439
|
+
- `delete`
|
|
440
|
+
- `listen`
|
|
441
|
+
|
|
442
|
+
#### Aliases
|
|
443
|
+
|
|
444
|
+
- `webhooks ls` → `list`
|
|
445
|
+
- `webhooks rm` → `delete`
|
|
446
|
+
|
|
447
|
+
---
|
|
448
|
+
|
|
449
|
+
#### **`resend webhooks list`**
|
|
450
|
+
|
|
451
|
+
Lists existing webhooks.
|
|
452
|
+
|
|
453
|
+
Running `resend webhooks` with no subcommand runs `list`.
|
|
454
|
+
|
|
455
|
+
| Flag | Description |
|
|
456
|
+
| ------------------- | --------------------------------------------------------- |
|
|
457
|
+
| `--limit <n>` | Max webhooks to return (`1`–`100`, default `10`) |
|
|
458
|
+
| `--after <cursor>` | Return webhooks after this cursor (webhook ID; next page) |
|
|
459
|
+
| `--before <cursor>` | Return webhooks before this cursor (previous page) |
|
|
460
|
+
|
|
461
|
+
Only one of `--after` or `--before` may be used. The API response includes `has_more` when more pages exist.
|
|
462
|
+
|
|
463
|
+
```bash
|
|
464
|
+
resend webhooks list
|
|
465
|
+
resend webhooks list --limit 25
|
|
466
|
+
resend webhooks list --after wh_abc123 --json
|
|
467
|
+
```
|
|
468
|
+
|
|
469
|
+
#### **`resend webhooks create`**
|
|
470
|
+
|
|
471
|
+
Registers a new endpoint.
|
|
472
|
+
|
|
473
|
+
The endpoint must use **HTTPS**. The **`signing_secret`** in the response is shown **once**. Store it immediately to verify incoming payloads.
|
|
474
|
+
|
|
475
|
+
In interactive mode, the CLI can prompt for endpoint and events. In non-interactive mode (pipes, CI, `--json`), **`--endpoint` and `--events` are required.**
|
|
476
|
+
|
|
477
|
+
| Flag | Description |
|
|
478
|
+
| ---------------------- | ------------------------------------------------- |
|
|
479
|
+
| `--endpoint <url>` | HTTPS URL that receives webhook POSTs |
|
|
480
|
+
| `--events <events...>` | Event names (comma- or space-separated), or `all` |
|
|
481
|
+
|
|
482
|
+
```bash
|
|
483
|
+
resend webhooks create --endpoint https://app.example.com/hooks/resend --events all
|
|
484
|
+
resend webhooks create --endpoint https://app.example.com/hooks/resend --events email.sent email.bounced
|
|
485
|
+
resend webhooks create --endpoint https://app.example.com/hooks/resend --events email.sent,email.delivered
|
|
486
|
+
```
|
|
487
|
+
|
|
488
|
+
#### **`resend webhooks get`**
|
|
489
|
+
|
|
490
|
+
Fetches one webhook by ID.
|
|
491
|
+
|
|
492
|
+
Omit the ID in a terminal to pick from a list.
|
|
493
|
+
|
|
494
|
+
```bash
|
|
495
|
+
resend webhooks get wh_abc123
|
|
496
|
+
resend webhooks get wh_abc123 --json
|
|
497
|
+
```
|
|
498
|
+
|
|
499
|
+
The signing secret is not returned from `get`. To rotate secrets, delete the webhook and create a new one.
|
|
500
|
+
|
|
501
|
+
#### **`resend webhooks update`**
|
|
502
|
+
|
|
503
|
+
Updates the webhook:
|
|
504
|
+
|
|
505
|
+
- endpoint URL
|
|
506
|
+
- the full event list
|
|
507
|
+
- delivery status
|
|
508
|
+
|
|
509
|
+
**At least one** of `--endpoint`, `--events`, or `--status` is required.
|
|
510
|
+
|
|
511
|
+
| Flag | Description |
|
|
512
|
+
| ---------------------- | ------------------------ |
|
|
513
|
+
| `--endpoint <url>` | New HTTPS URL |
|
|
514
|
+
| `--events <events...>` | New event list, or `all` |
|
|
515
|
+
| `--status <status>` | `enabled` or `disabled` |
|
|
516
|
+
|
|
517
|
+
Disabled status pauses delivery without deleting the webhook.
|
|
518
|
+
|
|
519
|
+
```bash
|
|
520
|
+
resend webhooks update wh_abc123 --status disabled
|
|
521
|
+
resend webhooks update wh_abc123 --endpoint https://new-app.example.com/hooks/resend
|
|
522
|
+
resend webhooks update wh_abc123 --events email.sent email.bounced
|
|
523
|
+
```
|
|
524
|
+
|
|
525
|
+
#### **`resend webhooks delete`**
|
|
526
|
+
|
|
527
|
+
Deletes a webhook and stops deliveries.
|
|
528
|
+
|
|
529
|
+
In non-interactive mode, **`--yes` is required** to confirm.
|
|
530
|
+
|
|
531
|
+
```bash
|
|
532
|
+
resend webhooks delete wh_abc123 --yes
|
|
533
|
+
```
|
|
534
|
+
|
|
535
|
+
To pause delivery temporarily, prefer `resend webhooks update <id> --status disabled`.
|
|
536
|
+
|
|
537
|
+
#### **`resend webhooks listen`**
|
|
538
|
+
|
|
539
|
+
Built-in local development helper. It:
|
|
540
|
+
|
|
541
|
+
- Starts a small HTTP server
|
|
542
|
+
- Registers a temporary Resend webhook pointing at your public tunnel URL
|
|
543
|
+
- Prints events in the terminal
|
|
544
|
+
- Deletes the webhook on exit
|
|
545
|
+
|
|
546
|
+
Your tunnel must forward to the same port as `--port`, e.g. `ngrok http 4318`.
|
|
547
|
+
|
|
548
|
+
| Flag | Description |
|
|
549
|
+
| ---------------------- | ------------------------------------------------------------ |
|
|
550
|
+
| `--url <url>` | Public URL (tunnel) that reaches this machine — **required** |
|
|
551
|
+
| `--port <port>` | Local server port (default `4318`) |
|
|
552
|
+
| `--events <events...>` | Events to subscribe to (default: all) |
|
|
553
|
+
| `--forward-to <url>` | Also POST each payload to this URL (Svix headers preserved) |
|
|
554
|
+
|
|
555
|
+
```bash
|
|
556
|
+
# Terminal 1: tunnel to the listen port
|
|
557
|
+
ngrok http 4318
|
|
558
|
+
|
|
559
|
+
# Terminal 2: use the HTTPS URL ngrok gives you
|
|
560
|
+
resend webhooks listen --url https://xxxx.ngrok-free.app
|
|
561
|
+
resend webhooks listen --url https://xxxx.ngrok-free.app --forward-to localhost:3000/api/webhooks/resend
|
|
562
|
+
resend webhooks listen --url https://xxxx.ngrok-free.app --port 8080 --events email.sent email.bounced
|
|
563
|
+
```
|
|
564
|
+
|
|
565
|
+
---
|
|
566
|
+
|
|
401
567
|
## Global options
|
|
402
568
|
|
|
403
569
|
These flags work on every command and are passed before the subcommand:
|
|
@@ -406,14 +572,14 @@ These flags work on every command and are passed before the subcommand:
|
|
|
406
572
|
resend [global options] <command> [command options]
|
|
407
573
|
```
|
|
408
574
|
|
|
409
|
-
| Flag
|
|
410
|
-
|
|
411
|
-
| `--api-key <key>`
|
|
412
|
-
| `-p, --profile <name>` | Profile to use (overrides `RESEND_PROFILE` env var)
|
|
413
|
-
| `--json`
|
|
414
|
-
| `-q, --quiet`
|
|
415
|
-
| `--version`
|
|
416
|
-
| `--help`
|
|
575
|
+
| Flag | Description |
|
|
576
|
+
| ---------------------- | ------------------------------------------------------------- |
|
|
577
|
+
| `--api-key <key>` | Override API key for this invocation (takes highest priority) |
|
|
578
|
+
| `-p, --profile <name>` | Profile to use (overrides `RESEND_PROFILE` env var) |
|
|
579
|
+
| `--json` | Force JSON output even in interactive terminals |
|
|
580
|
+
| `-q, --quiet` | Suppress spinners and status output (implies `--json`) |
|
|
581
|
+
| `--version` | Print version and exit |
|
|
582
|
+
| `--help` | Show help text |
|
|
417
583
|
|
|
418
584
|
---
|
|
419
585
|
|
|
@@ -421,10 +587,10 @@ resend [global options] <command> [command options]
|
|
|
421
587
|
|
|
422
588
|
The CLI has two output modes:
|
|
423
589
|
|
|
424
|
-
| Mode
|
|
425
|
-
|
|
426
|
-
| **Interactive** | Terminal (TTY)
|
|
427
|
-
| **Machine**
|
|
590
|
+
| Mode | When | Stdout | Stderr |
|
|
591
|
+
| --------------- | ---------------------- | ------------------- | ---------------------------------------- |
|
|
592
|
+
| **Interactive** | Terminal (TTY) | Formatted text | Spinners, prompts, human-readable errors |
|
|
593
|
+
| **Machine** | Piped, CI, or `--json` | Success JSON only | JSON errors; optional warnings (e.g. flags) |
|
|
428
594
|
|
|
429
595
|
Switching is automatic — pipe to another command and JSON output activates:
|
|
430
596
|
|
|
@@ -435,12 +601,16 @@ resend emails send --from ... --to ... --subject ... --text ... | jq '.id'
|
|
|
435
601
|
|
|
436
602
|
### Error output
|
|
437
603
|
|
|
438
|
-
Errors always exit with code `1
|
|
604
|
+
Errors always exit with code `1`. The format on **stderr** depends on output mode (same rules as the table above):
|
|
605
|
+
|
|
606
|
+
- **Machine** (piped stdout, CI, `--json`, or `-q`): structured JSON so **stdout** stays success-only for scripting (`jq`, etc.):
|
|
439
607
|
|
|
440
608
|
```json
|
|
441
609
|
{ "error": { "message": "No API key found", "code": "auth_error" } }
|
|
442
610
|
```
|
|
443
611
|
|
|
612
|
+
- **Interactive** (TTY without `--json` / `-q`): a human-readable line such as `Error: No API key found` (still on stderr).
|
|
613
|
+
|
|
444
614
|
---
|
|
445
615
|
|
|
446
616
|
## Agent & CI/CD usage
|
|
@@ -457,7 +627,7 @@ steps:
|
|
|
457
627
|
- run: |
|
|
458
628
|
resend emails send \
|
|
459
629
|
--from "deploy@yourdomain.com" \
|
|
460
|
-
--to "
|
|
630
|
+
--to "delivered@resend.com" \
|
|
461
631
|
--subject "Deploy complete" \
|
|
462
632
|
--text "Version ${{ github.sha }} deployed."
|
|
463
633
|
```
|
|
@@ -467,19 +637,35 @@ steps:
|
|
|
467
637
|
Agents calling the CLI as a subprocess automatically get JSON output (non-TTY detection). The contract:
|
|
468
638
|
|
|
469
639
|
- **Input:** All required flags must be provided (no interactive prompts)
|
|
470
|
-
- **Output:** JSON
|
|
640
|
+
- **Output:** Success JSON on stdout; error JSON on stderr (use `2>` or combined capture if you need both)
|
|
471
641
|
- **Exit code:** `0` success, `1` error
|
|
472
642
|
- **Errors:** Always include `message` and `code` fields
|
|
643
|
+
- **Discovery:** `resend commands` prints the full command tree as JSON (subcommands, options, descriptions).
|
|
644
|
+
|
|
645
|
+
### `resend commands`
|
|
646
|
+
|
|
647
|
+
Prints the CLI command tree as JSON for scripting and AI agents. In an interactive terminal, pass global `--json` if you need machine output; when stdout is piped, JSON is used automatically.
|
|
648
|
+
|
|
649
|
+
---
|
|
650
|
+
|
|
651
|
+
## Dry-run (no API call)
|
|
652
|
+
|
|
653
|
+
`--dry-run` is only implemented where agents most often need to **validate a complex payload** before a high-impact send:
|
|
654
|
+
|
|
655
|
+
- **`resend emails send ... --dry-run`** — validates inputs and prints `{ "dryRun": true, "request": { ... } }` without sending. Attachments appear as `filename` and `byteLength` only.
|
|
656
|
+
- **`resend broadcasts create ... --dry-run`** — same for the broadcast create payload.
|
|
657
|
+
|
|
658
|
+
Other write commands (batch, `broadcasts send`, webhooks, contacts, etc.) do not support `--dry-run` yet. If that would help your workflow, open an issue — likely next candidates are **`emails batch`** (large JSON files) and **`broadcasts send`** (confirm id + schedule before delivery).
|
|
473
659
|
|
|
474
660
|
---
|
|
475
661
|
|
|
476
662
|
## Configuration
|
|
477
663
|
|
|
478
|
-
| Item
|
|
479
|
-
|
|
480
|
-
| Config directory
|
|
481
|
-
| Credentials
|
|
482
|
-
| Install directory | `~/.resend/bin/`
|
|
664
|
+
| Item | Path | Notes |
|
|
665
|
+
| ----------------- | ----------------------------------- | ------------------------------------------------------------ |
|
|
666
|
+
| Config directory | `~/.config/resend/` | Respects `$XDG_CONFIG_HOME` on Linux, `%APPDATA%` on Windows |
|
|
667
|
+
| Credentials | `~/.config/resend/credentials.json` | `0600` permissions (owner read/write) |
|
|
668
|
+
| Install directory | `~/.resend/bin/` | Respects `$RESEND_INSTALL` |
|
|
483
669
|
|
|
484
670
|
## License
|
|
485
671
|
|