Operate via an agent
Drive a product from create to publish entirely through the CLI (and the matching MCP tools).
Drive a product from create to publish entirely through the CLI (and the matching MCP tools).
Everything in the dashboard except connecting accounts and deleting a product is
operable headless. The farthershore CLI is the canonical agent surface: every
command takes --format json, exits non-zero on failure, and prints a stable
bracketed error code. The MCP server (farthershore-mcp) projects the same
operations as fs_* tools — a CI test enforces that every MCP tool has a sibling
CLI command, so anything an agent can do over MCP it can do over the CLI.
This recipe takes a product from nothing to live, then exercises it — the agent equivalent of the metered-capability and launch recipes.
Create a maker token in the dashboard, then hand it to the CLI. For agents and CI,
the FARTHERSHORE_TOKEN env var skips the credential file entirely.
export FARTHERSHORE_TOKEN=mk_xxx
farthershore auth whoami --format json # confirm org, role, scopes
Creation provisions the editable frontend/ repo, so a connected GitHub owner +
repo name are required. --meters applies a smart-default meter set (here,
requests); the product starts as a DRAFT.
farthershore product create \
--name croncloud \
--display-name "CronCloud" \
--origin https://api.example.com \
--repo-owner acme \
--repo-name croncloud \
--meters requests \
--format json
The response includes the clone URL and agent bootstrap instructions. Edit
product/product.config.ts in that repo to grow the product (add @Meter,
@Feature, @Plan members) and build locally:
farthershore build --format json # deterministic local compile, CI-safe
Billing connection is the one step the agent cannot complete headless — it's a browser KYC flow. The CLI reports status so an agent can hand off a URL to a human and poll until it clears.
farthershore connect stripe croncloud --format json
Publishing is blocked until this is verified; the gate surfaces as
STRIPE_NOT_CONNECTED, STRIPE_NOT_VERIFIED, or BILLING_TAX_NOT_ENROLLED.
A product needs at least one plan to publish. Every plan must carry a rate limit; the CLI applies a 600/min default unless you override it.
farthershore plan create croncloud \
--key pro --name "Pro" \
--recurring-fee-cents 19900 \
--format json
publish auto-derives the semver bump from the diff and cuts a vX.Y.Z release.
Use --dry-run to preview the bump and reasons without cutting a tag — this is
the agent's preview path (non-TTY publishes apply directly).
# Preview the computed release without mutating anything.
farthershore product publish croncloud --dry-run --format json
# Cut the release.
farthershore product publish croncloud --format json
# Verify the product is actually serving (not just ACTIVE).
farthershore product status croncloud --format json
product status returns status, latestReleaseVersion, the latest deployment,
and a derived live boolean — poll it until live: true.
If your upstream reports dynamic usage (tokens, compute, credits) it needs
@farthershore/backend and an FS_RUNTIME_TOKEN. Create a backend, then mint a
token — the plaintext secret is returned once.
farthershore backend create croncloud \
--name "Production API" \
--origin-url https://api.example.com \
--transport direct \
--format json
# The result's token is your FS_RUNTIME_TOKEN — capture it now; it isn't shown again.
farthershore backend tokens create croncloud --backend <backendId> --format json
Tunnel backends (private, outbound-only) use --transport tunnel and need the
tunnel capability: --capabilities gateway_verification,metering,health,tunnel.
Create a preview environment on a branch, then mint a test API key so the agent can curl the gateway and confirm metering — no real customer needed. Personas only work in test-strategy environments.
farthershore env create croncloud --name preview --branch env/preview --format json
# Returns a one-time fsk_test_ key scoped to the env + plan.
farthershore persona bootstrap croncloud --env preview --plan pro --format json
# After driving traffic with the key:
farthershore usage summary croncloud --format json
Run the MCP server over stdio for an agent host:
FARTHERSHORE_TOKEN=mk_xxx npx -p @farthershore/cli farthershore-mcp
The writable surface maps 1:1 to the CLI:
| CLI command | MCP tool |
|---|---|
product list / product status / product publish | fs_product_list / fs_product_status / fs_product_publish |
product update | fs_brand_update (brand only; plans/routes are code-managed) |
plan list / plan migrate | fs_plan_list / fs_plan_migrate |
env list / env create | fs_env_list / fs_env_create |
backend create / backend tokens create | fs_backend_create / fs_runtime_token_mint |
persona bootstrap / usage summary | fs_persona_bootstrap / fs_usage_read |
Plans, pricing, routes, and meters are managed as code. An API/MCP write to
those returns MANAGED_BY_CODE — edit the product repo's
product/product.config.ts and push. fs_plan_list reads the live state but
cannot mutate it; fs_plan_migrate is the exception, because moving live
subscribers is an operate action, not a code change.
farthershore auth whoami returns the expected org and scopes.product status reports live: true after publish.fsk_test_ persona key calls the gateway and usage lands on the right meter.--format json and exit code 0 in a non-TTY shell.fs_plan_migrate to move subscribers.FS_RUNTIME_TOKEN you minted here into withUsage.publish enforces.