@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.
- package/README.md +126 -124
- package/dist/index.js +92 -242
- package/dist/mcp.js +43 -181
- 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
|
|
53
|
-
|
|
|
54
|
-
| `--token <token>`
|
|
55
|
-
| `--api-url <url>`
|
|
56
|
-
| `--env <environment>`
|
|
57
|
-
| `--format <format>`
|
|
58
|
-
| `--version`
|
|
59
|
-
| `--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.
|
|
74
|
-
fills in the 5-knob spec
|
|
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 `
|
|
98
|
-
`
|
|
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
|
|
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
|
-
|
|
142
|
-
|
|
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
|
-
|
|
216
|
-
`
|
|
217
|
-
|
|
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
|
-
|
|
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
|
|
234
|
-
|
|
|
235
|
-
| `meters[]`
|
|
236
|
-
| `recurring_fee_cents`
|
|
237
|
-
| `recurring_credit_grant_cents`
|
|
238
|
-
| `one_time_credit_grant_cents`
|
|
239
|
-
| `trial_days`
|
|
240
|
-
| `max_monthly_spend_cents`
|
|
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
|
|
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
|
|
316
|
-
| --------------- |
|
|
317
|
-
| `recurring` | `amount_cents`
|
|
318
|
-
| `one_time` | `amount_cents`
|
|
319
|
-
| `promotional` | `amount_cents`, `label`, optional `expires_after_days`
|
|
320
|
-
| `trial` | (none)
|
|
321
|
-
| `rollover` | `percent` (0–100)
|
|
322
|
-
| `top_up` | `sku`, `label`, `price_cents`, `credit_cents`
|
|
323
|
-
| `auto_recharge` | `threshold_cents`, `refill_cents`
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
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
|
-
|
|
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`
|
|
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
|
|
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
|
|
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
|
-
- `
|
|
422
|
+
- `build --validate` emits an informational warning so the builder
|
|
381
423
|
sees the active policy locally.
|
|
382
|
-
-
|
|
383
|
-
|
|
384
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
462
|
+
The MCP server (`farthershore-mcp`) exposes one tool:
|
|
459
463
|
|
|
460
|
-
- `
|
|
461
|
-
|
|
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`
|
|
490
|
-
|
|
491
|
+
safe to script. `farthershore build --validate` is CI-safe and can be
|
|
492
|
+
run under `CI` / `GITHUB_ACTIONS` for automation.
|