Use the Sapporta CLI
View as MarkdownThe Sapporta CLI is a client for a running application. It discovers tables and documented endpoints, performs generated row operations, calls application routes, and exposes ability-gated SQL for exceptional administration. SQL bypasses generated row helpers even when the caller is allowed to use it.
Verify the installed command
Section titled “Verify the installed command”Use the project-local binary so the commands match the installed framework version:
pnpm exec sapporta --versionpnpm exec sapporta --helppnpm exec sapporta rows list --helppnpm exec sapporta rows count --helppnpm exec sapporta api post --helpVerify nested help before automating a command. The current CLI groups live API
work under endpoints, tables, rows, api, and sql; subcommand options
remain the authoritative grammar for the installed version.
Target the running app
Section titled “Target the running app”Run from inside a project and API-backed commands need no URL: the CLI reads
SAPPORTA_API_PORT from the project’s .env.development and targets that port
on localhost. Outside a project it falls back to http://localhost:3000. Set an
explicit URL when the target is not unquestionably the intended application. A
protected app also needs a bearer token.
export SAPPORTA_API_URL="https://app.example.com"read -s SAPPORTA_API_TOKENexport SAPPORTA_API_TOKEN
pnpm exec sapporta endpoints list--api-url, --api-token, and --output override SAPPORTA_API_URL,
SAPPORTA_API_TOKEN, and SAPPORTA_OUTPUT_FORMAT. Prefer an environment
variable or secret injection to --api-token, which can expose the credential
in process arguments or logs.
Discover, change, and confirm
Section titled “Discover, change, and confirm”The following commands use an illustrative books table. Replace the table,
columns, and ID with values discovered from the target application.
pnpm exec sapporta tables listpnpm exec sapporta tables show bookspnpm exec sapporta endpoints show "GET /api/tables/books"pnpm exec sapporta --output json rows list books \ --q "Relativity" \ --limit 10Resolve the intended row from that visible result. Do not copy an ID from
documentation or guess a foreign key. Once exactly one row is identified, set
BOOK_ID to that returned value. The shell guard and exact read below confirm
the target before the ordinary field update:
: "${BOOK_ID:?Set BOOK_ID from the single inspected row}"pnpm exec sapporta --output json rows get books "$BOOK_ID"pnpm exec sapporta rows update books "$BOOK_ID" \ --values '{"author":"Albert Einstein"}'pnpm exec sapporta --output json rows get books "$BOOK_ID"Payloads contain fields accepted by the owning operation. Omit server-managed workspace, ownership, role, audit, and row-scope fields rather than trying to change authority from the client.
Use api only after discovery when a named application operation or report owns
the task. For example, if the live inventory contains an operation such as
POST /api/books/{id}/publish, inspect its exact body and responses before
calling its mounted path:
pnpm exec sapporta endpoints show "POST /api/books/{id}/publish"pnpm exec sapporta --output json \ api post "/api/books/$BOOK_ID/publish" --body '{}'That route is illustrative, not generated by Sapporta. Use only an application
operation returned by endpoints list, then confirm its intended consequence
with a harmless read.
Count visible rows
Section titled “Count visible rows”Use rows count when a read-only question is a filtered total over one table:
pnpm exec sapporta --output json rows count tasks \ --where '{"status":{"neq":"completed"}}'The JSON result is explicit about whether it is scalar:
{ "data": { "kind": "total", "count": 8 } }Add --group-by, --order, and --limit for bounded grouped results:
pnpm exec sapporta --output json rows count tasks \ --where '{"status":{"neq":"completed"}}' \ --group-by project_id \ --order desc \ --limit 10The count uses the caller’s read ability and row visibility. It does not
define what a business word such as “pending” means; map that word to a declared
value or use the report that already owns the definition. Grouped foreign keys
remain keys, and their labels come from a separate lookup with its own
authorization boundary.
Use structured output and error codes
Section titled “Use structured output and error codes”Table output is convenient for interactive inspection. Non-TTY output defaults
to JSON, but explicit --output json makes automation deterministic. Successful
commands return the server’s structured result when one exists. CLI failures in
JSON mode use this envelope:
{ "ok": false, "error": "...", "code": "stable_owner_code" }Branch on code, not error prose. Direct HTTP clients can also branch on the
owning status/code pair.
| Failure owner | Example code | Response |
|---|---|---|
| CLI target or network | APP_SERVER_UNREACHABLE | Check the URL, running server, and network permission |
| Shared application authentication | unauthenticated, token_expired, or token_revoked | Stop and repair the caller authority |
| Generated table operation | ROW_NOT_FOUND or a query-validation code | Correct the visible ID, query, or payload |
| Application endpoint | Code declared by that feature contract | Follow only the recovery branch owned by that operation |
A harmless rows list ... --limit 1 is suitable for checking a credential. Do
not test authority with a mutation. Also do not retry a mutation after an
ambiguous transport failure until a read shows whether it took effect.
Malformed local input is a safe way to verify the failure envelope without contacting an application:
pnpm exec sapporta --output json rows list books --where '{'{ "ok": false, "error": "Invalid JSON for --where", "code": "INVALID_JSON" }The CLI operates the same mounted application surface as the browser. Its value is a repeatable read-back loop and machine-readable output, not a second data model.
Migration commands are project package scripts rather than running-app CLI operations. Use the schema changes and migrations guide instead of inferring migration readiness from a data command.