This release is a pre-release and may not be stable for production use.
qualia-cli — terminal client for the Qualia robotics data and VLA platform
Status: beta source candidate (0.3.0rc4) · Distribution: PyPI, qualia-cli
Wraps the public Qualia API: authenticate once, then manage projects, import datasets, launch
fine-tuning jobs and follow their progress from a shell. Every command takes --json, so the same
surface works interactively and in CI.
The CLI and the endpoint it talks to negotiate the upload protocol exactly, so a deployment running ahead of the public release needs the matching pre-release wheel. See Install below.
Install
pip install qualia-cli
Or with uv:
uv tool install qualia-cli
Pre-release builds
Pin the wheel that matches the endpoint's generation. This source candidate is
0.3.0rc4 and requires qualia-sdk>=0.8.0rc4 for workspace-bound saved upload
destinations. Use these commands after the candidates are published and your
deployment supports the merged-upload lifecycle; otherwise select the matching
published version.
pip install 'qualia-cli==0.3.0rc4'
uv does not resolve a pre-release through a dependency, even one that names it, so uv needs the flag as well as the pin:
uv tool install --prerelease=allow 'qualia-cli==0.3.0rc4'
Usage
# Authenticate (pick one)
qualia auth login # interactive, saves to config
export QUALIA_API_KEY="your-api-key" # env var
qualia --token <KEY> <command> # inline, for CI/scripts
# List available models
qualia model list
# List GPU instances
qualia instance list
# Create a project
qualia project create "My Robot"
# Start a fine-tuning job
qualia job launch \
--project-id <id> \
--vla-type pi05 \
--model-id lerobot/pi05_base \
--dataset-version-id <DATASET_VERSION_UUID> \
--hours 2.0 \
--camera-mappings '{"cam_1": "observation.images.top"}'
# Check job status (a pipeline with map nodes also shows each map's item
# progress and its map ID)
qualia job get <job-id>
# A failed job also prints who caused it (your side or ours), what, why, and its credits
# Page a map's items: one row per attempt, filtered by state if you like
qualia job items <job-id> <map-id> --status failed --limit 50 --offset 0
# Upload a recorded MCAP session; a session no bag can derive is refused
# before upload unless you pass --allow-underivable
qualia dataset upload ./session dk1-kitchen --source-format mcap_ros2
# exits 0 published/degraded, 1 nothing uploaded, 3 stored but no episode derived
# A teleop arm needs no config when its state is a JointState topic named
# joint_state(s) and its action is a JointTrajectory topic, or a JointState or
# MultiArray topic named cmd, command or action. In <session>/meta/ingest.toml,
# declare [actions] alone when a topic named like a command is operator input
# (a joystick), and both [state] and [actions] when a second JointState topic
# (a leader arm) would be read as state, or the rig publishes poses and has no
# JointState:
# schema = 1
# [state]
# topics = ["/controller/left/pose", "/controller/right/pose"]
# [actions]
# topics = [] # no action column
# Fields are carried as recorded, with no rotation conversion. [clock] takes
# row_clock_topic or fixed_hz, not both.
# Guide: https://docs.qualiastudios.dev/global/guides/data-collection
# A successful upload prints the topics that fed state and action, and says
# "action: none (no action column)" when there is none. --quiet still prints them.
# LeRobot trees are checked before upload too. A structural problem the server
# always refuses (bad meta/info.json, codebase_version not matching
# --source-format, no parquet under data/, v2.1 without episodes.jsonl or
# tasks.jsonl) exits 1 with nothing uploaded; --allow-underivable cannot
# override it. A missing video only warns, naming the episode and camera; the
# upload continues and that episode will be flagged (you should probably
# exclude it).
qualia dataset upload ./my-recording my-dataset --source-format lerobot_v3
# Save a default merged-dataset destination for uploads in this local config.
# It is bound to this API host, account, and workspace; changing it affects
# future upload intents, not uploads already in flight.
qualia dataset destination set accounts/<account-uuid>/datasets/<merged-uuid>
qualia dataset destination show
qualia dataset destination clear
# Override that default for one upload, or keep one upload standalone.
qualia dataset upload ./week-2 week-2 --source-format lerobot_v3 \
--merge-target accounts/<account-uuid>/datasets/<merged-uuid>
qualia dataset upload ./calibration calibration --source-format lerobot_v3 --standalone
# Workspace selection is the gateway's X-Qualia-Workspace context. An explicit
# selection overrides the workspace bound to the saved destination; a mismatch
# leaves this upload standalone instead of sending it into another workspace.
qualia --workspace <project-uuid> dataset upload ./week-3 week-3 \
--source-format lerobot_v3
export QUALIA_WORKSPACE=<project-uuid> # alternatively, select it for this shell
# If append needs action, the upload remains published and the command prints
# its dataset ID and reason. A retry after an explicit revert keeps that intent
# reverted; it never silently appends again.
# List your uploads; Verdict is published | degraded | underivable. With your account set
# (see Tasks below) it reads qualia.v1 and --json prints qualia.v1 Datasets (reason:
# verdict_reason); without one it reads the older route (reason: qds.verdict_reason).
qualia dataset list
# Filter the account-scoped list by any canonical method tag.
qualia dataset list --method umi --method teleop
# Replace the canonical method-tag set on an upload or merged dataset. A
# merged dataset writes the same set to every upload it holds; --clear records
# an explicit Unknown rather than leaving tags unset.
qualia dataset methods <dataset-uuid> --method umi --method teleop
qualia dataset methods <dataset-uuid> --clear
# Cut episodes into child episodes at their markers, or, where the recorder
# marked nothing, at instants (seconds from the start of the recording, the
# same instants in each named episode). --dry-run plans without writing;
# `qualia dataset unsplit` undoes it. A request cuts at markers or at
# instants, not both.
qualia dataset split <episode> -d <dataset> --cut-at success --dry-run
qualia dataset split <episode> -d <dataset> --at 12.5 --at 31 --dry-run
# Import an exact Hugging Face dataset commit. HF_TOKEN is read from the
# environment or the Hub's protected local credential store, never an argv flag.
export HF_TOKEN="..." # omit for public datasets
qualia dataset import-hf \
qualia-robotics/openarm-cube-in-box-v1 \
17c29c487d886878ddcb3c5649101b2860fbc047 \
openarm-cube-in-box \
--source-format lerobot_v3
Tasks
Tasks say what a robot should do and how success shows, as five pieces of
prose: description, scene, steps (one per line), success and failure. They live
under your account: pass --account <UUID>, set QUALIA_ACCOUNT, or save it
with qualia auth login --account <UUID>.
qualia task create --name "Restock shelf" -d "Move every box from the tray to the shelf"
qualia task edit <task-id> --steps $'Pick a box from the tray\nPlace it upright on the shelf' \
--success "The tray is empty and every box stands upright"
# just those fields; "" clears one
# Or author the five fields as a file, as `qualia task get <id> --json` prints
# a task (displayName, etag, draft) or as a bare spec:
cat > shelf.yaml <<'EOF'
description: Move every box from the tray to the shelf
scene: A tray of six boxes beside a two-level wire shelf
steps: |
Pick a box from the tray
Place it upright on the shelf
success: The tray is empty and every box stands upright
failure: A box falls over or drops to the floor
EOF
qualia task edit <task-id> shelf.yaml # replaces the whole draft
# A spec file may also hold an optional procedure: the task as a state machine of
# steps and transitions, checked when the task is published.
cat >> shelf.yaml <<'EOF'
procedure:
steps:
- {id: start, kind: START, description: Boxes in the tray}
- {id: place, description: Place a box upright on the shelf, min_count: 6, max_count: 6}
- {id: shelved, kind: SUCCESS, description: All boxes shelved}
- {id: fallen, kind: FAILURE, description: A box fell over}
transitions:
- {source: start, target: place}
- {source: place, target: shelved}
- {source: place, target: fallen}
EOF
qualia task edit <task-id> shelf.yaml
qualia task get <task-id> # each field under its heading, then the procedure
qualia task publish <task-id> -m "first cut" # needs a description and a success
qualia task revisions <task-id>
qualia task get <task-id> --revision 1
qualia task list
qualia task delete <task-id> [--force] # account owners only
Link recorded data to the task it was recorded against (CLI 0.3.0rc3). The label stays the text training reads; a link changes no revision or version, and deleting the task unlinks.
qualia dataset link-task <upload-id> <task-id> # --unlink removes it
qualia dataset assign-task -d <upload-id> --task <task-id> --filter 'state = KEPT'
# links and labels them with the task's name
qualia dataset assign-task <episode-id>... -d <upload-id> --label "restock shelf"
# a label alone leaves links as they are
Checks
Run a check over a dataset and read its findings. The VLM check reads each
episode against its linked, published task; estimate says what a run would
reserve without starting or charging anything.
qualia check estimate <dataset> # credits, episodes, the model and those offered
qualia check run <dataset> --model <model> --wait # --check episode-rules|mixture|reach; - for defaults
qualia check status <run-name> # QUEUED, RUNNING, SUCCEEDED or FAILED, with counts
qualia check runs --check vlm -d <dataset> --state FAILED
qualia check findings <dataset> # issues and notes, with verdict, confidence and moments
JSON output
All commands support --json for machine-readable output:
qualia project list --json
qualia credit --json
API
The CLI is a client for the public Qualia API. Request and response shapes for every command are in the API reference: https://docs.qualiastudios.dev
Working in the repo instead? sdk/cli/qualia-cli.spec.md carries the same contract, and the
gateway generates the OpenAPI spec it is drawn from. Neither ships in the wheel.
License
MIT, Qualia Studios.
A saved merge destination is used only with a known matching account, normalized
API host and workspace. An environment API key alone does not confirm the saved
account; supply the matching account configuration explicitly. Explicit
--merge-target and --standalone retain their per-call meaning.
Metadata
Release files for qualia-cli 0.3.0rc4
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| qualia_cli-0.3.0rc4.tar.gz | 123.5 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| qualia_cli-0.3.0rc4-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 170.4 kB
Release files / qualia_cli-0.3.0rc4.tar.gz
| Download URL | qualia_cli-0.3.0rc4.tar.gz |
|---|---|
| Size | 123.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
6d2cf6cf07f543b4d695d1cbfb93718b92db7b2eb4964ceaf6bbf3592cbcad5e
|
|
BLAKE2b-256 checksum How to use checksums |
e4fad124f2f9d87eb7e924fc680f3aadac1f8f1f3fa0d468fb62774d2b6a6d12
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.9.17 {"installer":{"name":"uv","version":"0.9.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Alpine Linux","version":"3.23.0","id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / qualia_cli-0.3.0rc4-py3-none-any.whl
| Download URL | qualia_cli-0.3.0rc4-py3-none-any.whl |
|---|---|
| Size | 46.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
8dcd09768d4f358625bb84e6d05f1d2cec143d28bc3bfac06aee5c5cf0e4bc6b
|
|
BLAKE2b-256 checksum How to use checksums |
14f545a82a2311a258d193f6f50b6d58579242b4d8294dc355123c0f8f99c776
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.9.17 {"installer":{"name":"uv","version":"0.9.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Alpine Linux","version":"3.23.0","id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Security for qualia-cli 0.3.0rc4
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.