CLI
Install and use the definite CLI to operate and exercise an on-prem deployment.
The definite CLI is a single static binary with two layers:
- Admin / cluster ops —
init,upgrade,status,doctor,logs,bootstrap,export-helm. Talks tokubectlandhelmagainst your cluster. These are covered in Agent setup and the per-cloud guides (AWS, GCP, Azure). - API client —
definite run …. Talks to the deployed API over HTTPS using a bearer token. This page is mostly about that layer: querying the lakehouse, loading files, kicking off Fi, managing data apps, and so on.
Installation
The CLI ships as a single static binary. The fastest install is the public installer script — it detects your OS + arch, downloads the matching release, verifies its SHA256, and drops the binary into ~/.local/bin/definite.
curl -fsSL https://storage.googleapis.com/definite-public/definite-onprem/install.sh | sh
definite version
Supports macOS (Intel + Apple Silicon) and Linux (x86_64 + arm64). Override the defaults with env vars:
# Pin a specific version
DEFINITE_VERSION=v0.0.18 curl -fsSL .../install.sh | sh
# Install somewhere other than ~/.local/bin
DEFINITE_BIN_DIR=/usr/local/bin curl -fsSL .../install.sh | sudo sh
Run via Docker (Windows, CI, air-gapped)
If you'd rather not install natively — Windows hosts, ephemeral CI runners, or an environment where you don't want a ~/.local/bin mutation — the same binary is available as a public container image. The tag matches your deployment's API version.
docker run --rm \
-e DEFINITE_API_URL -e DEFINITE_TOKEN \
us-central1-docker.pkg.dev/definite-quack-spike/definite-onprem/cli:0.0.18 \
run query "SELECT 1"
To make it feel like a local install, alias it and mount ~/.definite so definite login (below) persists across runs:
alias definite='docker run --rm -i \
-v ~/.definite:/root/.definite \
-e DEFINITE_API_URL -e DEFINITE_TOKEN \
us-central1-docker.pkg.dev/definite-quack-spike/definite-onprem/cli:0.0.18'
Pin to your deployment's exact tag
To track whatever version the cluster is currently on:
TAG=$(helm get values definite -n definite | awk '/^ tag:/ {print $2; exit}')
DEFINITE_VERSION=v$TAG curl -fsSL \
https://storage.googleapis.com/definite-public/definite-onprem/install.sh | sh
Authenticate
The API client uses bearer-token auth. Sessions are opaque ~43-character tokens with a ~14-day TTL.
The recommended flow is definite login, which prompts for credentials and writes the session token to ~/.definite/credentials.json (mode 0600). Every subsequent definite run … call picks it up automatically — no flags or env vars needed.
definite login https://your-deployment.example.com
# Email: you@example.com
# Password: ********
# ✓ logged in as you@example.com — credentials saved to ~/.definite/credentials.json
A bare hostname is assumed to be https://; pass an explicit http://… for a TLS-disabled deployment. Other useful forms:
# Non-interactive (CI, scripts) — read the password from stdin
echo "$DEFINITE_PASSWORD" | definite login your-deployment.example.com \
--email you@example.com --password-stdin
Verify you're logged in:
definite run query "SELECT 1"
Without definite login (env-var fallback)
When you can't (or don't want to) write a credentials file — ephemeral containers, sandboxes, one-off scripts — definite run also honors DEFINITE_API_URL + DEFINITE_TOKEN. Mint a token by calling /api/v1/auth/login directly:
curl -sS -X POST "https://your-deployment.example.com/api/v1/auth/login" \
-H "Content-Type: application/json" \
-d '{"email": "you@example.com", "password": "..."}'
The response looks like:
{
"token": "eyJhbGciOi...",
"expires_at": "2026-06-10T18:42:11Z"
}
export DEFINITE_API_URL=https://your-deployment.example.com
export DEFINITE_TOKEN=<paste token>
Explicit --api-url / --token flags on a definite run invocation override both env vars and the stored credentials file.
curl -sS -H "Authorization: Bearer $DEFINITE_TOKEN" \
"$DEFINITE_API_URL/api/v1/auth/me"
A 200 with your user record means the token is good. A 401 means it expired or never validated — log in (or mint) again.
Commands
Every definite run subcommand respects DEFINITE_API_URL and DEFINITE_TOKEN. For an exhaustive list of flags, run:
definite run <subcommand> --help
run query
Execute SQL against the lakehouse.
# Inline SQL
definite run query "SELECT 1 AS one, 'hello' AS greeting"
# From a file
definite run query -f path/to/q.sql
# JSON output for jq
definite run query --format json "SELECT now()" | jq
--format defaults to table on a TTY and json when stdout is piped. csv is also valid.
run load
Upload a local file. Two modes:
# Mode 1: just upload to Drive (object storage)
definite run load ./mydata.csv
# Mode 2: upload AND register as a lakehouse table
definite run load ./sales.csv --table analytics.sales --mode replace
definite run load ./more.parquet --table analytics.sales --mode append
When --table is set, --mode is required: either replace (drop and recreate) or append (insert into the existing table). Format auto-detects from the extension (.csv, .parquet, .json, .ndjson, .jsonl) and is overridable with --file-format.
run drive get
Fetch a file back from Drive. Accepts either a full gs://…/drive/<id>/<name> URL or just the bare file id.
definite run drive get gs://your-bucket/drive/abc123/sales.csv
definite run drive get abc123
run app
Manage data apps.
definite run app list
definite run app upload <slug> ./index.html ./app.json
definite run app delete <slug>
definite run app scaffold
run fi
Kick off the Fi agent in a new or existing thread.
# Start a new thread
definite run fi "summarize the orders table" --title "ad-hoc"
# Continue an existing thread
definite run fi "follow-up question" --thread-id <id>
run automation
Trigger a manual run of an automation pipeline by id.
definite run automation run <pipeline-id>
run integration
List, inspect, and test saved integrations. Secrets are never echoed back — inspect shows config shape only.
definite run integration list
definite run integration inspect <id>
definite run integration test <id>
run agent
Manage autonomous agents (long-running, scheduled, or event-driven Fi runners).
definite run agent list
definite run agent show <id>
run script
Manage reusable Python automation scripts.
definite run script list
definite run script run <id>
run maintenance
Run DuckLake table maintenance (compaction, vacuum, expire-snapshots).
definite run maintenance compact <schema>.<table>
definite run maintenance vacuum <schema>.<table>
run event-source
Manage browser-safe event ingest sources.
definite run event-source list
definite run event-source show <id>
run permission
Manage app roles, sharing, and data-access roles.
definite run permission list
definite run permission grant <role> <subject>
Output formats and scripting
Most subcommands take --format table|json|csv. The default depends on context:
- On a TTY (interactive shell):
table. - Piped or redirected stdout (CI, scripts, agent sandboxes):
json.
That flip means you can pipe straight into jq without specifying --format json every time:
definite run query "SELECT id, total FROM orders LIMIT 5" | jq '.[].total'
Troubleshooting
invalid or expired token from /auth/me
Tokens expire after ~14 days. Run definite login <host> again — the new token overwrites the stored one. If you're on the env-var fallback, re-mint and re-export DEFINITE_TOKEN.
cargo warnings about ~/.cargo/registry/index/.../.cache permissions
Harmless. Only relevant if you ever build the CLI from source on a machine with a partially-shared ~/.cargo. The shipped binary doesn't touch ~/.cargo at runtime.
Connection refused / DNS failure
Sanity-check $DEFINITE_API_URL resolves and is reachable from where you're running the CLI. If your deployment is on private DNS, run the CLI from inside the VPC (a bastion, or a one-off kubectl run pod).
Next
- Agent setup — let Claude Code, Cursor, or Windsurf drive a fresh install using the admin side of the CLI.
- AWS install guide — provision with Terraform, install with
definite init.