superacli 1.1.5 → 1.1.6

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/__tests__/resend-plugin.test.js +22 -1
  2. package/package.json +1 -1
  3. package/plugins/plugins.json +2 -2
  4. package/plugins/resend/plugin.json +279 -2
  5. package/plugins/resend/skills/quickstart/SKILL.md +32 -13
  6. package/temp_resend_cli/repo/.github/scripts/pr-title-check.js +34 -0
  7. package/temp_resend_cli/repo/.github/workflows/ci.yml +67 -0
  8. package/temp_resend_cli/repo/.github/workflows/post-release.yml +51 -0
  9. package/temp_resend_cli/repo/.github/workflows/pr-title-check.yml +13 -0
  10. package/temp_resend_cli/repo/.github/workflows/release.yml +175 -0
  11. package/temp_resend_cli/repo/.github/workflows/test-install-unix.yml +34 -0
  12. package/temp_resend_cli/repo/.github/workflows/test-install-windows.yml +48 -0
  13. package/temp_resend_cli/repo/CHANGELOG.md +31 -0
  14. package/temp_resend_cli/repo/LICENSE +21 -0
  15. package/temp_resend_cli/repo/README.md +450 -0
  16. package/temp_resend_cli/repo/biome.json +36 -0
  17. package/temp_resend_cli/repo/install.ps1 +141 -0
  18. package/temp_resend_cli/repo/install.sh +301 -0
  19. package/temp_resend_cli/repo/package.json +61 -0
  20. package/temp_resend_cli/repo/pnpm-lock.yaml +2439 -0
  21. package/temp_resend_cli/repo/renovate.json +4 -0
  22. package/temp_resend_cli/repo/src/cli.ts +98 -0
  23. package/temp_resend_cli/repo/src/commands/api-keys/create.ts +114 -0
  24. package/temp_resend_cli/repo/src/commands/api-keys/delete.ts +47 -0
  25. package/temp_resend_cli/repo/src/commands/api-keys/index.ts +26 -0
  26. package/temp_resend_cli/repo/src/commands/api-keys/list.ts +35 -0
  27. package/temp_resend_cli/repo/src/commands/api-keys/utils.ts +8 -0
  28. package/temp_resend_cli/repo/src/commands/auth/index.ts +20 -0
  29. package/temp_resend_cli/repo/src/commands/auth/login.ts +234 -0
  30. package/temp_resend_cli/repo/src/commands/auth/logout.ts +105 -0
  31. package/temp_resend_cli/repo/src/commands/broadcasts/create.ts +196 -0
  32. package/temp_resend_cli/repo/src/commands/broadcasts/delete.ts +46 -0
  33. package/temp_resend_cli/repo/src/commands/broadcasts/get.ts +59 -0
  34. package/temp_resend_cli/repo/src/commands/broadcasts/index.ts +43 -0
  35. package/temp_resend_cli/repo/src/commands/broadcasts/list.ts +60 -0
  36. package/temp_resend_cli/repo/src/commands/broadcasts/send.ts +56 -0
  37. package/temp_resend_cli/repo/src/commands/broadcasts/update.ts +95 -0
  38. package/temp_resend_cli/repo/src/commands/broadcasts/utils.ts +35 -0
  39. package/temp_resend_cli/repo/src/commands/contact-properties/create.ts +118 -0
  40. package/temp_resend_cli/repo/src/commands/contact-properties/delete.ts +48 -0
  41. package/temp_resend_cli/repo/src/commands/contact-properties/get.ts +46 -0
  42. package/temp_resend_cli/repo/src/commands/contact-properties/index.ts +48 -0
  43. package/temp_resend_cli/repo/src/commands/contact-properties/list.ts +68 -0
  44. package/temp_resend_cli/repo/src/commands/contact-properties/update.ts +88 -0
  45. package/temp_resend_cli/repo/src/commands/contact-properties/utils.ts +17 -0
  46. package/temp_resend_cli/repo/src/commands/contacts/add-segment.ts +78 -0
  47. package/temp_resend_cli/repo/src/commands/contacts/create.ts +122 -0
  48. package/temp_resend_cli/repo/src/commands/contacts/delete.ts +49 -0
  49. package/temp_resend_cli/repo/src/commands/contacts/get.ts +53 -0
  50. package/temp_resend_cli/repo/src/commands/contacts/index.ts +58 -0
  51. package/temp_resend_cli/repo/src/commands/contacts/list.ts +57 -0
  52. package/temp_resend_cli/repo/src/commands/contacts/remove-segment.ts +48 -0
  53. package/temp_resend_cli/repo/src/commands/contacts/segments.ts +39 -0
  54. package/temp_resend_cli/repo/src/commands/contacts/topics.ts +45 -0
  55. package/temp_resend_cli/repo/src/commands/contacts/update-topics.ts +90 -0
  56. package/temp_resend_cli/repo/src/commands/contacts/update.ts +77 -0
  57. package/temp_resend_cli/repo/src/commands/contacts/utils.ts +119 -0
  58. package/temp_resend_cli/repo/src/commands/doctor.ts +216 -0
  59. package/temp_resend_cli/repo/src/commands/domains/create.ts +83 -0
  60. package/temp_resend_cli/repo/src/commands/domains/delete.ts +42 -0
  61. package/temp_resend_cli/repo/src/commands/domains/get.ts +47 -0
  62. package/temp_resend_cli/repo/src/commands/domains/index.ts +35 -0
  63. package/temp_resend_cli/repo/src/commands/domains/list.ts +53 -0
  64. package/temp_resend_cli/repo/src/commands/domains/update.ts +75 -0
  65. package/temp_resend_cli/repo/src/commands/domains/utils.ts +44 -0
  66. package/temp_resend_cli/repo/src/commands/domains/verify.ts +38 -0
  67. package/temp_resend_cli/repo/src/commands/emails/batch.ts +140 -0
  68. package/temp_resend_cli/repo/src/commands/emails/get.ts +44 -0
  69. package/temp_resend_cli/repo/src/commands/emails/index.ts +30 -0
  70. package/temp_resend_cli/repo/src/commands/emails/list.ts +84 -0
  71. package/temp_resend_cli/repo/src/commands/emails/receiving/attachment.ts +55 -0
  72. package/temp_resend_cli/repo/src/commands/emails/receiving/attachments.ts +68 -0
  73. package/temp_resend_cli/repo/src/commands/emails/receiving/get.ts +58 -0
  74. package/temp_resend_cli/repo/src/commands/emails/receiving/index.ts +28 -0
  75. package/temp_resend_cli/repo/src/commands/emails/receiving/list.ts +59 -0
  76. package/temp_resend_cli/repo/src/commands/emails/receiving/utils.ts +38 -0
  77. package/temp_resend_cli/repo/src/commands/emails/send.ts +189 -0
  78. package/temp_resend_cli/repo/src/commands/open.ts +27 -0
  79. package/temp_resend_cli/repo/src/commands/segments/create.ts +50 -0
  80. package/temp_resend_cli/repo/src/commands/segments/delete.ts +47 -0
  81. package/temp_resend_cli/repo/src/commands/segments/get.ts +38 -0
  82. package/temp_resend_cli/repo/src/commands/segments/index.ts +36 -0
  83. package/temp_resend_cli/repo/src/commands/segments/list.ts +58 -0
  84. package/temp_resend_cli/repo/src/commands/segments/utils.ts +7 -0
  85. package/temp_resend_cli/repo/src/commands/teams/index.ts +10 -0
  86. package/temp_resend_cli/repo/src/commands/teams/list.ts +35 -0
  87. package/temp_resend_cli/repo/src/commands/teams/remove.ts +86 -0
  88. package/temp_resend_cli/repo/src/commands/teams/switch.ts +76 -0
  89. package/temp_resend_cli/repo/src/commands/topics/create.ts +73 -0
  90. package/temp_resend_cli/repo/src/commands/topics/delete.ts +47 -0
  91. package/temp_resend_cli/repo/src/commands/topics/get.ts +42 -0
  92. package/temp_resend_cli/repo/src/commands/topics/index.ts +42 -0
  93. package/temp_resend_cli/repo/src/commands/topics/list.ts +34 -0
  94. package/temp_resend_cli/repo/src/commands/topics/update.ts +59 -0
  95. package/temp_resend_cli/repo/src/commands/topics/utils.ts +16 -0
  96. package/temp_resend_cli/repo/src/commands/webhooks/create.ts +128 -0
  97. package/temp_resend_cli/repo/src/commands/webhooks/delete.ts +49 -0
  98. package/temp_resend_cli/repo/src/commands/webhooks/get.ts +42 -0
  99. package/temp_resend_cli/repo/src/commands/webhooks/index.ts +42 -0
  100. package/temp_resend_cli/repo/src/commands/webhooks/list.ts +55 -0
  101. package/temp_resend_cli/repo/src/commands/webhooks/listen.ts +379 -0
  102. package/temp_resend_cli/repo/src/commands/webhooks/update.ts +83 -0
  103. package/temp_resend_cli/repo/src/commands/webhooks/utils.ts +36 -0
  104. package/temp_resend_cli/repo/src/commands/whoami.ts +71 -0
  105. package/temp_resend_cli/repo/src/lib/actions.ts +157 -0
  106. package/temp_resend_cli/repo/src/lib/client.ts +37 -0
  107. package/temp_resend_cli/repo/src/lib/config.ts +217 -0
  108. package/temp_resend_cli/repo/src/lib/files.ts +15 -0
  109. package/temp_resend_cli/repo/src/lib/help-text.ts +38 -0
  110. package/temp_resend_cli/repo/src/lib/output.ts +56 -0
  111. package/temp_resend_cli/repo/src/lib/pagination.ts +36 -0
  112. package/temp_resend_cli/repo/src/lib/prompts.ts +149 -0
  113. package/temp_resend_cli/repo/src/lib/spinner.ts +100 -0
  114. package/temp_resend_cli/repo/src/lib/table.ts +57 -0
  115. package/temp_resend_cli/repo/src/lib/tty.ts +28 -0
  116. package/temp_resend_cli/repo/src/lib/update-check.ts +169 -0
  117. package/temp_resend_cli/repo/src/lib/version.ts +4 -0
  118. package/temp_resend_cli/repo/tests/commands/api-keys/create.test.ts +196 -0
  119. package/temp_resend_cli/repo/tests/commands/api-keys/delete.test.ts +157 -0
  120. package/temp_resend_cli/repo/tests/commands/api-keys/list.test.ts +134 -0
  121. package/temp_resend_cli/repo/tests/commands/auth/login.test.ts +153 -0
  122. package/temp_resend_cli/repo/tests/commands/auth/logout.test.ts +153 -0
  123. package/temp_resend_cli/repo/tests/commands/broadcasts/create.test.ts +454 -0
  124. package/temp_resend_cli/repo/tests/commands/broadcasts/delete.test.ts +183 -0
  125. package/temp_resend_cli/repo/tests/commands/broadcasts/get.test.ts +147 -0
  126. package/temp_resend_cli/repo/tests/commands/broadcasts/list.test.ts +199 -0
  127. package/temp_resend_cli/repo/tests/commands/broadcasts/send.test.ts +162 -0
  128. package/temp_resend_cli/repo/tests/commands/broadcasts/update.test.ts +288 -0
  129. package/temp_resend_cli/repo/tests/commands/contact-properties/create.test.ts +251 -0
  130. package/temp_resend_cli/repo/tests/commands/contact-properties/delete.test.ts +184 -0
  131. package/temp_resend_cli/repo/tests/commands/contact-properties/get.test.ts +145 -0
  132. package/temp_resend_cli/repo/tests/commands/contact-properties/list.test.ts +181 -0
  133. package/temp_resend_cli/repo/tests/commands/contact-properties/update.test.ts +217 -0
  134. package/temp_resend_cli/repo/tests/commands/contacts/add-segment.test.ts +189 -0
  135. package/temp_resend_cli/repo/tests/commands/contacts/create.test.ts +271 -0
  136. package/temp_resend_cli/repo/tests/commands/contacts/delete.test.ts +193 -0
  137. package/temp_resend_cli/repo/tests/commands/contacts/get.test.ts +149 -0
  138. package/temp_resend_cli/repo/tests/commands/contacts/list.test.ts +176 -0
  139. package/temp_resend_cli/repo/tests/commands/contacts/remove-segment.test.ts +167 -0
  140. package/temp_resend_cli/repo/tests/commands/contacts/segments.test.ts +168 -0
  141. package/temp_resend_cli/repo/tests/commands/contacts/topics.test.ts +164 -0
  142. package/temp_resend_cli/repo/tests/commands/contacts/update-topics.test.ts +248 -0
  143. package/temp_resend_cli/repo/tests/commands/contacts/update.test.ts +206 -0
  144. package/temp_resend_cli/repo/tests/commands/doctor.test.ts +164 -0
  145. package/temp_resend_cli/repo/tests/commands/domains/create.test.ts +193 -0
  146. package/temp_resend_cli/repo/tests/commands/domains/delete.test.ts +157 -0
  147. package/temp_resend_cli/repo/tests/commands/domains/get.test.ts +138 -0
  148. package/temp_resend_cli/repo/tests/commands/domains/list.test.ts +165 -0
  149. package/temp_resend_cli/repo/tests/commands/domains/update.test.ts +224 -0
  150. package/temp_resend_cli/repo/tests/commands/domains/verify.test.ts +118 -0
  151. package/temp_resend_cli/repo/tests/commands/emails/batch.test.ts +324 -0
  152. package/temp_resend_cli/repo/tests/commands/emails/get.test.ts +132 -0
  153. package/temp_resend_cli/repo/tests/commands/emails/receiving/attachment.test.ts +141 -0
  154. package/temp_resend_cli/repo/tests/commands/emails/receiving/attachments.test.ts +169 -0
  155. package/temp_resend_cli/repo/tests/commands/emails/receiving/get.test.ts +141 -0
  156. package/temp_resend_cli/repo/tests/commands/emails/receiving/list.test.ts +182 -0
  157. package/temp_resend_cli/repo/tests/commands/emails/send.test.ts +312 -0
  158. package/temp_resend_cli/repo/tests/commands/segments/create.test.ts +164 -0
  159. package/temp_resend_cli/repo/tests/commands/segments/delete.test.ts +183 -0
  160. package/temp_resend_cli/repo/tests/commands/segments/get.test.ts +138 -0
  161. package/temp_resend_cli/repo/tests/commands/segments/list.test.ts +174 -0
  162. package/temp_resend_cli/repo/tests/commands/teams/list.test.ts +62 -0
  163. package/temp_resend_cli/repo/tests/commands/teams/remove.test.ts +110 -0
  164. package/temp_resend_cli/repo/tests/commands/teams/switch.test.ts +103 -0
  165. package/temp_resend_cli/repo/tests/commands/topics/create.test.ts +192 -0
  166. package/temp_resend_cli/repo/tests/commands/topics/delete.test.ts +157 -0
  167. package/temp_resend_cli/repo/tests/commands/topics/get.test.ts +126 -0
  168. package/temp_resend_cli/repo/tests/commands/topics/list.test.ts +125 -0
  169. package/temp_resend_cli/repo/tests/commands/topics/update.test.ts +178 -0
  170. package/temp_resend_cli/repo/tests/commands/webhooks/create.test.ts +225 -0
  171. package/temp_resend_cli/repo/tests/commands/webhooks/delete.test.ts +157 -0
  172. package/temp_resend_cli/repo/tests/commands/webhooks/get.test.ts +126 -0
  173. package/temp_resend_cli/repo/tests/commands/webhooks/list.test.ts +178 -0
  174. package/temp_resend_cli/repo/tests/commands/webhooks/update.test.ts +207 -0
  175. package/temp_resend_cli/repo/tests/commands/whoami.test.ts +98 -0
  176. package/temp_resend_cli/repo/tests/e2e/smoke.test.ts +93 -0
  177. package/temp_resend_cli/repo/tests/helpers.ts +86 -0
  178. package/temp_resend_cli/repo/tests/lib/client.test.ts +71 -0
  179. package/temp_resend_cli/repo/tests/lib/config.test.ts +451 -0
  180. package/temp_resend_cli/repo/tests/lib/files.test.ts +73 -0
  181. package/temp_resend_cli/repo/tests/lib/help-text.test.ts +97 -0
  182. package/temp_resend_cli/repo/tests/lib/output.test.ts +136 -0
  183. package/temp_resend_cli/repo/tests/lib/prompts.test.ts +185 -0
  184. package/temp_resend_cli/repo/tests/lib/spinner.test.ts +166 -0
  185. package/temp_resend_cli/repo/tests/lib/table.test.ts +63 -0
  186. package/temp_resend_cli/repo/tests/lib/tty.test.ts +89 -0
  187. package/temp_resend_cli/repo/tests/lib/update-check.test.ts +179 -0
  188. package/temp_resend_cli/repo/tsconfig.json +14 -0
  189. package/temp_resend_cli/repo/vitest.config.e2e.ts +8 -0
  190. package/temp_resend_cli/repo/vitest.config.ts +10 -0
  191. package/tests/test-resend-smoke.sh +7 -3
@@ -0,0 +1,450 @@
1
+ # Resend CLI
2
+
3
+ The official CLI for [Resend](https://resend.com).
4
+
5
+ Built for humans, AI agents, and CI/CD pipelines.
6
+
7
+ ```
8
+ ██████╗ ███████╗███████╗███████╗███╗ ██╗██████╗
9
+ ██╔══██╗██╔════╝██╔════╝██╔════╝████╗ ██║██╔══██╗
10
+ ██████╔╝█████╗ ███████╗█████╗ ██╔██╗ ██║██║ ██║
11
+ ██╔══██╗██╔══╝ ╚════██║██╔══╝ ██║╚██╗██║██║ ██║
12
+ ██║ ██║███████╗███████║███████╗██║ ╚████║██████╔╝
13
+ ╚═╝ ╚═╝╚══════╝╚══════╝╚══════╝╚═╝ ╚═══╝╚═════╝
14
+ ```
15
+
16
+ ## Install
17
+
18
+ ### Homebrew (macOS)
19
+
20
+ ```bash
21
+ brew install resend/cli/resend
22
+ ```
23
+
24
+ ### Shell script (macOS and Linux)
25
+
26
+ ```bash
27
+ curl -fsSL https://resend.com/install.sh | bash
28
+ ```
29
+
30
+ ### npx
31
+
32
+ ```bash
33
+ npx resend-cli
34
+ ```
35
+
36
+ ## Local development
37
+
38
+ Use this when you want to change the CLI and run your build locally.
39
+
40
+ ### Prerequisites
41
+
42
+ - [Node.js](https://nodejs.org) 20+
43
+
44
+ ### Setup
45
+
46
+ 1. **Clone the repo**
47
+
48
+ ```bash
49
+ git clone https://github.com/resend/resend-cli.git
50
+ cd resend-cli
51
+ ```
52
+
53
+ 2. **Install dependencies**
54
+
55
+ ```bash
56
+ npm install
57
+ ```
58
+
59
+ 3. **Build locally**
60
+
61
+ ```bash
62
+ npm run build
63
+ ```
64
+
65
+ Output: `./dist/cli.cjs`
66
+
67
+ ### Running the CLI locally
68
+
69
+ Use the dev script:
70
+
71
+ ```bash
72
+ npm run dev -- --version
73
+ ```
74
+
75
+ Or run the built JS bundle:
76
+
77
+ ```bash
78
+ node dist/cli.cjs --version
79
+ ```
80
+
81
+ ### Making changes
82
+
83
+ After editing source files, rebuild:
84
+
85
+ ```bash
86
+ npm run build
87
+ ```
88
+
89
+ ### Building native binaries
90
+
91
+ To build a standalone native binary:
92
+
93
+ ```bash
94
+ npm run build:bin
95
+ ```
96
+
97
+ Output: `./dist/resend`
98
+
99
+ ## Quick start
100
+
101
+ ```bash
102
+ # Authenticate
103
+ resend login
104
+
105
+ # Send an email
106
+ resend emails send \
107
+ --from "you@yourdomain.com" \
108
+ --to recipient@example.com \
109
+ --subject "Hello from Resend CLI" \
110
+ --text "Sent from my terminal."
111
+
112
+ # Check your environment
113
+ resend doctor
114
+ ```
115
+
116
+ ---
117
+
118
+ ## Authentication
119
+
120
+ The CLI resolves your API key using the following priority chain:
121
+
122
+ | Priority | Source | How to set |
123
+ |----------|--------|------------|
124
+ | 1 (highest) | `--api-key` flag | `resend --api-key re_xxx emails send ...` |
125
+ | 2 | `RESEND_API_KEY` env var | `export RESEND_API_KEY=re_xxx` |
126
+ | 3 (lowest) | Config file | `resend login` |
127
+
128
+ If no key is found from any source, the CLI errors with code `auth_error`.
129
+
130
+ ---
131
+
132
+ ## Commands
133
+
134
+ ### `resend login`
135
+
136
+ Authenticate by storing your API key locally. The key is validated against the Resend API before being saved.
137
+
138
+ ```bash
139
+ resend login
140
+ ```
141
+
142
+ #### Interactive mode (default in terminals)
143
+
144
+ When run in a terminal, the command checks for an existing key:
145
+
146
+ - **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.
147
+ - **Existing key found** — Shows the key source (`env`, `config`) and prompts for a new key to replace it.
148
+
149
+ The key is entered via a masked password input and must start with `re_`.
150
+
151
+ #### Non-interactive mode (CI, pipes, scripts)
152
+
153
+ When stdin is not a TTY, the `--key` flag is required:
154
+
155
+ ```bash
156
+ resend login --key re_xxxxxxxxxxxxx
157
+ ```
158
+
159
+ Omitting `--key` in non-interactive mode exits with error code `missing_key`.
160
+
161
+ #### Options
162
+
163
+ | Flag | Description |
164
+ |------|-------------|
165
+ | `--key <key>` | API key to store (required in non-interactive mode) |
166
+
167
+ #### Output
168
+
169
+ 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.
170
+
171
+ ```bash
172
+ # JSON output
173
+ resend login --key re_xxx --json
174
+ # => {"success":true,"config_path":"/Users/you/.config/resend/credentials.json"}
175
+ ```
176
+
177
+ #### Error codes
178
+
179
+ | Code | Cause |
180
+ |------|-------|
181
+ | `missing_key` | No `--key` provided in non-interactive mode |
182
+ | `invalid_key_format` | Key does not start with `re_` |
183
+ | `validation_failed` | Resend API rejected the key |
184
+
185
+ ---
186
+
187
+ ### `resend emails send`
188
+
189
+ Send an email via the Resend API. Provide all options via flags for scripting, or let the CLI prompt interactively for missing fields.
190
+
191
+ ```bash
192
+ resend emails send \
193
+ --from "Name <sender@yourdomain.com>" \
194
+ --to recipient@example.com \
195
+ --subject "Subject line" \
196
+ --text "Plain text body"
197
+ ```
198
+
199
+ #### Options
200
+
201
+ | Flag | Required | Description |
202
+ |------|----------|-------------|
203
+ | `--from <address>` | Yes | Sender email address (must be from a verified domain) |
204
+ | `--to <addresses...>` | Yes | One or more recipient email addresses (space-separated) |
205
+ | `--subject <subject>` | Yes | Email subject line |
206
+ | `--text <text>` | One of text/html/html-file | Plain text body |
207
+ | `--html <html>` | One of text/html/html-file | HTML body as a string |
208
+ | `--html-file <path>` | One of text/html/html-file | Path to an HTML file to use as body |
209
+ | `--cc <addresses...>` | No | CC recipients (space-separated) |
210
+ | `--bcc <addresses...>` | No | BCC recipients (space-separated) |
211
+ | `--reply-to <address>` | No | Reply-to email address |
212
+
213
+ #### Interactive mode
214
+
215
+ When run in a terminal without all required flags, the CLI prompts for missing fields:
216
+
217
+ ```bash
218
+ # prompts for from, to, subject, and body
219
+ resend emails send
220
+
221
+ # prompts only for missing fields
222
+ resend emails send --from "you@yourdomain.com"
223
+ ```
224
+
225
+ #### Non-interactive mode
226
+
227
+ When piped or run in CI, all required flags must be provided. Missing flags cause an error listing what's needed:
228
+
229
+ ```bash
230
+ echo "" | resend emails send --from "you@yourdomain.com"
231
+ # Error: Missing required flags: --to, --subject
232
+ ```
233
+
234
+ A body (`--text`, `--html`, or `--html-file`) is also required — omitting all three exits with code `missing_body`.
235
+
236
+ #### Examples
237
+
238
+ **Multiple recipients:**
239
+
240
+ ```bash
241
+ resend emails send \
242
+ --from "you@yourdomain.com" \
243
+ --to alice@example.com bob@example.com \
244
+ --subject "Team update" \
245
+ --text "Hello everyone"
246
+ ```
247
+
248
+ **HTML from a file:**
249
+
250
+ ```bash
251
+ resend emails send \
252
+ --from "you@yourdomain.com" \
253
+ --to recipient@example.com \
254
+ --subject "Newsletter" \
255
+ --html-file ./newsletter.html
256
+ ```
257
+
258
+ **With CC, BCC, and reply-to:**
259
+
260
+ ```bash
261
+ resend emails send \
262
+ --from "you@yourdomain.com" \
263
+ --to recipient@example.com \
264
+ --subject "Meeting notes" \
265
+ --text "See attached." \
266
+ --cc manager@example.com \
267
+ --bcc archive@example.com \
268
+ --reply-to noreply@example.com
269
+ ```
270
+
271
+ **Overriding the API key for one send:**
272
+
273
+ ```bash
274
+ resend --api-key re_other_key emails send \
275
+ --from "you@yourdomain.com" \
276
+ --to recipient@example.com \
277
+ --subject "Test" \
278
+ --text "Using a different key"
279
+ ```
280
+
281
+ #### Output
282
+
283
+ Returns the email ID on success:
284
+
285
+ ```json
286
+ { "id": "49a3999c-0ce1-4ea6-ab68-afcd6dc2e794" }
287
+ ```
288
+
289
+ #### Error codes
290
+
291
+ | Code | Cause |
292
+ |------|-------|
293
+ | `auth_error` | No API key found or client creation failed |
294
+ | `missing_body` | No `--text`, `--html`, or `--html-file` provided |
295
+ | `file_read_error` | Could not read the file passed to `--html-file` |
296
+ | `send_error` | Resend API returned an error |
297
+
298
+ ---
299
+
300
+ ### `resend doctor`
301
+
302
+ Run environment diagnostics. Verifies your CLI version, API key, domains, and detects AI agent integrations.
303
+
304
+ ```bash
305
+ resend doctor
306
+ ```
307
+
308
+ #### Checks performed
309
+
310
+ | Check | Pass | Warn | Fail |
311
+ |-------|------|------|------|
312
+ | **CLI Version** | Running latest | Update available or registry unreachable | — |
313
+ | **API Key** | Key found (shows masked key + source) | — | No key found |
314
+ | **Domains** | Verified domains exist | No domains or all pending verification | API key invalid |
315
+ | **AI Agents** | Lists detected agents (or none) | — | — |
316
+
317
+ The API key is always masked in output (e.g. `re_...xxxx`).
318
+
319
+ #### Interactive mode
320
+
321
+ In a terminal, shows animated spinners for each check with colored status icons:
322
+
323
+ ```
324
+ Resend Doctor
325
+
326
+ ✔ CLI Version: v0.1.0 (latest)
327
+ ✔ API Key: re_...xxxx (source: env)
328
+ ✔ Domains: 2 verified, 0 pending
329
+ ✔ AI Agents: Detected: Cursor, Claude Desktop
330
+ ```
331
+
332
+ #### JSON mode
333
+
334
+ ```bash
335
+ resend doctor --json
336
+ ```
337
+
338
+ ```json
339
+ {
340
+ "ok": true,
341
+ "checks": [
342
+ { "name": "CLI Version", "status": "pass", "message": "v0.1.0 (latest)" },
343
+ { "name": "API Key", "status": "pass", "message": "re_...xxxx (source: env)" },
344
+ { "name": "Domains", "status": "pass", "message": "2 verified, 0 pending" },
345
+ { "name": "AI Agents", "status": "pass", "message": "Detected: Cursor" }
346
+ ]
347
+ }
348
+ ```
349
+
350
+ Each check has a `status` of `pass`, `warn`, or `fail`. The top-level `ok` is `false` if any check is `fail`.
351
+
352
+ #### Detected AI agents
353
+
354
+ | Agent | Detection method |
355
+ |-------|-----------------|
356
+ | OpenClaw | `~/clawd/skills` directory exists |
357
+ | Cursor | `~/.cursor` directory exists |
358
+ | Claude Desktop | Platform-specific config file exists |
359
+ | VS Code | `.vscode/mcp.json` in current directory |
360
+
361
+ #### Exit code
362
+
363
+ Exits `0` when all checks pass or warn. Exits `1` if any check fails.
364
+
365
+ ---
366
+
367
+ ## Global options
368
+
369
+ These flags work on every command and are passed before the subcommand:
370
+
371
+ ```bash
372
+ resend [global options] <command> [command options]
373
+ ```
374
+
375
+ | Flag | Description |
376
+ |------|-------------|
377
+ | `--api-key <key>` | Override API key for this invocation (takes highest priority) |
378
+ | `--json` | Force JSON output even in interactive terminals |
379
+ | `--version` | Print version and exit |
380
+ | `--help` | Show help text |
381
+
382
+ ---
383
+
384
+ ## Output behavior
385
+
386
+ The CLI has two output modes:
387
+
388
+ | Mode | When | Stdout | Stderr |
389
+ |------|------|--------|--------|
390
+ | **Interactive** | Terminal (TTY) | Formatted text | Spinners, prompts |
391
+ | **Machine** | Piped, CI, or `--json` | JSON | Nothing |
392
+
393
+ Switching is automatic — pipe to another command and JSON output activates:
394
+
395
+ ```bash
396
+ resend doctor | jq '.checks[].name'
397
+ resend emails send --from ... --to ... --subject ... --text ... | jq '.id'
398
+ ```
399
+
400
+ ### Error output
401
+
402
+ Errors always exit with code `1` and output structured JSON to stdout:
403
+
404
+ ```json
405
+ { "error": { "message": "No API key found", "code": "auth_error" } }
406
+ ```
407
+
408
+ ---
409
+
410
+ ## Agent & CI/CD usage
411
+
412
+ ### CI/CD
413
+
414
+ Set `RESEND_API_KEY` as an environment variable — no `resend login` needed:
415
+
416
+ ```yaml
417
+ # GitHub Actions
418
+ env:
419
+ RESEND_API_KEY: ${{ secrets.RESEND_API_KEY }}
420
+ steps:
421
+ - run: |
422
+ resend emails send \
423
+ --from "deploy@yourdomain.com" \
424
+ --to "team@yourdomain.com" \
425
+ --subject "Deploy complete" \
426
+ --text "Version ${{ github.sha }} deployed."
427
+ ```
428
+
429
+ ### AI agents
430
+
431
+ Agents calling the CLI as a subprocess automatically get JSON output (non-TTY detection). The contract:
432
+
433
+ - **Input:** All required flags must be provided (no interactive prompts)
434
+ - **Output:** JSON to stdout, nothing to stderr
435
+ - **Exit code:** `0` success, `1` error
436
+ - **Errors:** Always include `message` and `code` fields
437
+
438
+ ---
439
+
440
+ ## Configuration
441
+
442
+ | Item | Path | Notes |
443
+ |------|------|-------|
444
+ | Config directory | `~/.config/resend/` | Respects `$XDG_CONFIG_HOME` on Linux, `%APPDATA%` on Windows |
445
+ | Credentials | `~/.config/resend/credentials.json` | `0600` permissions (owner read/write) |
446
+ | Install directory | `~/.resend/bin/` | Respects `$RESEND_INSTALL` |
447
+
448
+ ## License
449
+
450
+ MIT
@@ -0,0 +1,36 @@
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", "!**/node_modules", "!.claude"]
35
+ }
36
+ }
@@ -0,0 +1,141 @@
1
+ #!/usr/bin/env pwsh
2
+ # Resend CLI installer for Windows
3
+ #
4
+ # Usage (PowerShell):
5
+ # irm https://resend.com/install.ps1 | iex
6
+ #
7
+ # Pin a version:
8
+ # $env:RESEND_VERSION = 'v0.1.0'; irm https://resend.com/install.ps1 | iex
9
+ #
10
+ # Environment variables:
11
+ # RESEND_INSTALL - Custom install directory (default: $HOME\.resend)
12
+ # RESEND_VERSION - Version to install (default: latest)
13
+
14
+ param(
15
+ [string]$Version = $env:RESEND_VERSION
16
+ )
17
+
18
+ Set-StrictMode -Version Latest
19
+ $ErrorActionPreference = 'Stop'
20
+
21
+ # ─── Helpers ─────────────────────────────────────────────────────────────────
22
+
23
+ function Write-Info { param($msg) Write-Host " $msg" -ForegroundColor DarkGray }
24
+ function Write-Ok { param($msg) Write-Host " $msg" -ForegroundColor Green }
25
+
26
+ function Write-Fail {
27
+ param($msg)
28
+ Write-Host " error: $msg" -ForegroundColor Red
29
+ exit 1
30
+ }
31
+
32
+ # ─── Architecture detection ───────────────────────────────────────────────────
33
+
34
+ if ($env:PROCESSOR_ARCHITECTURE -notin @('AMD64', 'EM64T')) {
35
+ Write-Fail "Unsupported architecture: $env:PROCESSOR_ARCHITECTURE`n`n Resend CLI currently supports Windows x64 only."
36
+ }
37
+
38
+ # ─── Version + Download URL ───────────────────────────────────────────────────
39
+
40
+ $repo = 'https://github.com/resend/resend-cli'
41
+ $target = 'windows-x64'
42
+
43
+ if ($Version) {
44
+ $Version = $Version.TrimStart('v')
45
+ if ($Version -notmatch '^\d+\.\d+\.\d+(-[a-zA-Z0-9.]+)?$') {
46
+ Write-Fail "Invalid version format: $Version`n`n Expected: semantic version like 0.1.0 or 1.2.3-beta.1`n Usage: `$env:RESEND_VERSION = 'v0.1.0'; irm https://resend.com/install.ps1 | iex"
47
+ }
48
+ $url = "$repo/releases/download/v$Version/resend-$target.zip"
49
+ } else {
50
+ $url = "$repo/releases/latest/download/resend-$target.zip"
51
+ }
52
+
53
+ # ─── Install directory ────────────────────────────────────────────────────────
54
+
55
+ $installDir = if ($env:RESEND_INSTALL) { $env:RESEND_INSTALL } else { Join-Path $HOME '.resend' }
56
+ $binDir = Join-Path $installDir 'bin'
57
+ $exe = Join-Path $binDir 'resend.exe'
58
+
59
+ if (-not (Test-Path $binDir)) {
60
+ New-Item -ItemType Directory -Path $binDir -Force | Out-Null
61
+ }
62
+
63
+ # ─── Download + Extract ───────────────────────────────────────────────────────
64
+
65
+ Write-Host ""
66
+ Write-Host " Installing Resend CLI..." -ForegroundColor White
67
+ Write-Host ""
68
+ Write-Info "Downloading from $url"
69
+ Write-Host ""
70
+
71
+ $tmpDir = Join-Path ([System.IO.Path]::GetTempPath()) "resend-$([System.Guid]::NewGuid())"
72
+ New-Item -ItemType Directory -Path $tmpDir -Force | Out-Null
73
+ $tmpZip = Join-Path $tmpDir 'resend.zip'
74
+
75
+ try {
76
+ try {
77
+ # Force TLS 1.2 for Windows PowerShell 5.1 (no-op on PowerShell 7+ where it is the default)
78
+ [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
79
+ $ProgressPreference = 'SilentlyContinue' # Invoke-WebRequest is ~10x faster without progress bar
80
+ Invoke-WebRequest -Uri $url -OutFile $tmpZip -UseBasicParsing
81
+ } catch {
82
+ Write-Fail "Download failed.`n`n Possible causes:`n - No internet connection`n - The version does not exist: $(if ($Version) { $Version } else { 'latest' })`n - GitHub is unreachable`n`n URL: $url"
83
+ }
84
+
85
+ try {
86
+ Expand-Archive -Path $tmpZip -DestinationPath $binDir -Force
87
+ } catch {
88
+ Write-Fail "Failed to extract archive: $_"
89
+ }
90
+ }
91
+ finally {
92
+ Remove-Item -Recurse -Force $tmpDir -ErrorAction SilentlyContinue
93
+ }
94
+
95
+ if (-not (Test-Path $exe)) {
96
+ Write-Fail "Binary not found after extraction. The download may be corrupted — try again."
97
+ }
98
+
99
+ # ─── Verify installation ──────────────────────────────────────────────────────
100
+
101
+ try {
102
+ $installedVersion = (& $exe --version 2>$null).Trim()
103
+ } catch {
104
+ $installedVersion = 'unknown'
105
+ }
106
+
107
+ Write-Host ""
108
+ Write-Ok "Resend CLI $installedVersion installed successfully!"
109
+ Write-Host ""
110
+ Write-Info "Binary: $exe"
111
+
112
+ # ─── PATH setup ───────────────────────────────────────────────────────────────
113
+
114
+ $userPath = [Environment]::GetEnvironmentVariable('PATH', 'User') ?? ''
115
+ $pathEntries = $userPath -split ';' | Where-Object { $_ -ne '' }
116
+
117
+ if ($pathEntries -contains $binDir) {
118
+ # Already on PATH — just print the getting-started line
119
+ Write-Host ""
120
+ Write-Host " Run " -NoNewline
121
+ Write-Host "resend --help" -ForegroundColor Cyan -NoNewline
122
+ Write-Host " to get started"
123
+ Write-Host ""
124
+ exit 0
125
+ }
126
+
127
+ # Add to user PATH (persists across sessions — no admin rights needed)
128
+ $newPath = ($pathEntries + $binDir) -join ';'
129
+ [Environment]::SetEnvironmentVariable('PATH', $newPath, 'User')
130
+ $env:PATH = "$env:PATH;$binDir" # Also update the current session
131
+
132
+ Write-Info "Added $binDir to PATH (User scope)"
133
+ Write-Host ""
134
+ Write-Info "Restart your terminal, then:"
135
+ Write-Host ""
136
+ Write-Info "Next steps:"
137
+ Write-Host ""
138
+ Write-Host " `$env:RESEND_API_KEY = 're_...'" -ForegroundColor Cyan
139
+ Write-Host " resend --help" -ForegroundColor Cyan
140
+ Write-Host ""
141
+ exit 0