Skip to main content
Pre-release

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 (0.3.0rc3) · Published: 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. The current release candidate is 0.3.0rc3; if your deployment is on a different one, swap it in.

pip install 'qualia-cli==0.3.0rc3'

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.0rc3'

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
qualia job get <job-id>
# A failed job also prints who caused it (your side or ours), what, why, and its credits

# 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

# 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

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.

Metadata

Release files for qualia-cli 0.3.0rc3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for qualia-cli 0.3.0rc3
File Size Uploaded Provenance
qualia_cli-0.3.0rc3.tar.gz 115.1 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for qualia-cli 0.3.0rc3
File Interpreter ABI Platform
qualia_cli-0.3.0rc3-py3-none-any.whl Python 3 none any Details

Total release size: 155.0 kB

Release files / qualia_cli-0.3.0rc3.tar.gz

Download URL qualia_cli-0.3.0rc3.tar.gz
Size 115.1 kB
Tags Source
SHA-256 checksum
How to use checksums
7d3f9d28b3f484bb6440a9b8aea70584e6decd7738ef0492c852f9b27f281bc9
BLAKE2b-256 checksum
How to use checksums
20b91a3cea633a0186a1fc7f7bc6adc2f2f49a0b183d658c2a32f129f8fbf4fe
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.0rc3-py3-none-any.whl

Download URL qualia_cli-0.3.0rc3-py3-none-any.whl
Size 39.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
259fe74dcf9369b7cb88ae332b9f06b19a6dcdbf428ce1277f2d7b3c66b9b4b4
BLAKE2b-256 checksum
How to use checksums
1dddb52bbcf457caa0ce73b6498eb4ab361c72594b6cc0d070d82d3f96215d01
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.0rc3

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.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page