Skip to content

CLI

The onebooks CLI wraps the developer console API for the workflows that benefit most from scripting: authenticating, finding your app’s internal id, scaffolding the starter app, and deploying and testing hosted functions. Listing management, extensions, app data fields and sandbox installs are console-only today — see Publishing your app, UI extensions, App data and Sandbox.

Requires Node 20 or later. onebooks --version prints the version; onebooks help lists the commands.

Terminal window
onebooks login [--api <url>] [--email <email>]

Prompts for your developer console email and password (the password is masked), then saves a session token to ~/.config/onebooks/config.json (mode 0600) — separate from any OneBooks business login. --api <url> points at a non-default API base (the default is the last one you used, or https://api.getonebooks.com); --email <email> skips the email prompt. Round it out with:

Terminal window
onebooks whoami [--json]
onebooks logout

logout clears the session token but keeps the API base. Set ONEBOOKS_CONFIG_DIR to keep the config somewhere else — useful for two isolated sessions or for CI.

Every functions command needs your app’s internal id — not its public client_id — because it calls the same /developer/apps/:id/* routes the console does:

Terminal window
onebooks apps list [--org <slug-or-id>] [--json]

Lists every app across every organization you belong to (or one org with --org), printing its org, id, clientId, name, active flag and review status. Use the id column — not clientId — as --app below.

Terminal window
onebooks functions list --app <appId> [--json]
onebooks functions deploy --app <appId> --name <fn> --file <path> \
[--events invoice.paid,payment.received] \
[--egress hooks.example.com] \
[--description "Posts paid invoices to Slack"] \
[--activate] \
[--notes "fix retry bug"] \
[--json]
onebooks functions logs --app <appId> --name <fn> \
[--status QUEUED|RUNNING|SUCCEEDED|FAILED|SKIPPED] [--cursor <runId>] [--json]
onebooks functions test --app <appId> --name <fn> \
--business <sandboxBusinessId> --event invoice.paid \
[--data '{"id":"…"}'] [--json]

deploy is the one command that does real work end to end:

  1. If no function named --name exists yet on this app, it’s created first. --events (comma-separated) is required then — a function needs at least one event, and the CLI stops with a usage error before uploading anything if you leave it out. --egress (comma-separated hostnames, which the CLI lowercases and de-duplicates) and --description are optional. All three apply only when creating: for a function that already exists they’re ignored, with a note saying so — change them on the app’s Functions tab in the console.
  2. --file is uploaded as a new version, with --notes attached if given. A source file over 1 MB fails locally before any request is made; the upload must be a single ES module that exports its handler — CommonJS (module.exports) is rejected with FUNCTION_SOURCE_NO_HANDLER. That check only reads the source text, so once the version is active, confirm it loads with test.
  3. With --activate, that version goes live immediately; without it, the upload sits as an inactive version until you activate it in the console.

The name must be 2–40 characters of lowercase letters, numbers and hyphens, starting with a letter.

Lists a function’s runs, newest first, 20 at a time — each with its status, trigger (EVENT or TEST), event, business, attempts, timings, error and captured log lines (--json is easier to read for those). --status filters to one status. When more runs exist, the output ends with the --cursor <runId> to pass for the next page.

Runs the function’s active version once for real, through the same executor and limits a production run uses, against --business — one of your organization’s sandbox businesses, with the app installed. It sends the event catalog’s sample payload for --event, or your own JSON with --data. A test executes exactly once and is never retried, so the result is that attempt’s outcome; if it doesn’t finish, the run is marked FAILED rather than run again. See Hosted functions.

Terminal window
onebooks init my-onebooks-app [--template embedded-node]

Copies the embedded-node starter app into my-onebooks-app/ (the directory is created if missing, and must be empty if it already exists). --template defaults to embedded-node, the only template shipped today. init also points the new app’s @onebooks/node dependency at the SDK version that matches your CLI — it prints which — and sets up its .gitignore. After scaffolding:

Terminal window
cd my-onebooks-app
cp .env.example .env # fill in your app credentials
npm install
node server.mjs

See Starter template for what’s inside, and the quickstart for the console setup it needs.

whoami and every functions command accept --json for the raw API response, and apps list --json prints the same rows as its table, as JSON; without --json, output is a table (for lists) or key: value lines. login, logout and init have no --json. Every command exits 0 on success and 1 on failure; an error from the console API is printed as <message> (HTTP <status>).

Starter template — what onebooks init scaffolds.