resend-cli 1.9.0-preview-automations.0 → 1.9.0

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 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 including non-interactive flags, output formats, and common pitfalls.
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
- ### Running the CLI locally
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 | 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` |
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** 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.
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
- The key is entered via a masked password input and must start with `re_`.
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 | Description |
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 | 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 |
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. Provide all options via flags for scripting, or let the CLI prompt interactively for missing fields.
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 recipient@example.com \
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 | Required | Description |
236
- |------|----------|-------------|
237
- | `--from <address>` | Yes | Sender email address (must be from a verified domain) |
238
- | `--to <addresses...>` | Yes | One or more recipient email addresses (space-separated) |
239
- | `--subject <subject>` | Yes | Email subject line |
240
- | `--text <text>` | One of text/html/html-file | Plain text body |
241
- | `--html <html>` | One of text/html/html-file | HTML body as a string |
242
- | `--html-file <path>` | One of text/html/html-file | Path to an HTML file to use as body |
243
- | `--cc <addresses...>` | No | CC recipients (space-separated) |
244
- | `--bcc <addresses...>` | No | BCC recipients (space-separated) |
245
- | `--reply-to <address>` | No | Reply-to email address |
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 alice@example.com bob@example.com \
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 recipient@example.com \
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 recipient@example.com \
299
+ --to delivered@resend.dev \
298
300
  --subject "Meeting notes" \
299
301
  --text "See attached." \
300
302
  --cc manager@example.com \
301
- --bcc archive@example.com \
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 recipient@example.com \
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 | Cause |
326
- |------|-------|
327
- | `auth_error` | No API key found or client creation failed |
328
- | `missing_body` | No `--text`, `--html`, or `--html-file` provided |
329
- | `file_read_error` | Could not read the file passed to `--html-file` |
330
- | `send_error` | Resend API returned an 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 | Pass | Warn | Fail |
345
- |-------|------|------|------|
346
- | **CLI Version** | Running latest | Update available or registry unreachable | — |
347
- | **API Key** | Key found (shows masked key + source) | — | No key found |
348
- | **Domains** | Verified domains exist | No domains or all pending verification | API key invalid |
349
- | **AI Agents** | Lists detected agents (or none) | — | — |
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
- { "name": "API Key", "status": "pass", "message": "re_...xxxx (source: env)" },
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 | Detection method |
389
- |-------|-----------------|
390
- | OpenClaw | `~/clawd/skills` directory exists |
391
- | Cursor | `~/.cursor` directory exists |
392
- | Claude Desktop | Platform-specific config file exists |
393
- | VS Code | `.vscode/mcp.json` in current directory |
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 | Description |
410
- |------|-------------|
411
- | `--api-key <key>` | Override API key for this invocation (takes highest priority) |
412
- | `-p, --profile <name>` | Profile to use (overrides `RESEND_PROFILE` env var) |
413
- | `--json` | Force JSON output even in interactive terminals |
414
- | `-q, --quiet` | Suppress spinners and status output (implies `--json`) |
415
- | `--version` | Print version and exit |
416
- | `--help` | Show help text |
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 | When | Stdout | Stderr |
425
- |------|------|--------|--------|
426
- | **Interactive** | Terminal (TTY) | Formatted text | Spinners, prompts |
427
- | **Machine** | Piped, CI, or `--json` | JSON | Nothing |
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` and output structured JSON to stdout:
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 "team@yourdomain.com" \
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 to stdout, nothing to stderr
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 | Path | Notes |
479
- |------|------|-------|
480
- | Config directory | `~/.config/resend/` | Respects `$XDG_CONFIG_HOME` on Linux, `%APPDATA%` on Windows |
481
- | Credentials | `~/.config/resend/credentials.json` | `0600` permissions (owner read/write) |
482
- | Install directory | `~/.resend/bin/` | Respects `$RESEND_INSTALL` |
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