@farthershore/cli 0.7.3 → 0.9.0

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 (4) hide show
  1. package/README.md +126 -124
  2. package/dist/index.js +92 -242
  3. package/dist/mcp.js +43 -181
  4. package/package.json +1 -1
package/README.md CHANGED
@@ -49,14 +49,14 @@ farthershore auth logout # Clear stored credentials
49
49
 
50
50
  ## Global flags
51
51
 
52
- | Flag | Description |
53
- | ---------------------- | ----------------------------------------------------- |
54
- | `--token <token>` | Override auth token for this command |
55
- | `--api-url <url>` | Override API base URL |
56
- | `--env <environment>` | Environment scope (use `production`/`prod`/`main`) |
57
- | `--format <format>` | `json` for machine-readable output (default for non-TTY) |
58
- | `--version` | Show version |
59
- | `--help` | Show help |
52
+ | Flag | Description |
53
+ | --------------------- | -------------------------------------------------------- |
54
+ | `--token <token>` | Override auth token for this command |
55
+ | `--api-url <url>` | Override API base URL |
56
+ | `--env <environment>` | Environment scope (use `production`/`prod`/`main`) |
57
+ | `--format <format>` | `json` for machine-readable output (default for non-TTY) |
58
+ | `--version` | Show version |
59
+ | `--help` | Show help |
60
60
 
61
61
  ## Environment variables
62
62
 
@@ -70,9 +70,9 @@ farthershore auth logout # Clear stored credentials
70
70
 
71
71
  ### `farthershore init`
72
72
 
73
- Scaffold a starter `product.yaml` from a named plan preset. Each preset
74
- fills in the 5-knob spec for a common shape so first-time builders skip
75
- the blank-page problem.
73
+ Scaffold a starter `product/product.config.ts` from a named plan preset. Each
74
+ preset fills in the 5-knob spec through the Product SDK so first-time builders
75
+ skip the blank-page problem.
76
76
 
77
77
  ```bash
78
78
  # Interactive walkthrough (TTY only) — pick a preset by number/name + path
@@ -86,20 +86,38 @@ farthershore init --template metered --format json
86
86
 
87
87
  Templates (sourced from shared-types `listPlanPresets()`):
88
88
 
89
- | Template | Shape |
90
- | --------- | ------------------------------------------------------------------ |
91
- | `free` | $0 plan, hard-enforced 1k requests/month limit |
92
- | `starter` | $20/mo + $20 included usage, $0.001/request overage |
93
- | `pro` | $100/mo + $200 included usage, 14-day trial, $0.0005/request |
94
- | `prepaid` | $50 one-time signup credit, then PAYG |
95
- | `metered` | Pure pay-as-you-go at $0.001/request |
89
+ | Template | Shape |
90
+ | --------- | ------------------------------------------------------------ |
91
+ | `free` | $0 plan, hard-enforced 1k requests/month limit |
92
+ | `starter` | $20/mo + $20 included usage, $0.001/request overage |
93
+ | `pro` | $100/mo + $200 included usage, 14-day trial, $0.0005/request |
94
+ | `prepaid` | $50 one-time signup credit, then PAYG |
95
+ | `metered` | Pure pay-as-you-go at $0.001/request |
96
96
 
97
- After `init`, edit `product.name` + `product.baseUrl`, then run
98
- `farthershore validate` to confirm the scaffolded YAML is acceptable.
97
+ After `init`, edit the `fs.business(...)` product name + base URL in
98
+ `product/product.config.ts`, split the product into any imported modules you
99
+ want, then run `farthershore build --validate` to confirm the scaffolded
100
+ manifest compiles.
101
+
102
+ ### `farthershore build`
103
+
104
+ Build a product-as-code `product/product.config.ts` with the repo-local
105
+ `./node_modules/.bin/farthershore-manifest-build` binary. The command
106
+ emits a Manifest IR envelope to `manifest-ir.json` by default.
107
+
108
+ ```bash
109
+ farthershore build
110
+ farthershore build --entry product/product.config.ts --out manifest-ir.json
111
+ farthershore build --format json
112
+
113
+ # Optional dry-run compile against core after the local build succeeds
114
+ farthershore build --validate weather-api --format json
115
+ farthershore build --validate weather-api --env preview --format json
116
+ ```
99
117
 
100
118
  ### `farthershore product`
101
119
 
102
- Product lifecycle commands — direct API, no local `product.yaml` round-trip.
120
+ Product lifecycle commands — direct API, no local manifest upload flow.
103
121
 
104
122
  ```bash
105
123
  farthershore product list --format json
@@ -112,7 +130,18 @@ farthershore product create \
112
130
  --base-url https://api.example.com \
113
131
  --format json
114
132
 
133
+ # Meter templates — the same smart defaults the dashboard offers:
134
+ # requests (default) | ai-tokens | credits | spend | compute
135
+ farthershore product create --name llm-api --meters ai-tokens --format json
136
+
137
+ # Or a fully custom meter list (key[:display[:unit]], repeatable):
138
+ farthershore product create --name image-api \
139
+ --meter requests \
140
+ --meter images:Images:image \
141
+ --format json
142
+
115
143
  farthershore product update weather-api --display-name "Weather" --format json
144
+ farthershore product publish weather-api --format json
116
145
  farthershore product delete weather-api --yes --format json
117
146
 
118
147
  farthershore product compile weather-api --dry-run --format json
@@ -122,7 +151,27 @@ farthershore product compile weather-api --branch env/preview --format json
122
151
  `product create` provisions a managed GitHub repo and returns clone-URL +
123
152
  agent bootstrap instructions in the response. Plan pricing lives on the
124
153
  plan (see `farthershore plan create` below) — the product itself no
125
- longer carries a `billingStrategy`.
154
+ longer carries a `billingStrategy`. Omitting both meter flags gives the
155
+ product a `requests` meter; variable-value meters (tokens, credits, spend)
156
+ are settled from upstream `x-fs-cost-{key}` response headers.
157
+
158
+ A new product starts as a DRAFT with a generated `frontend/` project ready for
159
+ customization. Going live mirrors the dashboard's "Finish setting up" checklist:
160
+
161
+ ```bash
162
+ farthershore product create --name llm-api --meters ai-tokens # 1. create
163
+ farthershore connect stripe llm-api # 2. connect billing
164
+ farthershore plan create llm-api --key pro --name "Pro" \
165
+ --recurring-fee-cents 2900 # 3. how you charge
166
+ farthershore product update llm-api \
167
+ --base-url https://api.example.com # 4. endpoint
168
+ farthershore product publish llm-api # 5. go live
169
+ ```
170
+
171
+ `product publish` enforces the same gates as the dashboard: at least one
172
+ plan, a base URL, and a verified Stripe connection (clear remediation is
173
+ printed for `STRIPE_NOT_CONNECTED` / `STRIPE_NOT_VERIFIED` /
174
+ `BILLING_TAX_NOT_ENROLLED`).
126
175
 
127
176
  ### `farthershore env`
128
177
 
@@ -138,8 +187,8 @@ farthershore env delete weather-api preview --yes --format json
138
187
  ### `farthershore plan`
139
188
 
140
189
  Plan CRUD via the management API. The body uses the unified 5-knob
141
- spec (see "`product.yaml` plan shape" below) — pass cents-denominated
142
- flags for whichever knobs the plan flavor needs.
190
+ shape (see "Plan knobs" below) — pass cents-denominated flags for
191
+ whichever knobs the plan flavor needs.
143
192
 
144
193
  ```bash
145
194
  # Human-readable table (default in TTY)
@@ -210,34 +259,31 @@ farthershore token create --name "ci-bot" --scope products:update products:publi
210
259
  farthershore token revoke <tokenId> --yes --format json
211
260
  ```
212
261
 
213
- ### `farthershore validate`
262
+ ### `farthershore build --validate <product>`
214
263
 
215
- Validate the managed repo (`product.yaml`, `brand.yaml`, `docs/`,
216
- `skills/`, `.github/workflows/`) through the same backend checks the
217
- Farther Shore GitHub bot runs.
264
+ `build --validate` runs a local manifest compile + server-side validation
265
+ pass after `product/product.config.ts` is built. This is the replacement for the
266
+ deleted `validate`/`apply` proposal flow.
218
267
 
219
268
  ```bash
220
- farthershore validate
221
- farthershore validate --format json
269
+ farthershore build --validate weather-api --format json
270
+ farthershore build --validate weather-api --env preview --format json
222
271
  ```
223
272
 
224
- Emits GitHub Actions-formatted annotations when run under `CI` /
225
- `GITHUB_ACTIONS`.
226
-
227
- #### `product.yaml` plan shape
273
+ #### Plan knobs
228
274
 
229
275
  Every plan is a configuration of 5 orthogonal knobs (shared-types
230
276
  v0.53.0). Older shapes with `pricing.{model, monthlyPriceCents}` and
231
277
  top-level `billing.strategy` are no longer accepted by the validator.
232
278
 
233
- | Knob | Cents/unit | Meaning |
234
- | ------------------------------- | ---------------- | ------------------------------------------------------------ |
235
- | `meters[]` | micros/unit | Per-dimension usage price (zero or more dimensions) |
236
- | `recurring_fee_cents` | cents | Charged each billing period (recurring subscription) |
237
- | `recurring_credit_grant_cents` | cents | Credit issued each period; drains against meter charges |
238
- | `one_time_credit_grant_cents` | cents | Prepaid balance at subscription start; drains once |
239
- | `trial_days` | days | Waive everything for N days at the start |
240
- | `max_monthly_spend_cents` | cents (optional) | Hard cap; the gateway blocks once exceeded (orthogonal) |
279
+ | Knob | Cents/unit | Meaning |
280
+ | ------------------------------ | ---------------- | ------------------------------------------------------- |
281
+ | `meters[]` | micros/unit | Per-dimension usage price (zero or more dimensions) |
282
+ | `recurring_fee_cents` | cents | Charged each billing period (recurring subscription) |
283
+ | `recurring_credit_grant_cents` | cents | Credit issued each period; drains against meter charges |
284
+ | `one_time_credit_grant_cents` | cents | Prepaid balance at subscription start; drains once |
285
+ | `trial_days` | days | Waive everything for N days at the start |
286
+ | `max_monthly_spend_cents` | cents (optional) | Hard cap; the gateway blocks once exceeded (orthogonal) |
241
287
 
242
288
  Billing math (handled by Stripe Billing v2 at invoice finalization):
243
289
  `bill = recurring_fee + max(0, total_meter_cost − applied_credit_balance)`.
@@ -258,21 +304,21 @@ plans:
258
304
  capacity: 1000
259
305
  enforcement: enforce
260
306
 
261
- # Flat subscription: recurring fee only
307
+ # Flat subscription: recurring fee only
262
308
  - key: starter
263
309
  name: Starter
264
310
  recurring_fee_cents: 2900
265
311
 
266
- # Included usage: fee + monthly credit grant + metered
312
+ # Included usage: fee + monthly credit grant + metered
267
313
  - key: pro
268
314
  name: Pro
269
315
  recurring_fee_cents: 2000
270
316
  recurring_credit_grant_cents: 2000
271
317
  meters:
272
318
  - dimension: requests
273
- price_per_unit_micros: 1000 # $0.001/request
319
+ price_per_unit_micros: 1000 # $0.001/request
274
320
 
275
- # Overage: fee + metered, no credit
321
+ # Overage: fee + metered, no credit
276
322
  - key: growth
277
323
  name: Growth
278
324
  recurring_fee_cents: 4900
@@ -280,7 +326,7 @@ plans:
280
326
  - dimension: requests
281
327
  price_per_unit_micros: 500
282
328
 
283
- # Prepaid: one-time grant + metered
329
+ # Prepaid: one-time grant + metered
284
330
  - key: prepaid
285
331
  name: Prepaid
286
332
  one_time_credit_grant_cents: 10000
@@ -288,13 +334,13 @@ plans:
288
334
  - dimension: requests
289
335
  price_per_unit_micros: 1000
290
336
 
291
- # Trial: trial_days + recurring fee
337
+ # Trial: trial_days + recurring fee
292
338
  - key: trial
293
339
  name: Trial
294
340
  recurring_fee_cents: 2900
295
341
  trial_days: 14
296
342
 
297
- # Pay-as-you-go: metered only (no recurring fee)
343
+ # Pay-as-you-go: metered only (no recurring fee)
298
344
  - key: metered
299
345
  name: Metered
300
346
  meters:
@@ -312,20 +358,19 @@ entries from the legacy knobs so existing specs keep working.
312
358
 
313
359
  Valid `kind` values:
314
360
 
315
- | Kind | Required fields | Use case |
316
- | --------------- | ---------------------------------------------------------- | -------------------------------------------------------- |
317
- | `recurring` | `amount_cents` | Monthly credit (e.g. $20 included usage) |
318
- | `one_time` | `amount_cents` | Signup bonus / prepaid balance |
319
- | `promotional` | `amount_cents`, `label`, optional `expires_after_days` | Launch bonus, win-back, holiday promo |
320
- | `trial` | (none) | Trial entry — requires `trial_days > 0` on the plan |
321
- | `rollover` | `percent` (0–100) | "Unused balance rolls over X% to the next period" |
322
- | `top_up` | `sku`, `label`, `price_cents`, `credit_cents` | Buy-extra-credit SKU exposed in checkout |
323
- | `auto_recharge` | `threshold_cents`, `refill_cents` | "When balance < $X auto-purchase $Y" |
324
- | `minimum_commit`| `period` (`monthly` / `annual`), `amount_cents` | Floor for billing — charge at least this much |
325
-
326
- `recurring`, `rollover`, `trial`, and `minimum_commit` are single-shot
327
- per plan; declaring more than one entry of the same kind triggers a
328
- warning (only the first is honored).
361
+ | Kind | Required fields | Use case |
362
+ | --------------- | ------------------------------------------------------ | --------------------------------------------------- |
363
+ | `recurring` | `amount_cents` | Monthly credit (e.g. $20 included usage) |
364
+ | `one_time` | `amount_cents` | Signup bonus / prepaid balance |
365
+ | `promotional` | `amount_cents`, `label`, optional `expires_after_days` | Launch bonus, win-back, holiday promo |
366
+ | `trial` | (none) | Trial entry — requires `trial_days > 0` on the plan |
367
+ | `rollover` | `percent` (0–100) | "Unused balance rolls over X% to the next period" |
368
+ | `top_up` | `sku`, `label`, `price_cents`, `credit_cents` | Buy-extra-credit SKU exposed in checkout |
369
+ | `auto_recharge` | `threshold_cents`, `refill_cents` | "When balance < $X auto-purchase $Y" |
370
+
371
+ `recurring`, `rollover`, and `trial` are single-shot per plan;
372
+ declaring more than one entry of the same kind triggers a warning
373
+ (only the first is honored).
329
374
 
330
375
  Example:
331
376
 
@@ -351,22 +396,19 @@ plans:
351
396
  - kind: auto_recharge
352
397
  threshold_cents: 500
353
398
  refill_cents: 5000
354
- - kind: minimum_commit
355
- period: monthly
356
- amount_cents: 5000
357
399
  ```
358
400
 
359
- The validator surfaces:
401
+ Validation surfaces:
360
402
 
361
403
  - **error** — invalid `kind` is rewritten to `Unknown grant kind. Valid kinds: …`
362
- - **warning** — `grants[]` declares `recurring`/`one_time` *and* the matching legacy knob is also non-zero (legacy is silently ignored)
404
+ - **warning** — `grants[]` declares `recurring`/`one_time` _and_ the matching legacy knob is also non-zero (legacy is silently ignored)
363
405
  - **warning** — `{ kind: trial }` declared but `trial_days` is 0
364
- - **warning** — singleton kinds (`recurring`, `rollover`, `trial`, `minimum_commit`) declared more than once
406
+ - **warning** — singleton kinds (`recurring`, `rollover`, `trial`) declared more than once
365
407
 
366
408
  #### Deprecation window (Phase 3b)
367
409
 
368
410
  The product top-level `lifecycle.breaking_changes` block declares the
369
- breaking-change governance policy enforced on `apply`:
411
+ breaking-change governance policy validated during `build --validate`:
370
412
 
371
413
  ```yaml
372
414
  lifecycle:
@@ -377,52 +419,16 @@ lifecycle:
377
419
 
378
420
  When the policy is set:
379
421
 
380
- - `farthershore validate` emits an informational warning so the builder
422
+ - `build --validate` emits an informational warning so the builder
381
423
  sees the active policy locally.
382
- - `farthershore apply` (which compares the proposed spec against the
383
- accepted spec) emits a `route_removed` change for every route
384
- dropped from `features.<x>.routes[]` and warns that the server-side
385
- `breaking-change-safety-check` cron will gate the publish via
424
+ - It emits a `route_removed` change for every route dropped from
425
+ `features.<x>.routes[]` and warns when the server-side
426
+ `breaking-change-safety-check` cron will gate publish via
386
427
  `ConsumerActivity` lookup. When `require_successor_route` is true,
387
- the apply path additionally surfaces a successor-required warning.
428
+ it also adds a successor-required warning.
388
429
 
389
430
  The CLI never blocks on the window itself — the per-consumer lookup
390
431
  lives server-side (Phase 1c `ConsumerActivity` table + Phase 3b cron).
391
- The CLI's job is to surface the policy and the route delta locally so
392
- the builder knows what the gate will see.
393
-
394
- ### `farthershore apply [product]`
395
-
396
- Publish the shared server draft as one product release. Core accepts the
397
- release only after schema validation, transition-safety validation, and
398
- a compiler dry-run all pass.
399
-
400
- ```bash
401
- # Publish the current shared draft
402
- farthershore apply
403
-
404
- # Or pass the product slug/UUID explicitly
405
- farthershore apply weather-api
406
-
407
- # Validate and compile without publishing
408
- farthershore apply --dry-run --format json
409
- farthershore apply --env preview --dry-run --format json
410
-
411
- # Submit a local product.yaml as a one-off proposal
412
- farthershore apply --to product.yaml --dry-run --format json
413
- farthershore apply --to product.yaml --format json
414
-
415
- # Also stage that file as the shared draft before publishing
416
- farthershore apply --to product.yaml --save-draft --format json
417
-
418
- # Pin compilation to a specific branch
419
- farthershore apply weather-api --branch feature/billing-change --dry-run --format json
420
- ```
421
-
422
- JSON output is stable: `{ ok, success, errors, warnings, lifecyclePlan,
423
- nextActions, ... }`. `lifecyclePlan` is always present (or `null` on
424
- first deploys / older core builds) and surfaces ADR-0010 per-domain
425
- subscriber-migration actions.
426
432
 
427
433
  ## Agent workflow
428
434
 
@@ -440,27 +446,23 @@ farthershore plan create weather-api --key free --name "Free" --free --format js
440
446
  farthershore plan create weather-api \
441
447
  --key pro --name "Pro" --recurring-fee-cents 2900 --format json
442
448
 
443
- farthershore apply weather-api --dry-run --format json
444
- farthershore apply weather-api --format json
449
+ farthershore build --validate weather-api --format json
445
450
  farthershore product show weather-api --format json
446
451
  ```
447
452
 
448
- For a YAML-driven flow, edit `product.yaml` in the managed repo, then:
453
+ For product updates, edit `product/product.config.ts` or any modules it imports
454
+ and validate with:
449
455
 
450
456
  ```bash
451
- farthershore validate --format json
452
- farthershore apply --to product.yaml --dry-run --format json
453
- farthershore apply --to product.yaml --format json
457
+ farthershore build --validate weather-api --format json
454
458
  ```
455
459
 
456
460
  ## MCP server
457
461
 
458
- The MCP server (`farthershore-mcp`) exposes two tools:
462
+ The MCP server (`farthershore-mcp`) exposes one tool:
459
463
 
460
- - `farthershore_draft_validate` — run server-side validation on the shared
461
- draft.
462
- - `farthershore_apply` — apply the draft, optionally with a `product.yaml`
463
- proposal via `toFile`. Defaults to `dryRun: true`.
464
+ - `farthershore_status` — return product list context and selected product
465
+ metadata.
464
466
 
465
467
  Both accept optional `product` and `env` fields and return JSON.
466
468
 
@@ -486,5 +488,5 @@ for CI scripts.
486
488
  The CLI is non-interactive whenever a token is available via the
487
489
  `--token` flag or `FARTHERSHORE_TOKEN` env var — `auth login` only
488
490
  prompts when stdin is a TTY and no token argument was passed, so it's
489
- safe to script. `validate` and `apply` emit GitHub Actions-formatted
490
- annotations when run under `CI` / `GITHUB_ACTIONS`.
491
+ safe to script. `farthershore build --validate` is CI-safe and can be
492
+ run under `CI` / `GITHUB_ACTIONS` for automation.