@tallpond/cli
v0.0.8
Published
The tallpond developer CLI — sign in, register an app, and deploy schema + frontend with one command.
Maintainers
Readme
@tallpond/cli
The tallpond CLI is the whole developer workflow for tallpond:
sign in once, register an app, and ship schema + frontend with one command. No
dashboard steps, no hand-provisioned OAuth clients, no shared secrets.
Install
Run it without installing:
npx @tallpond/cli loginor install globally so the tallpond command is on your PATH:
npm i -g @tallpond/cliQuick start
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 ./distA deployed app is served at https://<slug>.tallpond.app with the schema live
behind the gateway.
tallpond login
Device-flow sign-in: the CLI prints an approval URL with a short confirmation
code, you approve it in the browser using your existing tallpond session, and the
CLI receives a developer token saved to ~/.config/tallpond/credentials.json
(mode 600). The code in the URL can only approve — it can never mint a token,
so a leaked link doesn't compromise the login.
TALLPOND_DEV_TOKEN overrides the saved token (for CI / non-interactive agents).
tallpond logout forgets it; tallpond whoami prints the signed-in user.
tallpond deploy [schemaFile] [--dir dist] [--no-bundle]
Applies .tallpond.schema.ts (compiled locally) and uploads ./dist as a new
immutable version, then flips the live pointer in one call. Safe schema changes
apply automatically; destructive ones are blocked pending an explicit migration.
The schema file is TypeScript: the CLI compiles it in-process (via esbuild) so it runs on any supported Node — no bun or global TS loader required.
Functions
If the project has a functions/ directory, tallpond deploy also deploys it.
The convention: each .ts/.js file directly under functions/ is one
invokable function, named after the file, and must export default its
handler:
// functions/submitMove.ts — invoked as tallpond.functions.invoke('submitMove', args)
import type { FunctionContext } from '@tallpond/sdk' // type-only; nothing bundled
export default async (ctx: FunctionContext, args: { resourceId: string; move: unknown }) => {
await ctx.db.query({
scope: { kind: 'resource', resourceId: args.resourceId },
table: 'moves',
op: 'insert',
values: { move: args.move },
})
return { ok: true }
}The ctx surface is exactly userId, resourceId, fn, invocationId,
db.query/db.batch (raw /v1/db wire shape), and gateway(path, body?, opts?)
(POST by default, { method: 'GET' } for read routes) —
annotate with FunctionContext so the compiler enforces it. Full contract:
https://tallpond.com/docs/functions/.
File names must be identifiers (letters/digits/underscores). Shared helpers and
types belong in a subdirectory (e.g. functions/lib/) — subdirectories aren't
scanned, and handlers can import from them freely (everything is bundled). A
top-level file without a default export is skipped with a warning rather than
deployed.
tallpond test-session [--user name]
End-to-end testing without a browser: mints a bearer token for a synthetic test user of your app. Test users have no wallet — their usage bills your own balance directly (bounded by your per-app budget), and tokens expire after 24h. The token alone goes to stdout:
ALICE=$(tallpond test-session --user alice)
curl -H "Authorization: Bearer $ALICE" https://api.tallpond.com/v1/users/meIt authenticates on every user-facing route — tables, resources, functions, files, AI — as that user, metering normally. Mint two names for multi-user flows.
Full command reference: https://tallpond.com → docs → CLI.
License
MIT
