@farthershore/cli 0.15.0 → 0.17.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 +233 -396
  2. package/dist/index.js +55 -55
  3. package/dist/mcp.js +14 -14
  4. package/package.json +3 -3
package/README.md CHANGED
@@ -1,12 +1,21 @@
1
1
  # @farthershore/cli
2
2
 
3
- Bootstrap and operate [FartherShore](https://farthershore.com) software
4
- businesses from the terminal. Product behavior is authored in the GitHub repo;
5
- the CLI is the agent-friendly tool layer for setup, release, observability, and
6
- runtime operations. Every command supports `--format json` for non-TTY
7
- scripting. GitHub account linking and Stripe Connect/KYC stay browser-hosted;
8
- the CLI reports their status so agents can continue after the builder completes
9
- those flows.
3
+ Create and operate [FartherShore](https://farthershore.com) software businesses
4
+ from the terminal.
5
+
6
+ **Status: `0.16.0`.** Pre-1.0 — the command surface is stable but may still
7
+ change between minor versions. Pin an exact version in CI.
8
+
9
+ FartherShore lets you define a software business as code, then sells, meters,
10
+ and bills access to it at the edge. Product behavior — plans, pricing, limits,
11
+ routes, meters, and origins — is authored in your GitHub repo with
12
+ [`@farthershore/business`](https://www.npmjs.com/package/@farthershore/business)
13
+ and applied automatically when you push. This CLI is the tool layer around that
14
+ repo: scaffold a new business, validate it locally before you push, connect
15
+ billing, publish it live, and run day-to-day operations (consumers, secrets,
16
+ backends, webhooks, promo codes, usage). It is designed to be safe for both
17
+ humans and agents — every command takes `--format json` for non-interactive
18
+ scripting, and the same surface is exposed as an MCP server.
10
19
 
11
20
  ## Install
12
21
 
@@ -14,7 +23,7 @@ those flows.
14
23
  npm install -g @farthershore/cli
15
24
  ```
16
25
 
17
- Or use directly with npx:
26
+ Or run it directly with npx:
18
27
 
19
28
  ```bash
20
29
  npx @farthershore/cli --help
@@ -43,79 +52,84 @@ farthershore auth login --token mk_xxx
43
52
  export FARTHERSHORE_TOKEN=mk_xxx
44
53
  ```
45
54
 
46
- Tokens are stored in `~/.farthershore/credentials.json`. Maker tokens are
47
- exchanged for a short-lived CLI access token on first authenticated request.
55
+ Tokens are stored in `~/.farthershore/credentials.json`. A maker token is
56
+ exchanged for a short-lived CLI access token on the first authenticated request.
48
57
 
49
58
  ```bash
50
- farthershore auth whoami # Show current org, role, scopes
59
+ farthershore auth whoami # Show current org, role, and scopes
51
60
  farthershore auth logout # Clear stored credentials
52
61
  ```
53
62
 
54
- ## Agent skills
63
+ GitHub account linking and Stripe Connect/KYC are browser-hosted flows; the CLI
64
+ reports their status (see `connect`) so you — or an agent — can continue once the
65
+ flow is finished in the dashboard.
55
66
 
56
- Inside a managed business repo, install SDK-compatible agent skills from the SDK
57
- versions the repo actually uses. The Business SDK and Frontend SDK tracks are
58
- recommended independently, so updating `@farthershore/business` does not force a
59
- `@farthershore/farthershore-js` skill update, or the reverse.
67
+ ## Quickstart
68
+
69
+ Scaffold a business, validate it, connect billing, and publish:
60
70
 
61
71
  ```bash
62
- farthershore skills recommend --format json
63
- SKILLS_CMD=$(farthershore skills recommend --format json | jq -r '.data.recommendation.command')
64
- eval "$SKILLS_CMD"
72
+ export FARTHERSHORE_TOKEN=mk_xxx
73
+
74
+ # 1. Create the managed repo (provisions GitHub repo + starter frontend)
75
+ farthershore business create --name weather-api --display-name "Weather API"
76
+
77
+ # 2. Edit business behavior in the repo
78
+ gh repo clone acme/weather-api
79
+ cd weather-api
80
+ # ...edit business/business.config.ts with @farthershore/business...
81
+
82
+ # 3. Validate the same way the PR check will, before pushing
83
+ farthershore preflight --business weather-api
84
+
85
+ # 4. Push — the GitHub bot compiles + applies your manifest
86
+ git push --set-upstream origin feature/pricing
87
+ farthershore change-set list weather-api # inspect checks + apply state
65
88
 
66
- # Refresh only the track for the SDK that changed:
67
- farthershore skills recommend --format json \
68
- | jq -r '.data.recommendation.tracks[] | "\(.packageName) -> \(.command)"'
89
+ # 5. Connect billing, then go live
90
+ farthershore connect stripe weather-api
91
+ farthershore business publish weather-api
69
92
  ```
70
93
 
94
+ Plans, prices, limits, routes, meters, and origins are **repo-controlled**:
95
+ change them by editing `business/business.config.ts` and pushing. The CLI's
96
+ write commands cover **operational** state that lives outside the manifest
97
+ (consumers, secrets, backends, webhooks, promo codes, brand presentation).
98
+
71
99
  ## Global flags
72
100
 
73
101
  | Flag | Description |
74
102
  | --------------------- | -------------------------------------------------------- |
75
103
  | `--token <token>` | Override auth token for this command |
76
104
  | `--api-url <url>` | Override platform Core API URL |
77
- | `--env <environment>` | Environment scope (use `production`/`prod`/`main`) |
105
+ | `--env <environment>` | Environment scope (`production`/`prod`/`main` aliases) |
78
106
  | `--format <format>` | `json` for machine-readable output (default for non-TTY) |
79
- | `--no-input` | Never prompt; use non-interactive agent-safe paths |
107
+ | `--no-input` | Never prompt; use non-interactive, agent-safe paths |
80
108
  | `--version` | Show version |
81
109
  | `--help` | Show help |
82
110
 
83
111
  ## Environment variables
84
112
 
85
- | Variable | Description |
86
- | ---------------------- | ---------------------------------------------------------------- |
87
- | `FARTHERSHORE_TOKEN` | API token (overrides stored credentials) |
88
- | `FARTHERSHORE_API_URL` | Platform Core API URL (default: `https://core.farthershore.com`) |
89
- | `FARTHERSHORE_ENV` | Default environment scope when `--env` is omitted |
113
+ | Variable | Description |
114
+ | ---------------------- | --------------------------------------------------------------- |
115
+ | `FARTHERSHORE_TOKEN` | API token (overrides stored credentials) |
116
+ | `FARTHERSHORE_API_URL` | Platform Core API URL (default `https://core.farthershore.com`) |
117
+ | `FARTHERSHORE_ENV` | Default environment scope when `--env` is omitted |
90
118
 
91
119
  ## Commands
92
120
 
93
- ### `farthershore operations`
94
-
95
- Print the machine-readable action boundary before an agent attempts a change:
96
- repo-authored product behavior, API-controlled runtime operations, dual
97
- repo/API operations, and browser-only prerequisites.
98
-
99
- ```bash
100
- farthershore operations list --format json
101
- ```
102
-
103
- `contract` rows are changed in `business/business.config.ts` and pushed through
104
- GitHub. `operate` rows are CLI/Core API actions. `dual` rows reconcile through
105
- either path. `browserOnlyPrerequisites` currently includes GitHub account
106
- linking and Stripe Connect onboarding, both status-only from the CLI.
121
+ Run `farthershore <group> --help` for the full flag set of any command.
107
122
 
108
123
  ### `farthershore init`
109
124
 
110
- Scaffold a starter software-business repo from a named plan preset. Each preset
111
- fills in the 5-knob spec in a single decorated `business/business.config.ts` — one
112
- `@Business` class with `@Meter`/`@Feature`/`@Plan` members.
113
- The command also creates a customer `frontend/` project, repo-local
114
- `business/package.json`, `business/tsconfig.json`, and `.gitignore`, matching the
115
- two-root shape generated by dashboard product creation.
125
+ Scaffold a starter business repo locally from a named plan preset. Each preset
126
+ fills in a single decorated `business/business.config.ts` (one `@Business` class
127
+ with `@Meter`/`@Feature`/`@Plan` members) and creates the matching customer
128
+ `frontend/` project, repo-local `business/package.json`, `business/tsconfig.json`,
129
+ and `.gitignore`.
116
130
 
117
131
  ```bash
118
- # Interactive walkthrough (TTY only) — pick a preset by number/name + path
132
+ # Interactive walkthrough (TTY only) — pick a preset and a path
119
133
  farthershore init
120
134
 
121
135
  # Non-interactive — pass --template explicitly (required when not a TTY)
@@ -125,35 +139,28 @@ farthershore init --template metered --format json
125
139
  farthershore init --template starter --surface frontend --surface agent
126
140
  ```
127
141
 
128
- Templates (sourced from shared-types `listPlanPresets()`):
129
-
130
142
  | Template | Shape |
131
143
  | --------- | ------------------------------------------------------------ |
132
144
  | `free` | $0 plan, hard-enforced 1k requests/month limit |
133
145
  | `starter` | $20/mo + $20 included usage, $0.001/request overage |
134
146
  | `pro` | $100/mo + $200 included usage, 14-day trial, $0.0005/request |
135
- | `prepaid` | $50 one-time signup credit, then PAYG |
147
+ | `prepaid` | $50 one-time signup credit, then pay-as-you-go |
136
148
  | `metered` | Pure pay-as-you-go at $0.001/request |
137
149
 
138
- After `init`, edit the `@Business({ name, origin })` decorator in
139
- `business/business.config.ts`. `origin` is the business logic destination Farther
140
- Shore calls for customer-facing actions. Add `@Meter`/`@Feature`/`@Plan`
141
- members to the class to grow the business. Pass repeatable
150
+ After `init`, edit the `@Business({ name, origin })` decorator — `origin` is the
151
+ business-logic destination FartherShore calls for customer-facing actions — and
152
+ add `@Meter`/`@Feature`/`@Plan` members to grow the business. Pass repeatable
142
153
  `--surface <frontend|api|docs|widget|dashboard|webhook|worker|agent>` to seed a
143
- frontend-only, agent, worker, API, or hybrid business. Omitting `--surface`
144
- keeps the default `frontend + api` starter and its sample gateway route. Run
145
- `npm install` in `business/` once, then run `farthershore build` from the repo
146
- root to confirm the scaffolded business compiles locally. Customize `frontend/`
147
- for signup, pricing, account, and usage screens.
154
+ specific shape; omitting it keeps the default `frontend + api` starter. Run
155
+ `npm install` in `business/`, then `farthershore build` from the repo root to
156
+ confirm it compiles.
148
157
 
149
158
  ### `farthershore build`
150
159
 
151
- Build a business-as-code `business/business.config.ts` with the Business SDK
152
- manifest builder. The CLI first uses the builder installed under `business/`,
153
- then falls back to a root install. The command emits a Manifest IR envelope to
154
- `business-build.json` by default. Server-side validation and accepted lifecycle
155
- state are handled by the GitHub bot when `business/**` changes are pushed to the
156
- repo-backed business.
160
+ Compile `business/business.config.ts` to a Manifest IR envelope locally (default
161
+ output `business-build.json`). The CLI uses the Business SDK installed under
162
+ `business/`, falling back to a root install. This is local compilation only;
163
+ server-side validation and apply happen when you push `business/**` changes.
157
164
 
158
165
  ```bash
159
166
  farthershore build
@@ -161,11 +168,26 @@ farthershore build --entry business/business.config.ts --out business-build.json
161
168
  farthershore build --format json
162
169
  ```
163
170
 
171
+ ### `farthershore preflight`
172
+
173
+ Run the same verdict the GitHub `farthershore/validate` PR check produces, before
174
+ you push. It builds the manifest twice and compares the IR hash (the determinism
175
+ check the build runner enforces), then — when you pass `--business` — submits the
176
+ IR for a server dry-run that returns compile diagnostics, the semantic diff, and
177
+ an economic-change verdict.
178
+
179
+ ```bash
180
+ farthershore preflight # local build + determinism only
181
+ farthershore preflight --business weather-api # + full server verdict
182
+ farthershore preflight --local-only --format json
183
+ ```
184
+
164
185
  ### `farthershore business`
165
186
 
166
- Business lifecycle commands. Creation requires a connected GitHub account because
167
- Farther Shore always provisions the editable `frontend/` starter repo for a new
168
- product.
187
+ Business lifecycle. Creation provisions a managed GitHub repo (the source of
188
+ truth for product behavior) under your connected GitHub account and returns the
189
+ clone URL plus bootstrap instructions. A new business starts as a DRAFT with a
190
+ generated `frontend/` ready to customize.
169
191
 
170
192
  ```bash
171
193
  farthershore business list --format json
@@ -177,12 +199,9 @@ farthershore business create \
177
199
  --display-name "Weather API" \
178
200
  --format json
179
201
 
180
- # Meter templates — the same smart defaults the dashboard offers:
202
+ # Seed a meter from the same templates the dashboard offers:
181
203
  # requests (default) | ai-tokens | credits | spend | compute
182
- farthershore business create \
183
- --name llm-api \
184
- --meters ai-tokens \
185
- --format json
204
+ farthershore business create --name llm-api --meters ai-tokens --format json
186
205
 
187
206
  # Or a fully custom meter list (key[:display[:unit]], repeatable):
188
207
  farthershore business create --name image-api \
@@ -190,71 +209,51 @@ farthershore business create --name image-api \
190
209
  --meter images:Images:image \
191
210
  --format json
192
211
 
193
- # Seed initial Business SDK surfaces (repeatable). Defaults to frontend + API.
212
+ # Seed initial Business SDK surfaces (repeatable; defaults to frontend + api):
194
213
  farthershore business create \
195
214
  --name support-agent \
196
215
  --surface frontend \
197
216
  --surface agent \
198
217
  --format json
199
218
 
200
- farthershore business update weather-api --display-name "Weather" --format json
219
+ farthershore business publish weather-api --format json
220
+ farthershore business delete weather-api --yes --format json
221
+ ```
222
+
223
+ `business update` is presentation-only — it changes display name, description,
224
+ icon, and logo (icon/logo accept PNG, JPEG, or WEBP). Plans, prices, limits,
225
+ routes, meters, and origins are repo-controlled and must be changed through the
226
+ Business SDK code path.
227
+
228
+ ```bash
201
229
  farthershore business update weather-api \
202
230
  --display-name "Weather" \
203
231
  --description "Weather API for agents" \
204
- --primary-color '#22c55e' \
205
232
  --icon-file ./brand/icon.png \
206
233
  --logo-file ./brand/logo.webp \
207
234
  --format json
208
235
  farthershore business update weather-api \
209
- --clear-primary-color --clear-icon --clear-logo --format json
210
- farthershore business publish weather-api --format json
211
- farthershore business delete weather-api --yes --format json
236
+ --clear-icon --clear-logo --format json
212
237
  ```
213
238
 
214
- `business create` provisions a managed GitHub repo under the connected GitHub
215
- account and returns clone-URL plus agent bootstrap instructions in the response.
216
- That repo is the product behavior source of truth. Plans, prices, limits,
217
- routes, meters, policies, workflows, gateway config, origins, and backend
218
- definitions are changed by editing the Business SDK program and pushing a
219
- branch. Business SDK changes can be built locally with `farthershore build`;
220
- accepted changes are compiled and published by the GitHub bot after they are
221
- committed and pushed.
222
-
223
- `business update` is deliberately presentation-only. It updates operate-state
224
- fields that are not the product contract: display name, description, primary
225
- brand color, icon, and logo. Local icon/logo uploads accept PNG, JPEG, or WEBP
226
- files. Plans, prices, limits, routes, meters, policies, workflows, origins, and
227
- backend definitions are repo-controlled and must be changed through the Business
228
- SDK code path.
229
-
230
- Omitting both meter flags during bootstrap gives the starter business a
231
- `requests` meter. Plain request counting is platform-managed. Variable-value
232
- meters such as tokens, credits, or compute must be declared in the Business SDK
233
- as route `reports` and reported by the upstream with `@farthershore/backend`.
234
-
235
- A new product starts as a DRAFT with a generated `frontend/` project ready for
236
- customization. Going live mirrors the dashboard's "Finish setting up" checklist:
239
+ `business publish` enforces the same go-live gates as the dashboard: at least one
240
+ plan, an origin, and a verified Stripe connection (clear remediation is printed
241
+ for `STRIPE_NOT_CONNECTED` / `STRIPE_NOT_VERIFIED` / `BILLING_TAX_NOT_ENROLLED`).
242
+
243
+ ### `farthershore change-set`
244
+
245
+ Inspect repo-backed change sets — PRs, pushes, releases, checks, semantic diffs,
246
+ and apply state — for a business.
237
247
 
238
248
  ```bash
239
- farthershore business create \
240
- --name llm-api # 1. create repo
241
- gh repo clone acme/llm-api # 2. edit business/
242
- farthershore build --format json # 3. validate locally
243
- git push --set-upstream origin feature/pricing # 4. open PR
244
- farthershore change-set list llm-api --format json # 5. inspect checks
245
- farthershore connect stripe llm-api # 6. connect billing
246
- farthershore business publish llm-api # 7. go live
249
+ farthershore change-set list weather-api --format json
250
+ farthershore change-set inspect weather-api 42 --format json # by id, PR #, branch, or SHA
247
251
  ```
248
252
 
249
- `business publish` enforces the same gates as the dashboard: at least one
250
- plan, an origin, and a verified Stripe connection (clear remediation is
251
- printed for `STRIPE_NOT_CONNECTED` / `STRIPE_NOT_VERIFIED` /
252
- `BILLING_TAX_NOT_ENROLLED`).
253
-
254
253
  ### `farthershore env`
255
254
 
256
- Manage preview/production environments. Production is the default scope
257
- when `--env` is omitted; `production`, `prod`, and `main` are aliases.
255
+ Manage preview/production environments. Production is the default scope when
256
+ `--env` is omitted (`production`, `prod`, and `main` are aliases).
258
257
 
259
258
  ```bash
260
259
  farthershore env list weather-api --format json
@@ -264,26 +263,40 @@ farthershore env delete weather-api preview --yes --format json
264
263
 
265
264
  ### `farthershore plan`
266
265
 
267
- Read code-managed plans and operate live subscriber migrations. The CLI does
268
- not create, update, or delete plan definitions; edit the Business SDK program in
269
- the repo for product behavior changes.
266
+ Read code-managed plans and operate live subscriber migrations. The CLI does not
267
+ create, update, or delete plan definitions — edit the Business SDK program for
268
+ that.
270
269
 
271
270
  ```bash
272
- # Human-readable table (default in TTY)
273
- farthershore plan list weather-api
274
- farthershore plan list weather-api --format table
275
-
276
- # JSON envelope (default outside TTY; suitable for jq pipelines)
271
+ farthershore plan list weather-api # table (default in TTY)
277
272
  farthershore plan list weather-api --format json
278
273
 
279
- # Operate live subscribers after a repo-authored plan version is released
274
+ # Migrate live subscribers after a repo-authored plan version is released
280
275
  farthershore plan migrate weather-api pro --from 1 --to head --policy next_renewal --format json
281
276
  ```
282
277
 
278
+ ### `farthershore frontend`
279
+
280
+ Managed Frontend Hosting operations plus a local preview. `deploy`, `status`,
281
+ `rollback`, and `env` operate the hosted build; `preview` runs the generated
282
+ `frontend/`'s `vite dev` with an injected `window.__FS_CONFIG__` shim so the
283
+ portal renders locally exactly as it serves in production.
284
+
285
+ ```bash
286
+ farthershore frontend status weather-api --format json
287
+ farthershore frontend deploy weather-api --format json
288
+ farthershore frontend rollback weather-api --release-id <hash> --format json
289
+ farthershore frontend env list weather-api --format json
290
+ farthershore frontend env set weather-api VITE_PUBLIC_FOO bar --target BUILD --format json
291
+
292
+ # Local preview (shells out to vite; needs a frontend/ project)
293
+ farthershore frontend preview --core-url http://localhost:8787
294
+ ```
295
+
283
296
  ### `farthershore persona`
284
297
 
285
- Test-environment personas — mint fresh `fsk_test_*` API keys so an agent
286
- can exercise the gateway end-to-end. Only works in test-strategy envs.
298
+ Mint fresh `fsk_test_*` API keys in a test-strategy environment so you can
299
+ exercise the gateway end-to-end.
287
300
 
288
301
  ```bash
289
302
  farthershore persona bootstrap weather-api --env preview --plan pro --format json
@@ -301,47 +314,42 @@ farthershore usage summary weather-api --format json
301
314
 
302
315
  ### `farthershore consumer`
303
316
 
304
- Manage live business users/consumers. These are API-controlled runtime actions,
305
- not repo-authored product behavior.
317
+ Manage live business users. These are operational actions, not repo-authored
318
+ behavior.
306
319
 
307
320
  ```bash
308
321
  farthershore consumer list weather-api --format json
309
- farthershore consumer list weather-api --env preview --format json
310
322
  farthershore consumer block weather-api <subscriberId> --yes --format json
311
323
  farthershore consumer remove weather-api <subscriberId> --yes --format json
312
324
  ```
313
325
 
314
- Use `consumer list` first to discover `subscriberId`. `block` suspends a user
315
- and revokes active API keys. `remove` is irreversible and tears down subscriber
316
- state across billing, edge credentials, and subscriptions.
326
+ Use `consumer list` first to find a `subscriberId`. `block` suspends a user and
327
+ revokes active API keys. `remove` is irreversible and tears down subscriber state
328
+ across billing, edge credentials, and subscriptions.
317
329
 
318
330
  ### `farthershore secret`
319
331
 
320
- Manage private business secrets. These are API-controlled operational values,
321
- not repo-authored product behavior. Values are encrypted at rest and list/read
332
+ Manage private business secrets. Values are encrypted at rest; list/read
322
333
  responses return metadata only.
323
334
 
324
335
  ```bash
325
336
  farthershore secret list weather-api --format json
326
337
  printf '%s' "$CLERK_SECRET_KEY" | farthershore secret set weather-api \
327
- CLERK_SECRET_KEY \
328
- --from-stdin \
329
- --target RUNTIME \
330
- --format json
338
+ CLERK_SECRET_KEY --from-stdin --target RUNTIME --format json
331
339
  farthershore secret delete weather-api CLERK_SECRET_KEY --yes --format json
332
340
  ```
333
341
 
334
- Use `frontend env` for public browser-visible variables such as
335
- `NEXT_PUBLIC_*`, `VITE_PUBLIC_*`, or analytics keys. Use `secret` for server
336
- runtime and private build values. `BUILD` secrets are injected only into managed
337
- frontend builds and require a redeploy after changes; `RUNTIME` secrets are for
338
- trusted server/backend runtime code and are never emitted into browser config.
342
+ Use `frontend env` for public, browser-visible variables (`VITE_PUBLIC_*`,
343
+ analytics keys). Use `secret` for server runtime and private build values.
344
+ `BUILD` secrets are injected into managed frontend builds and require a redeploy;
345
+ `RUNTIME` secrets are for trusted server/backend code and are never exposed to
346
+ the browser.
339
347
 
340
348
  ### `farthershore backend`
341
349
 
342
- Create BYO backends and provision runtime tokens for upstream services. Core
343
- stores only token hashes; the raw token is returned once and should be deployed
344
- as `FS_RUNTIME_TOKEN`.
350
+ Create bring-your-own backends and provision runtime tokens for your upstream
351
+ services. Only token hashes are stored; the raw token is returned once and should
352
+ be deployed as `FS_RUNTIME_TOKEN`.
345
353
 
346
354
  ```bash
347
355
  farthershore backend list weather-api --format json
@@ -349,14 +357,14 @@ farthershore backend create weather-api \
349
357
  --name "Production API" \
350
358
  --origin-url https://api.example.com \
351
359
  --format json
352
- farthershore backend tokens list weather-api --format json
353
360
  farthershore backend tokens create weather-api --backend <backendId> --format json
354
361
  farthershore backend tokens rotate weather-api <tokenId> --format json
355
362
  farthershore backend tokens revoke weather-api <tokenId> --yes --format json
356
- farthershore backend delete weather-api <backendId> --yes --format json
357
363
  ```
358
364
 
359
- Pair the token with `@farthershore/backend` in the upstream:
365
+ Pair the token with
366
+ [`@farthershore/backend`](https://www.npmjs.com/package/@farthershore/backend) in
367
+ your upstream:
360
368
 
361
369
  ```ts
362
370
  import { fartherShore, withUsage } from "@farthershore/backend";
@@ -384,10 +392,9 @@ export async function POST(request: Request) {
384
392
 
385
393
  ### `farthershore webhook`
386
394
 
387
- Provision outbound webhook endpoints and inspect delivery health. The dashboard
388
- exposes the same API-managed surface. If the business declares webhooks in
389
- `business/business.config.ts`, Core returns `409 MANAGED_BY_CODE` for writes so
390
- the repo remains canonical.
395
+ Provision outbound webhook endpoints and inspect delivery health. If the business
396
+ declares webhooks in `business/business.config.ts`, writes return
397
+ `409 MANAGED_BY_CODE` so the repo stays canonical.
391
398
 
392
399
  ```bash
393
400
  farthershore webhook list weather-api --format json
@@ -401,50 +408,32 @@ farthershore webhook deliveries weather-api <webhookId> --limit 20 --format json
401
408
  farthershore webhook delete weather-api <webhookId> --yes --format json
402
409
  ```
403
410
 
404
- `webhook create` returns the signing secret once. Store it in the receiving app;
405
- subsequent list/delivery commands never return the secret.
411
+ `webhook create` returns the signing secret once; store it in the receiving app.
406
412
 
407
413
  ### `farthershore promo-code`
408
414
 
409
- Manage checkout promo codes. Promo codes are API-controlled operational state,
410
- not part of `business/business.config.ts`, so agents can manage them through the
411
- CLI just like the dashboard.
415
+ Manage checkout promo codes (operational state, not part of the manifest).
412
416
 
413
417
  ```bash
414
418
  farthershore promo-code list weather-api --format json
415
419
  farthershore promo-code create weather-api \
416
- --code LAUNCH25 \
417
- --kind percent_off \
418
- --percent 25 \
419
- --duration-months 3 \
420
- --plan <planId> \
421
- --format json
420
+ --code LAUNCH25 --kind percent_off --percent 25 --duration-months 3 \
421
+ --plan <planId> --format json
422
422
  farthershore promo-code create weather-api \
423
- --code SAVE500 \
424
- --kind amount_off \
425
- --amount-cents 500 \
426
- --duration-months 1 \
427
- --format json
428
- farthershore promo-code update weather-api <promoCodeId> \
429
- --code LAUNCH30 \
430
- --kind percent_off \
431
- --percent 30 \
432
- --duration-months 3 \
433
- --all-plans \
434
- --format json
423
+ --code SAVE500 --kind amount_off --amount-cents 500 --duration-months 1 --format json
435
424
  farthershore promo-code archive weather-api <promoCodeId> --format json
436
425
  farthershore promo-code reactivate weather-api <promoCodeId> --format json
437
426
  ```
438
427
 
439
- Stripe coupon changes require a complete discount spec, so `promo-code update`
440
- requires `--kind`, `--duration-months`, and the required amount flag for that
441
- kind whenever you change code, amount, dates, plan scope, or redemption limits.
428
+ Because a Stripe coupon change requires a complete discount spec, `promo-code
429
+ update` requires `--kind`, `--duration-months`, and the amount flag for that kind
430
+ whenever you change the code, amount, dates, plan scope, or redemption limits.
442
431
  Use `--all-plans` to clear plan scoping.
443
432
 
444
433
  ### `farthershore connect`
445
434
 
446
- GitHub OAuth and Stripe Connect flows are browser-only. These commands
447
- report status so an agent can poll until the user finishes the flow.
435
+ GitHub OAuth and Stripe Connect are browser-only. These commands report status so
436
+ you can poll until the flow is finished in the dashboard.
448
437
 
449
438
  ```bash
450
439
  farthershore connect github --format json
@@ -460,239 +449,87 @@ farthershore token list --format json
460
449
  farthershore token create --name "ci-bot" --scope products:update products:publish --format json
461
450
  farthershore token rotate <tokenId> --sync-to-github --format json
462
451
  farthershore token revoke <tokenId> --yes --format json
463
- farthershore token delete <tokenId> --yes --format json
464
- ```
465
-
466
- #### Plan knobs
467
-
468
- Every repo-authored plan is a configuration of orthogonal billing knobs. Older
469
- shapes with `pricing.{model, monthlyPriceCents}`, top-level `billing.strategy`,
470
- or scalar credit grant fields are no longer accepted by the validator.
471
-
472
- | Knob | Cents/unit | Meaning |
473
- | ------------------------- | ---------------- | ------------------------------------------------------- |
474
- | `meters[]` | micros/unit | Per-dimension usage price (zero or more dimensions) |
475
- | `recurring_fee_cents` | cents | Charged each billing period (recurring subscription) |
476
- | `grants[]` | varies by kind | Credit grants, top-ups, rollover, and recharge policy |
477
- | `trial_days` | days | Waive everything for N days at the start |
478
- | `max_monthly_spend_cents` | cents (optional) | Hard cap; the gateway blocks once exceeded (orthogonal) |
479
-
480
- Billing math (handled by Stripe Billing v2 at invoice finalization):
481
- `bill = recurring_fee + max(0, total_meter_cost − applied_credit_balance)`.
482
-
483
- Every plan flavor — free, flat, included, overage, prepaid, trial,
484
- pay-as-you-go — is a knob combination. Examples:
485
-
486
- ```yaml
487
- # Free plan: explicit `free: true` flag + hard-enforced limit
488
- plans:
489
- - key: free
490
- name: Free
491
- free: true
492
- recurring_fee_cents: 0
493
- limits:
494
- - dimension: requests
495
- window: { type: named, name: month }
496
- capacity: 1000
497
- enforcement: enforce
498
-
499
- # Flat subscription: recurring fee only
500
- - key: starter
501
- name: Starter
502
- recurring_fee_cents: 2900
503
-
504
- # Included usage: fee + monthly credit grant + metered
505
- - key: pro
506
- name: Pro
507
- recurring_fee_cents: 2000
508
- grants:
509
- - kind: recurring
510
- amount_cents: 2000
511
- meters:
512
- - dimension: requests
513
- price_per_unit_micros: 1000 # $0.001/request
514
-
515
- # Overage: fee + metered, no credit
516
- - key: growth
517
- name: Growth
518
- recurring_fee_cents: 4900
519
- meters:
520
- - dimension: requests
521
- price_per_unit_micros: 500
522
-
523
- # Prepaid: one-time grant + metered
524
- - key: prepaid
525
- name: Prepaid
526
- grants:
527
- - kind: one_time
528
- amount_cents: 10000
529
- meters:
530
- - dimension: requests
531
- price_per_unit_micros: 1000
532
-
533
- # Trial: trial_days + recurring fee
534
- - key: trial
535
- name: Trial
536
- recurring_fee_cents: 2900
537
- trial_days: 14
538
-
539
- # Pay-as-you-go: metered only (no recurring fee)
540
- - key: metered
541
- name: Metered
542
- meters:
543
- - dimension: tokens
544
- price_per_unit_micros: 100
545
452
  ```
546
453
 
547
- #### `grants[]` array
548
-
549
- Plans accept a typed `grants[]` array. It is the only public credit surface.
550
- Declare grants in the Business SDK program and push the repo change through the
551
- normal change-set flow.
552
-
553
- Valid `kind` values:
554
-
555
- | Kind | Required fields | Use case |
556
- | --------------- | ------------------------------------------------------ | --------------------------------------------------- |
557
- | `recurring` | `amount_cents` | Monthly credit (e.g. $20 included usage) |
558
- | `one_time` | `amount_cents` | Signup bonus / prepaid balance |
559
- | `promotional` | `amount_cents`, `label`, optional `expires_after_days` | Launch bonus, win-back, holiday promo |
560
- | `trial` | (none) | Trial entry — requires `trial_days > 0` on the plan |
561
- | `rollover` | `percent` (0–100) | "Unused balance rolls over X% to the next period" |
562
- | `top_up` | `sku`, `label`, `price_cents`, `credit_cents` | Buy-extra-credit SKU exposed in checkout |
563
- | `auto_recharge` | `threshold_cents`, `refill_cents` | "When balance < $X auto-purchase $Y" |
564
-
565
- `recurring`, `one_time`, `rollover`, and `trial` are single-shot per plan;
566
- declaring more than one entry of the same kind triggers a warning
567
- (only the first is honored).
568
-
569
- Example:
570
-
571
- ```yaml
572
- plans:
573
- - key: pro
574
- name: Pro
575
- recurring_fee_cents: 10000
576
- trial_days: 14
577
- meters:
578
- - dimension: requests
579
- price_per_unit_micros: 500
580
- grants:
581
- - kind: recurring
582
- amount_cents: 20000
583
- - kind: trial
584
- - kind: promotional
585
- amount_cents: 1000
586
- label: launch-bonus
587
- expires_after_days: 30
588
- - kind: rollover
589
- percent: 25
590
- - kind: auto_recharge
591
- threshold_cents: 500
592
- refill_cents: 5000
593
- ```
454
+ ### `farthershore skills`
594
455
 
595
- Validation surfaces:
456
+ Inside a business repo, recommend agent skills matching the FartherShore SDK
457
+ versions the repo actually uses. The Business SDK and Frontend SDK tracks are
458
+ recommended independently, so updating one does not force a skill update for the
459
+ other.
596
460
 
597
- - **error** — invalid `kind` is rewritten to `Unknown grant kind. Valid kinds: …`
598
- - **warning** — `{ kind: trial }` declared but `trial_days` is 0
599
- - **warning** — singleton kinds (`recurring`, `one_time`, `rollover`, `trial`) declared more than once
461
+ ```bash
462
+ farthershore skills recommend --format json
463
+ SKILLS_CMD=$(farthershore skills recommend --format json | jq -r '.data.recommendation.command')
464
+ eval "$SKILLS_CMD"
465
+ ```
600
466
 
601
- #### Deprecation window (Phase 3b)
467
+ ### `farthershore operations`
602
468
 
603
- The product top-level `lifecycle.breaking_changes` block declares the
604
- breaking-change governance policy validated by the GitHub bot/Core release
605
- path:
469
+ Print the machine-readable action boundary: which operations are repo-authored
470
+ (`contract`), which are CLI/API operations (`operate`), which reconcile through
471
+ either path (`dual`), and which are browser-only prerequisites (GitHub linking,
472
+ Stripe Connect).
606
473
 
607
- ```yaml
608
- lifecycle:
609
- breaking_changes:
610
- require_deprecation_window_days: 90
611
- require_successor_route: true
474
+ ```bash
475
+ farthershore operations list --format json
612
476
  ```
613
477
 
614
- When the policy is set, Core emits a `route_removed` change for every route
615
- dropped from `features.<x>.routes[]` and warns when the server-side
616
- `breaking-change-safety-check` cron will gate publish via `ConsumerActivity`
617
- lookup. When `require_successor_route` is true, it also adds a
618
- successor-required warning.
478
+ ## Errors and exit codes
619
479
 
620
- The CLI never blocks on the window itself — the per-consumer lookup
621
- lives server-side (Phase 1c `ConsumerActivity` table + Phase 3b cron).
480
+ In `--format json` mode, every command prints a single canonical envelope to
481
+ stdout — `{ ok, op, data }` on success, or `{ ok: false, op, error }` on failure,
482
+ where `error` carries a stable `code`, `message`, HTTP `status`, a `retryable`
483
+ flag, and a remediation `hint` when one is registered. Diagnostics go to stderr.
622
484
 
623
- ## Agent workflow
485
+ In table mode, failures print `Error [CODE]: message` plus a `Hint:` line:
624
486
 
625
- A typical agent flow:
487
+ ```text
488
+ Error [STRIPE_NOT_CONFIGURED]: connect Stripe before running billing operations
489
+ Hint: Stripe isn't connected on this product. Connect it in the dashboard before running billing operations.
490
+ ```
626
491
 
627
- ```bash
628
- export FARTHERSHORE_TOKEN=mk_xxx
492
+ The bracketed code is stable across releases — quote it in support threads.
629
493
 
630
- farthershore business create \
631
- --name weather-api \
632
- --format json
494
+ Exit codes are a branchable taxonomy so a script can tell failure classes apart
495
+ without parsing text:
633
496
 
634
- gh repo clone acme/weather-api
635
- cd weather-api
636
- # Edit business/business.config.ts with the Business SDK.
637
- farthershore build --format json
638
- git push --set-upstream origin feature/pricing
639
- farthershore change-set list weather-api --format json
640
- farthershore business show weather-api --format json
641
- ```
497
+ | Exit | Meaning |
498
+ | ---- | ------------------------------------------------------------ |
499
+ | `0` | Success |
500
+ | `2` | Validation error (HTTP 400/422) — fix your input |
501
+ | `3` | Auth / permission error (401/403) — re-authenticate |
502
+ | `4` | Conflict / managed-by-code (409) — change it in the repo |
503
+ | `5` | Server error (5xx) — retry |
504
+ | `1` | Any other failure (local error, 402/404, argument errors, …) |
642
505
 
643
- For business updates, edit `business/business.config.ts` or any modules it imports
644
- and build locally with:
506
+ ## CI and agent usage
645
507
 
646
- ```bash
647
- farthershore build --format json
648
- ```
508
+ The CLI is non-interactive whenever a token is available via `--token` or
509
+ `FARTHERSHORE_TOKEN` — `auth login` only prompts when stdin is a TTY and no token
510
+ was passed, so it is safe to script. `farthershore build` and `farthershore
511
+ preflight --local-only` need no network or auth and are safe to run in CI.
649
512
 
650
513
  ## MCP server
651
514
 
652
- The MCP server (`farthershore-mcp`) projects tool definitions from the same
653
- operation registry that generates the CLI command groups. Tool names use the
654
- `fs_*` prefix and cover the agent-operable platform surface:
655
-
656
- - Products: `fs_business_list`, `fs_brand_update`, `fs_business_publish`
657
- - Environments: `fs_env_list`, `fs_env_create`
658
- - Plans: `fs_plan_list`
659
- - Backends: `fs_backend_list`, `fs_backend_create`, `fs_backend_delete`
660
- - Runtime tokens: `fs_runtime_token_list`, `fs_runtime_token_mint`,
661
- `fs_runtime_token_rotate`, `fs_runtime_token_revoke`
662
- - Webhooks: `fs_webhook_list`, `fs_webhook_create`, `fs_webhook_update`,
663
- `fs_webhook_delete`, `fs_webhook_test`, `fs_webhook_deliveries`
664
- - Promo codes: `fs_promo_code_list`, `fs_promo_code_create`,
665
- `fs_promo_code_update`, `fs_promo_code_archive`,
666
- `fs_promo_code_reactivate`
667
- - Consumers: `fs_consumer_list`, `fs_consumer_block`, `fs_consumer_remove`
668
- - Secrets: `fs_secret_list`, `fs_secret_set`, `fs_secret_delete`
669
- - Personas: `fs_persona_bootstrap`, `fs_persona_list`, `fs_persona_revoke`
670
- - Usage and maker tokens: `fs_usage_read`, `fs_maker_token_list`
671
-
672
- Every MCP tool has a sibling CLI operation by construction; the parity test in
673
- `apps/cli/src/operations/mcp-cli-parity.test.ts` enforces that invariant.
674
-
675
- ## Errors and exit codes
676
-
677
- The CLI exits `0` on success and `1` on any failure (including
678
- commander-level argument errors). When the API returns a 4XX/5XX, the
679
- CLI prints the canonical error code in brackets and a one-line
680
- remediation hint when one is registered:
515
+ The MCP server (`farthershore-mcp`) projects its tools from the same operation
516
+ registry that defines the CLI commands, so every MCP tool has a CLI sibling. Tool
517
+ names use the `fs_*` prefix and cover the agent-operable surface: businesses,
518
+ environments, plans, frontends, backends, runtime tokens, webhooks, promo codes,
519
+ consumers, secrets, personas, usage, and maker tokens.
681
520
 
682
- ```text
683
- Error [STRIPE_NOT_CONFIGURED]: connect Stripe before running billing operations
684
- Hint: Stripe isn't connected on this product. Connect it in the dashboard before running billing operations.
521
+ ```bash
522
+ FARTHERSHORE_TOKEN=mk_xxx farthershore-mcp
685
523
  ```
686
524
 
687
- The bracketed code is stable across releases — quote it in support threads.
525
+ ## Learn more
688
526
 
689
- `farthershore auth whoami --format json` emits a stable JSON shape suitable
690
- for CI scripts.
527
+ - Platform documentation: [farthershore.com](https://farthershore.com)
528
+ - Author product behavior:
529
+ [`@farthershore/business`](https://www.npmjs.com/package/@farthershore/business)
530
+ - Report usage from your backend:
531
+ [`@farthershore/backend`](https://www.npmjs.com/package/@farthershore/backend)
691
532
 
692
- ## CI / agent usage
533
+ ## License
693
534
 
694
- The CLI is non-interactive whenever a token is available via the
695
- `--token` flag or `FARTHERSHORE_TOKEN` env var — `auth login` only
696
- prompts when stdin is a TTY and no token argument was passed, so it's
697
- safe to script. `farthershore build` is CI-safe and can be run under `CI` /
698
- `GITHUB_ACTIONS` for local Business SDK compilation.
535
+ MIT