CLI — build, create, deploy

The tallpond CLI is the whole developer workflow: sign in once, register an app, and ship schema + frontend with one command. No dashboard steps, no hand-provisioned OAuth clients, no shared secrets.

sh
tallpond login                 # sign in (browser approval), saves a developer token
tallpond apps create "My App"  # registers the app + its OAuth client, writes tallpond.json
tallpond deploy                # applies .tallpond.schema.ts and publishes ./dist

A deployed app is served at https://<slug>.tallpond.app with the schema live behind the gateway. That's the entire path from empty directory to production.

tallpond login#

Starts a device-flow sign-in:

  1. The CLI prints (and opens) an approval URL containing a short confirmation code.
  2. You approve in the browser using your existing tallpond session.
  3. The CLI receives a developer token (osgd_…) and saves it to ~/.config/tallpond/credentials.json (mode 600), keyed by gateway URL.

The code in the URL can only approve — it can never mint a token, so a leaked link doesn't compromise the login. Tokens are stored server-side only as a SHA-256 hash.

TALLPOND_DEV_TOKEN overrides the saved token (CI). tallpond logout forgets it. tallpond whoami prints the signed-in user.

tallpond apps create <name> [--slug my-app]#

Registers an app under your account:

json
{
  "appId": "",
  "slug": "my-app",
  "name": "My App",
  "gatewayUrl": "https://api.tallpond.com",
  "url": "https://my-app.tallpond.app"
}

Commit this file — it's how tallpond deploy knows which app this repo is. It contains no secrets. tallpond apps list shows everything you own (20 apps per account).

tallpond deploy [schemaFile] [--dir dist] [--no-bundle]#

Two steps, both idempotent, run in order:

  1. Schema — if .tallpond.schema.ts (or the given file) exists, it is compiled locally and applied to the app's deployment. Safe changes apply automatically; destructive ones are blocked (409) pending an explicit migration — see Schema & deploy.
  2. Bundle — if ./dist (or --dir) exists, every file uploads under a new immutable version, then one activate call flips the live pointer. A failed upload can never leave the site half-updated. The directory must contain index.html; files are capped at 25 MB each.

Hosting behavior: content-hashed files under assets/ are cached immutably, HTML revalidates on every request (activations are instant), and extensionless paths fall back to index.html for client-side routing.

Served HTML also gets the app's identity injected as window.__TALLPOND__ = { gatewayUrl, clientId }, so hosted apps call createClient() with no arguments — there is no client id to copy into app code, and nothing in the bundle decides which app it is (the serving domain does). On hosted origins the injected gatewayUrl is "/_osg", so SDK traffic is same-origin and does not use credentialed CORS.

Deploys are authorized by ownership: your developer token can only deploy to apps you created. There is nothing to configure.

Platform/CI escape hatch#

The original shared-token path still exists for platform-managed deploys:

sh
tallpond deploy --app-id <id> --deployment-id <id> --token $DEPLOY_TOKEN

If a deploy token is supplied (flag or TALLPOND_DEPLOY_TOKEN), the CLI uses the legacy /deploy endpoint and skips the self-serve path entirely.

tallpond typegen [schemaFile] [--out tallpond-env.d.ts]#

Generates row types from the schema for end-to-end type safety. Unchanged.

HTTP surface (for tooling)#

Everything the CLI does is plain HTTP on the gateway, under /dev:

Method & pathAuthPurpose
POST /dev/cli/startnonebegin device flow → { device_code, user_code, verification_url }
GET/POST /dev/cli/approvebrowser sessionapproval page + form
POST /dev/cli/tokendevice_codepoll; 428 pending, then { token } once
GET /dev/medev token{ user_id }
GET /dev/apps / POST /dev/appsdev tokenlist / create apps
POST /dev/apps/:appId/deploydev token (owner)apply a compiled SchemaIR
PUT /dev/apps/:appId/bundle/:version/:pathdev token (owner)upload one bundle file
POST /dev/apps/:appId/bundle/:version/activatedev token (owner)flip the live version

Dev tokens go in Authorization: Bearer osgd_…. Owner checks return 404 for apps that aren't yours, so app existence is not leaked.