@letterstory/cli 0.108.1 → 0.108.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.
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.108.1";
63
+ export const VERSION = "0.108.2";
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
@@ -14,7 +14,7 @@
14
14
  // The old names — evals, eval-add, eval-set, proposals, propose-eval, capture-eval, reject-eval — still work.)
15
15
  // admin evals scoreboard|cases|runs|run|triage|guard|retire … (fleet:read / tuning:experiment)
16
16
  // admin fleet-experiments list|articles|clients|mark|unmark|new|assign|assign-eligible|assign-orgs|spin-up|apply|start|stop|decide … (fleet:read / fleet:experiment)
17
- // admin crm import|capture|outreach|signals|record|signal|accounts|account|score|slack-channels|link-slack|white-glove|set-white-glove|churn|record-churn|undo-churn|onboard|onboarding|retry-onboarding|onboard-plan|payment-link … (crm:read / crm:write)
17
+ // admin crm import|capture|outreach|signals|record|signal|accounts|account|score|slack-channels|link-slack|white-glove|set-white-glove|churn|revenue|record-churn|undo-churn|onboard|onboarding|retry-onboarding|onboard-plan|payment-link … (crm:read / crm:write)
18
18
  // admin spend summary|reconcile|pnl|entries|add|import|usage|remove|reference|stripe-sync|services|service … (spend:read / spend:write)
19
19
  // admin brand-detection <org-id> (fleet:read)
20
20
  // admin brand-detection <org-id> [--term t]... [--exact t]... [--exclude p]... [--note "…"] | --clear [--note "…"] (fleet:instrument)
@@ -3325,6 +3325,24 @@ async function cmdAdminCrm(ctx) {
3325
3325
  ].join("\n")
3326
3326
  );
3327
3327
  }
3328
+ case "revenue": {
3329
+ // admin crm revenue — monthly NRR/GRR since 2026-08-10, the bridge, spend per client (docs/architecture/retention.md).
3330
+ const pct = (x) => (x == null ? "—" : `${(x * 100).toFixed(1)}%`);
3331
+ const usd = (cents) => `$${Math.round(cents / 100).toLocaleString("en-US")}`;
3332
+ return out(await staffRequest(ctx, "GET", `${CRM}/revenue`), (r) =>
3333
+ [
3334
+ r.headline
3335
+ ? `${r.headline.month}: NRR ${pct(r.headline.nrr)} · GRR ${pct(r.headline.grr)} · expansion ${usd(r.headline.expansionCents)} · avg ${r.headline.avgCents == null ? "—" : usd(r.headline.avgCents)}/client`
3336
+ : "No complete month yet.",
3337
+ `Clients counted: ${r.coverage.counted} (${r.coverage.stripe} Stripe, ${r.coverage.deal} deal) · comp ${r.coverage.comp} · ${usd(r.coverage.countedCents)}/mo`,
3338
+ "",
3339
+ ...r.periods.map(
3340
+ (p) =>
3341
+ `${p.month}${p.partial ? " (partial)" : ""}${p.estimated ? " ~" : ""} ${usd(p.startCents)} → ${usd(p.endCents)} NRR ${pct(p.nrr)} +new ${usd(p.moves.new)} +back ${usd(p.moves.reactivated)} +exp ${usd(p.moves.expansion)} −con ${usd(p.moves.contraction)} −churn ${usd(p.moves.churn)} ±reclassified ${usd(p.moves.reclassified)}`
3342
+ ),
3343
+ ].join("\n")
3344
+ );
3345
+ }
3328
3346
  case "record-churn": {
3329
3347
  // admin crm record-churn <account-id> <reason> [--note "…"] [--at ISO] [--mrr-cents N]
3330
3348
  if (!id || !action) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@letterstory/cli",
3
- "version": "0.108.1",
3
+ "version": "0.108.2",
4
4
  "description": "Spin up and manage Letterstory phantom blogs from your terminal.",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",