Skip to content

Overview

The official command-line interface for the Qualia robotics data and VLA platform. Built on the Python SDK.

Terminal window
pip install 'qualia-cli==0.3.0rc11'
# or with uv
uv tool install 'qualia-cli==0.3.0rc11' --with 'qualia-sdk==0.8.0rc11'

This deployment runs ahead of the public release, so it needs the matching pre-release wheel — 0.3.0rc11. Pin it rather than upgrading: the upload protocol is negotiated exactly, so the client and the endpoint it talks to have to be the same generation. A plain pip install qualia-cli resolves to the current public release and will be turned away by this deployment.

You need an API key and the API origin of the environment your account is on. The key names its own account, so no command needs your account id.

In the Qualia dashboard, open Settings, then Account › API keys. Click New key, then Create key, and copy the key from the API key created dialog. The name starts as the day (Key 4 Nov 2026); type over it to name the machine or pipeline instead. The key is shown once. If you lose it, revoke it and make a new one. The page lists your keys in every organization you belong to.

A key acts as you, in the whole organization (every workspace you can reach) unless you open More options and pick one workspace. It carries every scope except the admin scopes below, including the data:read and data:write that uploads and curation need. It acts with your role in each workspace it reaches, so where you are a Viewer it can only read. Keys expire after 90 days by default.

Three scopes let a key do admin work. None is on by default: open More options and tick it under Admin (opt-in) when you make the key. A key with * does not get them, and no wildcard such as members:* exists; a key holds one only by its exact name. Each still acts within your role, so a Contributor’s key with members:write cannot change roles. A guest’s key cannot use them.

ScopeLets the key
members:readSee people, roles and invitations
members:writeInvite people, change their roles, remove them
integrations:writeList, add and remove integration keys; never reads a key back

members:read is for qualia member list and show and qualia invitation list. members:write is for qualia member role and remove, and qualia invitation send and withdraw.

No key can make another key.

Terminal window
qualia auth login --base-url https://dev-api.qualiastudios.dev

The CLI prompts for the key and hides what you type. You can also pass it with --api-key <YOUR_KEY>. --base-url is the API origin of your environment, with no path. Production is https://api.qualiastudios.dev, which is also the default when you leave the flag out. Dev is https://dev-api.qualiastudios.dev.

qualia auth login writes the key, the base URL and the account to a config file that only you can read:

  • Linux: ~/.config/qualia/config.toml
  • macOS: ~/Library/Application Support/qualia/config.toml
  • Windows: %APPDATA%\qualia\config.toml

Each login replaces the key, base URL and account in that file: a login without --account clears a stored account. Check what is stored with:

Terminal window
qualia auth status
API key: configured
Base URL: https://dev-api.qualiastudios.dev
Account: the API key's own
Scope: Whole organization

It never prints the key. Account: the API key's own means no account is stored, which is the normal case. Scope is the key’s reach, asked of the server: Whole organization (every workspace you can reach), Workspace <name> (one workspace only) or Restricted (a custom list). When the server cannot be reached it prints Scope: unknown and the reason.

A new user has a personal account: an organization of one, with one workspace. Your datasets, tasks, robots and checks live under that account, at accounts/{account}/…. An organization you create or join later is a different account, with its own id.

An API key belongs to exactly one account, so no command asks for it. The CLI and SDK name it accounts/- in every call, and the API reads - as the key’s own account. Nothing is looked up first, and nothing is stored.

Workspace lists (qualia status list, qualia activity list) need no --workspace either: they ask the server once what the key reaches (GET /v1/whoami). An organization-wide key lists the whole organization; a workspace key lists its own workspace.

--account, QUALIA_ACCOUNT and qualia auth login --account still exist as an explicit override. A key acts only in its own account, so they are never needed with a key.

Where a command takes an id, a full name such as accounts/<ACCOUNT_UUID>/datasets/<DATASET_UUID> also works: it carries its account.

Finding your account id. Ask the server who your key is (over the API, GET /v1/whoami answers the same, for any valid key):

Terminal window
qualia auth whoami
Account: Acme Robotics (0b6c6f3e-1f43-4c55-9a3e-1d0c3f5a2b7e)
Workspace: Arms (5b1e0f6a-7c2d-4e8f-9a1b-2c3d4e5f6a7b)
Key: laptop (qla_1a2b3c4d…), scope: Whole organization
Expires: 2027-01-01T00:00:00+00:00

The workspace is the one the key acts in: the key’s own, or the one --workspace names. --json prints the server’s whole answer. A revoked or expired key exits 1 with the server’s message. The id is a lowercase UUID; the CLI refuses any other form.

Without a key at hand: in an empty workspace, the dashboard’s getting started steps fill it into the login command. The dashboard also keeps the account you work in as the q-account cookie. While signed in, open your browser’s developer tools, go to Application (Chrome, Edge) or Storage (Firefox, Safari), then Cookies, and copy the value of q-account.

Pass the key on the command line, or set it in the environment:

Terminal window
qualia --token <API_KEY> credit
export QUALIA_API_KEY="your-api-key"
export QUALIA_BASE_URL="https://dev-api.qualiastudios.dev"

When QUALIA_API_KEY is set, the CLI ignores the config file, including its base URL and account. Set QUALIA_BASE_URL next to it, or the CLI talks to production. The account is the key’s own.

Terminal window
# Log in and check what is stored
qualia auth login --base-url https://dev-api.qualiastudios.dev
qualia auth status
# Save a version (tag 1.0); it prints the DatasetVersion id.
qualia dataset pin <DATASET_UUID> 1.0
# Use the dataset slug (or UUID) and tag; the command prints the resolved id
# Inspect the exact camera descriptors training will use
qualia dataset training-features my-dataset:1.0
# Download that version (--format lerobot_v3 | lerobot_v2_1 | mcap_ros2), or with
# --format original (no version) every file uploaded to the dataset, byte for byte
qualia dataset download my-dataset:1.0 ./my-dataset-1.0 --format lerobot_v3

All commands that display data support a --json flag for machine-readable output:

Terminal window
qualia credit --json
qualia dataset training-features my-dataset:1.0 --json

Without --json, output is displayed as formatted tables using Rich.

FlagEnv varConfig file keyWhat it sets
--tokenQUALIA_API_KEYapi_keyAPI key
--base-urlQUALIA_BASE_URLbase_urlAPI origin (default https://api.qualiastudios.dev)
--accountQUALIA_ACCOUNTaccountOptional account UUID; default the API key’s own
--workspaceQUALIA_WORKSPACE—Workspace UUID to act in, instead of the key’s workspace

These are global options: they go before the command, as in qualia --workspace <WORKSPACE_UUID> status list. qualia auth login writes the config file keys. The workspace is never stored.

Priority: flag > environment variable > config file. The config file’s base_url and account are read only together with its api_key: once QUALIA_API_KEY is set, nothing comes from the file.

  • Python 3.10+
  • qualia-sdk 0.8.0rc11 (installed automatically)