resend-cli 1.2.0 → 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 (193) hide show
  1. package/.github/workflows/release.yml +35 -8
  2. package/README.md +12 -1
  3. package/biome.json +1 -1
  4. package/bun.lock +0 -3
  5. package/package.json +3 -4
  6. package/src/cli.ts +23 -5
  7. package/src/commands/auth/login.ts +10 -8
  8. package/src/commands/doctor.ts +30 -112
  9. package/src/lib/client.ts +3 -0
  10. package/src/lib/config.ts +2 -3
  11. package/src/lib/spinner.ts +17 -10
  12. package/src/lib/update-check.ts +172 -0
  13. package/tests/commands/auth/login.test.ts +3 -1
  14. package/tests/lib/config.test.ts +4 -6
  15. package/tests/lib/update-check.test.ts +169 -0
  16. package/.claude/worktrees/emails-list/.claude/settings.local.json +0 -5
  17. package/.claude/worktrees/emails-list/.github/scripts/pr-title-check.js +0 -34
  18. package/.claude/worktrees/emails-list/.github/workflows/ci.yml +0 -32
  19. package/.claude/worktrees/emails-list/.github/workflows/pr-title-check.yml +0 -13
  20. package/.claude/worktrees/emails-list/.github/workflows/release.yml +0 -93
  21. package/.claude/worktrees/emails-list/CHANGELOG.md +0 -31
  22. package/.claude/worktrees/emails-list/LICENSE +0 -21
  23. package/.claude/worktrees/emails-list/README.md +0 -424
  24. package/.claude/worktrees/emails-list/biome.json +0 -36
  25. package/.claude/worktrees/emails-list/bun.lock +0 -76
  26. package/.claude/worktrees/emails-list/bunfig.toml +0 -2
  27. package/.claude/worktrees/emails-list/install.ps1 +0 -140
  28. package/.claude/worktrees/emails-list/install.sh +0 -301
  29. package/.claude/worktrees/emails-list/package.json +0 -43
  30. package/.claude/worktrees/emails-list/renovate.json +0 -6
  31. package/.claude/worktrees/emails-list/src/cli.ts +0 -74
  32. package/.claude/worktrees/emails-list/src/commands/api-keys/create.ts +0 -114
  33. package/.claude/worktrees/emails-list/src/commands/api-keys/delete.ts +0 -47
  34. package/.claude/worktrees/emails-list/src/commands/api-keys/index.ts +0 -26
  35. package/.claude/worktrees/emails-list/src/commands/api-keys/list.ts +0 -35
  36. package/.claude/worktrees/emails-list/src/commands/api-keys/utils.ts +0 -8
  37. package/.claude/worktrees/emails-list/src/commands/auth/index.ts +0 -20
  38. package/.claude/worktrees/emails-list/src/commands/auth/login.ts +0 -207
  39. package/.claude/worktrees/emails-list/src/commands/auth/logout.ts +0 -105
  40. package/.claude/worktrees/emails-list/src/commands/broadcasts/create.ts +0 -196
  41. package/.claude/worktrees/emails-list/src/commands/broadcasts/delete.ts +0 -46
  42. package/.claude/worktrees/emails-list/src/commands/broadcasts/get.ts +0 -59
  43. package/.claude/worktrees/emails-list/src/commands/broadcasts/index.ts +0 -43
  44. package/.claude/worktrees/emails-list/src/commands/broadcasts/list.ts +0 -60
  45. package/.claude/worktrees/emails-list/src/commands/broadcasts/send.ts +0 -56
  46. package/.claude/worktrees/emails-list/src/commands/broadcasts/update.ts +0 -95
  47. package/.claude/worktrees/emails-list/src/commands/broadcasts/utils.ts +0 -35
  48. package/.claude/worktrees/emails-list/src/commands/contact-properties/create.ts +0 -118
  49. package/.claude/worktrees/emails-list/src/commands/contact-properties/delete.ts +0 -48
  50. package/.claude/worktrees/emails-list/src/commands/contact-properties/get.ts +0 -46
  51. package/.claude/worktrees/emails-list/src/commands/contact-properties/index.ts +0 -48
  52. package/.claude/worktrees/emails-list/src/commands/contact-properties/list.ts +0 -68
  53. package/.claude/worktrees/emails-list/src/commands/contact-properties/update.ts +0 -88
  54. package/.claude/worktrees/emails-list/src/commands/contact-properties/utils.ts +0 -17
  55. package/.claude/worktrees/emails-list/src/commands/contacts/add-segment.ts +0 -78
  56. package/.claude/worktrees/emails-list/src/commands/contacts/create.ts +0 -122
  57. package/.claude/worktrees/emails-list/src/commands/contacts/delete.ts +0 -49
  58. package/.claude/worktrees/emails-list/src/commands/contacts/get.ts +0 -53
  59. package/.claude/worktrees/emails-list/src/commands/contacts/index.ts +0 -58
  60. package/.claude/worktrees/emails-list/src/commands/contacts/list.ts +0 -57
  61. package/.claude/worktrees/emails-list/src/commands/contacts/remove-segment.ts +0 -48
  62. package/.claude/worktrees/emails-list/src/commands/contacts/segments.ts +0 -39
  63. package/.claude/worktrees/emails-list/src/commands/contacts/topics.ts +0 -45
  64. package/.claude/worktrees/emails-list/src/commands/contacts/update-topics.ts +0 -90
  65. package/.claude/worktrees/emails-list/src/commands/contacts/update.ts +0 -77
  66. package/.claude/worktrees/emails-list/src/commands/contacts/utils.ts +0 -119
  67. package/.claude/worktrees/emails-list/src/commands/doctor.ts +0 -298
  68. package/.claude/worktrees/emails-list/src/commands/domains/create.ts +0 -83
  69. package/.claude/worktrees/emails-list/src/commands/domains/delete.ts +0 -42
  70. package/.claude/worktrees/emails-list/src/commands/domains/get.ts +0 -47
  71. package/.claude/worktrees/emails-list/src/commands/domains/index.ts +0 -35
  72. package/.claude/worktrees/emails-list/src/commands/domains/list.ts +0 -53
  73. package/.claude/worktrees/emails-list/src/commands/domains/update.ts +0 -75
  74. package/.claude/worktrees/emails-list/src/commands/domains/utils.ts +0 -44
  75. package/.claude/worktrees/emails-list/src/commands/domains/verify.ts +0 -38
  76. package/.claude/worktrees/emails-list/src/commands/emails/batch.ts +0 -140
  77. package/.claude/worktrees/emails-list/src/commands/emails/index.ts +0 -28
  78. package/.claude/worktrees/emails-list/src/commands/emails/list.ts +0 -73
  79. package/.claude/worktrees/emails-list/src/commands/emails/receiving/attachment.ts +0 -55
  80. package/.claude/worktrees/emails-list/src/commands/emails/receiving/attachments.ts +0 -68
  81. package/.claude/worktrees/emails-list/src/commands/emails/receiving/get.ts +0 -58
  82. package/.claude/worktrees/emails-list/src/commands/emails/receiving/index.ts +0 -28
  83. package/.claude/worktrees/emails-list/src/commands/emails/receiving/list.ts +0 -59
  84. package/.claude/worktrees/emails-list/src/commands/emails/receiving/utils.ts +0 -38
  85. package/.claude/worktrees/emails-list/src/commands/emails/send.ts +0 -189
  86. package/.claude/worktrees/emails-list/src/commands/open.ts +0 -24
  87. package/.claude/worktrees/emails-list/src/commands/segments/create.ts +0 -50
  88. package/.claude/worktrees/emails-list/src/commands/segments/delete.ts +0 -47
  89. package/.claude/worktrees/emails-list/src/commands/segments/get.ts +0 -38
  90. package/.claude/worktrees/emails-list/src/commands/segments/index.ts +0 -36
  91. package/.claude/worktrees/emails-list/src/commands/segments/list.ts +0 -58
  92. package/.claude/worktrees/emails-list/src/commands/segments/utils.ts +0 -7
  93. package/.claude/worktrees/emails-list/src/commands/teams/index.ts +0 -10
  94. package/.claude/worktrees/emails-list/src/commands/teams/list.ts +0 -35
  95. package/.claude/worktrees/emails-list/src/commands/teams/remove.ts +0 -83
  96. package/.claude/worktrees/emails-list/src/commands/teams/switch.ts +0 -73
  97. package/.claude/worktrees/emails-list/src/commands/topics/create.ts +0 -73
  98. package/.claude/worktrees/emails-list/src/commands/topics/delete.ts +0 -47
  99. package/.claude/worktrees/emails-list/src/commands/topics/get.ts +0 -42
  100. package/.claude/worktrees/emails-list/src/commands/topics/index.ts +0 -42
  101. package/.claude/worktrees/emails-list/src/commands/topics/list.ts +0 -34
  102. package/.claude/worktrees/emails-list/src/commands/topics/update.ts +0 -59
  103. package/.claude/worktrees/emails-list/src/commands/topics/utils.ts +0 -16
  104. package/.claude/worktrees/emails-list/src/commands/webhooks/create.ts +0 -128
  105. package/.claude/worktrees/emails-list/src/commands/webhooks/delete.ts +0 -49
  106. package/.claude/worktrees/emails-list/src/commands/webhooks/get.ts +0 -42
  107. package/.claude/worktrees/emails-list/src/commands/webhooks/index.ts +0 -44
  108. package/.claude/worktrees/emails-list/src/commands/webhooks/list.ts +0 -55
  109. package/.claude/worktrees/emails-list/src/commands/webhooks/update.ts +0 -83
  110. package/.claude/worktrees/emails-list/src/commands/webhooks/utils.ts +0 -36
  111. package/.claude/worktrees/emails-list/src/commands/whoami.ts +0 -71
  112. package/.claude/worktrees/emails-list/src/lib/actions.ts +0 -157
  113. package/.claude/worktrees/emails-list/src/lib/client.ts +0 -34
  114. package/.claude/worktrees/emails-list/src/lib/config.ts +0 -211
  115. package/.claude/worktrees/emails-list/src/lib/files.ts +0 -15
  116. package/.claude/worktrees/emails-list/src/lib/help-text.ts +0 -38
  117. package/.claude/worktrees/emails-list/src/lib/output.ts +0 -54
  118. package/.claude/worktrees/emails-list/src/lib/pagination.ts +0 -36
  119. package/.claude/worktrees/emails-list/src/lib/prompts.ts +0 -149
  120. package/.claude/worktrees/emails-list/src/lib/spinner.ts +0 -93
  121. package/.claude/worktrees/emails-list/src/lib/table.ts +0 -57
  122. package/.claude/worktrees/emails-list/src/lib/tty.ts +0 -28
  123. package/.claude/worktrees/emails-list/src/lib/version.ts +0 -4
  124. package/.claude/worktrees/emails-list/tests/commands/api-keys/create.test.ts +0 -195
  125. package/.claude/worktrees/emails-list/tests/commands/api-keys/delete.test.ts +0 -156
  126. package/.claude/worktrees/emails-list/tests/commands/api-keys/list.test.ts +0 -133
  127. package/.claude/worktrees/emails-list/tests/commands/auth/login.test.ts +0 -119
  128. package/.claude/worktrees/emails-list/tests/commands/auth/logout.test.ts +0 -146
  129. package/.claude/worktrees/emails-list/tests/commands/broadcasts/create.test.ts +0 -447
  130. package/.claude/worktrees/emails-list/tests/commands/broadcasts/delete.test.ts +0 -182
  131. package/.claude/worktrees/emails-list/tests/commands/broadcasts/get.test.ts +0 -146
  132. package/.claude/worktrees/emails-list/tests/commands/broadcasts/list.test.ts +0 -196
  133. package/.claude/worktrees/emails-list/tests/commands/broadcasts/send.test.ts +0 -161
  134. package/.claude/worktrees/emails-list/tests/commands/broadcasts/update.test.ts +0 -283
  135. package/.claude/worktrees/emails-list/tests/commands/contact-properties/create.test.ts +0 -250
  136. package/.claude/worktrees/emails-list/tests/commands/contact-properties/delete.test.ts +0 -183
  137. package/.claude/worktrees/emails-list/tests/commands/contact-properties/get.test.ts +0 -144
  138. package/.claude/worktrees/emails-list/tests/commands/contact-properties/list.test.ts +0 -180
  139. package/.claude/worktrees/emails-list/tests/commands/contact-properties/update.test.ts +0 -216
  140. package/.claude/worktrees/emails-list/tests/commands/contacts/add-segment.test.ts +0 -188
  141. package/.claude/worktrees/emails-list/tests/commands/contacts/create.test.ts +0 -270
  142. package/.claude/worktrees/emails-list/tests/commands/contacts/delete.test.ts +0 -192
  143. package/.claude/worktrees/emails-list/tests/commands/contacts/get.test.ts +0 -148
  144. package/.claude/worktrees/emails-list/tests/commands/contacts/list.test.ts +0 -175
  145. package/.claude/worktrees/emails-list/tests/commands/contacts/remove-segment.test.ts +0 -166
  146. package/.claude/worktrees/emails-list/tests/commands/contacts/segments.test.ts +0 -167
  147. package/.claude/worktrees/emails-list/tests/commands/contacts/topics.test.ts +0 -163
  148. package/.claude/worktrees/emails-list/tests/commands/contacts/update-topics.test.ts +0 -247
  149. package/.claude/worktrees/emails-list/tests/commands/contacts/update.test.ts +0 -205
  150. package/.claude/worktrees/emails-list/tests/commands/doctor.test.ts +0 -165
  151. package/.claude/worktrees/emails-list/tests/commands/domains/create.test.ts +0 -192
  152. package/.claude/worktrees/emails-list/tests/commands/domains/delete.test.ts +0 -156
  153. package/.claude/worktrees/emails-list/tests/commands/domains/get.test.ts +0 -137
  154. package/.claude/worktrees/emails-list/tests/commands/domains/list.test.ts +0 -164
  155. package/.claude/worktrees/emails-list/tests/commands/domains/update.test.ts +0 -223
  156. package/.claude/worktrees/emails-list/tests/commands/domains/verify.test.ts +0 -117
  157. package/.claude/worktrees/emails-list/tests/commands/emails/batch.test.ts +0 -313
  158. package/.claude/worktrees/emails-list/tests/commands/emails/list.test.ts +0 -196
  159. package/.claude/worktrees/emails-list/tests/commands/emails/receiving/attachment.test.ts +0 -140
  160. package/.claude/worktrees/emails-list/tests/commands/emails/receiving/attachments.test.ts +0 -168
  161. package/.claude/worktrees/emails-list/tests/commands/emails/receiving/get.test.ts +0 -140
  162. package/.claude/worktrees/emails-list/tests/commands/emails/receiving/list.test.ts +0 -181
  163. package/.claude/worktrees/emails-list/tests/commands/emails/send.test.ts +0 -309
  164. package/.claude/worktrees/emails-list/tests/commands/segments/create.test.ts +0 -163
  165. package/.claude/worktrees/emails-list/tests/commands/segments/delete.test.ts +0 -182
  166. package/.claude/worktrees/emails-list/tests/commands/segments/get.test.ts +0 -137
  167. package/.claude/worktrees/emails-list/tests/commands/segments/list.test.ts +0 -173
  168. package/.claude/worktrees/emails-list/tests/commands/teams/list.test.ts +0 -63
  169. package/.claude/worktrees/emails-list/tests/commands/teams/remove.test.ts +0 -103
  170. package/.claude/worktrees/emails-list/tests/commands/teams/switch.test.ts +0 -96
  171. package/.claude/worktrees/emails-list/tests/commands/topics/create.test.ts +0 -191
  172. package/.claude/worktrees/emails-list/tests/commands/topics/delete.test.ts +0 -156
  173. package/.claude/worktrees/emails-list/tests/commands/topics/get.test.ts +0 -125
  174. package/.claude/worktrees/emails-list/tests/commands/topics/list.test.ts +0 -124
  175. package/.claude/worktrees/emails-list/tests/commands/topics/update.test.ts +0 -177
  176. package/.claude/worktrees/emails-list/tests/commands/webhooks/create.test.ts +0 -224
  177. package/.claude/worktrees/emails-list/tests/commands/webhooks/delete.test.ts +0 -156
  178. package/.claude/worktrees/emails-list/tests/commands/webhooks/get.test.ts +0 -125
  179. package/.claude/worktrees/emails-list/tests/commands/webhooks/list.test.ts +0 -177
  180. package/.claude/worktrees/emails-list/tests/commands/webhooks/update.test.ts +0 -206
  181. package/.claude/worktrees/emails-list/tests/commands/whoami.test.ts +0 -99
  182. package/.claude/worktrees/emails-list/tests/helpers.ts +0 -93
  183. package/.claude/worktrees/emails-list/tests/lib/client.test.ts +0 -71
  184. package/.claude/worktrees/emails-list/tests/lib/config.test.ts +0 -414
  185. package/.claude/worktrees/emails-list/tests/lib/files.test.ts +0 -65
  186. package/.claude/worktrees/emails-list/tests/lib/help-text.test.ts +0 -97
  187. package/.claude/worktrees/emails-list/tests/lib/output.test.ts +0 -127
  188. package/.claude/worktrees/emails-list/tests/lib/prompts.test.ts +0 -178
  189. package/.claude/worktrees/emails-list/tests/lib/spinner.test.ts +0 -146
  190. package/.claude/worktrees/emails-list/tests/lib/table.test.ts +0 -63
  191. package/.claude/worktrees/emails-list/tests/lib/tty.test.ts +0 -85
  192. package/.claude/worktrees/emails-list/tsconfig.json +0 -14
  193. package/.github/workflows/test-build-windows.yml +0 -44
@@ -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
@@ -1,140 +0,0 @@
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 ""