@letterstory/cli 0.176.39 → 0.176.41

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/lib/cli.mjs CHANGED
@@ -83,7 +83,7 @@ import {
83
83
  import { fetchParkedSections, withoutParked } from "./parked.mjs";
84
84
 
85
85
  // Matches cli/package.json; publish-cli.yml rewrites both to the published version.
86
- export const VERSION = "0.176.39";
86
+ export const VERSION = "0.176.41";
87
87
 
88
88
  /** The exit code for a gate refusal (CARD_REQUIRED, PAYMENT_FAILED, OUT_OF_TOKENS): 1 is a plain error. */
89
89
  export const EXIT_PAYMENT_REQUIRED = 3;
@@ -94,6 +94,8 @@ export const EXIT_PAYMENT_REQUIRED = 3;
94
94
  export const BOOLEAN_FLAGS = new Set([
95
95
  // build list: also move the builds' open changes along while polling.
96
96
  "advance",
97
+ // build list: only what the Plan started.
98
+ "from-plan",
97
99
  // build: a website or app of its own (deploy create's path). deploy create: hold until its build starts.
98
100
  "new-site",
99
101
  "wait",
@@ -625,16 +627,17 @@ Reviewers:
625
627
  automate list Your automations: an event, which ones it acts on,
626
628
  and what Letterpress then does
627
629
  automate show <automation-id>
628
- automate add [--template post_new_issues|recommended_actions|competitor_pages|icp_visitors|plan_updates]
630
+ automate add [--template post_new_issues|recommended_actions|competitor_pages|icp_visitors|vc_visitors|plan_updates]
629
631
  [--name <n>] [--trigger competitor_page|visitor_identified|issue_found|build_suggestion|plan_update|custom]
630
632
  [--prompt <what Letterpress does with each event>] [--slack-channel <C…>] [--instruction <which events>]
631
633
  [--event <name>] [--kind post|landing] [--competitor <host>] [--site <host>]
632
- [--hot-leads-only] [--per-day <n>] [--off]
634
+ [--hot-leads-only] [--per-day <n>] [--backfill all|<YYYY-MM-DD>] [--off]
633
635
  Make one (a template fills what you leave out): it starts
634
- from now, acts on its own, and posts each event it acts on
636
+ from now (--backfill also runs it on past events, oldest
637
+ first), acts on its own, and posts each event it acts on
635
638
  to --slack-channel with its buttons
636
639
  automate set <automation-id> [--name <n>] [--instruction <text>] [--prompt <text>] [--slack-channel <C…>|none]
637
- [--on|--off] ...
640
+ [--backfill all|<YYYY-MM-DD>] [--on|--off] ...
638
641
  automate try [<automation-id>] [--trigger <t> --prompt <text> --instruction <text> ...] [--limit <n>]
639
642
  What it would do with the latest events (acts on none)
640
643
  automate runs [--automation <id>] [--status acting|acted|skipped|failed|proposed|rejected] [--limit <n>]
@@ -1670,7 +1673,7 @@ Insights:
1670
1673
  Plan tab's box), what's broken (--lens fix, most pressing
1671
1674
  first), what to build (--lens build), or your own words. Nothing asked:
1672
1675
  each list's head. The same answer as the console and Slack.
1673
- plan auto [activate|disable] [--site host] [--veto-hours <1-168>|off] [--auto-merge on|off]
1676
+ plan auto [activate|disable] [--site host] [--veto-hours <1-168>|off] [--pace-hours <1-168>] [--auto-merge on|off]
1674
1677
  [--aggression low|medium|high|xhigh] [--goal geo|seo|agent_conviction|inbound_conversion|any]
1675
1678
  [--slack-channel <C…>|none]
1676
1679
  Auto-Plan on a site: Letterpress picks its strategies and builds
@@ -1725,7 +1728,7 @@ Build (a change to your site, or launching what isn't code; the Build box's own
1725
1728
  Staff only. The same prompt on Letterpress-1 (as Build runs it) and on
1726
1729
  stock Claude Code and stock Codex, each a preview to compare
1727
1730
  build benchmarks [--id <uuid>] [--limit <n>] Staff only. Benchmarks, each arm's state, preview, cost and agent time
1728
- build list [--limit <n>] [--site <host>] [--kind build|fix] [--open|--archived]
1731
+ build list [--limit <n>] [--site <host>] [--kind build|fix] [--open|--archived] [--from-plan]
1729
1732
  Your builds, newest first, with where each stands
1730
1733
  build status <build-id> One build: each change's state, its preview and pull request
1731
1734
  build follow <build-id> [--json] What its agents do, line by line, until nothing in it is at
@@ -8,7 +8,14 @@ import { CliError } from "../client.mjs";
8
8
  import { printResult, ok, argsFromFlags, flagList, refuseUnknownFlags } from "./shared.mjs";
9
9
 
10
10
  const TRIGGERS = ["competitor_page", "visitor_identified", "issue_found", "build_suggestion", "plan_update", "custom"];
11
- const TEMPLATES = ["post_new_issues", "recommended_actions", "competitor_pages", "icp_visitors", "plan_updates"];
11
+ const TEMPLATES = [
12
+ "post_new_issues",
13
+ "recommended_actions",
14
+ "competitor_pages",
15
+ "icp_visitors",
16
+ "vc_visitors",
17
+ "plan_updates",
18
+ ];
12
19
  const STATUSES = ["pending", "proposed", "acting", "acted", "skipped", "failed", "rejected"];
13
20
 
14
21
  const triggerParams = {
@@ -31,6 +38,19 @@ const slackChannel = {
31
38
  : String(flags["slack-channel"]),
32
39
  };
33
40
  const enabled = { value: (flags) => (flags.off === true ? false : flags.on === true ? true : undefined) };
41
+ // --backfill all (the whole history the trigger's source keeps) or --backfill 2026-09-01 (from that day):
42
+ // also run it on past events, oldest first.
43
+ const backfill = {
44
+ value: (flags) => {
45
+ const v = flags.backfill;
46
+ if (v === undefined) return undefined;
47
+ if (v === true || v === "all") return "all";
48
+ const day = String(v);
49
+ if (!/^\d{4}-\d{2}-\d{2}$/.test(day))
50
+ throw new CliError(`--backfill takes all or a day (YYYY-MM-DD), got: ${day}`);
51
+ return { since: `${day}T00:00:00Z` };
52
+ },
53
+ };
34
54
 
35
55
  /** --fact plan=team --fact seats=40 → { plan: "team", seats: 40 } (numbers and true/false read as such). */
36
56
  function factsOf(flags) {
@@ -69,6 +89,7 @@ export const ARGS = {
69
89
  prompt: { flag: "prompt" },
70
90
  slack_channel: slackChannel,
71
91
  enabled,
92
+ backfill,
72
93
  },
73
94
  update_event_automation: {
74
95
  automation_id: { positional: 0, label: "automation-id", required: true },
@@ -78,6 +99,7 @@ export const ARGS = {
78
99
  prompt: { flag: "prompt" },
79
100
  slack_channel: slackChannel,
80
101
  enabled,
102
+ backfill,
81
103
  },
82
104
  delete_event_automation: {
83
105
  automation_id: { positional: 0, label: "automation-id", required: true },
@@ -8,7 +8,7 @@
8
8
  // build benchmark <words…> → start_build_benchmark (staff only: Letterpress-1, stock Claude Code
9
9
  // and stock Codex on the same prompt, each a preview)
10
10
  // build benchmarks → list_build_benchmarks (staff only; --id <uuid> for one)
11
- // build list → list_growth_builds (newest first; --site, --kind, --open/--archived)
11
+ // build list → list_growth_builds (newest first; --site, --kind, --open/--archived, --from-plan)
12
12
  // build status <id> → list_growth_builds (one build: its steps, previews and PRs)
13
13
  // build follow <id> → list_growth_builds (advance) + get_repo_change_activity, until nothing is at work
14
14
  // build conversations → list_build_conversations
@@ -101,6 +101,8 @@ const ARGS = {
101
101
  archived: { flag: "archived", type: "bool", negate: "open" },
102
102
  // --advance: also move the builds' open changes along while polling (a queued change takes its sandbox, a merge asked for its next step).
103
103
  advance: { flag: "advance", type: "bool" },
104
+ // --from-plan: only what the Plan started (a strategy's row, Auto-Plan's pick), as the Plan's Actions list shows it.
105
+ from_plan: { flag: "from-plan", type: "bool" },
104
106
  },
105
107
  list_build_conversations: { limit: { flag: "limit", type: "num" } },
106
108
  get_build_conversation: {
@@ -272,7 +274,7 @@ async function readBuild(client, args) {
272
274
  /** `build list`: the organization's builds, newest first. */
273
275
  async function buildList(ctx) {
274
276
  const { client, flags, io } = ctx;
275
- refuseUnknownFlags(ctx, {}, ["limit", "kind", "site", "archived", "open", "advance"]);
277
+ refuseUnknownFlags(ctx, {}, ["limit", "kind", "site", "archived", "open", "advance", "from-plan"]);
276
278
  const args = argsFromFlags(ARGS.list_growth_builds, flags, []);
277
279
  const result = await client.callTool("list_growth_builds", args);
278
280
  printResult(io, flags, result, (r) =>
@@ -1,7 +1,7 @@
1
1
  // `plan` — Auto-Plan on one site (Plan → Auto-Plan; Plan is scoped to one website, --site, else the
2
2
  // organization's own domain). The same calls as the Plan's modal and its sidebar's Pending rows.
3
3
  // plan auto → get_auto_plan
4
- // plan auto [activate|disable] [--veto-hours <1-168>|off] [--auto-merge on|off]
4
+ // plan auto [activate|disable] [--veto-hours <1-168>|off] [--pace-hours <1-168>] [--auto-merge on|off]
5
5
  // [--aggression low|medium|high|xhigh] [--goal geo|seo|agent_conviction|inbound_conversion|any]
6
6
  // [--slack-channel <C…>|none] → set_auto_plan
7
7
  // plan pending → list_auto_plan_proposals (status pending)
@@ -43,6 +43,8 @@ export const ARGS = {
43
43
  return n;
44
44
  },
45
45
  },
46
+ // --pace-hours <1-168> how often it picks the next action (1 every hour, 24 every day, 168 every week).
47
+ pace_hours: { flag: "pace-hours", type: "num" },
46
48
  merge: { value: onOff("auto-merge") },
47
49
  aggression: { flag: "aggression", enum: ["low", "medium", "high", "xhigh"] },
48
50
  // --goal geo picks strategies for that goal only; --goal any (the default) reads every strategy.
@@ -87,7 +89,7 @@ export const ARGS = {
87
89
  },
88
90
  };
89
91
 
90
- const SETTING_FLAGS = ["veto-hours", "auto-merge", "aggression", "goal", "slack-channel"];
92
+ const SETTING_FLAGS = ["veto-hours", "pace-hours", "auto-merge", "aggression", "goal", "slack-channel"];
91
93
 
92
94
  export async function cmdPlan(ctx) {
93
95
  const { client, flags, io } = ctx;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@letterstory/cli",
3
- "version": "0.176.39",
3
+ "version": "0.176.41",
4
4
  "description": "Spin up and manage Letter phantom blogs from your terminal.",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",