resend-cli 1.2.1 → 1.2.2

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.
Files changed (191) hide show
  1. package/biome.json +1 -1
  2. package/bun.lock +0 -3
  3. package/package.json +2 -3
  4. package/src/cli.ts +11 -1
  5. package/src/commands/auth/login.ts +35 -8
  6. package/src/commands/doctor.ts +33 -115
  7. package/src/commands/teams/remove.ts +5 -2
  8. package/src/commands/teams/switch.ts +3 -0
  9. package/src/lib/config.ts +37 -31
  10. package/src/lib/spinner.ts +17 -10
  11. package/src/lib/update-check.ts +172 -0
  12. package/tests/commands/auth/login.test.ts +37 -0
  13. package/tests/lib/config.test.ts +38 -7
  14. package/tests/lib/update-check.test.ts +169 -0
  15. package/.claude/worktrees/emails-list/.claude/settings.local.json +0 -5
  16. package/.claude/worktrees/emails-list/.github/scripts/pr-title-check.js +0 -34
  17. package/.claude/worktrees/emails-list/.github/workflows/ci.yml +0 -32
  18. package/.claude/worktrees/emails-list/.github/workflows/pr-title-check.yml +0 -13
  19. package/.claude/worktrees/emails-list/.github/workflows/release.yml +0 -93
  20. package/.claude/worktrees/emails-list/CHANGELOG.md +0 -31
  21. package/.claude/worktrees/emails-list/LICENSE +0 -21
  22. package/.claude/worktrees/emails-list/README.md +0 -424
  23. package/.claude/worktrees/emails-list/biome.json +0 -36
  24. package/.claude/worktrees/emails-list/bun.lock +0 -76
  25. package/.claude/worktrees/emails-list/bunfig.toml +0 -2
  26. package/.claude/worktrees/emails-list/install.ps1 +0 -140
  27. package/.claude/worktrees/emails-list/install.sh +0 -301
  28. package/.claude/worktrees/emails-list/package.json +0 -43
  29. package/.claude/worktrees/emails-list/renovate.json +0 -6
  30. package/.claude/worktrees/emails-list/src/cli.ts +0 -74
  31. package/.claude/worktrees/emails-list/src/commands/api-keys/create.ts +0 -114
  32. package/.claude/worktrees/emails-list/src/commands/api-keys/delete.ts +0 -47
  33. package/.claude/worktrees/emails-list/src/commands/api-keys/index.ts +0 -26
  34. package/.claude/worktrees/emails-list/src/commands/api-keys/list.ts +0 -35
  35. package/.claude/worktrees/emails-list/src/commands/api-keys/utils.ts +0 -8
  36. package/.claude/worktrees/emails-list/src/commands/auth/index.ts +0 -20
  37. package/.claude/worktrees/emails-list/src/commands/auth/login.ts +0 -207
  38. package/.claude/worktrees/emails-list/src/commands/auth/logout.ts +0 -105
  39. package/.claude/worktrees/emails-list/src/commands/broadcasts/create.ts +0 -196
  40. package/.claude/worktrees/emails-list/src/commands/broadcasts/delete.ts +0 -46
  41. package/.claude/worktrees/emails-list/src/commands/broadcasts/get.ts +0 -59
  42. package/.claude/worktrees/emails-list/src/commands/broadcasts/index.ts +0 -43
  43. package/.claude/worktrees/emails-list/src/commands/broadcasts/list.ts +0 -60
  44. package/.claude/worktrees/emails-list/src/commands/broadcasts/send.ts +0 -56
  45. package/.claude/worktrees/emails-list/src/commands/broadcasts/update.ts +0 -95
  46. package/.claude/worktrees/emails-list/src/commands/broadcasts/utils.ts +0 -35
  47. package/.claude/worktrees/emails-list/src/commands/contact-properties/create.ts +0 -118
  48. package/.claude/worktrees/emails-list/src/commands/contact-properties/delete.ts +0 -48
  49. package/.claude/worktrees/emails-list/src/commands/contact-properties/get.ts +0 -46
  50. package/.claude/worktrees/emails-list/src/commands/contact-properties/index.ts +0 -48
  51. package/.claude/worktrees/emails-list/src/commands/contact-properties/list.ts +0 -68
  52. package/.claude/worktrees/emails-list/src/commands/contact-properties/update.ts +0 -88
  53. package/.claude/worktrees/emails-list/src/commands/contact-properties/utils.ts +0 -17
  54. package/.claude/worktrees/emails-list/src/commands/contacts/add-segment.ts +0 -78
  55. package/.claude/worktrees/emails-list/src/commands/contacts/create.ts +0 -122
  56. package/.claude/worktrees/emails-list/src/commands/contacts/delete.ts +0 -49
  57. package/.claude/worktrees/emails-list/src/commands/contacts/get.ts +0 -53
  58. package/.claude/worktrees/emails-list/src/commands/contacts/index.ts +0 -58
  59. package/.claude/worktrees/emails-list/src/commands/contacts/list.ts +0 -57
  60. package/.claude/worktrees/emails-list/src/commands/contacts/remove-segment.ts +0 -48
  61. package/.claude/worktrees/emails-list/src/commands/contacts/segments.ts +0 -39
  62. package/.claude/worktrees/emails-list/src/commands/contacts/topics.ts +0 -45
  63. package/.claude/worktrees/emails-list/src/commands/contacts/update-topics.ts +0 -90
  64. package/.claude/worktrees/emails-list/src/commands/contacts/update.ts +0 -77
  65. package/.claude/worktrees/emails-list/src/commands/contacts/utils.ts +0 -119
  66. package/.claude/worktrees/emails-list/src/commands/doctor.ts +0 -298
  67. package/.claude/worktrees/emails-list/src/commands/domains/create.ts +0 -83
  68. package/.claude/worktrees/emails-list/src/commands/domains/delete.ts +0 -42
  69. package/.claude/worktrees/emails-list/src/commands/domains/get.ts +0 -47
  70. package/.claude/worktrees/emails-list/src/commands/domains/index.ts +0 -35
  71. package/.claude/worktrees/emails-list/src/commands/domains/list.ts +0 -53
  72. package/.claude/worktrees/emails-list/src/commands/domains/update.ts +0 -75
  73. package/.claude/worktrees/emails-list/src/commands/domains/utils.ts +0 -44
  74. package/.claude/worktrees/emails-list/src/commands/domains/verify.ts +0 -38
  75. package/.claude/worktrees/emails-list/src/commands/emails/batch.ts +0 -140
  76. package/.claude/worktrees/emails-list/src/commands/emails/index.ts +0 -28
  77. package/.claude/worktrees/emails-list/src/commands/emails/list.ts +0 -73
  78. package/.claude/worktrees/emails-list/src/commands/emails/receiving/attachment.ts +0 -55
  79. package/.claude/worktrees/emails-list/src/commands/emails/receiving/attachments.ts +0 -68
  80. package/.claude/worktrees/emails-list/src/commands/emails/receiving/get.ts +0 -58
  81. package/.claude/worktrees/emails-list/src/commands/emails/receiving/index.ts +0 -28
  82. package/.claude/worktrees/emails-list/src/commands/emails/receiving/list.ts +0 -59
  83. package/.claude/worktrees/emails-list/src/commands/emails/receiving/utils.ts +0 -38
  84. package/.claude/worktrees/emails-list/src/commands/emails/send.ts +0 -189
  85. package/.claude/worktrees/emails-list/src/commands/open.ts +0 -24
  86. package/.claude/worktrees/emails-list/src/commands/segments/create.ts +0 -50
  87. package/.claude/worktrees/emails-list/src/commands/segments/delete.ts +0 -47
  88. package/.claude/worktrees/emails-list/src/commands/segments/get.ts +0 -38
  89. package/.claude/worktrees/emails-list/src/commands/segments/index.ts +0 -36
  90. package/.claude/worktrees/emails-list/src/commands/segments/list.ts +0 -58
  91. package/.claude/worktrees/emails-list/src/commands/segments/utils.ts +0 -7
  92. package/.claude/worktrees/emails-list/src/commands/teams/index.ts +0 -10
  93. package/.claude/worktrees/emails-list/src/commands/teams/list.ts +0 -35
  94. package/.claude/worktrees/emails-list/src/commands/teams/remove.ts +0 -83
  95. package/.claude/worktrees/emails-list/src/commands/teams/switch.ts +0 -73
  96. package/.claude/worktrees/emails-list/src/commands/topics/create.ts +0 -73
  97. package/.claude/worktrees/emails-list/src/commands/topics/delete.ts +0 -47
  98. package/.claude/worktrees/emails-list/src/commands/topics/get.ts +0 -42
  99. package/.claude/worktrees/emails-list/src/commands/topics/index.ts +0 -42
  100. package/.claude/worktrees/emails-list/src/commands/topics/list.ts +0 -34
  101. package/.claude/worktrees/emails-list/src/commands/topics/update.ts +0 -59
  102. package/.claude/worktrees/emails-list/src/commands/topics/utils.ts +0 -16
  103. package/.claude/worktrees/emails-list/src/commands/webhooks/create.ts +0 -128
  104. package/.claude/worktrees/emails-list/src/commands/webhooks/delete.ts +0 -49
  105. package/.claude/worktrees/emails-list/src/commands/webhooks/get.ts +0 -42
  106. package/.claude/worktrees/emails-list/src/commands/webhooks/index.ts +0 -44
  107. package/.claude/worktrees/emails-list/src/commands/webhooks/list.ts +0 -55
  108. package/.claude/worktrees/emails-list/src/commands/webhooks/update.ts +0 -83
  109. package/.claude/worktrees/emails-list/src/commands/webhooks/utils.ts +0 -36
  110. package/.claude/worktrees/emails-list/src/commands/whoami.ts +0 -71
  111. package/.claude/worktrees/emails-list/src/lib/actions.ts +0 -157
  112. package/.claude/worktrees/emails-list/src/lib/client.ts +0 -34
  113. package/.claude/worktrees/emails-list/src/lib/config.ts +0 -211
  114. package/.claude/worktrees/emails-list/src/lib/files.ts +0 -15
  115. package/.claude/worktrees/emails-list/src/lib/help-text.ts +0 -38
  116. package/.claude/worktrees/emails-list/src/lib/output.ts +0 -54
  117. package/.claude/worktrees/emails-list/src/lib/pagination.ts +0 -36
  118. package/.claude/worktrees/emails-list/src/lib/prompts.ts +0 -149
  119. package/.claude/worktrees/emails-list/src/lib/spinner.ts +0 -93
  120. package/.claude/worktrees/emails-list/src/lib/table.ts +0 -57
  121. package/.claude/worktrees/emails-list/src/lib/tty.ts +0 -28
  122. package/.claude/worktrees/emails-list/src/lib/version.ts +0 -4
  123. package/.claude/worktrees/emails-list/tests/commands/api-keys/create.test.ts +0 -195
  124. package/.claude/worktrees/emails-list/tests/commands/api-keys/delete.test.ts +0 -156
  125. package/.claude/worktrees/emails-list/tests/commands/api-keys/list.test.ts +0 -133
  126. package/.claude/worktrees/emails-list/tests/commands/auth/login.test.ts +0 -119
  127. package/.claude/worktrees/emails-list/tests/commands/auth/logout.test.ts +0 -146
  128. package/.claude/worktrees/emails-list/tests/commands/broadcasts/create.test.ts +0 -447
  129. package/.claude/worktrees/emails-list/tests/commands/broadcasts/delete.test.ts +0 -182
  130. package/.claude/worktrees/emails-list/tests/commands/broadcasts/get.test.ts +0 -146
  131. package/.claude/worktrees/emails-list/tests/commands/broadcasts/list.test.ts +0 -196
  132. package/.claude/worktrees/emails-list/tests/commands/broadcasts/send.test.ts +0 -161
  133. package/.claude/worktrees/emails-list/tests/commands/broadcasts/update.test.ts +0 -283
  134. package/.claude/worktrees/emails-list/tests/commands/contact-properties/create.test.ts +0 -250
  135. package/.claude/worktrees/emails-list/tests/commands/contact-properties/delete.test.ts +0 -183
  136. package/.claude/worktrees/emails-list/tests/commands/contact-properties/get.test.ts +0 -144
  137. package/.claude/worktrees/emails-list/tests/commands/contact-properties/list.test.ts +0 -180
  138. package/.claude/worktrees/emails-list/tests/commands/contact-properties/update.test.ts +0 -216
  139. package/.claude/worktrees/emails-list/tests/commands/contacts/add-segment.test.ts +0 -188
  140. package/.claude/worktrees/emails-list/tests/commands/contacts/create.test.ts +0 -270
  141. package/.claude/worktrees/emails-list/tests/commands/contacts/delete.test.ts +0 -192
  142. package/.claude/worktrees/emails-list/tests/commands/contacts/get.test.ts +0 -148
  143. package/.claude/worktrees/emails-list/tests/commands/contacts/list.test.ts +0 -175
  144. package/.claude/worktrees/emails-list/tests/commands/contacts/remove-segment.test.ts +0 -166
  145. package/.claude/worktrees/emails-list/tests/commands/contacts/segments.test.ts +0 -167
  146. package/.claude/worktrees/emails-list/tests/commands/contacts/topics.test.ts +0 -163
  147. package/.claude/worktrees/emails-list/tests/commands/contacts/update-topics.test.ts +0 -247
  148. package/.claude/worktrees/emails-list/tests/commands/contacts/update.test.ts +0 -205
  149. package/.claude/worktrees/emails-list/tests/commands/doctor.test.ts +0 -165
  150. package/.claude/worktrees/emails-list/tests/commands/domains/create.test.ts +0 -192
  151. package/.claude/worktrees/emails-list/tests/commands/domains/delete.test.ts +0 -156
  152. package/.claude/worktrees/emails-list/tests/commands/domains/get.test.ts +0 -137
  153. package/.claude/worktrees/emails-list/tests/commands/domains/list.test.ts +0 -164
  154. package/.claude/worktrees/emails-list/tests/commands/domains/update.test.ts +0 -223
  155. package/.claude/worktrees/emails-list/tests/commands/domains/verify.test.ts +0 -117
  156. package/.claude/worktrees/emails-list/tests/commands/emails/batch.test.ts +0 -313
  157. package/.claude/worktrees/emails-list/tests/commands/emails/list.test.ts +0 -196
  158. package/.claude/worktrees/emails-list/tests/commands/emails/receiving/attachment.test.ts +0 -140
  159. package/.claude/worktrees/emails-list/tests/commands/emails/receiving/attachments.test.ts +0 -168
  160. package/.claude/worktrees/emails-list/tests/commands/emails/receiving/get.test.ts +0 -140
  161. package/.claude/worktrees/emails-list/tests/commands/emails/receiving/list.test.ts +0 -181
  162. package/.claude/worktrees/emails-list/tests/commands/emails/send.test.ts +0 -309
  163. package/.claude/worktrees/emails-list/tests/commands/segments/create.test.ts +0 -163
  164. package/.claude/worktrees/emails-list/tests/commands/segments/delete.test.ts +0 -182
  165. package/.claude/worktrees/emails-list/tests/commands/segments/get.test.ts +0 -137
  166. package/.claude/worktrees/emails-list/tests/commands/segments/list.test.ts +0 -173
  167. package/.claude/worktrees/emails-list/tests/commands/teams/list.test.ts +0 -63
  168. package/.claude/worktrees/emails-list/tests/commands/teams/remove.test.ts +0 -103
  169. package/.claude/worktrees/emails-list/tests/commands/teams/switch.test.ts +0 -96
  170. package/.claude/worktrees/emails-list/tests/commands/topics/create.test.ts +0 -191
  171. package/.claude/worktrees/emails-list/tests/commands/topics/delete.test.ts +0 -156
  172. package/.claude/worktrees/emails-list/tests/commands/topics/get.test.ts +0 -125
  173. package/.claude/worktrees/emails-list/tests/commands/topics/list.test.ts +0 -124
  174. package/.claude/worktrees/emails-list/tests/commands/topics/update.test.ts +0 -177
  175. package/.claude/worktrees/emails-list/tests/commands/webhooks/create.test.ts +0 -224
  176. package/.claude/worktrees/emails-list/tests/commands/webhooks/delete.test.ts +0 -156
  177. package/.claude/worktrees/emails-list/tests/commands/webhooks/get.test.ts +0 -125
  178. package/.claude/worktrees/emails-list/tests/commands/webhooks/list.test.ts +0 -177
  179. package/.claude/worktrees/emails-list/tests/commands/webhooks/update.test.ts +0 -206
  180. package/.claude/worktrees/emails-list/tests/commands/whoami.test.ts +0 -99
  181. package/.claude/worktrees/emails-list/tests/helpers.ts +0 -93
  182. package/.claude/worktrees/emails-list/tests/lib/client.test.ts +0 -71
  183. package/.claude/worktrees/emails-list/tests/lib/config.test.ts +0 -414
  184. package/.claude/worktrees/emails-list/tests/lib/files.test.ts +0 -65
  185. package/.claude/worktrees/emails-list/tests/lib/help-text.test.ts +0 -97
  186. package/.claude/worktrees/emails-list/tests/lib/output.test.ts +0 -127
  187. package/.claude/worktrees/emails-list/tests/lib/prompts.test.ts +0 -178
  188. package/.claude/worktrees/emails-list/tests/lib/spinner.test.ts +0 -146
  189. package/.claude/worktrees/emails-list/tests/lib/table.test.ts +0 -63
  190. package/.claude/worktrees/emails-list/tests/lib/tty.test.ts +0 -85
  191. package/.claude/worktrees/emails-list/tsconfig.json +0 -14
@@ -1,21 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) 2025 Resend
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
@@ -1,424 +0,0 @@
1
- # Resend CLI
2
-
3
- Command-line interface for the [Resend](https://resend.com) email API. Works for humans, AI agents, and CI/CD pipelines.
4
-
5
- ## Install
6
-
7
- ### Homebrew (macOS)
8
-
9
- ```bash
10
- brew install resend/cli/resend
11
- ```
12
-
13
- ### Shell script (macOS and Linux)
14
-
15
- ```bash
16
- curl -fsSL https://resend.com/install.sh | bash
17
- ```
18
-
19
- ## Local development
20
-
21
- Use this when you want to change the CLI and run your build locally.
22
-
23
- ### Prerequisites
24
-
25
- - [Bun](https://bun.sh) (runtime and package manager)
26
-
27
- ### Setup
28
-
29
- 1. **Clone the repo**
30
-
31
- ```bash
32
- git clone https://github.com/resend/resend-cli.git
33
- cd resend-cli
34
- ```
35
-
36
- 2. **Install dependencies**
37
-
38
- ```bash
39
- bun install
40
- ```
41
-
42
- 3. **Build locally**
43
-
44
- ```bash
45
- bun run build
46
- ```
47
-
48
- Output: `./dist/resend`
49
-
50
- ### Running the CLI locally
51
-
52
- Use the built binary directly:
53
-
54
- ```bash
55
- ./dist/resend --version
56
- ```
57
-
58
- Or add the project to your `PATH`:
59
-
60
- ```bash
61
- export PATH="$(pwd)/dist:$PATH"
62
- resend doctor
63
- ```
64
-
65
- ### Making changes
66
-
67
- After editing source files, rebuild:
68
-
69
- ```bash
70
- bun run build
71
- ```
72
-
73
- ## Quick start
74
-
75
- ```bash
76
- # Authenticate
77
- resend login
78
-
79
- # Send an email
80
- resend emails send \
81
- --from "you@yourdomain.com" \
82
- --to recipient@example.com \
83
- --subject "Hello from Resend CLI" \
84
- --text "Sent from my terminal."
85
-
86
- # Check your environment
87
- resend doctor
88
- ```
89
-
90
- ---
91
-
92
- ## Authentication
93
-
94
- The CLI resolves your API key using the following priority chain:
95
-
96
- | Priority | Source | How to set |
97
- |----------|--------|------------|
98
- | 1 (highest) | `--api-key` flag | `resend --api-key re_xxx emails send ...` |
99
- | 2 | `RESEND_API_KEY` env var | `export RESEND_API_KEY=re_xxx` |
100
- | 3 (lowest) | Config file | `resend login` |
101
-
102
- If no key is found from any source, the CLI errors with code `auth_error`.
103
-
104
- ---
105
-
106
- ## Commands
107
-
108
- ### `resend login`
109
-
110
- Authenticate by storing your API key locally. The key is validated against the Resend API before being saved.
111
-
112
- ```bash
113
- resend login
114
- ```
115
-
116
- #### Interactive mode (default in terminals)
117
-
118
- When run in a terminal, the command checks for an existing key:
119
-
120
- - **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.
121
- - **Existing key found** — Shows the key source (`env`, `config`) and prompts for a new key to replace it.
122
-
123
- The key is entered via a masked password input and must start with `re_`.
124
-
125
- #### Non-interactive mode (CI, pipes, scripts)
126
-
127
- When stdin is not a TTY, the `--key` flag is required:
128
-
129
- ```bash
130
- resend login --key re_xxxxxxxxxxxxx
131
- ```
132
-
133
- Omitting `--key` in non-interactive mode exits with error code `missing_key`.
134
-
135
- #### Options
136
-
137
- | Flag | Description |
138
- |------|-------------|
139
- | `--key <key>` | API key to store (required in non-interactive mode) |
140
-
141
- #### Output
142
-
143
- On success, credentials are saved to `~/.config/resend/credentials.json` with `0600` permissions (owner read/write only). The config directory is created with `0700` permissions.
144
-
145
- ```bash
146
- # JSON output
147
- resend login --key re_xxx --json
148
- # => {"success":true,"config_path":"/Users/you/.config/resend/credentials.json"}
149
- ```
150
-
151
- #### Error codes
152
-
153
- | Code | Cause |
154
- |------|-------|
155
- | `missing_key` | No `--key` provided in non-interactive mode |
156
- | `invalid_key_format` | Key does not start with `re_` |
157
- | `validation_failed` | Resend API rejected the key |
158
-
159
- ---
160
-
161
- ### `resend emails send`
162
-
163
- Send an email via the Resend API. Provide all options via flags for scripting, or let the CLI prompt interactively for missing fields.
164
-
165
- ```bash
166
- resend emails send \
167
- --from "Name <sender@yourdomain.com>" \
168
- --to recipient@example.com \
169
- --subject "Subject line" \
170
- --text "Plain text body"
171
- ```
172
-
173
- #### Options
174
-
175
- | Flag | Required | Description |
176
- |------|----------|-------------|
177
- | `--from <address>` | Yes | Sender email address (must be from a verified domain) |
178
- | `--to <addresses...>` | Yes | One or more recipient email addresses (space-separated) |
179
- | `--subject <subject>` | Yes | Email subject line |
180
- | `--text <text>` | One of text/html/html-file | Plain text body |
181
- | `--html <html>` | One of text/html/html-file | HTML body as a string |
182
- | `--html-file <path>` | One of text/html/html-file | Path to an HTML file to use as body |
183
- | `--cc <addresses...>` | No | CC recipients (space-separated) |
184
- | `--bcc <addresses...>` | No | BCC recipients (space-separated) |
185
- | `--reply-to <address>` | No | Reply-to email address |
186
-
187
- #### Interactive mode
188
-
189
- When run in a terminal without all required flags, the CLI prompts for missing fields:
190
-
191
- ```bash
192
- # prompts for from, to, subject, and body
193
- resend emails send
194
-
195
- # prompts only for missing fields
196
- resend emails send --from "you@yourdomain.com"
197
- ```
198
-
199
- #### Non-interactive mode
200
-
201
- When piped or run in CI, all required flags must be provided. Missing flags cause an error listing what's needed:
202
-
203
- ```bash
204
- echo "" | resend emails send --from "you@yourdomain.com"
205
- # Error: Missing required flags: --to, --subject
206
- ```
207
-
208
- A body (`--text`, `--html`, or `--html-file`) is also required — omitting all three exits with code `missing_body`.
209
-
210
- #### Examples
211
-
212
- **Multiple recipients:**
213
-
214
- ```bash
215
- resend emails send \
216
- --from "you@yourdomain.com" \
217
- --to alice@example.com bob@example.com \
218
- --subject "Team update" \
219
- --text "Hello everyone"
220
- ```
221
-
222
- **HTML from a file:**
223
-
224
- ```bash
225
- resend emails send \
226
- --from "you@yourdomain.com" \
227
- --to recipient@example.com \
228
- --subject "Newsletter" \
229
- --html-file ./newsletter.html
230
- ```
231
-
232
- **With CC, BCC, and reply-to:**
233
-
234
- ```bash
235
- resend emails send \
236
- --from "you@yourdomain.com" \
237
- --to recipient@example.com \
238
- --subject "Meeting notes" \
239
- --text "See attached." \
240
- --cc manager@example.com \
241
- --bcc archive@example.com \
242
- --reply-to noreply@example.com
243
- ```
244
-
245
- **Overriding the API key for one send:**
246
-
247
- ```bash
248
- resend --api-key re_other_key emails send \
249
- --from "you@yourdomain.com" \
250
- --to recipient@example.com \
251
- --subject "Test" \
252
- --text "Using a different key"
253
- ```
254
-
255
- #### Output
256
-
257
- Returns the email ID on success:
258
-
259
- ```json
260
- { "id": "49a3999c-0ce1-4ea6-ab68-afcd6dc2e794" }
261
- ```
262
-
263
- #### Error codes
264
-
265
- | Code | Cause |
266
- |------|-------|
267
- | `auth_error` | No API key found or client creation failed |
268
- | `missing_body` | No `--text`, `--html`, or `--html-file` provided |
269
- | `file_read_error` | Could not read the file passed to `--html-file` |
270
- | `send_error` | Resend API returned an error |
271
-
272
- ---
273
-
274
- ### `resend doctor`
275
-
276
- Run environment diagnostics. Verifies your CLI version, API key, domains, and detects AI agent integrations.
277
-
278
- ```bash
279
- resend doctor
280
- ```
281
-
282
- #### Checks performed
283
-
284
- | Check | Pass | Warn | Fail |
285
- |-------|------|------|------|
286
- | **CLI Version** | Running latest | Update available or registry unreachable | — |
287
- | **API Key** | Key found (shows masked key + source) | — | No key found |
288
- | **Domains** | Verified domains exist | No domains or all pending verification | API key invalid |
289
- | **AI Agents** | Lists detected agents (or none) | — | — |
290
-
291
- The API key is always masked in output (e.g. `re_...xxxx`).
292
-
293
- #### Interactive mode
294
-
295
- In a terminal, shows animated spinners for each check with colored status icons:
296
-
297
- ```
298
- Resend Doctor
299
-
300
- ✔ CLI Version: v0.1.0 (latest)
301
- ✔ API Key: re_...xxxx (source: env)
302
- ✔ Domains: 2 verified, 0 pending
303
- ✔ AI Agents: Detected: Cursor, Claude Desktop
304
- ```
305
-
306
- #### JSON mode
307
-
308
- ```bash
309
- resend doctor --json
310
- ```
311
-
312
- ```json
313
- {
314
- "ok": true,
315
- "checks": [
316
- { "name": "CLI Version", "status": "pass", "message": "v0.1.0 (latest)" },
317
- { "name": "API Key", "status": "pass", "message": "re_...xxxx (source: env)" },
318
- { "name": "Domains", "status": "pass", "message": "2 verified, 0 pending" },
319
- { "name": "AI Agents", "status": "pass", "message": "Detected: Cursor" }
320
- ]
321
- }
322
- ```
323
-
324
- Each check has a `status` of `pass`, `warn`, or `fail`. The top-level `ok` is `false` if any check is `fail`.
325
-
326
- #### Detected AI agents
327
-
328
- | Agent | Detection method |
329
- |-------|-----------------|
330
- | OpenClaw | `~/clawd/skills` directory exists |
331
- | Cursor | `~/.cursor` directory exists |
332
- | Claude Desktop | Platform-specific config file exists |
333
- | VS Code | `.vscode/mcp.json` in current directory |
334
-
335
- #### Exit code
336
-
337
- Exits `0` when all checks pass or warn. Exits `1` if any check fails.
338
-
339
- ---
340
-
341
- ## Global options
342
-
343
- These flags work on every command and are passed before the subcommand:
344
-
345
- ```bash
346
- resend [global options] <command> [command options]
347
- ```
348
-
349
- | Flag | Description |
350
- |------|-------------|
351
- | `--api-key <key>` | Override API key for this invocation (takes highest priority) |
352
- | `--json` | Force JSON output even in interactive terminals |
353
- | `--version` | Print version and exit |
354
- | `--help` | Show help text |
355
-
356
- ---
357
-
358
- ## Output behavior
359
-
360
- The CLI has two output modes:
361
-
362
- | Mode | When | Stdout | Stderr |
363
- |------|------|--------|--------|
364
- | **Interactive** | Terminal (TTY) | Formatted text | Spinners, prompts |
365
- | **Machine** | Piped, CI, or `--json` | JSON | Nothing |
366
-
367
- Switching is automatic — pipe to another command and JSON output activates:
368
-
369
- ```bash
370
- resend doctor | jq '.checks[].name'
371
- resend emails send --from ... --to ... --subject ... --text ... | jq '.id'
372
- ```
373
-
374
- ### Error output
375
-
376
- Errors always exit with code `1` and output structured JSON to stdout:
377
-
378
- ```json
379
- { "error": { "message": "No API key found", "code": "auth_error" } }
380
- ```
381
-
382
- ---
383
-
384
- ## Agent & CI/CD usage
385
-
386
- ### CI/CD
387
-
388
- Set `RESEND_API_KEY` as an environment variable — no `resend login` needed:
389
-
390
- ```yaml
391
- # GitHub Actions
392
- env:
393
- RESEND_API_KEY: ${{ secrets.RESEND_API_KEY }}
394
- steps:
395
- - run: |
396
- resend emails send \
397
- --from "deploy@yourdomain.com" \
398
- --to "team@yourdomain.com" \
399
- --subject "Deploy complete" \
400
- --text "Version ${{ github.sha }} deployed."
401
- ```
402
-
403
- ### AI agents
404
-
405
- Agents calling the CLI as a subprocess automatically get JSON output (non-TTY detection). The contract:
406
-
407
- - **Input:** All required flags must be provided (no interactive prompts)
408
- - **Output:** JSON to stdout, nothing to stderr
409
- - **Exit code:** `0` success, `1` error
410
- - **Errors:** Always include `message` and `code` fields
411
-
412
- ---
413
-
414
- ## Configuration
415
-
416
- | Item | Path | Notes |
417
- |------|------|-------|
418
- | Config directory | `~/.config/resend/` | Respects `$XDG_CONFIG_HOME` on Linux, `%APPDATA%` on Windows |
419
- | Credentials | `~/.config/resend/credentials.json` | `0600` permissions (owner read/write) |
420
- | Install directory | `~/.resend/bin/` | Respects `$RESEND_INSTALL` |
421
-
422
- ## License
423
-
424
- MIT
@@ -1,36 +0,0 @@
1
- {
2
- "$schema": "https://biomejs.dev/schemas/2.4.6/schema.json",
3
- "assist": {
4
- "actions": {
5
- "source": {
6
- "organizeImports": "on"
7
- }
8
- }
9
- },
10
- "formatter": {
11
- "indentStyle": "space",
12
- "indentWidth": 2,
13
- "lineWidth": 80
14
- },
15
- "javascript": {
16
- "formatter": {
17
- "quoteStyle": "single"
18
- }
19
- },
20
- "linter": {
21
- "enabled": true,
22
- "rules": {
23
- "recommended": true,
24
- "correctness": {
25
- "noUnusedImports": "error",
26
- "noUnusedVariables": "error"
27
- },
28
- "style": {
29
- "useBlockStatements": "error"
30
- }
31
- }
32
- },
33
- "files": {
34
- "includes": ["**", "!**/dist", "!**/bun.lock"]
35
- }
36
- }
@@ -1,76 +0,0 @@
1
- {
2
- "lockfileVersion": 1,
3
- "configVersion": 0,
4
- "workspaces": {
5
- "": {
6
- "name": "resend-cli",
7
- "dependencies": {
8
- "@clack/prompts": "1.1.0",
9
- "@commander-js/extra-typings": "14.0.0",
10
- "commander": "14.0.3",
11
- "resend": "6.9.3",
12
- "unicode-animations": "1.0.3",
13
- },
14
- "devDependencies": {
15
- "@biomejs/biome": "2.4.6",
16
- "@types/bun": "1.3.10",
17
- "typescript": "5.9.3",
18
- },
19
- },
20
- },
21
- "packages": {
22
- "@biomejs/biome": ["@biomejs/biome@2.4.6", "", { "optionalDependencies": { "@biomejs/cli-darwin-arm64": "2.4.6", "@biomejs/cli-darwin-x64": "2.4.6", "@biomejs/cli-linux-arm64": "2.4.6", "@biomejs/cli-linux-arm64-musl": "2.4.6", "@biomejs/cli-linux-x64": "2.4.6", "@biomejs/cli-linux-x64-musl": "2.4.6", "@biomejs/cli-win32-arm64": "2.4.6", "@biomejs/cli-win32-x64": "2.4.6" }, "bin": { "biome": "bin/biome" } }, "sha512-QnHe81PMslpy3mnpL8DnO2M4S4ZnYPkjlGCLWBZT/3R9M6b5daArWMMtEfP52/n174RKnwRIf3oT8+wc9ihSfQ=="],
23
-
24
- "@biomejs/cli-darwin-arm64": ["@biomejs/cli-darwin-arm64@2.4.6", "", { "os": "darwin", "cpu": "arm64" }, "sha512-NW18GSyxr+8sJIqgoGwVp5Zqm4SALH4b4gftIA0n62PTuBs6G2tHlwNAOj0Vq0KKSs7Sf88VjjmHh0O36EnzrQ=="],
25
-
26
- "@biomejs/cli-darwin-x64": ["@biomejs/cli-darwin-x64@2.4.6", "", { "os": "darwin", "cpu": "x64" }, "sha512-4uiE/9tuI7cnjtY9b07RgS7gGyYOAfIAGeVJWEfeCnAarOAS7qVmuRyX6d7JTKw28/mt+rUzMasYeZ+0R/U1Mw=="],
27
-
28
- "@biomejs/cli-linux-arm64": ["@biomejs/cli-linux-arm64@2.4.6", "", { "os": "linux", "cpu": "arm64" }, "sha512-kMLaI7OF5GN1Q8Doymjro1P8rVEoy7BKQALNz6fiR8IC1WKduoNyteBtJlHT7ASIL0Cx2jR6VUOBIbcB1B8pew=="],
29
-
30
- "@biomejs/cli-linux-arm64-musl": ["@biomejs/cli-linux-arm64-musl@2.4.6", "", { "os": "linux", "cpu": "arm64" }, "sha512-F/JdB7eN22txiTqHM5KhIVt0jVkzZwVYrdTR1O3Y4auBOQcXxHK4dxULf4z43QyZI5tsnQJrRBHZy7wwtL+B3A=="],
31
-
32
- "@biomejs/cli-linux-x64": ["@biomejs/cli-linux-x64@2.4.6", "", { "os": "linux", "cpu": "x64" }, "sha512-oHXmUFEoH8Lql1xfc3QkFLiC1hGR7qedv5eKNlC185or+o4/4HiaU7vYODAH3peRCfsuLr1g6v2fK9dFFOYdyw=="],
33
-
34
- "@biomejs/cli-linux-x64-musl": ["@biomejs/cli-linux-x64-musl@2.4.6", "", { "os": "linux", "cpu": "x64" }, "sha512-C9s98IPDu7DYarjlZNuzJKTjVHN03RUnmHV5htvqsx6vEUXCDSJ59DNwjKVD5XYoSS4N+BYhq3RTBAL8X6svEg=="],
35
-
36
- "@biomejs/cli-win32-arm64": ["@biomejs/cli-win32-arm64@2.4.6", "", { "os": "win32", "cpu": "arm64" }, "sha512-xzThn87Pf3YrOGTEODFGONmqXpTwUNxovQb72iaUOdcw8sBSY3+3WD8Hm9IhMYLnPi0n32s3L3NWU6+eSjfqFg=="],
37
-
38
- "@biomejs/cli-win32-x64": ["@biomejs/cli-win32-x64@2.4.6", "", { "os": "win32", "cpu": "x64" }, "sha512-7++XhnsPlr1HDbor5amovPjOH6vsrFOCdp93iKXhFn6bcMUI6soodj3WWKfgEO6JosKU1W5n3uky3WW9RlRjTg=="],
39
-
40
- "@clack/core": ["@clack/core@1.1.0", "", { "dependencies": { "sisteransi": "^1.0.5" } }, "sha512-SVcm4Dqm2ukn64/8Gub2wnlA5nS2iWJyCkdNHcvNHPIeBTGojpdJ+9cZKwLfmqy7irD4N5qLteSilJlE0WLAtA=="],
41
-
42
- "@clack/prompts": ["@clack/prompts@1.1.0", "", { "dependencies": { "@clack/core": "1.1.0", "sisteransi": "^1.0.5" } }, "sha512-pkqbPGtohJAvm4Dphs2M8xE29ggupihHdy1x84HNojZuMtFsHiUlRvqD24tM2+XmI+61LlfNceM3Wr7U5QES5g=="],
43
-
44
- "@commander-js/extra-typings": ["@commander-js/extra-typings@14.0.0", "", { "peerDependencies": { "commander": "~14.0.0" } }, "sha512-hIn0ncNaJRLkZrxBIp5AsW/eXEHNKYQBh0aPdoUqNgD+Io3NIykQqpKFyKcuasZhicGaEZJX/JBSIkZ4e5x8Dg=="],
45
-
46
- "@stablelib/base64": ["@stablelib/base64@1.0.1", "", {}, "sha512-1bnPQqSxSuc3Ii6MhBysoWCg58j97aUjuCSZrGSmDxNqtytIi0k8utUenAwTZN4V5mXXYGsVUI9zeBqy+jBOSQ=="],
47
-
48
- "@types/bun": ["@types/bun@1.3.10", "", { "dependencies": { "bun-types": "1.3.10" } }, "sha512-0+rlrUrOrTSskibryHbvQkDOWRJwJZqZlxrUs1u4oOoTln8+WIXBPmAuCF35SWB2z4Zl3E84Nl/D0P7803nigQ=="],
49
-
50
- "@types/node": ["@types/node@25.2.3", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-m0jEgYlYz+mDJZ2+F4v8D1AyQb+QzsNqRuI7xg1VQX/KlKS0qT9r1Mo16yo5F/MtifXFgaofIFsdFMox2SxIbQ=="],
51
-
52
- "bun-types": ["bun-types@1.3.10", "", { "dependencies": { "@types/node": "*" } }, "sha512-tcpfCCl6XWo6nCVnpcVrxQ+9AYN1iqMIzgrSKYMB/fjLtV2eyAVEg7AxQJuCq/26R6HpKWykQXuSOq/21RYcbg=="],
53
-
54
- "commander": ["commander@14.0.3", "", {}, "sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw=="],
55
-
56
- "fast-sha256": ["fast-sha256@1.3.0", "", {}, "sha512-n11RGP/lrWEFI/bWdygLxhI+pVeo1ZYIVwvvPkW7azl/rOy+F3HYRZ2K5zeE9mmkhQppyv9sQFx0JM9UabnpPQ=="],
57
-
58
- "postal-mime": ["postal-mime@2.7.3", "", {}, "sha512-MjhXadAJaWgYzevi46+3kLak8y6gbg0ku14O1gO/LNOuay8dO+1PtcSGvAdgDR0DoIsSaiIA8y/Ddw6MnrO0Tw=="],
59
-
60
- "resend": ["resend@6.9.3", "", { "dependencies": { "postal-mime": "2.7.3", "svix": "1.84.1" }, "peerDependencies": { "@react-email/render": "*" }, "optionalPeers": ["@react-email/render"] }, "sha512-GRXjH9XZBJA+daH7bBVDuTShr22iWCxXA8P7t495G4dM/RC+d+3gHBK/6bz9K6Vpcq11zRQKmD+B+jECwQlyGQ=="],
61
-
62
- "sisteransi": ["sisteransi@1.0.5", "", {}, "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg=="],
63
-
64
- "standardwebhooks": ["standardwebhooks@1.0.0", "", { "dependencies": { "@stablelib/base64": "^1.0.0", "fast-sha256": "^1.3.0" } }, "sha512-BbHGOQK9olHPMvQNHWul6MYlrRTAOKn03rOe4A8O3CLWhNf4YHBqq2HJKKC+sfqpxiBY52pNeesD6jIiLDz8jg=="],
65
-
66
- "svix": ["svix@1.84.1", "", { "dependencies": { "standardwebhooks": "1.0.0", "uuid": "^10.0.0" } }, "sha512-K8DPPSZaW/XqXiz1kEyzSHYgmGLnhB43nQCMeKjWGCUpLIpAMMM8kx3rVVOSm6Bo6EHyK1RQLPT4R06skM/MlQ=="],
67
-
68
- "typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
69
-
70
- "undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
71
-
72
- "unicode-animations": ["unicode-animations@1.0.3", "", { "dependencies": { "unicode-animations": "^1.0.1" }, "bin": { "unicode-animations": "scripts/demo.cjs" } }, "sha512-+klB2oWwcYZjYWhwP4Pr8UZffWDFVx6jKeIahE6z0QYyM2dwDeDPyn5nevCYbyotxvtT9lh21cVURO1RX0+YMg=="],
73
-
74
- "uuid": ["uuid@10.0.0", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ=="],
75
- }
76
- }
@@ -1,2 +0,0 @@
1
- [install]
2
- peer = false