Install
A single self-contained binary. The machine needs nothing installed first — no runtime, no package manager. That is what makes it usable in a lean CI image.
curl -fsSL https://api.datarunner.app/downloads/cli/install.sh | bashirm https://api.datarunner.app/downloads/cli/install.ps1 | iexNeither asks for root or administrator: it installs into a user directory and adjusts that user PATH. The installer verifies the published SHA256 before installing and refuses on a mismatch.
Pin the version in CI. A pipeline that resolves “latest” on every run is a pipeline whose behaviour changes without anybody making a commit.
curl -fsSL https://api.datarunner.app/downloads/cli/install.sh | bash -s -- --version 0.1.1The first five minutes
After installing, this is a whole session end to end. The step that usually goes missing is the second one: a query has an id, and listing is the only place it comes from.
- 01Log in, once per machine. The key comes from Settings → API keys in the console, and is only shown at the moment you create it.
- 02List what exists in the workspace. This is where the id the other commands want comes from.
- 03Run a query and look at the result.
- 04Turn that query into a check the build understands.
datarunner auth login --url https://api.datarunner.app --key dr_...
Conectado como you@acme.com (admin) em https://api.datarunner.app.
Perfil 'default' salvo em ~/.datarunner/config.json.datarunner query list
id nome conexao atualizada
──────────────────────────────────── ─────────────── ────────── ──────────────
3f2a91c4-8e17-4b2a-9f03-1d5c7e8a2b60 Monthly revenue Postgres 2026-09-01 14:22
a7c04e12-3b95-4d81-b6ef-92a10c4d7f38 Orphan orders Postgres 2026-08-28 09:10datarunner query run 3f2a91c4-8e17-4b2a-9f03-1d5c7e8a2b60
month total
────────── ─────────
2026-07 184320.50
2026-08 201455.00
2 linha(s) em 340ms.datarunner query assert a7c04e12-3b95-4d81-b6ef-92a10c4d7f38 --expect-empty
ok — 0 linha(s) em 120ms.That last command exits 0 when no row came back and 1 when one did. That, and only that, is what stops a pipeline when data integrity broke.
Credential
The key comes from Settings → API keys. Its scopes narrow what the tool reaches on top of the role of whoever created it: a restricted key stays restricted even when it belongs to an admin, and a key never grants platform-wide powers.
datarunner auth login --url https://api.datarunner.app --key dr_...export DATARUNNER_URL=https://api.datarunner.app
export DATARUNNER_KEY=dr_...To run queries in a pipeline, tick the run:queries scope. It already includes reading and cannot change anything. Listing queries and executing SQL against a production database are different powers, so read:queries alone does not run.
API keys are not available on the free plan, so neither is the command line.
A query as a build step
A query that lists orphaned rows is something anybody can write today and cannot enforce anywhere. With the command below it becomes a pipeline step: if a migration broke referential integrity, the build fails instead of production finding out later.
datarunner query assert 3f2a... --expect-empty| Check | Fails when |
|---|---|
| --expect-empty | any row came back |
| --expect-rows <n> | the count is not exactly that |
| --min-rows <n> | fewer than that came back |
| --max-rows <n> | more than that came back |
If the result hits the plan row cap, the check fails rather than passes. A truncated count is not a count, and an --expect-empty that passes because the cap hid the rows is worse than no check at all — somebody is relying on it.
Every command
| Command | What it does | Key scope |
|---|---|---|
| auth login | list | use | logout | stores and switches credentials | — |
| whoami | checks the current credential | — |
| query list | lists queries, with the id | read:queries |
| query run <id> | runs and prints | run:queries |
| query assert <id> | runs and checks; exits 1 on failure | run:queries |
| monitor list | status | monitor state | read:monitors |
| sync list | lists syncs | read:syncs |
| sync run <id> --wait | starts one and follows it | write:syncs |
| connection list | lists connections | read:connections |
Every command has its own help: datarunner help query, datarunner help sync, and so on. datarunner help ci prints a ready pipeline file.
run:queries already includes reading, so a CI key that only checks data needs nothing else. Listing queries and executing SQL against a production database are different powers — which is why read:queries alone does not run anything.
Working with more than one environment
The first thing anybody does with this is point it at staging and then at production. Profiles exist so that switch is not another login.
datarunner auth login --url https://api.acme.dev --key dr_... --profile dev
datarunner auth login --url https://api.acme.com --key dr_... --profile prod
datarunner auth use prod
datarunner query list --profile dev # without switching the current oneThe file lives at ~/.datarunner/config.json, mode 600 on Linux and macOS. Logout removes the profile from your machine; the key stays valid on the server until somebody revokes it in the console.
Output and exit codes
The default format is a table. Pass --json or --csv when a program will read the output — and only then does progress go to standard error, so it cannot dirty what you are capturing. Nothing is guessed: PowerShell reports output as redirected even at an ordinary prompt, so trying to detect it printed JSON at people who just wanted to look.
datarunner query run 3f2a... | jq '.rows[0]'
datarunner query run 3f2a... --format csv > revenue.csv| Code | Means |
|---|---|
| 0 | ok |
| 1 | a check you asked for failed — the tool worked |
| 2 | wrong usage |
| 3 | credential missing or refused |
| 4 | the server refused, or could not be reached |
The split between 1 and 4 is the point: a pipeline has to tell “the data is wrong” from “the tool is broken” without parsing prose.
Other commands
- datarunner monitor status --fail-on-down — hold a deploy while something is already down.
- datarunner sync run <id> --wait — start a sync and follow it to the end. Without --wait, “queued” is not “worked”.
- datarunner query list, connection list, whoami.