@letterstory/cli 0.103.2 → 0.104.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/lib/cli.mjs +14 -5
- package/lib/commands/outbound.mjs +21 -1
- package/lib/commands/repo.mjs +44 -3
- package/lib/commands/site.mjs +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -817,8 +817,8 @@ here can SEND email or spend money, so they refuse unknown flags instead of igno
|
|
|
817
817
|
```bash
|
|
818
818
|
# Mailers
|
|
819
819
|
letterstory mail vercel-key set --token-file - --team team_AbC123 # optional: buy domains on YOUR Vercel team (token on stdin)
|
|
820
|
-
letterstory mail registrant --first-name Dana --last-name Lee --email d@acme.com --phone
|
|
821
|
-
--address "1 Main St" --city Oakland --state CA --zip 94607 --country
|
|
820
|
+
letterstory mail registrant --first-name Dana --last-name Lee --email d@acme.com --phone "(415) 555-0100" \
|
|
821
|
+
--address "1 Main St" --city Oakland --state CA --zip 94607 --country "United States" # WHOIS owner; any phone format
|
|
822
822
|
letterstory mailers quote acme-mail.com # price it first: nothing is bought
|
|
823
823
|
letterstory mailers launch acme-mail.com --mailer "hello:Hello Team" --forward-to me@acme.com --yes
|
|
824
824
|
letterstory mailers domains # every domain: setup job, mailers, warmup
|
package/lib/cli.mjs
CHANGED
|
@@ -60,7 +60,7 @@ import {
|
|
|
60
60
|
} from "./commands.mjs";
|
|
61
61
|
|
|
62
62
|
// Keep in sync with cli/package.json.
|
|
63
|
-
export const VERSION = "0.
|
|
63
|
+
export const VERSION = "0.104.1";
|
|
64
64
|
|
|
65
65
|
// Flags that never take a value. Listing them explicitly means `deploy get --json <id>`
|
|
66
66
|
// can't accidentally swallow the id as --json's value. Every `type: "bool"` flag (and its
|
|
@@ -186,6 +186,8 @@ export const BOOLEAN_FLAGS = new Set([
|
|
|
186
186
|
"no-postal-address-footer",
|
|
187
187
|
// `mailers launch … --no-warmup` / `--warmup` / `--consent`: value-less switches.
|
|
188
188
|
"no-warmup",
|
|
189
|
+
"move-vercel-key",
|
|
190
|
+
"keep-vercel-key",
|
|
189
191
|
"warmup",
|
|
190
192
|
"consent",
|
|
191
193
|
"no-redesign",
|
|
@@ -1108,6 +1110,9 @@ Mailers (the sending mailboxes):
|
|
|
1108
1110
|
Buy or reuse the domain, create mailers, warm them up
|
|
1109
1111
|
(a net-new domain is a real, auto-renewing purchase)
|
|
1110
1112
|
mailers domains Every domain you own: mail status, setup job, mailers
|
|
1113
|
+
mailers move <owned-domain-id> --to <org-id> --yes [--keep-vercel-key]
|
|
1114
|
+
Move a domain, its setup and mailers to another org you
|
|
1115
|
+
admin (with this org's Vercel key unless --keep-vercel-key)
|
|
1111
1116
|
mailers list [--domain <apex>] Your mailers + status + daily send limit
|
|
1112
1117
|
mailers domain <owned-domain-id> Provisioning stage, DNS state, mailers on a domain
|
|
1113
1118
|
mailers messages <mailer-id> [--folder all|inbox|sent] [--limit <n>]
|
|
@@ -1129,9 +1134,10 @@ Mail:
|
|
|
1129
1134
|
mail vercel-key set (--token <t> | --token-file <path|->) [--team <team_id>]
|
|
1130
1135
|
Buy and own mail domains on your Vercel account / team
|
|
1131
1136
|
mail vercel-key remove --yes Future purchases go back to Letterstory's account
|
|
1132
|
-
mail registrant --first-name <f> --last-name <l> --email <e> --phone
|
|
1133
|
-
--address <a> [--address2 <a>] --city <c> --state <s> --zip <z> --country
|
|
1137
|
+
mail registrant --first-name <f> --last-name <l> --email <e> --phone "(415) 555-1234"
|
|
1138
|
+
--address <a> [--address2 <a>] --city <c> --state <s> --zip <z> --country "United States" [--company <c>]
|
|
1134
1139
|
WHOIS registrant for purchases on your Vercel key
|
|
1140
|
+
(any phone format; country as a name or a 2-letter code)
|
|
1135
1141
|
|
|
1136
1142
|
Insights:
|
|
1137
1143
|
insights summary [--period …] [--part <block>]... Measure Overview: AI named/cited rates, share of voice, search, targets
|
|
@@ -1172,9 +1178,12 @@ Repo changes (Claude Code edits your repo in a sandbox; the Letterstory GitHub A
|
|
|
1172
1178
|
repo branches --repo owner/name Branches a change can start from (default first)
|
|
1173
1179
|
repo suggestions Fixes found and not acted on yet, and how to start each
|
|
1174
1180
|
repo settings [--action build|build_pr|slack] [--branch <name>|none] [--slack-agent <name|U…>|none]
|
|
1181
|
+
[--slack-channel <C…>|none]
|
|
1175
1182
|
The org's defaults for every fix: build (preview first),
|
|
1176
|
-
build_pr, or slack (post it for your
|
|
1177
|
-
--slack-agent), and the branch changes go to
|
|
1183
|
+
build_pr, or slack (post it to --slack-channel for your
|
|
1184
|
+
own agent, tagging --slack-agent), and the branch changes go to
|
|
1185
|
+
repo slack-targets Slack channels and people Send to Slack can use, with ids
|
|
1186
|
+
repo slack-test Post a test into the Send to Slack channel
|
|
1178
1187
|
repo start --repo <owner/name> --instructions <text>|--instructions-file <path|->
|
|
1179
1188
|
[--branch <base>] [--attach <path>]... [--attach-url <name>=<https url>]...
|
|
1180
1189
|
[--action build|build_pr|slack] [--wait]
|
|
@@ -394,6 +394,11 @@ export const ARGS = {
|
|
|
394
394
|
mail_postal_address: { positional: 0, label: "address", required: true },
|
|
395
395
|
},
|
|
396
396
|
list_mail_domains: {},
|
|
397
|
+
move_mail_domain: {
|
|
398
|
+
owned_domain_id: { positional: 0, label: "owned-domain-id", required: true },
|
|
399
|
+
to_org_id: { flag: "to", required: true },
|
|
400
|
+
move_vercel_key: { flag: "move-vercel-key", type: "bool", negate: "keep-vercel-key" },
|
|
401
|
+
},
|
|
397
402
|
quote_mail_domain: {
|
|
398
403
|
domain: { positional: 0, label: "domain", required: true },
|
|
399
404
|
},
|
|
@@ -693,7 +698,7 @@ async function prospectsColumns(ctx, sub) {
|
|
|
693
698
|
}
|
|
694
699
|
}
|
|
695
700
|
|
|
696
|
-
const MAILERS_USAGE = `Usage: mailers <list|domains|domain|quote|launch|messages|message|forward|warmup|limit|retire|suppressions>`;
|
|
701
|
+
const MAILERS_USAGE = `Usage: mailers <list|domains|domain|quote|launch|move|messages|message|forward|warmup|limit|retire|suppressions>`;
|
|
697
702
|
|
|
698
703
|
export async function cmdMailers(ctx) {
|
|
699
704
|
const sub = ctx.positionals[0];
|
|
@@ -708,6 +713,21 @@ export async function cmdMailers(ctx) {
|
|
|
708
713
|
return run(rest, "get_mailer_domain_status");
|
|
709
714
|
case "quote":
|
|
710
715
|
return run(rest, "quote_mail_domain");
|
|
716
|
+
case "move": {
|
|
717
|
+
// Re-homes the domain, its mailers and (by default) the org's Vercel key: confirm first.
|
|
718
|
+
if (!rest.flags.yes) {
|
|
719
|
+
const id = flagStr(rest.positionals[0]) ?? "<owned-domain-id>";
|
|
720
|
+
ctx.io.error(
|
|
721
|
+
`Moving re-homes the domain, its setup and mailers (and this org's Vercel key unless --keep-vercel-key) in the other organization. Re-run with --yes to confirm: ${ctx.bin} mailers move ${id} --to <org-id> --yes`
|
|
722
|
+
);
|
|
723
|
+
return 1;
|
|
724
|
+
}
|
|
725
|
+
return run(
|
|
726
|
+
rest,
|
|
727
|
+
"move_mail_domain",
|
|
728
|
+
(r) => `Moved ${r?.domain ?? "the domain"} to ${r?.to_org_id ?? "the other organization"}.`
|
|
729
|
+
);
|
|
730
|
+
}
|
|
711
731
|
case "launch": {
|
|
712
732
|
// A net-new domain is a real purchase, so a launch needs --yes (quote it first).
|
|
713
733
|
if (!rest.flags.yes) {
|
package/lib/commands/repo.mjs
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
// repo install-letterprove → letterprove_open_install_pr
|
|
8
8
|
// repo suggestions → list_suggested_fixes
|
|
9
9
|
// repo settings → get_repo_change_settings, or set_repo_change_settings with --action / --branch
|
|
10
|
+
// repo slack-targets → list_slack_fix_targets repo slack-test → send_slack_test_message
|
|
10
11
|
|
|
11
12
|
import { readFileSync } from "node:fs";
|
|
12
13
|
import { basename } from "node:path";
|
|
@@ -81,12 +82,18 @@ const ARGS = {
|
|
|
81
82
|
},
|
|
82
83
|
get_repo_change_settings: {},
|
|
83
84
|
list_suggested_fixes: {},
|
|
85
|
+
list_slack_fix_targets: {},
|
|
86
|
+
send_slack_test_message: {},
|
|
84
87
|
set_repo_change_settings: {
|
|
85
88
|
default_action: { flag: "action", enum: ["build", "build_pr", "slack"] },
|
|
86
89
|
// --branch <name>, or --branch none for each repo's own default.
|
|
87
90
|
default_branch: { value: (flags) => (flags.branch === "none" ? null : flagStr(flags.branch)) },
|
|
88
91
|
// --slack-agent Devin (or a U… member id), or --slack-agent none to tag nobody.
|
|
89
92
|
slack_agent: { value: (flags) => (flags["slack-agent"] === "none" ? null : flagStr(flags["slack-agent"])) },
|
|
93
|
+
// --slack-channel C0123ABCD (from repo slack-targets), or none for the first linked channel.
|
|
94
|
+
slack_channel: {
|
|
95
|
+
value: (flags) => (flags["slack-channel"] === "none" ? null : flagStr(flags["slack-channel"])),
|
|
96
|
+
},
|
|
90
97
|
},
|
|
91
98
|
get_repo_change: { run_id: { positional: 0, required: true, label: "run-id" } },
|
|
92
99
|
cancel_repo_change: { run_id: { positional: 0, required: true, label: "run-id" } },
|
|
@@ -151,9 +158,13 @@ export async function cmdRepo(ctx) {
|
|
|
151
158
|
return repoSettings(rest);
|
|
152
159
|
case "suggestions":
|
|
153
160
|
return repoSuggestions(rest);
|
|
161
|
+
case "slack-targets":
|
|
162
|
+
return repoSlackTargets(rest);
|
|
163
|
+
case "slack-test":
|
|
164
|
+
return repoSlackTest(rest);
|
|
154
165
|
default:
|
|
155
166
|
throw new CliError(
|
|
156
|
-
`Unknown repo subcommand: ${sub ?? "(none)"}. Try: start, fix-audit, install-letterprove, sites, set-site, reset-site, status, list, publish, cancel, repos, branches, settings, suggestions`
|
|
167
|
+
`Unknown repo subcommand: ${sub ?? "(none)"}. Try: start, fix-audit, install-letterprove, sites, set-site, reset-site, status, list, publish, cancel, repos, branches, settings, suggestions, slack-targets, slack-test`
|
|
157
168
|
);
|
|
158
169
|
}
|
|
159
170
|
}
|
|
@@ -407,8 +418,12 @@ async function repoBranches(ctx) {
|
|
|
407
418
|
*/
|
|
408
419
|
async function repoSettings(ctx) {
|
|
409
420
|
const { client, flags, io } = ctx;
|
|
410
|
-
refuseUnknownFlags(ctx, {}, ["action", "branch", "slack-agent"]);
|
|
411
|
-
const setting =
|
|
421
|
+
refuseUnknownFlags(ctx, {}, ["action", "branch", "slack-agent", "slack-channel"]);
|
|
422
|
+
const setting =
|
|
423
|
+
flags.action !== undefined ||
|
|
424
|
+
flags.branch !== undefined ||
|
|
425
|
+
flags["slack-agent"] !== undefined ||
|
|
426
|
+
flags["slack-channel"] !== undefined;
|
|
412
427
|
const result = setting
|
|
413
428
|
? await client.callTool("set_repo_change_settings", argsFromFlags(ARGS.set_repo_change_settings, flags))
|
|
414
429
|
: await client.callTool("get_repo_change_settings", {});
|
|
@@ -441,4 +456,30 @@ async function repoSuggestions(ctx) {
|
|
|
441
456
|
return 0;
|
|
442
457
|
}
|
|
443
458
|
|
|
459
|
+
/** `repo slack-targets`: the channels and people Send to Slack can use, with their ids. */
|
|
460
|
+
async function repoSlackTargets(ctx) {
|
|
461
|
+
const { client, flags, io } = ctx;
|
|
462
|
+
refuseUnknownFlags(ctx, {}, []);
|
|
463
|
+
const result = await client.callTool("list_slack_fix_targets", {});
|
|
464
|
+
printResult(io, flags, result, (r) =>
|
|
465
|
+
[
|
|
466
|
+
"Channels (repo settings --slack-channel <id>):",
|
|
467
|
+
...r.channels.map((c) => ` ${c.id} #${c.name}`),
|
|
468
|
+
"People (repo settings --slack-agent <id>):",
|
|
469
|
+
...r.people.map((p) => ` ${p.id} ${p.name}${p.is_bot ? " (bot)" : ""}`),
|
|
470
|
+
].join("\n")
|
|
471
|
+
);
|
|
472
|
+
return 0;
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
/** `repo slack-test`: post a test into the Send to Slack channel. */
|
|
476
|
+
async function repoSlackTest(ctx) {
|
|
477
|
+
const { client, flags, io } = ctx;
|
|
478
|
+
refuseUnknownFlags(ctx, {}, []);
|
|
479
|
+
const result = await client.callTool("send_slack_test_message", {});
|
|
480
|
+
ok(ctx, result.message);
|
|
481
|
+
printResult(io, flags, result);
|
|
482
|
+
return 0;
|
|
483
|
+
}
|
|
484
|
+
|
|
444
485
|
export { ARGS };
|
package/lib/commands/site.mjs
CHANGED