npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@farthershore/cli

v0.33.5

Published

FartherShore CLI — create and operate software businesses

Readme

@farthershore/cli

Create and operate FartherShore software businesses from the terminal.

Status: 0.33.5. Pre-1.0 — the command surface is stable but may still change between minor versions. Pin an exact version in CI.

FartherShore lets you define a software business as code, then sells, meters, and bills access to it at the edge. Business behavior — plans, pricing, limits, routes and meters — is authored in your GitHub repo with @farthershore/business and reconciled through repository checks and the apply timeline after you push. This CLI is the tool layer around that repo: provision a managed business repo, validate it locally before you push, inspect publication state, and run day-to-day operations (consumers, secrets, backends, webhooks, promo codes, usage). It is designed to be safe for both humans and agents — every command takes --format json for non-interactive scripting, and the MCP server exposes the explicitly agent-operable subset of the CLI surface.

Install

npm install -g @farthershore/[email protected]

Or run it directly with npx:

npx -p @farthershore/[email protected] farthershore --help

The package also ships an MCP stdio server for agents:

npx -p @farthershore/[email protected] farthershore-mcp

Authentication

Start the device login. The CLI opens the complete authorization request in your browser without printing a code, then waits for you to approve access:

farthershore login
farthershore auth whoami --format json

On a headless machine, print the manual verification URL and user code without trying to open a browser:

farthershore login --headless

Normal login creates a user-bound CLI session. It uses your live role in each organization instead of copying a permission list into the credential. By default it follows all of your current and future organization memberships and all businesses in them. Normal login has no permission or scope choices: use an organization-scoped MakerToken when automation needs narrower access.

Choose the active organization for a command with --organization <id-or-slug>, or save a default context:

farthershore auth organization list
farthershore auth organization use <id-or-slug>

For a separately issued organization-scoped MakerToken, pipe it through bounded stdin:

printf %s "$FARTHERSHORE_MAKER_TOKEN" | farthershore login --token-stdin

FARTHERSHORE_TOKEN accepts an organization-scoped MakerToken as an ephemeral process override and is never persisted automatically. farthershore logout deletes the stored credential after revoking the current user CLI session on the platform. Signing in again also supersedes older user CLI sessions. Membership and role changes take effect on the next authenticated request. A restricted MakerToken remains available through --token-stdin or FARTHERSHORE_TOKEN. Never write credentials into the managed repository.

Quickstart

Create a managed business repo, author the business, validate it, and push:

# 1. Create the managed repo. Human output is exactly its URL.
REPO_URL=$(farthershore business create weather-api \
  --idempotency-key <persisted-business-create-attempt-key>)

# 2. Clone it and author business/ from scratch.
git clone "$REPO_URL"
cd weather-api
# ...author business/ with @farthershore/business...

# 3. Validate the same way the PR check will, before pushing
farthershore validate --business weather-api

# 4. Push — the GitHub bot validates and records apply state
git push --set-upstream origin feature/pricing
farthershore apply-timeline list weather-api # inspect checks + apply state

# 5. Inspect accepted state, then use the CLI for platform operations.
farthershore business status weather-api --format json
farthershore operations list --format json

Do not infer a successful apply from a push alone. A default-branch runtime-only change may publish after validation; an economic change is deferred to a GitHub Release. Preview-environment branches publish only to that environment. Inspect the repository checks and apply timeline for the actual outcome.

Plans, prices, limits, routes, and meters are repo-controlled: change them by editing the program under business/ and pushing. Presentation and origin bindings are platform-owned operating state. The CLI's write commands cover operational state that lives outside the manifest (consumers, secrets, backends, webhooks, promo codes, brand presentation).

Global flags

| Flag | Description | | --------------------- | -------------------------------------------------------- | | --api-url <url> | Override platform Core API URL | | --env <environment> | Environment scope (production/prod/main aliases) | | --format <format> | json for machine-readable output (default for non-TTY) | | --no-input | Never prompt; use non-interactive, agent-safe paths | | --version | Show version | | --help | Show help |

Environment variables

| Variable | Description | | ----------------------------------------- | ------------------------------------------------------------------------ | | FARTHERSHORE_TOKEN | Ephemeral organization-scoped MakerToken; never persisted | | FARTHERSHORE_API_URL | Platform Core API URL (default https://core.farthershore.com) | | FARTHERSHORE_ENV | Default environment scope when --env is omitted | | FARTHERSHORE_CONSUMER_TOKEN | Ephemeral portal consumer session for service-account; never persisted | | FARTHERSHORE_ENVIRONMENT_ID | Portal environment UUID fallback for service-account | | FARTHERSHORE_SUBSCRIBER_ORGANIZATION_ID | Subscriber organization UUID fallback for service-account | | FS_CLI_CHANNEL | stage enables stage-channel commands for one invocation (see below) | | FS_CLI_STAGE_HOSTS | Extra hosts (comma separated) the stage-channel gate treats as stage |

Stage-channel commands

A few operations exist only to service stage. farthershore business delete is the only one today: deleting a business is unrecoverable, and there is no builder reason to do it from a terminal against production — the dashboard owns that path.

They are gated twice:

  1. Registration. The command is registered only when the CLI runs in the stage channel. make cli-stage writes {"channel":"stage"} into ~/.farthershore/config.json (make cli-prod writes "prod"), and FS_CLI_CHANNEL=stage does the same for a single invocation. Without the marker the command is absent from farthershore business --help and invoking it is an unknown-command error — so the published CLI, as a builder installs it, does not have it at all.
  2. Target. Even in the stage channel, the command refuses when the api-url it would call is not a stage host — --api-url https://core.farthershore.com, or FARTHERSHORE_API_URL pointed at production. It exits 2 with COMMAND_NOT_AVAILABLE_IN_PRODUCTION before any request is made.

Delete a production business from the dashboard instead.

Commands

Browse platform documentation (no login)

Docs are a read-only virtual filesystem: collections are root folders, sidebar sections are directories, and pages are files. Listing a page shows its heading anchors. Paths come from the published docs index, not your working directory.

farthershore docs ls --format json
farthershore docs ls backend-sdk --format json
farthershore docs tree backend-sdk --format json
farthershore docs ls backend-sdk/connect-your-application --format json
farthershore docs read backend-sdk/connect-your-application/metering --format json
farthershore docs ls backend-sdk/connect-your-application/metering --format json
farthershore docs read backend/metering --section "choose-the-correct-metering-channel" --format json
farthershore docs search "runtime token" --collection backend-sdk --limit 10 --format json
farthershore docs collection backend-sdk --format json

Use an anchor returned by docs ls <page> for --section. read also accepts the canonical slug or an official docs URL with a #heading fragment, so links in skills can be used directly. get aliases read; list aliases ls. A section includes all its child headings and complete code fences. Full pages and collections are not truncated; search results are bounded and include a total match count.

farthershore docs --stage ls selects stage; production is the default and --api-url does not change the documentation origin. No credentials or organization context are sent. JSON includes source URL and, for content reads, the docs source commit. Human output is available with --format table. The collection-aware llms.txt and corpus artifacts must be published first; unavailable artifacts produce an error, not stale bundled guidance. Business knowledge commands are separate authenticated resources.

Run farthershore <group> --help for the full flag set of any command.

Database-backed list commands use Core's shared query contract: repeat --filter field=value for exact AND filters, pass one --sort field[:asc|desc] (ascending when omitted), and use --search <text> for case-insensitive text search. Core applies all three before pagination; the CLI does not sort or filter a partial page locally. Each command rejects fields outside its endpoint-specific allowlist shown by --help.

farthershore create

Create local project components inside a managed builder repo. create api scaffolds a starter backend into api/ by downloading the public Node template tarball, then patches the repo root .gitignore.

farthershore create api
farthershore create api --path ../weather-api
farthershore create api --force
farthershore create api --node --ref v0.1.0 --format json

--node is the default language today: Node (TypeScript + Express). --ref accepts a template tag or branch name, trying tags first. More languages are planned.

farthershore build

Compile the program under business/ to a Manifest IR envelope locally (default output business-build.json). The CLI uses the Business SDK installed under business/, falling back to a root install. This is local compilation only; server-side validation and apply happen when you push business/** changes.

farthershore build
farthershore build --entry business/business.ts --out business-build.json
farthershore build --format json

farthershore validate

Run the same verdict the GitHub farthershore/validate PR check produces, before you push. It builds the manifest twice and compares the IR hash (the determinism check the build runner enforces), then — when you pass --business — submits the IR for a server verdict that returns compile diagnostics, the semantic diff, and an economic-change verdict. The server may retain a diagnostic compilation record, but validation never accepts or publishes business state, so it is safe to repeat and does not take an idempotency key.

farthershore validate                       # local build + determinism only
farthershore validate --business weather-api
farthershore validate --local-only --format json

farthershore business

Business lifecycle. Creation provisions a managed GitHub repo as the source of truth for business behavior and returns its URL. A new business starts as a DRAFT with repository tooling but no predefined business program.

farthershore business list --format json
farthershore business list --filter status=ACTIVE --sort updatedAt:desc --search weather --format json
farthershore business show weather-api --format json
farthershore business show weather-api --env preview --format json

# Is the slug free? (normalized, blocked-word and collision checked)
farthershore business subdomain-check weather-api --format json

farthershore business create weather-api \
  --display-name "Weather API" \
  --idempotency-key <persisted-business-create-attempt-key> \
  --format json

farthershore business publish weather-api --format json --idempotency-key <persisted-business-publish-attempt-key>
farthershore business rollback weather-api wfe_previous --reason "bad release" --format json --idempotency-key <persisted-business-rollback-attempt-key>

Deleting a business is stage only — the command is not registered in the published CLI at all (see Stage-channel commands). Run make cli-stage first; production businesses are deleted from the dashboard.

farthershore business delete weather-api --yes --format json

The JSON result includes data.business, data.repoUrl, and recovery metadata. Gather the product requirements, create the business/ program, and author its plans, prices, limits, routes, and meters from scratch.

business update changes platform-owned fields such as display name, description, icon, logo (icon/logo accept PNG, JPEG, or WEBP), and whether the product is listed on the organization's public page (https://farthershore.io/organization/<org-slug>, listed by default). Plans, prices, limits, routes, and meters are repo-controlled and must be changed through the Business SDK code path.

farthershore business update weather-api \
  --display-name "Weather" \
  --description "Weather API for agents" \
  --icon-file ./brand/icon.png \
  --logo-file ./brand/logo.webp \
  --format json
farthershore business update weather-api \
  --clear-icon --clear-logo --format json
farthershore business update weather-api \
  --unlist-from-org-page --format json

business publish enforces the same go-live gates as the dashboard and returns stable remediation errors when a prerequisite is missing. business rollback enqueues a rollback of the specified prior publish workflow and requires the exact business:rollback permission.

business rbac reads a business's Managed-RBAC state — the platform-owned rbacEnabled flag. business rbac enable / disable toggle that flag (like docsEnabled, it is platform-owned and never repo-authored); once enabled, subscriber organizations manage roles in their portal. Both toggles are idempotent. Subscriber role and assignment state is kept server-side on disable, so re-enabling is a pure flag flip.

farthershore business rbac weather-api --format json
farthershore business rbac enable weather-api --format json
farthershore business rbac disable weather-api --format json

business rbac subjects list lists the custom permission vocabulary: subjects whose <subject>:<verb> permissions are grantable to subscriber roles alongside the route-derived catalog. Subjects are repo-owned — declared via a permission-carrying fs.group(id, routes, { permission: { verbs, escalatory, description } }) in the business repo's business/ folder and synced from the accepted spec. To change them, edit the group declaration, run farthershore validate, and push; there are no CLI write commands.

farthershore business rbac subjects list weather-api --format json

farthershore apply-timeline

Inspect repo-backed applies — PRs, pushes, releases, checks, semantic diffs, and apply state — for a business.

farthershore apply-timeline list weather-api --format json
farthershore apply-timeline inspect weather-api 42 --format json # by id, PR #, branch, or SHA

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 list weather-api --filter branch=env/preview --sort createdAt:desc --search preview --format json
farthershore env create weather-api --name preview --branch env/preview --format json
farthershore env delete weather-api preview --yes --format json

farthershore organization

Manage organization members and the exact platform-permission roles assigned to them. Built-in and custom roles use the same list contract.

farthershore organization role list <organizationId> --filter builtIn=true --sort name --search security --format json
farthershore organization members <organizationId> --filter roleKey=auditor --sort email:asc --search person --format json

# Primary owner only; hands ultimate authority to another existing member.
farthershore organization ownership-transfer <organizationId> <newOwnerUserId> --yes --format json --idempotency-key <persisted-organization-ownership-transfer-attempt-key>

Selecting the default organization is a local credential concern, not an API call: farthershore auth organization use <id-or-slug> changes the stored default, and --org <id> overrides it for one command.

farthershore token

Create and administer organization-owned MakerTokens. These commands require a signed-in user CLI session (farthershore login); an existing MakerToken cannot list, mint, approve, rotate, revoke, or otherwise administer credentials. The entire group is CLI-only and is deliberately absent from farthershore-mcp.

# Exact permissions a human may delegate — read this before choosing --permissions.
farthershore token permission-catalog --org --format json

# Omit --businesses to snapshot ALL current and future org businesses.
farthershore token create deploy-bot --org \
  --permissions '["business:read","business:publish"]' \
  --businesses business_1,business_2 \
  --idempotency-key org-token-create-2026-08-11 \
  --format json

farthershore token list --org --format json
farthershore token approvals --org --format json
farthershore token approve <approvalId> --org --format json --idempotency-key <persisted-token-approve-attempt-key>
farthershore token approve <approvalId> --org \
  --idempotency-key <persisted-token-approve-attempt-key> \
  --permissions '["business:read"]' --format json # trim on approval
farthershore token deny <approvalId> --org --format json
farthershore token update <tokenId> --org \
  --permissions '["business:read"]' \
  --idempotency-key org-token-update-2026-08-11 --format json
farthershore token rotate <tokenId> --org --format json --idempotency-key <persisted-token-rotate-attempt-key>
farthershore token revoke <tokenId> --org --yes --format json

Creation and updates that exceed the caller's live authority return data.status: "PENDING", an approval id, and no plaintext credential. A direct ACTIVE create, an approved CREATE, or a rotation returns data.token exactly once; store it immediately. Human output follows the same rule: it prints plaintext only for an ACTIVE one-time-secret response and says explicitly when a PENDING request minted nothing.

Create and update require --idempotency-key. Persist the key before the first dispatch and reuse it only when repeating that exact logical request after an interrupted invocation. The CLI never generates a key: a process-local key would be lost across the restart where retry safety matters most.

farthershore stripe

Read the Stripe Connect account a business bills through (a per-business override when one exists, otherwise the organization default) and remove a per-business override. Both require a signed-in owner session; a MakerToken is rejected. Connecting Stripe is a browser-only onboarding handshake with Stripe, so there is deliberately no stripe connect command — do it from the dashboard and confirm with stripe status.

farthershore stripe status weather-api --format json
farthershore stripe disconnect weather-api --yes --format json

stripe disconnect is refused while any subscription on the business is still money-bearing.

farthershore service-account

Manage service accounts owned by a subscriber organization. This is a separate subscriber-plane trust boundary: it requires a current identity-provider portal consumer session in FARTHERSHORE_CONSUMER_TOKEN, plus the exact environment and subscriber organization context. The consumer bearer has no argv flag and is never exchanged or persisted by the CLI. A builder login or MakerToken cannot substitute for it.

export FARTHERSHORE_CONSUMER_TOKEN='<current portal session token>'
export FARTHERSHORE_ENVIRONMENT_ID='<environment UUID>'
export FARTHERSHORE_SUBSCRIBER_ORGANIZATION_ID='<subscriber organization UUID>'

farthershore service-account list <businessId> --format json
farthershore service-account create <businessId> deploy-bot \
  --permissions '["route:read","route:write"]' \
  --scopes '["production"]' \
  --idempotency-key sa-create-2026-08-11 --format json
farthershore service-account update <businessId> <serviceAccountId> \
  --permissions '["route:read"]' \
  --idempotency-key sa-update-2026-08-11 --format json
farthershore service-account approvals <businessId> --format json
farthershore service-account approve <businessId> <approvalId> \
  --permissions '["route:read"]' --format json # optional trim
farthershore service-account deny <businessId> <approvalId> --format json
farthershore service-account rotate <businessId> <serviceAccountId> --format json --idempotency-key <persisted-service-account-rotate-attempt-key>
farthershore service-account revoke <businessId> <serviceAccountId> --yes --format json

Pass --environment-id and --subscriber-organization to override the two context environment variables for one command. PENDING create/update responses never print plaintext. ACTIVE creates and rotations print the one-time key once. Create, update, and rotate require a caller-persisted key, just like one-time-secret org-token operations. A replayed success includes meta.idempotency.replayed: true; follow it with a list read before reporting current state.

This group is direct CLI-only and deliberately has no MCP projection: the MCP operation registry carries builder principals, not portal consumer sessions.

farthershore limit

Manage subscriber-owned usage limits with a portal consumer session. list reads the current limits; set creates a limit when --limit-id is omitted and updates that limit when --limit-id is present; remove deletes a limit.

farthershore limit list <business-id> --format json
farthershore limit set <business-id> \
  --quantity requests --mode BLOCK --scope ORG --units 10000 \
  --format json
farthershore limit set <business-id> \
  --limit-id <limit-id> --mode NOTIFY --units 20000 \
  --notify-at 0.8 --format json
farthershore limit remove <business-id> <limit-id> --format json

Changing a limit's scope, subject, or quantity requires removing and recreating the limit with the new target.

Every limit command requires FARTHERSHORE_CONSUMER_TOKEN, containing the current portal consumer session token. Pass --environment-id and --subscriber-organization, or set their respective fallbacks FARTHERSHORE_ENVIRONMENT_ID and FARTHERSHORE_SUBSCRIBER_ORGANIZATION_ID. These subscriber-portal credentials are separate from the organization-scoped MakerToken used by the rest of the CLI and are never persisted automatically.

farthershore plan

Read code-managed plans. The CLI does not create, update, or delete plan definitions — edit the Business SDK program for that.

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

farthershore frontend

Managed Frontend Hosting status, rollback, and a local preview. Builds are Git-triggered: production builds on a GitHub Release and preview environments build on pushes to their environment branch. preview runs the generated frontend/'s vite dev with an injected window.__FS_CONFIG__ shim so the portal renders locally exactly as it serves in production. Pass --mock to inject { mock: true } instead of Core/Clerk config for local page inspection with placeholder data and auth bypassed.

farthershore frontend status weather-api --format json
farthershore frontend rollback weather-api --release-id <hash> --format json

# Local preview (shells out to vite; needs a frontend/ project)
farthershore frontend dev                            # hot-reloading dev server, mock mode by default
farthershore frontend preview                        # production build served as-is, mock mode by default
farthershore frontend dev --live                     # against the real platform
farthershore frontend preview --core-url http://localhost:8787

# Local preview signed in as a test persona (hot reload against the real platform)
farthershore frontend dev --live --business acme --env preview --persona alice
farthershore frontend dev --live --business acme --env preview --persona persona_123 --port 4321

--live --business --env --persona (all three required, not combinable with --mock or --core-url) opens http://localhost:<port> (default 5173) already signed in as that test persona, exactly as the hosted portal would be. The CLI issues a short-lived, origin-bound preview lease from Core and holds it only in its own process memory; Vite runs on a private random loopback port behind a CLI-owned proxy that attaches the lease to portal requests and serves the secret-free sign-in bridge. Nothing secret ever reaches the browser URL, DOM, storage, or logs — the browser only ever holds the same HttpOnly session cookie the hosted portal uses. The lease renews automatically while the command runs and is revoked when it exits (Ctrl-C included); a lease that cannot be revoked expires within five minutes. Core is always the one selected for the authenticated CLI (--api-url / FARTHERSHORE_API_URL).

farthershore persona

Create temporary subscriber users in a test-strategy environment so an agent can exercise the same customer RBAC, browser session, and gateway paths as a human. The Business SDK contributes raw permissions; the subscribing organization composes those permissions into its own product roles.

# First persona creates and owns a temporary subscriber workspace.
farthershore persona bootstrap weather-api --env preview --plan pro --format json --idempotency-key <persisted-persona-bootstrap-attempt-key>
farthershore persona list weather-api --env preview --format json
farthershore persona login weather-api <ownerPersonaId> --env preview --format json

# Join the same subscriber after its owner has enabled subscriber RBAC and
# created roles/defaults through the normal customer RBAC surface.
farthershore persona bootstrap weather-api --env preview --plan pro \
  --subscriber-id <subscriberId> --account-role member --role viewer \
  --format json --idempotency-key <persisted-member-bootstrap-attempt-key>

farthershore persona rotate weather-api <personaId> --env preview --format json --idempotency-key <persisted-persona-rotate-attempt-key>
farthershore persona delete weather-api <personaId> --env preview --format json

Bootstrap and rotation return a key once. login sends the 60-second, single-use handoff only in the browser URL fragment to the platform-owned /persona-sign-in bridge. The bridge establishes an HttpOnly browser session and returns to the exact original portal path, query, and fragment. CLI output contains portal metadata but never the handoff or a session bearer. Product role keys must already exist in that subscriber's role catalog; omit --role to use its configured default. Deletion tears down the temporary user and credential, and deleting the environment also removes the remaining persona-owned workspace. After an environment-branch apply, existing personas remain available but are detached from the superseded subscription. Use persona login with the same persona id and select a plan from the new branch contract; the CLI does not fall back to a production plan. The old raw test key stays invalid. After the persona is reattached, run persona rotate to mint a replacement key for gateway testing; its product roles and explicit scope ceiling are preserved.

farthershore usage

Read recent usage off the management API.

farthershore usage summary weather-api --format json

farthershore consumer

Manage live business users. These are operational actions, not repo-authored behavior.

farthershore consumer list weather-api --format json
farthershore consumer block weather-api <subscriberId> --yes --format json
farthershore consumer remove weather-api <subscriberId> --yes --format json

Use consumer list first to find a subscriberId. block suspends a user and revokes active API keys. remove is irreversible and tears down subscriber state across billing, edge credentials, and subscriptions.

farthershore variables

Manage platform-owned variables. The name is the class: an FS_PUBLIC_ prefix makes a value public (inlined into the frontend bundle, readable by every visitor); any other name is a write-only secret — available to the isolated managed build (leak-scanned from its artifact) and injected by Gateway for any compiled integration that references it.

farthershore variables list weather-api --format json
printf '%s' "$SENTRY_AUTH_TOKEN" | farthershore variables set weather-api \
  SENTRY_AUTH_TOKEN --format json --idempotency-key <persisted-sentry-variable-attempt-key>
printf '%s' "$POSTHOG_PROJECT_KEY" | farthershore variables set weather-api \
  FS_PUBLIC_POSTHOG_KEY --format json --idempotency-key <persisted-posthog-variable-attempt-key>
farthershore variables revoke weather-api POSTHOG_SECRET --yes --format json --idempotency-key <persisted-variables-revoke-attempt-key>
farthershore variables rm weather-api POSTHOG_SECRET --yes --format json --idempotency-key <persisted-variables-rm-attempt-key>

There is no builder-managed public-variable surface and values are never revealed after write. Rotation preserves the delivery phase; changing phase requires revoke, delete, and recreate.

farthershore backend

Create bring-your-own backends and provision runtime tokens for your upstream services. Only token hashes are stored; 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 \
  --idempotency-key <persisted-backend-create-attempt-key> \
  --format json
farthershore backend bind weather-api api \
  --env preview-42 \
  --origin-url https://api-pr-42.example.com \
  --format json
farthershore backend tokens create weather-api --backend <backendId> --format json --idempotency-key <persisted-backend-tokens-create-attempt-key>
farthershore backend tokens rotate weather-api <tokenId> --format json --idempotency-key <persisted-backend-tokens-rotate-attempt-key>
farthershore backend tokens revoke weather-api <tokenId> --yes --format json

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

import { fartherShore } 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();

  const ctx = 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());
  await ctx.report({
    meter: "tokens_used",
    values: { tokens_used: result.tokensUsed },
  });
  return Response.json(result);
}

farthershore webhook

Provision outbound webhook endpoints and inspect delivery health. Endpoints are platform-owned operate records: they never live in the managed repo, so these writes work the same for every business regardless of repo linkage.

farthershore webhook list weather-api --format json
farthershore webhook create weather-api \
  --url https://hooks.example.com/farthershore \
  --events subscription.created,payment.failed \
  --idempotency-key <persisted-webhook-create-attempt-key> \
  --format json
farthershore webhook update weather-api <webhookId> --disable --format json
farthershore webhook test weather-api <webhookId> --idempotency-key <persisted-test-attempt-key> --format json
farthershore webhook trigger weather-api <webhookId> --type payment.failed --idempotency-key <persisted-trigger-attempt-key> --format json
farthershore webhook deliveries weather-api <webhookId> --limit 20 --format json
farthershore webhook rotate weather-api <webhookId> --format json --idempotency-key <persisted-webhook-rotate-attempt-key>
farthershore webhook delete weather-api <webhookId> --yes --format json

webhook create and webhook rotate return the signing secret once; store it in the receiving app. In human mode they also print it as an FS_WEBHOOK_SECRET= line plus a createWebhookHandler snippet.

webhook test sends the plain webhook.test ping. webhook trigger --type sends a signed, realistic sample of one catalog event (the deliveries log records it under that type) so every handler branch can be exercised locally.

For a receiver on your machine, webhook listen is the Stripe-CLI-style loop: it opens a Cloudflare quick tunnel to --forward-to, creates a temporary endpoint on it, prints the endpoint id / tunnel URL / (with --print-secret) the FS_WEBHOOK_SECRET= line, tails deliveries as time type status responseStatus id, and deletes the endpoint on Ctrl-C.

farthershore webhook listen weather-api \
  --forward-to http://localhost:3000/webhooks/farthershore \
  --print-secret --trigger payment.failed
farthershore webhook listen weather-api --forward-to localhost:3000/webhooks \
  --events subscription.created,payment.failed --format json

listen needs cloudflared — bundled as an optional @farthershore/cloudflared-<platform> dependency, or on your PATH. It has no MCP tool (long-running, process-owning). A listener killed hard leaves an endpoint with a *.trycloudflare.com URL; webhook delete --yes removes it.

farthershore promo-code

Manage checkout promo codes (operational state, not part of the manifest).

farthershore promo-code list weather-api --format json
farthershore promo-code create weather-api \
  --code LAUNCH25 --kind percent_off --percent 25 --duration-months 3 \
  --idempotency-key <persisted-promo-code-create-attempt-key> \
  --plan <planId> --format json
farthershore promo-code create weather-api \
  --idempotency-key <persisted-promo-code-create-attempt-key> \
  --code SAVE500 --kind amount_off --amount-cents 500 --duration-months 1 --format json
farthershore promo-code archive weather-api <promoCodeId> --format json
farthershore promo-code reactivate weather-api <promoCodeId> --format json

Because a Stripe coupon change requires a complete discount spec, promo-code update requires --kind, --duration-months, and the amount flag for that kind whenever you change the code, amount, dates, plan scope, or redemption limits. Use --all-plans to clear plan scoping.

Farther Shore agent skills

Install or refresh the platform-verified skills bundle together. The platform pins this immutable release, and CI plus a daily repository check compare it to GitHub's latest stable release so the guidance cannot silently drift. This command requires @farthershore/cli 0.33.5 or newer.

set -euo pipefail
CLI_VERSION=$(farthershore --version)
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] >= 5))) { console.error("Stop: CLI 0.33.5 or newer is required; ask the human to upgrade."); process.exitCode = 1; } })'
farthershore skills install --help
farthershore skills install

If either prerequisite fails, stop and ask the human to run npm install -g @farthershore/[email protected], then repeat the checks. Do not install or upgrade global tooling autonomously.

The Farther Shore CLI downloads the exact installer archive and verifies this SHA-512 before it extracts or executes any installer code.

farthershore operations

Print the machine-readable action boundary: which operations are repo-authored (contract) and which are CLI/API operations (operate).

farthershore operations list --format json

Errors and exit codes

In --format json mode, every command prints a single canonical envelope to stdout — { ok, op, data } on success, or { ok: false, op, error } on failure, where error carries a stable code, message, HTTP status, a retryable flag, and a remediation hint when one is registered. Diagnostics go to stderr.

In table mode, failures print Error [CODE]: message plus a Hint: line. The bracketed code is stable across releases — quote it in support threads.

Exit codes are a branchable taxonomy so a script can tell failure classes apart without parsing text:

| Exit | Meaning | | ---- | -------------------------------------------------------------- | | 0 | Success | | 2 | Validation error (HTTP 400/422) — fix your input | | 3 | Auth / permission error (401/403) — re-authenticate | | 4 | Conflict / managed-by-code (409) — change it in the repo | | 5 | Server error (5xx) — retry only when error.retryable is true | | 1 | Any other failure (local error, 402/404, argument errors, …) |

CI and agent usage

Authenticate before unattended work, or supply an organization-scoped MakerToken through FARTHERSHORE_TOKEN. Device login waits for human approval; use --headless when the CLI cannot open a browser. farthershore build and farthershore validate --local-only need no network or auth and are safe to run in CI.

MCP server

The MCP server (farthershore-mcp) projects its tools from the same operation registry that defines the CLI commands. Every MCP tool has a CLI sibling, but not every CLI command is exposed through MCP. Tool names use the fs_* prefix and cover only operations explicitly marked agent-operable in that registry. Organization, role, member, invitation, and org MakerToken administration requires a live-user CLI session and is not projected into MCP; audit logs, notifications, and apply timelines are also CLI-only.

farthershore-mcp

Learn more

License

MIT