@farthershore/cli 0.33.1 → 0.33.3
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 +83 -47
- package/dist/index.js +100 -100
- package/dist/mcp.js +84 -57
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Create and operate [FartherShore](https://farthershore.com) software businesses
|
|
4
4
|
from the terminal.
|
|
5
5
|
|
|
6
|
-
**Status: `0.33.
|
|
6
|
+
**Status: `0.33.3`.** Pre-1.0 — the command surface is stable but may still
|
|
7
7
|
change between minor versions. Pin an exact version in CI.
|
|
8
8
|
|
|
9
9
|
FartherShore lets you define a software business as code, then sells, meters,
|
|
@@ -21,19 +21,19 @@ the explicitly agent-operable subset of the CLI surface.
|
|
|
21
21
|
## Install
|
|
22
22
|
|
|
23
23
|
```bash
|
|
24
|
-
npm install -g @farthershore/cli@0.33.
|
|
24
|
+
npm install -g @farthershore/cli@0.33.3
|
|
25
25
|
```
|
|
26
26
|
|
|
27
27
|
Or run it directly with npx:
|
|
28
28
|
|
|
29
29
|
```bash
|
|
30
|
-
npx -p @farthershore/cli@0.33.
|
|
30
|
+
npx -p @farthershore/cli@0.33.3 farthershore --help
|
|
31
31
|
```
|
|
32
32
|
|
|
33
33
|
The package also ships an MCP stdio server for agents:
|
|
34
34
|
|
|
35
35
|
```bash
|
|
36
|
-
npx -p @farthershore/cli@0.33.
|
|
36
|
+
npx -p @farthershore/cli@0.33.3 farthershore-mcp
|
|
37
37
|
```
|
|
38
38
|
|
|
39
39
|
## Authentication
|
|
@@ -88,7 +88,8 @@ Create a managed business repo, author the business, validate it, and push:
|
|
|
88
88
|
|
|
89
89
|
```bash
|
|
90
90
|
# 1. Create the managed repo. Human output is exactly its URL.
|
|
91
|
-
REPO_URL=$(farthershore business create weather-api
|
|
91
|
+
REPO_URL=$(farthershore business create weather-api \
|
|
92
|
+
--idempotency-key <persisted-business-create-attempt-key>)
|
|
92
93
|
|
|
93
94
|
# 2. Clone it and author business/ from scratch.
|
|
94
95
|
git clone "$REPO_URL"
|
|
@@ -219,12 +220,14 @@ farthershore build --format json
|
|
|
219
220
|
Run the same verdict the GitHub `farthershore/validate` PR check produces, before
|
|
220
221
|
you push. It builds the manifest twice and compares the IR hash (the determinism
|
|
221
222
|
check the build runner enforces), then — when you pass `--business` — submits the
|
|
222
|
-
IR for a server
|
|
223
|
-
an economic-change verdict.
|
|
223
|
+
IR for a server verdict that returns compile diagnostics, the semantic diff, and
|
|
224
|
+
an economic-change verdict. The server may retain a diagnostic compilation
|
|
225
|
+
record, but validation never accepts or publishes business state, so it is safe
|
|
226
|
+
to repeat and does not take an idempotency key.
|
|
224
227
|
|
|
225
228
|
```bash
|
|
226
229
|
farthershore validate # local build + determinism only
|
|
227
|
-
farthershore validate --business weather-api
|
|
230
|
+
farthershore validate --business weather-api
|
|
228
231
|
farthershore validate --local-only --format json
|
|
229
232
|
```
|
|
230
233
|
|
|
@@ -245,10 +248,11 @@ farthershore business subdomain-check weather-api --format json
|
|
|
245
248
|
|
|
246
249
|
farthershore business create weather-api \
|
|
247
250
|
--display-name "Weather API" \
|
|
251
|
+
--idempotency-key <persisted-business-create-attempt-key> \
|
|
248
252
|
--format json
|
|
249
253
|
|
|
250
|
-
farthershore business publish weather-api --format json
|
|
251
|
-
farthershore business rollback weather-api wfe_previous --reason "bad release" --format json
|
|
254
|
+
farthershore business publish weather-api --format json --idempotency-key <persisted-business-publish-attempt-key>
|
|
255
|
+
farthershore business rollback weather-api wfe_previous --reason "bad release" --format json --idempotency-key <persisted-business-rollback-attempt-key>
|
|
252
256
|
farthershore business delete weather-api --yes --format json
|
|
253
257
|
```
|
|
254
258
|
|
|
@@ -338,7 +342,7 @@ farthershore organization role list <organizationId> --filter builtIn=true --sor
|
|
|
338
342
|
farthershore organization members <organizationId> --filter roleKey=auditor --sort email:asc --search person --format json
|
|
339
343
|
|
|
340
344
|
# Primary owner only; hands ultimate authority to another existing member.
|
|
341
|
-
farthershore organization ownership-transfer <organizationId> <newOwnerUserId> --yes --format json
|
|
345
|
+
farthershore organization ownership-transfer <organizationId> <newOwnerUserId> --yes --format json --idempotency-key <persisted-organization-ownership-transfer-attempt-key>
|
|
342
346
|
```
|
|
343
347
|
|
|
344
348
|
Selecting the default organization is a local credential concern, not an API
|
|
@@ -365,14 +369,15 @@ farthershore token create deploy-bot --org \
|
|
|
365
369
|
|
|
366
370
|
farthershore token list --org --format json
|
|
367
371
|
farthershore token approvals --org --format json
|
|
368
|
-
farthershore token approve <approvalId> --org --format json
|
|
372
|
+
farthershore token approve <approvalId> --org --format json --idempotency-key <persisted-token-approve-attempt-key>
|
|
369
373
|
farthershore token approve <approvalId> --org \
|
|
374
|
+
--idempotency-key <persisted-token-approve-attempt-key> \
|
|
370
375
|
--permissions '["business:read"]' --format json # trim on approval
|
|
371
376
|
farthershore token deny <approvalId> --org --format json
|
|
372
377
|
farthershore token update <tokenId> --org \
|
|
373
378
|
--permissions '["business:read"]' \
|
|
374
379
|
--idempotency-key org-token-update-2026-08-11 --format json
|
|
375
|
-
farthershore token rotate <tokenId> --org --format json
|
|
380
|
+
farthershore token rotate <tokenId> --org --format json --idempotency-key <persisted-token-rotate-attempt-key>
|
|
376
381
|
farthershore token revoke <tokenId> --org --yes --format json
|
|
377
382
|
```
|
|
378
383
|
|
|
@@ -383,9 +388,10 @@ exactly once; store it immediately. Human output follows the same rule: it
|
|
|
383
388
|
prints plaintext only for an ACTIVE one-time-secret response and says explicitly
|
|
384
389
|
when a PENDING request minted nothing.
|
|
385
390
|
|
|
386
|
-
Create and update
|
|
387
|
-
|
|
388
|
-
|
|
391
|
+
Create and update require `--idempotency-key`. Persist the key before the first
|
|
392
|
+
dispatch and reuse it only when repeating that exact logical request after an
|
|
393
|
+
interrupted invocation. The CLI never generates a key: a process-local key
|
|
394
|
+
would be lost across the restart where retry safety matters most.
|
|
389
395
|
|
|
390
396
|
### `farthershore stripe`
|
|
391
397
|
|
|
@@ -430,15 +436,17 @@ farthershore service-account approvals <businessId> --format json
|
|
|
430
436
|
farthershore service-account approve <businessId> <approvalId> \
|
|
431
437
|
--permissions '["route:read"]' --format json # optional trim
|
|
432
438
|
farthershore service-account deny <businessId> <approvalId> --format json
|
|
433
|
-
farthershore service-account rotate <businessId> <serviceAccountId> --format json
|
|
439
|
+
farthershore service-account rotate <businessId> <serviceAccountId> --format json --idempotency-key <persisted-service-account-rotate-attempt-key>
|
|
434
440
|
farthershore service-account revoke <businessId> <serviceAccountId> --yes --format json
|
|
435
441
|
```
|
|
436
442
|
|
|
437
443
|
Pass `--environment-id` and `--subscriber-organization` to override the two
|
|
438
444
|
context environment variables for one command. PENDING create/update responses
|
|
439
445
|
never print `plaintext`. ACTIVE creates
|
|
440
|
-
and rotations print the one-time key once. Create
|
|
441
|
-
|
|
446
|
+
and rotations print the one-time key once. Create, update, and rotate require a
|
|
447
|
+
caller-persisted key, just like one-time-secret org-token operations. A replayed
|
|
448
|
+
success includes `meta.idempotency.replayed: true`; follow it with a list read
|
|
449
|
+
before reporting current state.
|
|
442
450
|
|
|
443
451
|
This group is direct CLI-only and deliberately has no MCP projection: the MCP
|
|
444
452
|
operation registry carries builder principals, not portal consumer sessions.
|
|
@@ -484,8 +492,9 @@ farthershore plan list weather-api --format json
|
|
|
484
492
|
|
|
485
493
|
### `farthershore frontend`
|
|
486
494
|
|
|
487
|
-
Managed Frontend Hosting
|
|
488
|
-
|
|
495
|
+
Managed Frontend Hosting status, rollback, and a local preview. Builds are
|
|
496
|
+
Git-triggered: production builds on a GitHub Release and preview environments
|
|
497
|
+
build on pushes to their environment branch. `preview` runs the generated
|
|
489
498
|
`frontend/`'s `vite dev` with an injected `window.__FS_CONFIG__` shim so the
|
|
490
499
|
portal renders locally exactly as it serves in production. Pass `--mock` to
|
|
491
500
|
inject `{ mock: true }` instead of Core/Clerk config for local page inspection
|
|
@@ -493,7 +502,6 @@ with placeholder data and auth bypassed.
|
|
|
493
502
|
|
|
494
503
|
```bash
|
|
495
504
|
farthershore frontend status weather-api --format json
|
|
496
|
-
farthershore frontend deploy weather-api --format json
|
|
497
505
|
farthershore frontend rollback weather-api --release-id <hash> --format json
|
|
498
506
|
|
|
499
507
|
# Local preview (shells out to vite; needs a frontend/ project)
|
|
@@ -505,14 +513,38 @@ farthershore frontend preview --core-url http://localhost:8787
|
|
|
505
513
|
|
|
506
514
|
### `farthershore persona`
|
|
507
515
|
|
|
508
|
-
|
|
509
|
-
exercise the gateway
|
|
516
|
+
Create temporary subscriber users in a test-strategy environment so an agent
|
|
517
|
+
can exercise the same customer RBAC, browser session, and gateway paths as a
|
|
518
|
+
human. The Business SDK contributes raw permissions; the subscribing
|
|
519
|
+
organization composes those permissions into its own product roles.
|
|
510
520
|
|
|
511
521
|
```bash
|
|
512
|
-
|
|
522
|
+
# First persona creates and owns a temporary subscriber workspace.
|
|
523
|
+
farthershore persona bootstrap weather-api --env preview --plan pro --format json --idempotency-key <persisted-persona-bootstrap-attempt-key>
|
|
513
524
|
farthershore persona list weather-api --env preview --format json
|
|
514
|
-
farthershore persona
|
|
515
|
-
|
|
525
|
+
farthershore persona login weather-api <ownerPersonaId> --env preview --format json
|
|
526
|
+
|
|
527
|
+
# Join the same subscriber after its owner has enabled subscriber RBAC and
|
|
528
|
+
# created roles/defaults through the normal customer RBAC surface.
|
|
529
|
+
farthershore persona bootstrap weather-api --env preview --plan pro \
|
|
530
|
+
--subscriber-id <subscriberId> --account-role member --role viewer \
|
|
531
|
+
--format json --idempotency-key <persisted-member-bootstrap-attempt-key>
|
|
532
|
+
|
|
533
|
+
farthershore persona rotate weather-api <personaId> --env preview --format json --idempotency-key <persisted-persona-rotate-attempt-key>
|
|
534
|
+
farthershore persona delete weather-api <personaId> --env preview --format json
|
|
535
|
+
```
|
|
536
|
+
|
|
537
|
+
Bootstrap and rotation return a key once. `login` opens the hosted portal with
|
|
538
|
+
a 60-second single-use handoff and never prints its bearer. Product role keys
|
|
539
|
+
must already exist in that subscriber's role catalog; omit `--role` to use its
|
|
540
|
+
configured default. Deletion tears down the temporary user and credential, and
|
|
541
|
+
deleting the environment also removes the remaining persona-owned workspace.
|
|
542
|
+
After an environment-branch apply, existing personas remain available but are
|
|
543
|
+
detached from the superseded subscription. Use `persona login` with the same
|
|
544
|
+
persona id and select a plan from the new branch contract; the CLI does not
|
|
545
|
+
fall back to a production plan. The old raw test key stays invalid. After the
|
|
546
|
+
persona is reattached, run `persona rotate` to mint a replacement key for
|
|
547
|
+
gateway testing; its product roles and explicit scope ceiling are preserved.
|
|
516
548
|
|
|
517
549
|
### `farthershore usage`
|
|
518
550
|
|
|
@@ -548,11 +580,11 @@ compiled integration that references it.
|
|
|
548
580
|
```bash
|
|
549
581
|
farthershore variables list weather-api --format json
|
|
550
582
|
printf '%s' "$SENTRY_AUTH_TOKEN" | farthershore variables set weather-api \
|
|
551
|
-
SENTRY_AUTH_TOKEN --format json
|
|
583
|
+
SENTRY_AUTH_TOKEN --format json --idempotency-key <persisted-sentry-variable-attempt-key>
|
|
552
584
|
printf '%s' "$POSTHOG_PROJECT_KEY" | farthershore variables set weather-api \
|
|
553
|
-
FS_PUBLIC_POSTHOG_KEY --format json
|
|
554
|
-
farthershore variables revoke weather-api POSTHOG_SECRET --yes --format json
|
|
555
|
-
farthershore variables rm weather-api POSTHOG_SECRET --yes --format json
|
|
585
|
+
FS_PUBLIC_POSTHOG_KEY --format json --idempotency-key <persisted-posthog-variable-attempt-key>
|
|
586
|
+
farthershore variables revoke weather-api POSTHOG_SECRET --yes --format json --idempotency-key <persisted-variables-revoke-attempt-key>
|
|
587
|
+
farthershore variables rm weather-api POSTHOG_SECRET --yes --format json --idempotency-key <persisted-variables-rm-attempt-key>
|
|
556
588
|
```
|
|
557
589
|
|
|
558
590
|
There is no builder-managed public-variable surface and values are never
|
|
@@ -570,13 +602,14 @@ farthershore backend list weather-api --format json
|
|
|
570
602
|
farthershore backend create weather-api \
|
|
571
603
|
--name "Production API" \
|
|
572
604
|
--origin-url https://api.example.com \
|
|
605
|
+
--idempotency-key <persisted-backend-create-attempt-key> \
|
|
573
606
|
--format json
|
|
574
607
|
farthershore backend bind weather-api api \
|
|
575
608
|
--env preview-42 \
|
|
576
609
|
--origin-url https://api-pr-42.example.com \
|
|
577
610
|
--format json
|
|
578
|
-
farthershore backend tokens create weather-api --backend <backendId> --format json
|
|
579
|
-
farthershore backend tokens rotate weather-api <tokenId> --format json
|
|
611
|
+
farthershore backend tokens create weather-api --backend <backendId> --format json --idempotency-key <persisted-backend-tokens-create-attempt-key>
|
|
612
|
+
farthershore backend tokens rotate weather-api <tokenId> --format json --idempotency-key <persisted-backend-tokens-rotate-attempt-key>
|
|
580
613
|
farthershore backend tokens revoke weather-api <tokenId> --yes --format json
|
|
581
614
|
```
|
|
582
615
|
|
|
@@ -621,12 +654,13 @@ farthershore webhook list weather-api --format json
|
|
|
621
654
|
farthershore webhook create weather-api \
|
|
622
655
|
--url https://hooks.example.com/farthershore \
|
|
623
656
|
--events subscription.created,payment.failed \
|
|
657
|
+
--idempotency-key <persisted-webhook-create-attempt-key> \
|
|
624
658
|
--format json
|
|
625
659
|
farthershore webhook update weather-api <webhookId> --disable --format json
|
|
626
|
-
farthershore webhook test weather-api <webhookId> --format json
|
|
627
|
-
farthershore webhook trigger weather-api <webhookId> --type payment.failed --format json
|
|
660
|
+
farthershore webhook test weather-api <webhookId> --idempotency-key <persisted-test-attempt-key> --format json
|
|
661
|
+
farthershore webhook trigger weather-api <webhookId> --type payment.failed --idempotency-key <persisted-trigger-attempt-key> --format json
|
|
628
662
|
farthershore webhook deliveries weather-api <webhookId> --limit 20 --format json
|
|
629
|
-
farthershore webhook rotate weather-api <webhookId> --format json
|
|
663
|
+
farthershore webhook rotate weather-api <webhookId> --format json --idempotency-key <persisted-webhook-rotate-attempt-key>
|
|
630
664
|
farthershore webhook delete weather-api <webhookId> --yes --format json
|
|
631
665
|
```
|
|
632
666
|
|
|
@@ -665,8 +699,10 @@ Manage checkout promo codes (operational state, not part of the manifest).
|
|
|
665
699
|
farthershore promo-code list weather-api --format json
|
|
666
700
|
farthershore promo-code create weather-api \
|
|
667
701
|
--code LAUNCH25 --kind percent_off --percent 25 --duration-months 3 \
|
|
702
|
+
--idempotency-key <persisted-promo-code-create-attempt-key> \
|
|
668
703
|
--plan <planId> --format json
|
|
669
704
|
farthershore promo-code create weather-api \
|
|
705
|
+
--idempotency-key <persisted-promo-code-create-attempt-key> \
|
|
670
706
|
--code SAVE500 --kind amount_off --amount-cents 500 --duration-months 1 --format json
|
|
671
707
|
farthershore promo-code archive weather-api <promoCodeId> --format json
|
|
672
708
|
farthershore promo-code reactivate weather-api <promoCodeId> --format json
|
|
@@ -682,18 +718,18 @@ Use `--all-plans` to clear plan scoping.
|
|
|
682
718
|
Install or refresh the platform-verified skills bundle together. The platform
|
|
683
719
|
pins this immutable release, and CI plus a daily repository check compare it to
|
|
684
720
|
GitHub's latest stable release so the guidance cannot silently drift.
|
|
685
|
-
This command requires `@farthershore/cli` 0.33.
|
|
721
|
+
This command requires `@farthershore/cli` 0.33.3 or newer.
|
|
686
722
|
|
|
687
723
|
```bash
|
|
688
724
|
set -euo pipefail
|
|
689
725
|
CLI_VERSION=$(farthershore --version)
|
|
690
|
-
printf '%s' "$CLI_VERSION" | node -e 'let v=""; process.stdin.on("data", c => v += c).on("end", () => { const m = /^(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)(?:\+[0-9A-Za-z.-]+)?$/.exec(v.trim()); if (!m || !(+m[1] > 0 || +m[2] > 33 || (+m[2] === 33 && +m[3] >=
|
|
726
|
+
printf '%s' "$CLI_VERSION" | node -e 'let v=""; process.stdin.on("data", c => v += c).on("end", () => { const m = /^(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)(?:\+[0-9A-Za-z.-]+)?$/.exec(v.trim()); if (!m || !(+m[1] > 0 || +m[2] > 33 || (+m[2] === 33 && +m[3] >= 3))) { console.error("Stop: CLI 0.33.3 or newer is required; ask the human to upgrade."); process.exitCode = 1; } })'
|
|
691
727
|
farthershore skills install --help
|
|
692
728
|
farthershore skills install
|
|
693
729
|
```
|
|
694
730
|
|
|
695
731
|
If either prerequisite fails, stop and ask the human to run
|
|
696
|
-
`npm install -g @farthershore/cli@0.33.
|
|
732
|
+
`npm install -g @farthershore/cli@0.33.3`, then repeat the checks.
|
|
697
733
|
Do not install or upgrade global tooling autonomously.
|
|
698
734
|
|
|
699
735
|
The Farther Shore CLI downloads the exact installer archive and verifies this
|
|
@@ -721,14 +757,14 @@ bracketed code is stable across releases — quote it in support threads.
|
|
|
721
757
|
Exit codes are a branchable taxonomy so a script can tell failure classes apart
|
|
722
758
|
without parsing text:
|
|
723
759
|
|
|
724
|
-
| Exit | Meaning
|
|
725
|
-
| ---- |
|
|
726
|
-
| `0` | Success
|
|
727
|
-
| `2` | Validation error (HTTP 400/422) — fix your input
|
|
728
|
-
| `3` | Auth / permission error (401/403) — re-authenticate
|
|
729
|
-
| `4` | Conflict / managed-by-code (409) — change it in the repo
|
|
730
|
-
| `5` | Server error (5xx) — retry
|
|
731
|
-
| `1` | Any other failure (local error, 402/404, argument errors, …)
|
|
760
|
+
| Exit | Meaning |
|
|
761
|
+
| ---- | -------------------------------------------------------------- |
|
|
762
|
+
| `0` | Success |
|
|
763
|
+
| `2` | Validation error (HTTP 400/422) — fix your input |
|
|
764
|
+
| `3` | Auth / permission error (401/403) — re-authenticate |
|
|
765
|
+
| `4` | Conflict / managed-by-code (409) — change it in the repo |
|
|
766
|
+
| `5` | Server error (5xx) — retry only when `error.retryable` is true |
|
|
767
|
+
| `1` | Any other failure (local error, 402/404, argument errors, …) |
|
|
732
768
|
|
|
733
769
|
## CI and agent usage
|
|
734
770
|
|