cube) is a single-binary command-line interface for the Cube
platform. Use it to create and manage deployments, deploy data model code,
work with the data model Git workflow, connect GitHub repositories, tail
deployment logs, and automate workspace administration from scripts and CI.
The Cube CLI works with the Cube cloud platform. It is not required for
running Cube Core locally.
Installation
Linux / macOS:PATH. Set CUBE_VERSION to pin a release tag, or CUBE_INSTALL_DIR
to change the install location.
The CLI checks for new releases in the background and prints a notice when
one is available. Update in place at any time:
cube with no arguments prints the installed version above the help
text.
Authentication
Sign in with the browser device flow — the CLI prints a URL and a short code, opens your browser, and waits for approval:~/.config/cube/config.toml (Linux/macOS) or
%APPDATA%\cube\config.toml (Windows). Multiple accounts are supported as
named contexts (--name on login, --context on any command), and expired
access tokens refresh automatically.
For CI and scripts, use an API key instead:
Deploy a project
The core workflow — create a deployment, connect a database, upload your data model, and query it:1
Create a deployment
2
Connect a database
3
Deploy your project
cube deploy hashes local files, uploads only what changed, removes remote
files deleted locally (--keep-missing opts out), and triggers a single
build. Pass --branch to deploy to a specific data model branch instead of
the active dev-mode branch (or the deploy branch, if none is active).4
Watch the build and query
Import from GitHub
Connect a deployment to a GitHub repository instead of uploading files:Validate the data model
cube validate compiles a deployment’s data model and reports the compiler’s
errors, exiting non-zero when there are any — so it works as a CI gate:
--dev-mode, against your
uncommitted working copy, before you commit it.
--json for a machine-readable report (valid, errors[] with the file
each was reported against, cubesCount); the exit code is the same either way.
Command reference
Runcube <command> --help for the full options of any command.
List commands print tables by default; pass
--json anywhere for raw JSON
output, suitable for piping to jq.
Changing the Cube version
cube deployments versions lists the Cube versions a deployment can switch to
— the head of each update channel, plus the older
versions your account has run before:
update. Any of 1.7.20, v1.7.20 or cubejs/cube:v1.7.20 is
accepted; a version that is not on the list is rejected. The container image is
resolved from the version, so there is nothing else to set:
cube deployments settings DEPLOYMENT_ID reads back every setting, including
the version and channel currently in effect.
Discovering the API
cube spec prints the OpenAPI specification of the API you are logged into, so
neither you nor an AI agent has to guess an endpoint’s parameters. It reads
/api/v1/spec from the deployment itself, which means the contract you get is
the one that build actually serves.
With no arguments it lists every operation:
--json to get OpenAPI instead of a table. Unfiltered, that is the entire
document — pipe it into a code generator or a validator. Filtered, it is a
smaller but still valid document containing just the matching operations plus
every schema they reference, transitively:
$ref pointing into a document you would then have to fetch in full.
Data model Git workflow
Edit the data model through branches without touching production:commit pushes the dev branch’s edits to the shared branch it was forked from, and
merge-to-default merges that branch into the deploy branch, rebuilds production, and
deletes the branch it merged — pass --keep-branch to keep it.
That accounts for my-branch; exit-dev-mode and delete-branch account for what
you’d otherwise leave behind. Dev mode is per-credential state, so while a session stays open every
command that omits --branch targets that dev branch instead of the deploy branch, and
each pass through this workflow forks another dev-… branch. Releasing and pruning
before the merge also keeps the fork’s parent around until the fork is gone.
File writes (
put, delete, rename) only land on a personal dev-… branch,
which is what dev-mode forks and prints. Pass that name via --branch, or omit
--branch to use your active dev-mode branch. Writes to any other branch are
rejected by the API.create-branch --dev-mode is not a shortcut for this: it points your session at the
new branch without forking, so writes to the name you gave it are rejected with
“Branch … is not a dev-mode branch” even though build-status reports that branch
as dev_mode. Run dev-mode on it to get a name you can write to.enable-branch keeps a shared branch’s staging environment
always active, so it stays queryable without anyone viewing the branch in the
UI — useful for running tests against a branch from CI. disable-branch reverts
to the default, where the environment is only active while viewed.
cube data-model branches DEPLOYMENT_ID shows the current state per branch, and
cube environments list DEPLOYMENT_ID --type staging lists the enabled ones with
their API credentials.
dbt sync
Pull a dbt project’s models in as cubes. By default, Cube clones the repository configured on the deployment’s dbt integration and runs dbt to produce a manifest, so a Git-based sync needs only the deployment:--manifest parses the file as JSON and uploads it with the sync request. Cube
converts that exact artifact without cloning the dbt repository, using a repository
credential, provisioning a sandbox, or running dbt. This makes the sync faster and
also works when the deployment has no dbt Git integration. Any dbt command that
parses the project can produce target/manifest.json, including dbt parse, dbt compile, dbt run, and dbt build. Use --manifest - to read it from standard
input. Manifest upload requests must be no larger than 50 MiB; use the Git-based sync
path for larger projects.
After starting the sync, the CLI reads its history row to confirm the tenant honored
the manifest source instead of silently falling back to Git, so --manifest requires
both SchemaUpdate and SchemaRead access.
The server validates that the upload is a supported dbt manifest, rather than another
dbt artifact such as catalog.json or run_results.json. Saved conversion settings
are still applied when the deployment has them; otherwise their defaults are used.
Settings that require Cube to execute dbt, such as the model selector and catalog type
inference, apply only to Git-based syncs.
Each sync creates a new branch for the generated cubes and prints its name.
--wait polls until the sync finishes, reporting each stage, then prints the
generated files; it exits non-zero if the sync fails. Without --wait it returns
a syncJobId you can follow yourself:
--ref syncs a specific branch or tag of the dbt repository
instead of the one saved on the integration:
--ref takes a branch or tag, not a commit SHA, and can’t be combined with
--manifest: the uploaded manifest already identifies the exact dbt state to convert.
Git-based syncs provision a sandbox and parse the project, so prefer one per push over
one per commit. Manifest syncs skip those phases.Sync history and logs
history lists a deployment’s recent syncs — how each one was triggered, whether its
source was git or manifest, how it ended, and how long it took — and logs prints
one sync’s phase timeline, including the text a failed phase produced:
history narrows with --status (RUNNING, COMPLETED, FAILED, CANCELLED,
UNKNOWN) and --trigger (manual, api, webhook, agent, unknown) — both
case-sensitive as spelled here — and pages with --first/--after, taking the cursor
from pageInfo.endCursor in --json output. A page holds at most 100 runs, so a
larger --first returns 100 with pageInfo.hasNextPage set. logs takes no paging
flags — one sync’s timeline is one page, and each line carries the phase it belongs
to and how long that phase took.
Both need only SchemaRead. Durations are the server’s own single-clock figure, so
they never disagree with the run they describe. --json carries the rest of each
record — the dbt ref that was synced, the phase that failed, per-phase timings and
manifest counts. When the manifest provides them, stats.dbtVersion and
stats.manifestGeneratedAt identify the dbt version and when the artifact itself was
generated.
logs is what turns a red CI step into something self-explaining: a failed
--wait reports the reason, and the timeline says which phase produced it.
--wait --json still writes its document before exiting non-zero, which
is what leaves the syncJobId there to follow up on.
A cancelled sync is listed as
CANCELLED by history, but reported as a failure by
status and by sync --wait — a gate polling for a terminal answer needs one, and the
reason it prints says the sync was cancelled.dbt sync as a CI test gate
Parse the dbt project under review, upload that exact manifest, compile the generated Cube model, query it, and fail the job if any step breaks — without touching production or granting Cube access to the dbt repository:--wait --json, the sync returns the generated branch and terminal result in one
document. Uploading the artifact produced in the preceding dbt step ensures Cube
converts the same project state the job validated, even if the remote branch moves
while the job is running. The query must use the deployment’s deploymentUrl, and the
loop must retry Continue wait responses until data
arrives. Replace dbt_fct_orders.count with a measure generated by the sync.
Keep shell: bash on the piped step so a failed cube command cannot be hidden by a
successful jq process.
New dbt inputs such as dbt sync --ref reject an empty value, as do required branch
arguments such as data-model dev-mode and delete-branch. Existing optional flags keep
their previous behavior: deployments build-status --branch '' is still accepted for a
one-shot status request, but is rejected with the new --wait gate.
Other existing optional --branch flags may accept an empty value for compatibility;
omit them when you want the documented default.
The API key needs SchemaUpdate, SchemaRead, SchemaUpdateDevBranches, and
DeploymentRead for this deployment. See API keys and custom
roles.
A successful gate prunes both branches it creates: the sync branch and its personal
dev-… fork. Failed runs keep them for inspection. Add --remove-on-upstream to the
cleanup commands if the connected Git provider branch should also be deleted.Environment variables
Telemetry
The CLI sends anonymous usage events (command group, success/failure, version, platform). No personal data is collected; the anonymous identifier is a hash of the OS machine id. Telemetry is disabled automatically in CI, or explicitly withCUBE_NO_TELEMETRY=1 (or the legacy CUBEJS_TELEMETRY=false).