JSPM

  • Created
  • Published
  • Downloads 711
  • Score
    100M100P100Q112431F

Package Exports

  • @farthershore/cli

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (@farthershore/cli) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

@farthershore/cli

Create and manage FartherShore software products from the terminal. Designed for AI agents and humans alike — every command supports --format json for non-TTY scripting.

Install

npm install -g @farthershore/cli

Or use directly with npx:

npx @farthershore/cli --help

The package also ships an MCP stdio server for agents:

FARTHERSHORE_TOKEN=mk_xxx npx -p @farthershore/cli farthershore-mcp

Authentication

Create a maker token at farthershore.com/settings/tokens, then store it locally:

# Interactive — prompts for the token
farthershore auth login

# Non-interactive — pass it directly
farthershore auth login --token mk_xxx

# Or skip the file entirely with an env var (CI / agents)
export FARTHERSHORE_TOKEN=mk_xxx

Tokens are stored in ~/.farthershore/credentials.json. Maker tokens are exchanged for a short-lived CLI access token on first authenticated request.

farthershore auth whoami         # Show current org, role, scopes
farthershore auth logout         # Clear stored credentials

Global flags

Flag Description
--token <token> Override auth token for this command
--api-url <url> Override platform Core API URL
--env <environment> Environment scope (use production/prod/main)
--format <format> json for machine-readable output (default for non-TTY)
--version Show version
--help Show help

Environment variables

Variable Description
FARTHERSHORE_TOKEN API token (overrides stored credentials)
FARTHERSHORE_API_URL Platform Core API URL (default: https://core.farthershore.com)
FARTHERSHORE_ENV Default environment scope when --env is omitted

Commands

farthershore init

Scaffold a starter software-product repo from a named plan preset. Each preset fills in the 5-knob spec through product/plans.ts, with product/product.config.ts composing meters.ts, features.ts, and plans.ts. The command also creates a customer frontend/ project, repo-local product/package.json, product/tsconfig.json, and .gitignore, matching the two-root shape generated by dashboard product creation.

# Interactive walkthrough (TTY only) — pick a preset by number/name + path
farthershore init

# Non-interactive — pass --template explicitly (required when not a TTY)
farthershore init --template free
farthershore init --template starter --force
farthershore init --template metered --format json
farthershore init --template starter --surface frontend --surface agent

Templates (sourced from shared-types listPlanPresets()):

Template Shape
free $0 plan, hard-enforced 1k requests/month limit
starter $20/mo + $20 included usage, $0.001/request overage
pro $100/mo + $200 included usage, 14-day trial, $0.0005/request
prepaid $50 one-time signup credit, then PAYG
metered Pure pay-as-you-go at $0.001/request

After init, edit the fs.product(...) product name and origin in product/product.config.ts. origin is the business logic destination Farther Shore calls for customer-facing actions. Keep the generated module split or reorganize the product into any imported files you want. Pass repeatable --surface <frontend|api|docs|widget|dashboard|webhook|worker|agent> to seed a frontend-only, agent, worker, API, or hybrid product. Omitting --surface keeps the default frontend + api starter and its sample gateway route. Run npm install in product/ once, then run farthershore build from the repo root to confirm the scaffolded product compiles locally. Customize frontend/ for signup, pricing, account, and usage screens.

farthershore build

Build a product-as-code product/product.config.ts with the Product SDK manifest builder. The CLI first uses the builder installed under product/, then falls back to a root install. The command emits a Manifest IR envelope to manifest-ir.json by default. Server-side validation and accepted lifecycle state are handled by the GitHub bot when product/** changes are pushed to the repo-backed product.

farthershore build
farthershore build --entry product/product.config.ts --out manifest-ir.json
farthershore build --format json

farthershore product

Product lifecycle commands. Creation requires a connected GitHub account because Farther Shore always provisions the editable frontend/ starter repo for a new product.

farthershore product list --format json
farthershore product show weather-api --format json
farthershore product show weather-api --env preview --format json

farthershore product create \
  --name weather-api \
  --display-name "Weather API" \
  --origin https://api.example.com \
  --format json

# Meter templates — the same smart defaults the dashboard offers:
#   requests (default) | ai-tokens | credits | spend | compute
farthershore product create \
  --name llm-api \
  --origin https://api.llm.example.com \
  --meters ai-tokens \
  --format json

# Or a fully custom meter list (key[:display[:unit]], repeatable):
farthershore product create --name image-api \
  --origin https://api.images.example.com \
  --meter requests \
  --meter images:Images:image \
  --format json

# Seed initial Product SDK surfaces (repeatable). Defaults to frontend + API.
farthershore product create \
  --name support-agent \
  --origin https://app.example.com \
  --repo-owner acme \
  --repo-name support-agent \
  --surface frontend \
  --surface agent \
  --format json

farthershore product update weather-api --display-name "Weather" --format json
farthershore product publish weather-api --format json
farthershore product delete weather-api --yes --format json

product create provisions a managed GitHub repo and returns clone-URL + agent bootstrap instructions in the response. That repo is required for the starter frontend/ project and normal customization workflow. Product SDK changes can be built locally with farthershore build; accepted changes are compiled and published by the GitHub bot after they are committed and pushed.

Plan pricing lives on the plan (see farthershore plan create below) — the product itself no longer carries a billingStrategy. Omitting both meter flags gives the product a requests meter. Plain request counting is platform-managed. Variable-value meters such as tokens, credits, or compute must be declared in the Product SDK as route reports and reported by the upstream with @farthershore/backend.

A new product starts as a DRAFT with a generated frontend/ project ready for customization. Going live mirrors the dashboard's "Finish setting up" checklist:

farthershore product create \
  --name llm-api \
  --origin https://api.example.com \
  --meters ai-tokens                                            # 1. create
farthershore connect stripe llm-api                             # 2. connect billing
farthershore plan create llm-api --key pro --name "Pro" \
  --recurring-fee-cents 2900                                    # 3. how you charge
farthershore product publish llm-api                            # 4. go live

product publish enforces the same gates as the dashboard: at least one plan, an origin, and a verified Stripe connection (clear remediation is printed for STRIPE_NOT_CONNECTED / STRIPE_NOT_VERIFIED / BILLING_TAX_NOT_ENROLLED).

farthershore env

Manage preview/production environments. Production is the default scope when --env is omitted; production, prod, and main are aliases.

farthershore env list weather-api --format json
farthershore env create weather-api --name preview --branch env/preview --format json
farthershore env delete weather-api preview --yes --format json

farthershore plan

Plan CRUD via the management API. The body uses the unified 5-knob shape (see "Plan knobs" below) — pass cents-denominated flags for whichever knobs the plan flavor needs.

# Human-readable table (default in TTY)
farthershore plan list weather-api
farthershore plan list weather-api --format table

# JSON envelope (default outside TTY; suitable for jq pipelines)
farthershore plan list weather-api --format json

# Flat subscription: recurring fee only
farthershore plan create weather-api \
  --key pro \
  --name "Pro" \
  --recurring-fee-cents 2900 \
  --format json

# Included usage: fee + monthly credit grant
farthershore plan create weather-api \
  --key included \
  --name "Included" \
  --recurring-fee-cents 2000 \
  --grant recurring:2000 \
  --format json

# Free plan
farthershore plan create weather-api --key free --name "Free" --free --format json

farthershore plan update weather-api <planId> --recurring-fee-cents 3900 --format json
farthershore plan delete weather-api <planId> --yes --env preview --format json

farthershore persona

Test-environment personas — mint fresh fsk_test_* API keys so an agent can exercise the gateway end-to-end. Only works in test-strategy envs.

farthershore persona bootstrap weather-api --env preview --plan pro --format json
farthershore persona list weather-api --env preview --format json
farthershore persona revoke weather-api <personaId> --env preview --format json

farthershore usage

Read recent usage off the management API.

farthershore usage summary weather-api --format json

farthershore backend

Create BYO backends and provision runtime tokens for upstream services. Core stores only token hashes; the raw token is returned once and should be deployed as FS_RUNTIME_TOKEN.

farthershore backend list weather-api --format json
farthershore backend create weather-api \
  --name "Production API" \
  --origin-url https://api.example.com \
  --format json
farthershore backend tokens list weather-api --format json
farthershore backend tokens create weather-api --backend <backendId> --format json
farthershore backend tokens rotate weather-api <tokenId> --format json
farthershore backend tokens revoke weather-api <tokenId> --yes --format json
farthershore backend delete weather-api <backendId> --yes --format json

Pair the token with @farthershore/backend in the upstream:

import { fartherShore, withUsage } from "@farthershore/backend";

const fs = fartherShore.initFromEnv();

export async function POST(request: Request) {
  const url = new URL(request.url);
  const body = await request.clone().arrayBuffer();

  await fs.verifyRequest({
    method: request.method,
    path: url.pathname,
    query: url.search,
    headers: request.headers,
    body: new Uint8Array(body),
  });

  const result = await runWorkflow(await request.json());
  return withUsage(request, Response.json(result), {
    tokens_used: result.tokensUsed,
  });
}

farthershore connect

GitHub OAuth and Stripe Connect flows are browser-only. These commands report status so an agent can poll until the user finishes the flow.

farthershore connect github --format json
farthershore connect stripe weather-api --format json

farthershore token

Manage maker tokens for the current org.

farthershore token list --format json
farthershore token create --name "ci-bot" --scope products:update products:publish --format json
farthershore token revoke <tokenId> --yes --format json

Plan knobs

Every plan is a configuration of orthogonal billing knobs. Older shapes with pricing.{model, monthlyPriceCents}, top-level billing.strategy, or scalar credit grant fields are no longer accepted by the validator.

Knob Cents/unit Meaning
meters[] micros/unit Per-dimension usage price (zero or more dimensions)
recurring_fee_cents cents Charged each billing period (recurring subscription)
grants[] varies by kind Credit grants, top-ups, rollover, and recharge policy
trial_days days Waive everything for N days at the start
max_monthly_spend_cents cents (optional) Hard cap; the gateway blocks once exceeded (orthogonal)

Billing math (handled by Stripe Billing v2 at invoice finalization): bill = recurring_fee + max(0, total_meter_cost − applied_credit_balance).

Every plan flavor — free, flat, included, overage, prepaid, trial, pay-as-you-go — is a knob combination. Examples:

# Free plan: explicit `free: true` flag + hard-enforced limit
plans:
  - key: free
    name: Free
    free: true
    recurring_fee_cents: 0
    limits:
      - dimension: requests
        window: { type: named, name: month }
        capacity: 1000
        enforcement: enforce

  # Flat subscription: recurring fee only
  - key: starter
    name: Starter
    recurring_fee_cents: 2900

  # Included usage: fee + monthly credit grant + metered
  - key: pro
    name: Pro
    recurring_fee_cents: 2000
    grants:
      - kind: recurring
        amount_cents: 2000
    meters:
      - dimension: requests
        price_per_unit_micros: 1000 # $0.001/request

  # Overage: fee + metered, no credit
  - key: growth
    name: Growth
    recurring_fee_cents: 4900
    meters:
      - dimension: requests
        price_per_unit_micros: 500

  # Prepaid: one-time grant + metered
  - key: prepaid
    name: Prepaid
    grants:
      - kind: one_time
        amount_cents: 10000
    meters:
      - dimension: requests
        price_per_unit_micros: 1000

  # Trial: trial_days + recurring fee
  - key: trial
    name: Trial
    recurring_fee_cents: 2900
    trial_days: 14

  # Pay-as-you-go: metered only (no recurring fee)
  - key: metered
    name: Metered
    meters:
      - dimension: tokens
        price_per_unit_micros: 100

grants[] array

Plans accept a typed grants[] array. It is the only public credit surface. For CLI plan create/update, pass one or more canonical grants with --grant <kind:amount_cents>.

Valid kind values:

Kind Required fields Use case
recurring amount_cents Monthly credit (e.g. $20 included usage)
one_time amount_cents Signup bonus / prepaid balance
promotional amount_cents, label, optional expires_after_days Launch bonus, win-back, holiday promo
trial (none) Trial entry — requires trial_days > 0 on the plan
rollover percent (0–100) "Unused balance rolls over X% to the next period"
top_up sku, label, price_cents, credit_cents Buy-extra-credit SKU exposed in checkout
auto_recharge threshold_cents, refill_cents "When balance < $X auto-purchase $Y"

recurring, one_time, rollover, and trial are single-shot per plan; declaring more than one entry of the same kind triggers a warning (only the first is honored).

Example:

plans:
  - key: pro
    name: Pro
    recurring_fee_cents: 10000
    trial_days: 14
    meters:
      - dimension: requests
        price_per_unit_micros: 500
    grants:
      - kind: recurring
        amount_cents: 20000
      - kind: trial
      - kind: promotional
        amount_cents: 1000
        label: launch-bonus
        expires_after_days: 30
      - kind: rollover
        percent: 25
      - kind: auto_recharge
        threshold_cents: 500
        refill_cents: 5000

Validation surfaces:

  • error — invalid kind is rewritten to Unknown grant kind. Valid kinds: …
  • warning{ kind: trial } declared but trial_days is 0
  • warning — singleton kinds (recurring, one_time, rollover, trial) declared more than once

Deprecation window (Phase 3b)

The product top-level lifecycle.breaking_changes block declares the breaking-change governance policy validated by the GitHub bot/Core release path:

lifecycle:
  breaking_changes:
    require_deprecation_window_days: 90
    require_successor_route: true

When the policy is set, Core emits a route_removed change for every route dropped from features.<x>.routes[] and warns when the server-side breaking-change-safety-check cron will gate publish via ConsumerActivity lookup. When require_successor_route is true, it also adds a successor-required warning.

The CLI never blocks on the window itself — the per-consumer lookup lives server-side (Phase 1c ConsumerActivity table + Phase 3b cron).

Agent workflow

A typical agent flow:

export FARTHERSHORE_TOKEN=mk_xxx

farthershore product create \
  --name weather-api \
  --origin https://api.example.com \
  --format json

farthershore plan create weather-api --key free --name "Free" --free --format json
farthershore plan create weather-api \
  --key pro --name "Pro" --recurring-fee-cents 2900 --format json

farthershore build --format json
farthershore product show weather-api --format json

For product updates, edit product/product.config.ts or any modules it imports and build locally with:

farthershore build --format json

MCP server

The MCP server (farthershore-mcp) projects tool definitions from the same operation registry that generates the CLI command groups. Tool names use the fs_* prefix and cover the agent-writable product surface:

  • Products: fs_product_list, fs_brand_update, fs_product_publish
  • Environments: fs_env_list, fs_env_create
  • Plans: fs_plan_list
  • Backends: fs_backend_list, fs_backend_create, fs_backend_delete
  • Runtime tokens: fs_runtime_token_list, fs_runtime_token_mint, fs_runtime_token_rotate, fs_runtime_token_revoke
  • Personas: fs_persona_bootstrap, fs_persona_list, fs_persona_revoke
  • Usage and maker tokens: fs_usage_read, fs_maker_token_list

Every MCP tool has a sibling CLI operation by construction; the parity test in apps/cli/src/operations/mcp-cli-parity.test.ts enforces that invariant.

Errors and exit codes

The CLI exits 0 on success and 1 on any failure (including commander-level argument errors). When the API returns a 4XX/5XX, the CLI prints the canonical error code in brackets and a one-line remediation hint when one is registered:

Error [STRIPE_NOT_CONFIGURED]: connect Stripe before running billing operations
Hint: Stripe isn't connected on this product. Connect it in the dashboard before running billing operations.

The bracketed code is stable across releases — quote it in support threads.

farthershore auth whoami --format json emits a stable JSON shape suitable for CI scripts.

CI / agent usage

The CLI is non-interactive whenever a token is available via the --token flag or FARTHERSHORE_TOKEN env var — auth login only prompts when stdin is a TTY and no token argument was passed, so it's safe to script. farthershore build is CI-safe and can be run under CI / GITHUB_ACTIONS for local Product SDK compilation.