Commands
Global Options
Section titled “Global Options”These flags go before the command and work with any command that calls the API.
Each one overrides its environment variable, which overrides the config file
that qualia auth login writes.
| Option | Env var | Description |
|---|---|---|
--token | QUALIA_API_KEY | API key |
--base-url | QUALIA_BASE_URL | API origin, e.g. https://dev-api.qualiastudios.dev (default https://api.qualiastudios.dev) |
--account | QUALIA_ACCOUNT | Optional. Account UUID to act on; default is the API key’s own account (more) |
--workspace | QUALIA_WORKSPACE | Workspace UUID to act in instead of the API key’s own workspace; never stored in the config file; rarely needed |
qualia --token <API_KEY> creditqualia task list # the API key's own account; no --account neededqualia auth status shows the stored config and the environment variables, not
these flags.
qualia version
Section titled “qualia version”Show CLI and SDK versions.
qualia versionqualia auth
Section titled “qualia auth”qualia auth login
Section titled “qualia auth login”Save your API key, and optionally the API origin and an account, to the config
file. Prompts for the key when --api-key is left out, and hides what you type.
qualia auth login --base-url https://dev-api.qualiastudios.dev| Option | Description |
|---|---|
--api-key, --token | API key (prompted if omitted) |
--base-url | API origin, no path. Default https://api.qualiastudios.dev; dev is https://dev-api.qualiastudios.dev |
--account | Optional. Account UUID, lowercase; accounts/<uuid> also works. Default: the API key’s own account |
Each login replaces the stored key, base URL and account. Leave out --base-url
or --account and that value is no longer stored. Where the file lives and how
to find your account id: CLI overview.
qualia auth status
Section titled “qualia auth status”Show the stored login: whether a key is set (never the key), the base URL, and the account (the API key’s own unless one is stored).
qualia auth statusAPI key: configuredBase URL: https://dev-api.qualiastudios.devAccount: the API key's ownIt reads the config file and the QUALIA_* environment variables, not the
global flags. It exits 1 with Invalid authentication config: … when the
stored key or base URL is malformed. It does not call the API, so it does not
prove the key works.
qualia credit
Section titled “qualia credit”Show your current credit balance, and the split the billing page shows: starter credits, prepaid credits and each voucher, left of granted.
qualia creditqualia credit --jsonCredits: 1700 Starter: 80 of 100 Prepaid: 1,000 of 1,000 Voucher Launch: 620 of 1,000, expires 2026-12-31The split is for members of the organization. When the key’s creator is no
longer a member, only the total prints (null fields in --json).
qualia credit redeem
Section titled “qualia credit redeem”Redeem a credit voucher for your organization, as the billing page does. Any
member may redeem. The key needs the credits:write scope, and it must be an
organization key: credits are the organization’s, so a workspace key is
refused. Buying credits stays in the dashboard.
qualia credit redeem SPRING-2026qualia credit redeem SPRING-2026 --jsonVoucher redeemed: 1,500 credits added.--json prints {"credits_granted": 1500, "account_id": "…"}. An unknown,
used or expired code exits 1 with the reason the billing page shows, for
example Error: [400] Voucher code has already been redeemed.
qualia activity
Section titled “qualia activity”What people and their keys did: the dashboard’s Activity table. A workspace’s
activity is the one --workspace names, else the key’s own; --org reads the
whole organization’s, every workspace’s and its own. Reading needs data:read.
A key restricted to workspaces cannot read activity.
qualia activity list
Section titled “qualia activity list”List activity, newest first.
qualia activity listqualia activity list --org --filter 'verb = KEEP AND actor = API_KEY' --jsonqualia activity list --filter 'create_time >= "2026-10-01T00:00:00Z"' -n 100| Option | Description |
|---|---|
--org | The organization’s activity, not one workspace’s |
-f, --filter | AIP-160 comparisons joined by AND: verb, actor (PERSON, API_KEY, …), workspace, text, create_time, subject, action |
--raw | Every recorded event (action, summary), not only intentional actions |
-n, --limit | Page size; at most 100 for activity |
--cursor | The nextPageToken of the previous page |
--json | {"activity": [...], "nextPageToken": ...} ({"events": [...]} with --raw) |
The table names who acted where the record has a name, and prints each row’s
event id. --json prints full event names.
qualia activity show
Section titled “qualia activity show”Show one event as the record holds it. --details adds what it touched (its
episodes and their state before) and the fields it changed.
qualia activity show <EVENT_ID>qualia activity show accounts/<ACCOUNT>/workspaces/<WORKSPACE>/events/<EVENT_ID> --details --jsonAn id is read through the organization. A full name, which
qualia activity list --json prints, works too.
qualia activity export
Section titled “qualia activity export”Download the organization’s events record as JSON lines: one event per line, oldest first, every workspace’s and the organization’s own.
qualia activity export -o events.jsonlqualia activity export -o october.jsonl --start 2026-10-01T00:00:00Z --end 2026-11-01T00:00:00Z| Option | Description |
|---|---|
-o, --output | Where to write the file (required) |
--start | Events created at or after it (RFC 3339, with a timezone) |
--end | Events created before it |
--json | {"path": ..., "events": N} |
The file is personal data: member events carry usernames and emails. It needs a
key with audit:read, not restricted to workspaces, whose creator is an Admin
or Owner. The file appears only once the whole record has arrived; a download
that breaks leaves nothing behind.
qualia integration
Section titled “qualia integration”The organization’s Hugging Face tokens: new runs use the default one.
Every command needs a key with the opt-in integrations:write scope (* does
not grant it), made by an Admin or Owner of the organization, and not restricted
to workspaces. A key’s value goes in once and is never shown again: the list
prints its last four characters.
qualia integration list
Section titled “qualia integration list”List the organization’s integration keys, newest first.
qualia integration listqualia integration list --jsonID Provider Name Key Default Added550e8400-e29b-41d4-a716-446655440000 huggingface ci ...9f3a yes 2026-10-30660e8400-e29b-41d4-a716-446655440000 huggingface lab ...41bc 2026-10-29--json prints {"integrations": [{"id", "provider", "name", "last4", "is_default", "created_by", "created_at", "expires_at"}]}. last4 is null
for a key shorter than 12 characters.
qualia integration add
Section titled “qualia integration add”Add a key. The key is piped in with --secret-stdin, or typed at a prompt that
does not echo; on a terminal it always prompts. It is never taken from the
command line, where it would stay in your shell history.
qualia integration add huggingface --name lab # prompts for the tokenprintf %s "$HF_TOKEN" | qualia integration add huggingface --name ci --secret-stdin --json| Argument / Option | Description |
|---|---|
PROVIDER | huggingface |
--name | Up to 15 characters (required) |
--secret-stdin | Read the key from stdin; one trailing newline is dropped |
--json | Print the key as it is listed |
A Hugging Face token starts with hf_. The organization’s first token becomes
the default.
qualia integration remove
Section titled “qualia integration remove”Remove a key. Workspaces on a removed token move to the default.
qualia integration remove <ID>qualia integration remove <ID> --yes --jsonWithout a terminal it needs --yes.
qualia integration default
Section titled “qualia integration default”Make a Hugging Face token the one new runs use.
qualia integration default <ID>qualia member
Section titled “qualia member”Who is in the organization or a workspace, at which role, and changing it: the
dashboard’s Members pages. Without --project a command is about the
organization; with it, about that workspace.
A key needs the opt-in members:read scope to read and members:write to
change (see Admin scopes); reading a space also
takes projects:read. A key acts as the person who made it: it never gives a
role above that person’s own, and only an admin or owner manages people. A
workspace key acts only on its own workspace, so it always passes --project.
qualia member list
Section titled “qualia member list”List everyone with access, their role and where it comes from: granted here, from the organization, or through a space’s members.
qualia member listqualia member list --project <PROJECT_ID> --json| Option | Description |
|---|---|
-p, --project | A workspace; without it, the organization |
--json | {"space", "people": [...], "can_manage_members", "my_role"} as served |
qualia member show
Section titled “qualia member show”Show one person’s role on every space of the organization you can read, and the role granted on each. Needs an organization key.
qualia member show <USER_ID>qualia member role
Section titled “qualia member role”Give a person a role, or move them to another: on the organization, or on one
workspace with --project. An organization role is for the organization’s
members; invite anyone else. A workspace role raises a member above their
organization role there, or makes someone a guest of it.
qualia member role <USER_ID> contributorqualia member role <USER_ID> admin --project <PROJECT_ID> --json| Argument / Option | Description |
|---|---|
USER_ID | The person (required) |
ROLE | viewer, contributor, admin or owner |
-p, --project | A workspace; without it, the organization |
--json | The role before (from_role) and after, and the role they hold now |
qualia member remove
Section titled “qualia member remove”Take a person’s role on one workspace away (--project; they keep what the
organization gives them), or remove them from the organization. --keep names
the workspaces they stay a guest of. A key cannot remove the person who made
it from the organization: leaving one takes a signed-in session.
qualia member remove <USER_ID> --project <PROJECT_ID> --yesqualia member remove <USER_ID> --keep <PROJECT_ID> --yes| Option | Description |
|---|---|
-p, --project | A workspace; without it, the organization |
--keep | Removing from the organization: a workspace they stay a guest of (repeatable) |
-y, --yes | Skip the confirmation (needed without a terminal) |
--json | What they hold now (effective_role), and the workspaces kept |
qualia invitation
Section titled “qualia invitation”Invitations to the organization or a workspace. The same scopes and rules as
qualia member.
qualia invitation list
Section titled “qualia invitation list”List the pending invitations: to one workspace with --project, or every one
in the organization, each naming its space.
qualia invitation listqualia invitation list --project <PROJECT_ID> --jsonqualia invitation send
Section titled “qualia invitation send”Invite someone by email at a role: to the organization, or to one workspace as
a guest with --project. Never above your own role. Someone already in the
organization gets a role with qualia member role instead.
qualia invitation send new@example.com --role viewerqualia invitation send new@example.com --role contributor --project <PROJECT_ID>| Argument / Option | Description |
|---|---|
EMAIL | Their email address (required) |
-r, --role | viewer, contributor, admin or owner |
-p, --project | A workspace; without it, the organization |
--json | The invitation, with its id |
qualia invitation withdraw
Section titled “qualia invitation withdraw”Withdraw a pending invitation. Without --project it is found anywhere in the
organization; a workspace key passes its own workspace.
qualia invitation withdraw <INVITATION_ID> --yesqualia dataset
Section titled “qualia dataset”qualia dataset list
Section titled “qualia dataset list”List the datasets in your account, by name: uploads and merged datasets, or the kind you ask for. It reads the qualia.v1 Datasets API in the API key’s own account. An older qualia-sdk with no account set falls back to the older list route (uploads only).
qualia dataset listqualia dataset list --search cube --dataset-type lerobot_v3qualia dataset list --method umi --method teleopqualia dataset list --tag gello --tag warehouse-aqualia dataset list --kind mixturequalia dataset list --kind all --filter 'merged_dataset = "accounts/<a>/datasets/<id>"'qualia dataset list --limit 50 --json| Option | Description |
|---|---|
--limit, -n | Page size, 1–100 (default 20) |
--cursor | Pagination cursor printed by the previous page |
--search, -q | Only names containing this text |
--dataset-type | Filter: lerobot_v2_1, lerobot_v3, or mcap_ros2 |
--method | Any canonical tag; repeat to match alternatives |
--tag | Any collection tag; repeat to match alternatives |
--kind | upload, merged, mixture or all (default: uploads and merged) |
--filter | An AIP-160 filter, ANDed on (state, labels.*, target_robot, …) |
--filter 'merged_dataset = "<name>"' lists the uploads a merged dataset holds,
which the list otherwise leaves out.
--dataset-type filters each page after it arrives, so
a page can be shorter than --limit; follow the printed cursor to read on.
The Name column names each dataset as the dashboard does; a long name continues
on the next line. On the older route (an old qualia-sdk) there are no names, so it
shows the repository’s. --json also gives the repository (acct-<uuid>/<name>).
The Verdict column says what each upload amounted to: published,
degraded (episodes were derived, but part of the upload was flagged) or
underivable (no episode could be derived; the raw bytes are kept). Datasets
published before verdicts existed show published. --json prints what the
call returned: qualia.v1 Datasets with verdict and verdict_reason; on the
older route, the older items with qds.ingest_verdict and
qds.verdict_reason.
qualia dataset tags
Section titled “qualia dataset tags”Edit this dataset’s collection metadata and custom tags. The recognized names are
teleop, vr, umi, egocentric, policy-rollout, sim, real-world,
human and gello; your own tags are accepted too. The set holds at most
64 distinct tags. A merged dataset changes only its own set, and an append
preserves it. Version tags and episode curation tags are separate.
qualia dataset tags <dataset-uuid> --tag umi --tag real-world --tag human --tag gelloqualia dataset tags <dataset-uuid> --tag warehouse-aqualia dataset tags <dataset-uuid> --clearA changed, nonempty classification set updates saved metadata and customs in one
atomic write. Custom-only input, or unchanged classifications with edited customs,
replaces only customs and preserves declarations and inference. When classifications
are present, echo them to remove customs without declaring inferred methods. --clear
clears customs and explicitly makes every collection dimension Unknown, so inference
cannot refill it. Omitting both --tag and --clear is an error.
The command needs an account-scoped API connection and independent collection metadata
support. The SDK reads the owner and uses its etag unless --etag was supplied;
a stale caller etag is refused.
qualia dataset methods
Section titled “qualia dataset methods”Replace the six-name compatibility view on an upload or merged dataset.
A merged dataset changes only its own set. Other collection dimensions and
free tags remain; use qualia dataset tags for the other dimensions and customs.
The six tags are teleop, vr, umi, egocentric, policy-rollout and
sim. Use --clear to explicitly record an empty set (Unknown); omitting all
--method options is an error.
qualia dataset methods <dataset-uuid> --method umi --method teleopqualia dataset methods <dataset-uuid> --clearqualia dataset uploads
Section titled “qualia dataset uploads”Show the account’s in-flight uploads, the feed the dashboard’s pending band renders, from any machine, including one that is not running the upload.
qualia dataset uploadsqualia dataset uploads --watch --every 30qualia dataset uploads --json| Option | Description |
|---|---|
--watch, -w | Refresh until Ctrl-C |
--every | Seconds between refreshes (default 15, never under 5) |
Files and Bytes count content the lake has already accepted. Bytes go straight
to storage, so a first upload of new content reads 0 until it publishes; Phase
and Detail track the run throughout. Stop one with
cancel-upload, and clear a failed one with
dismiss-upload.
qualia dataset upload
Section titled “qualia dataset upload”Publish a local dataset directory as a pinned DatasetVersion. Bytes go straight to storage; Qualia verifies the manifest and publishes the two together. Episodes become visible only once that publication succeeds.
qualia dataset upload ./my-recording my-datasetqualia dataset upload ./teleop-session teleop-1026 --source-format mcap_ros2qualia dataset upload ./umi-session umi-1026 --source-format mcap_ros2 --rig umi-handheld--source-format takes lerobot_v2_1, lerobot_v3, or mcap_ros2. Leave it
out and the format is read from the directory: codebase_version in
meta/info.json tells LeRobot 2.1 from v3, and any .mcap makes it a session.
LeRobot 2.1 is never aliased or converted to v3, so its source provenance stays
distinct.
Use --source-format mcap_ros2 for a ROS 2 bag session. Lay it out as one
subdirectory per recording, each holding its .mcap bags and, optionally, an
episode.json sidecar carrying task and mode fallbacks. Every .mcap is
ingested on its own, so rosbag2 split files (bag_0.mcap, bag_1.mcap, …) are
accepted; see ROS 2 MCAP.
An MCAP session may carry meta/ingest.toml beside its bags, at the root of
the directory you upload, to declare its state and action topics, its clock and
its episode boundaries. Most teleoperated arms need none. See
Declaring state and action channels
and
Declaring episode boundaries.
Use --rig umi-handheld for a handheld (UMI) recording. --rig names a
gripper of your workspace: its name, its id, or its rig key (umi-handheld is
the workspace’s UMI gripper). The server writes that gripper’s rig and TCP
calibration into the upload’s meta/ingest.toml, so the recording converts to
gripper poses as it lands. Your local file is never written. See
Handheld (UMI) recordings.
Each upload is its own dataset unless you say otherwise. --merge-target
appends this one upload to an existing merged dataset; pass its dataset id or
its full resource name (accounts/{account}/datasets/{id}). A merged dataset
is made with the SDK’s client.datasets.merge and is listed as merged by
qualia dataset list. To append every upload to the same merged dataset, save
it once with qualia dataset destination set;
each upload then prints Upload destination: append to … on stderr.
--standalone keeps one upload on its own even when a destination is saved.
--merge-target and --standalone cannot be combined.
| Option | Default | Description |
|---|---|---|
--source-format | detected | Source layout: lerobot_v2_1, lerobot_v3 or mcap_ros2; detected from the directory when omitted |
--upload-workers | half your cores, 4–8 | Large (over 64 MiB) or edited files read and uploaded at once |
--chunk-threads | ≈ half your cores | Threads used to hash and split files |
--quiet | off | Silence the live per-phase progress on stderr |
--merge-target | saved destination | Append this upload to this merged dataset (id or resource name), for this run only |
--standalone | off | Keep this upload its own dataset even when a destination is saved |
--rig | none | Convert a handheld (UMI) recording at this gripper as it lands: its name, id or rig key (umi-handheld) |
--allow-underivable | off | Upload an MCAP session even when no bag in it can be derived; a LeRobot structure refusal cannot be lifted |
--json | off | Print the receipt as JSON on stdout (see the exit codes below) |
Before a byte moves, an mcap_ros2 upload checks every bag for damage the
server can never derive episodes from: a file too small to be MCAP, a bad
leading magic, a cut before its first complete data record, or a record whose
framing runs past the file. A well-formed bag with no messages is treated the
same way. A damaged or empty bag does not stop the upload: it is listed, with
the byte offset where it is known, and uploads as recorded; ingest reports it as
source_underivable and the rest of the session publishes.
A bag cut after the recording started is listed as source_truncated when the
part before the cut holds robot state, and the server derives the part that was
recorded. By default one JointState message is enough. When
meta/ingest.toml declares [state].topics, every declared topic needs a
message before the cut; one missing topic makes the bag source_underivable
(no_state), as does a cut bag with camera frames but no state. When the
client cannot open the bag’s compressed chunks (lz4, zstd before Python 3.14,
or a chunk too large to inspect), or cannot parse meta/ingest.toml, it lists
the bag as source_truncated and the server decides; the server may still find
no state and report no_state.
Only a session the server can derive nothing from, with no .mcap at all or
every bag damaged or empty, stops the upload with exit code 1:
BLOCKED — 2 file(s) the server cannot derive; nothing was uploaded: ./session/episode-0/recording.mcap: truncated MCAP file (missing the trailing magic) — the recording did not finish [source_underivable] ./session/episode-1/recording.mcap: truncated MCAP file (missing the trailing magic) — the recording did not finish [source_underivable] ./session: every bag is underivable — no episode can be derived [session_no_episodes]Re-run with --allow-underivable to upload the bytes as recorded.With --allow-underivable the bytes upload anyway and are kept as a source
dataset with no episodes. The receipt (--json) carries the check as
preflight.
A LeRobot upload (lerobot_v2_1 or lerobot_v3) is checked the same way. The
server refuses some structure outright, so these stop the upload with exit
code 1, all listed in one run:
| Check | Code |
|---|---|
meta/info.json missing or not a JSON object; fps not in (0, 1000]; total_tasks not a positive integer; no features object; a video_path placeholder the server cannot render; lerobot_v2_1 without a positive chunks_size | info_json_unreadable |
codebase_version is not v2.1 for lerobot_v2_1 or v3.0 for lerobot_v3 | codebase_version_mismatch |
no *.parquet file under data/ | data_shards_missing |
lerobot_v2_1 without meta/episodes.jsonl or meta/tasks.jsonl | info_json_unreadable |
--allow-underivable cannot override these: the server refuses the structure
whatever the flag says, so the upload stops with exit code 1 either way.
A camera whose video rate differs from the state and action row rate is accepted and flagged as video_rate_differs_from_rows; the viewer aligns them by time, but LeRobot download and fine-tuning require re-exporting the video at the row rate and uploading again.
A missing video does not stop the upload, and nothing is repaired for you.
Paths come from video_path in meta/info.json, or the server’s default
videos/{video_key}/chunk-{chunk_index:03d}/file-{file_index:03d}.mp4 when it
has none. For lerobot_v2_1 every episode’s video is checked and each missing
one is listed with its episode and camera; for lerobot_v3 each camera needs at
least one file matching the template, and a camera with none is listed as
missing from every episode. Both use camera_absent_for_episode: the upload
continues, those episodes will be flagged, and you should probably exclude
them. With no video for any camera, one warning says every episode will be
flagged.
Every completed upload ends with a verdict, ingest_verdict in the --json receipt
(with verdict_reason and verdict_source), and an exit code a script can
branch on:
| Exit | Verdict | Meaning |
|---|---|---|
0 | published or degraded | The dataset published; degraded means an ingest finding, a flagged episode or an unreadable ingest report |
1 | none | It failed or was refused: a pre-flight block or an error |
3 | underivable | The bytes are stored as a source dataset, but no episode could be derived |
An underivable upload ends with one line on stderr naming the dataset that keeps the bytes and the reason:
UNDERIVABLE — no episodes could be derived; the bytes are kept as dataset <ID>. Reason: session_no_episodes: …With --json, stdout carries the full receipt for a completed upload (exit 0
or 3) and {"preflight": …} for a pre-flight block (exit 1). Any other error
prints nothing on stdout and exits 1 with its message on stderr.
Exit 1 does not mean nothing is left. A pre-flight block moves nothing, but
after a transfer began the upload stays in
qualia dataset uploads as failed, with its bytes.
Progress is written to stderr, so --json output stays pipeable. The server-side
phases are bounded by silence rather than elapsed time: ingest parses every bag
and transcodes every camera, so a large upload is free to take as long as it
takes. See Configuration for the two environment variables
that govern that wait.
qualia dataset destination
Section titled “qualia dataset destination”A destination is a merged dataset that later uploads append to by default, so
you do not pass --merge-target every time. It is saved in this CLI’s config
file, bound to the API host, account and workspace it was saved under. An
upload made under another host, account or workspace ignores it, stays
standalone and says so on stderr.
qualia dataset destination set accounts/<account>/datasets/<id>qualia dataset destination showqualia dataset destination clear| Command | What it does |
|---|---|
set | Save TARGET, an existing merged dataset (its resource name or id), as the default --merge-target for later uploads |
show | Print the saved destination with its API host, account and workspace; --json prints them as JSON |
clear | Remove the saved destination; later uploads are standalone again |
set refuses a dataset that is not merged. A single upload can still go
elsewhere with --merge-target, or stay on its own with --standalone.
qualia dataset ingest-report
Section titled “qualia dataset ingest-report”Show which cameras a source dataset publishes and every degradation the ingest performed instead of failing. A camera missing from one bag is dropped from the whole dataset, so this is where a two-camera pin of a three-camera recording is explained. It opens with the upload’s report card: how many episodes were accepted, and which were flagged and why.
qualia dataset ingest-report <DATASET>qualia dataset ingest-report <DATASET> --jsonqualia dataset ingest-report acct-<ACCOUNT_UUID>/<NAME> --ref <COMMIT>| Argument / option | Description |
|---|---|
DATASET | Dataset id, full name or slug; or a canonical path acct-<uuid>/<name> |
--ref | With a path only: branch, tag or commit to read the report from (default: tip) |
By id, name or slug the report is read through the qualia.v1 Datasets API; a
merged dataset answers its uploads’ reports folded into one, and --json prints
that API’s IngestReport. A path reads the older route. A report too large to
read inline is an error, never shown as clean.
qualia dataset download
Section titled “qualia dataset download”Download a dataset version in a format, or every file uploaded to the dataset,
byte for byte (--format original).
# the newest version (stable), as LeRobot v3qualia dataset download my-dataset
# one version, in each formatqualia dataset download my-dataset:1.0qualia dataset download my-dataset:1.0 --format lerobot_v2_1qualia dataset download my-dataset:1.0 --format mcap_ros2
# every file uploaded, byte for bytequalia dataset download my-dataset --format originalDATASET is the dataset’s slug or id; add :<version> for a tag, stable
(the newest) or a digest prefix. A full
accounts/<account>/datasets/<dataset>/versions/<tag> name also works. Without
a version you get the newest one.
DEST defaults to ./<slug>-<tag>, with -v21 for LeRobot v2.1 and -mcap
for MCAP, and to ./<slug>-original for original.
| Argument / option | Description |
|---|---|
DATASET | <dataset>[:<version>], or a full version name |
DEST | Destination folder (optional) |
--format | lerobot_v3 (default), lerobot_v2_1, mcap_ros2 or original; dashes work too (mcap-ros2) |
--json | Print the result as JSON |
original is every file uploaded to the dataset, byte for byte, with no version
involved. It also holds what ingest stored beside those files: the annotations
under meta/qds, meta/ingest_report.json and, for an MCAP upload, the LeRobot
data and videos ingest made from the recordings. Trims and splits are not
applied: the takes are whole, and a split’s pieces are only annotations under
meta/qds. When the dataset has any, the command says how many on stderr and
how to get the curated episodes (tag a version, then download it). Only an
upload has files of its own, so a merged dataset or a mixture is refused:
download one of its uploads, or a version. For now original needs an
organization key; a workspace key is refused.
An MCAP download keeps only what was mapped at upload: tf, diagnostics and
custom topics do not come back, so use original when you need them.
While the server builds a version (or, for original, lists the files) you
see a spinner on stderr, then a bar with bytes, speed and files n/m. Files are checked as they arrive, and a run that
stops keeps the files it checked: run the same command again and it fetches
only the rest. Nothing is drawn with --json.
It ends with
Saved <version> as <format> to <DEST> (<N> files, <size>), plus
; <K> kept from an earlier run when files were reused.
--json prints destination, format, reference, version,
dataset_version_id, file_count, byte_count, downloaded_file_count,
reused_file_count and materialization (the qualia.v1 Materialization). For
original, reference is the dataset’s slug and version,
dataset_version_id and materialization are null.
The first download of a version in a format starts its rendering, which needs
a key that can write to the dataset (data:write); once it is rendered,
downloads of it in that format need read access only (data:read). head,
what a dataset yields right now, has no download: tag it first.
A version that contains a blocked episode (a NaN, an infinity, a missing value
or a wrong width in its state or action rows) is refused, because a download
carries every episode. Publish a curated version without them first, with
qualia dataset curate <DATASET_VERSION_UUID> --idempotency-key <UUID> --name <NEW_DATASET>,
and download that. --format original is not refused: it renders nothing, so it
downloads the upload’s files, blocked episodes included.
The dashboard gives the command with the version filled in: Download on a dataset or version page.
qualia dataset delete
Section titled “qualia dataset delete”Delete a mixture, or retire an upload or a merged dataset, for example after uploading the wrong folder. It leaves every list and every mixture, versions cut from it keep resolving, and no storage is reclaimed. A merged dataset is retired with the uploads it holds; the prompt says how many.
qualia dataset delete <FULL_DATASET_UUID>qualia dataset delete accounts/<account>/datasets/<id> --force --yesqualia dataset delete <FULL_DEFINITION_UUID> --definition --yesThe id must be the full UUID or the full name: qualia dataset list --json
shows it as name (accounts/<account>/datasets/<id>). It is refused while a
mixture reads the dataset, and while Tasks reference its episodes unless
--force. On the older route (an old qualia-sdk) it retires uploads only.
| Option | Description |
|---|---|
--force | Also remove the Task references to its episodes (the Tasks stay) |
--etag | Refuse if the dataset changed since this etag |
--definition | Delete a dataset definition instead; datasets are untouched |
--yes, -y | Skip the confirmation (required without a terminal) |
--json | Print name, displayName, kind and deleted |
qualia dataset import-hf
Section titled “qualia dataset import-hf”Import one exact Hugging Face dataset commit server-side. The command confirms the pinned coordinates, submits them once, and polls while Hub bytes stream straight into storage. Success creates a pinned immutable DatasetVersion.
export HF_TOKEN="..." # optional for public datasetsqualia dataset import-hf \ qualia-robotics/openarm-cube-in-box-v1 \ 17c29c487d886878ddcb3c5649101b2860fbc047 \ cube-in-box \ --source-format lerobot_v3The revision must be lowercase 40-hex; branches, tags, URLs, and embedded
credentials are rejected. HF_TOKEN is read only from the environment and is
never accepted as a command-line option, printed, or sent in poll requests.
Local file/byte/work-directory switches do not exist because no dataset body or
scratch file touches the CLI machine. --json requires --yes so stdout stays
valid JSON.
qualia dataset define
Section titled “qualia dataset define”Save a lake query as a dataset definition, a target curate can publish a
version into. qualia dataset pin <DEFINITION_UUID> freezes what it selects
as an immutable version.
qualia dataset define kitchen-2026-09-16 --dataset-id <SOURCE_DATASET_UUID>qualia dataset define audited-only --query ./query.json --description "human audited"| Argument / option | Description |
|---|---|
NAME | One path segment: letters, digits, ., _, - (required) |
--dataset-id | Select episodes of this source dataset; repeatable |
--task | Select one task |
--tag | Require this tag; repeatable |
--query | JSON file holding the complete saved query, instead of the flags |
--description | Free text |
--query takes the shape of the SDK’s DatasetSavedQuery: dataset_ids,
task, tier, min_duration_s, max_duration_s, tags, review_state,
search, numeric_predicates, predicates, episodes, query_text.
qualia dataset pin
Section titled “qualia dataset pin”Freeze something as an immutable DatasetVersion. The printed DatasetVersion id
is what training-features and curate take, and what the dashboard’s training
launcher trains on.
pin DATASET TAGtags what an upload or a mixture yields now (qualia.v1CreateVersion). Tags never move; a tag name is taken once per dataset. Acts in the API key’s own account (--accountis optional).pin DEFINITION_IDfreezes what a definition’s saved query selects now. This stays on the/v1path, because saved queries have no qualia.v1 equivalent.
qualia dataset pin <DATASET_UUID> 1.0 --note "first cut"qualia dataset pin <DATASET_UUID> 1.1 --digest <HEAD_DIGEST_YOU_REVIEWED>qualia dataset pin <DEFINITION_UUID> --note "first pin"| Argument / option | Description |
|---|---|
TARGET | With TAG: dataset id or full name. Without: a definition UUID |
TAG | Tag name, e.g. 1.0: 1-64 of [0-9A-Za-z._-] |
--note | What the version is |
--digest | With TAG: the head digest you reviewed; refused if head moved |
qualia dataset version list
Section titled “qualia dataset version list”List a dataset’s tags, newest first.
qualia dataset version list my-datasetqualia dataset version list my-dataset --json| Argument / option | Description |
|---|---|
DATASET | Dataset id, full name or slug |
--filter | AIP-160 filter over digest and create_time |
--limit, -n | Page size, 1-500 (default 50) |
--cursor | Next-page token |
--json | {"versions": [...], "nextPageToken": ...} |
qualia dataset version get
Section titled “qualia dataset version get”Show one version: its tag, reference, digest, episode counts, DatasetVersion id and note.
qualia dataset version get my-dataset:1.0qualia dataset version get stable --dataset my-dataset --jsonVERSION is <dataset>:<tag> (slug or UUID; a tag, stable, head or a digest
prefix), a full version name, or a tag with --dataset.
qualia dataset version diff
Section titled “qualia dataset version diff”What came in, went out or changed revision between two refs, and why. It also prints the note and the tag the dashboard’s tag dialog would offer.
qualia dataset version diff my-dataset # newest tag → headqualia dataset version diff my-dataset --base 1.0 --target 1.1 --json| Option | Description |
|---|---|
--base | A tag, stable or a digest prefix; default the newest tag |
--target | Default head |
--limit, -n | Changed episodes per page, 1-1000 (default 100) |
--cursor | Next-page token |
qualia dataset version create
Section titled “qualia dataset version create”Tag what the dataset yields now. The tag never moves.
qualia dataset version diff my-dataset --json # read targetDigestqualia dataset version create my-dataset 1.1 --note "dropped 3 jerky takes" --digest b3:…--digest is the head digest you reviewed; if head has moved since, the tag is
refused (409). qualia dataset pin DATASET TAG does the same without --digest.
qualia dataset version note
Section titled “qualia dataset version note”Edit a version’s note, the one thing about a tag that changes.
qualia dataset version note my-dataset:1.0 "first cut, 120 takes"--etag refuses the edit if the note changed since you read it.
qualia dataset version merges
Section titled “qualia dataset version merges”A merged dataset’s merges, newest first, and the uploads each took. A merge is final: none can be reverted.
qualia dataset version merges my-merged-dataset --jsonqualia dataset version record
Section titled “qualia dataset version record”What was done to the dataset in the round a version opened: from its creation
to the next tag’s (for head, since the newest tag). It lists rulings, edits,
splits and issues, each with who did it and when, as the dashboard’s
Curation of 1.0 panel does. A merged dataset’s record also reads the uploads
it holds. At most 2000 events are read; a longer round shows its newest.
qualia dataset version record my-dataset:1.0qualia dataset version record my-dataset:head --jsonIt reads the events of the dataset’s workspace.
qualia dataset curation-suggest
Section titled “qualia dataset curation-suggest”Explain bad-data recommendations for immutable DatasetVersions without
mutating them. Use --page-token to continue the result set.
qualia dataset curation-suggest <DATASET_VERSION_UUID>qualia dataset curation-suggest <DATASET_VERSION_UUID> --jsonqualia dataset curate
Section titled “qualia dataset curate”Publish the reviewed analysis’s sealed recommendation set as a new immutable DatasetVersion. Supply a stable idempotency UUID. Source bytes and Git history are not deleted. Retrying with the same idempotency key resumes or recovers that publication’s receipt instead of suggesting fresh evidence against a head the first attempt already moved. A failed publication keeps its key: publish again under a new one.
qualia dataset curate <DATASET_VERSION_UUID> \ --definition-id <DATASET_DEFINITION_UUID> \ --idempotency-key <OPERATION_UUID> \ --yesOmit --yes for an interactive confirmation.
Pass --name <NEW_DATASET> instead of --definition-id to publish the curated
version as a new dataset. That is the form to use on an upload: an upload’s own
dataset is source-owned and refuses a curated version. The curated version
leaves out every episode the analysis recommends removing, not only blocked
ones.
qualia dataset training-features
Section titled “qualia dataset training-features”Show the exact camera, stream, timebase, and frame-timestamp
descriptors for one immutable DatasetVersion. VERSION is <dataset>:<tag>, a
DatasetVersion UUID, or a full version name. The output includes the resolved id; head must be pinned first.
qualia dataset training-features my-dataset:1.0qualia dataset training-features my-dataset:1.0 --json| Argument | Description |
|---|---|
VERSION | <dataset>:<tag> (slug or dataset UUID), DatasetVersion UUID, or full version name (required) |
qualia dataset markers
Section titled “qualia dataset markers”Show the recorder markers inside one episode, in time order, in seconds from the start of the recording. Every edit command below cuts on these labels, so this is how you find out what a recording actually wrote.
The episode commands below speak qualia.v1, in the API key’s own account, and they
name episodes through the upload they were recorded in: --dataset/-d with
bare episode ids, or full names accounts/…/datasets/…/episodes/….
qualia dataset markers <EPISODE_UUID> -d <DATASET_UUID>qualia dataset markers <EPISODE_UUID> -d <DATASET_UUID> --jsonqualia dataset split
Section titled “qualia dataset split”Cut episodes into children at their own markers, at given instants, or around
windows to keep. Children are new episodes and the parents are left as they were,
but a split is published when it answers and cannot be undone: dataset unsplit
removes only children that were never published. Preview with --dry-run; once
split, curate a child by trimming or rejecting it.
qualia dataset split <EPISODE_UUID> -d <DATASET_UUID> --cut-at graspqualia dataset split <EPISODE_UUID> <EPISODE_UUID> -d <DATASET_UUID> --cut-at grasp --dry-runqualia dataset split <EPISODE_UUID> -d <DATASET_UUID> --at 12.5 --at 31qualia dataset split <EPISODE_UUID> -d <DATASET_UUID> --keep 0.5-6 --keep 8-14 --dry-run| Option | Description |
|---|---|
--dataset, -d | The upload the episodes were recorded in (required) |
--cut-at | Marker label to cut at, as the recording wrote it |
--at | Cut at this instant, in seconds from the start of the recording |
--keep | Keep this window as one child, START-END seconds, e.g. 1.5-9 |
--start-at-first | Drop the lead-in, up to the FIRST marker so labelled |
--end-at-last | Drop the run-out, after the LAST marker so labelled |
--dry-run | Plan the cuts without writing them |
--json | JSON output |
A request cuts one way: at markers, at instants or around windows. For markers,
name at least one label across --cut-at, --start-at-first or
--end-at-last. The narrowing options apply before the cut, which is how a
lead-in is dropped; given alone, each episode becomes one trimmed child. All
three accept repeats.
--at is for takes the recorder marked nothing at. Repeat it for several cuts;
every named episode is cut at the same instants. It cannot be combined with the
marker options. To find the instants, watch the take (dataset videos) or read
it with the SDK’s episodes.sample_series.
--keep makes one child of each window and drops what lies outside every
window: the lead-in, the run-out and the stretches between. Repeat it for
several windows, in time order and not overlapping; every named episode keeps
the same windows. It cannot be combined with --at or the marker options. The
summary counts the frames no child keeps.
A trimmed episode is cut inside its trim: its children keep only the frames the trim keeps, what the trim cut is counted as dropped, and a marker or instant there cuts nothing.
An episode with no matching cut, or with children already, is left alone.
qualia dataset unsplit
Section titled “qualia dataset unsplit”Delete the children of split episodes that were never published: those a split made before splits published. A published split is refused; curate its children by trimming or rejecting them.
qualia dataset unsplit <PARENT_EPISODE_UUID> -d <DATASET_UUID>qualia dataset trim
Section titled “qualia dataset trim”Trim episodes to their own markers, or to given seconds, reversibly. Each
episode is narrowed to start at ITS first named marker and end at ITS last.
The base extent never changes, so --clear restores it.
qualia dataset trim <EPISODE_UUID> -d <DATASET_UUID> --start-at-first ready --end-at-last donequalia dataset trim <EPISODE_UUID> -d <DATASET_UUID> --start 1.5 --end 12qualia dataset trim <EPISODE_UUID> -d <DATASET_UUID> --clear| Option | Description |
|---|---|
--dataset, -d | The upload the episodes were recorded in |
--start-at-first | Trim the lead up to the FIRST marker so labelled |
--end-at-last | Trim the tail after the LAST marker so labelled |
--start | Start each episode here, seconds from the start of the recording |
--end | End each episode here, seconds from the start of the recording |
--clear | Restore the full extent instead of trimming |
--json | JSON output |
Use one way per call: marker labels, --start/--end, or --clear.
--start or --end alone moves that end and keeps the episode’s other one
(the whole recording when it was untrimmed). Each episode is read first and
written with the etag it read, so an edit made in between is refused rather than
overwritten. An episode the server will not trim, such as a split parent, is left
alone with its reason.
qualia dataset subtasks
Section titled “qualia dataset subtasks”Name each episode’s subtask spans from its own markers — the same boundary rule
dataset split cuts on, used to label a span instead of carving it, so a whole
selection can be named at once.
qualia dataset subtasks <EPISODE_UUID> -d <DATASET_UUID> --at grasp --at placequalia dataset subtasks <EPISODE_UUID> -d <DATASET_UUID> --at grasp --starts-at| Option | Description |
|---|---|
--dataset, -d | The upload the episodes were recorded in (required) |
--at | Marker label whose presses bound a subtask (required, repeats) |
--starts-at | Each marker OPENS the span it names (default: it closes it) |
qualia dataset edit
Section titled “qualia dataset edit”Edit many episodes in one call: all of them change or none do, one revision
each. Name the episodes and the fields they all take, or pass --from with a
JSON list of per-episode edits (episode plus the fields to change, and an
etag to refuse the call if that episode changed since you read it). Up to 500
episodes of one upload per call. Trim with dataset trim and link tasks with
dataset assign-task or dataset link-episode.
qualia dataset edit <EPISODE_UUID>... -d <DATASET_UUID> --tag slow --outcome FAILUREqualia dataset edit -d <DATASET_UUID> --from edits.json| Option | Description |
|---|---|
--dataset, -d | The dataset the episodes are read through (required) |
--task | Task label |
--instruction | Instruction |
--scene | Scene |
--tag | Replace the tags with these (repeats) |
--clear-tags | Remove every tag |
--outcome | SUCCESS, PARTIAL, FAILURE or OUTCOME_UNSPECIFIED |
--from | JSON list of per-episode edits; - reads stdin |
qualia dataset assign-task
Section titled “qualia dataset assign-task”Label episodes with a task and link them to it. In an upload it changes all of
them or none. On a merged dataset it is all or none per upload: each upload
commits on its own, so a failed call can leave earlier uploads changed. Rerun it
to finish. With --task, every selected episode links to that Task and, without
--label, takes its display name as the label: the language instruction
training reads. A label alone sets the text and leaves links as they are.
Use it when the episodes need the label as well as the link. To only say which
Task an upload was recorded against, use link-task.
qualia dataset assign-task -d <DATASET_UUID> --task <TASK_UUID> --filter 'state = KEPT'qualia dataset assign-task <EPISODE_UUID> -d <DATASET_UUID> --label "restock shelf"| Option | Description |
|---|---|
--dataset, -d | The upload the episodes were recorded in (required) |
--task, -t | Task to link: id or accounts/.../tasks/... |
--label | The label; defaults to the task’s display name |
--filter | Select episodes by filter instead of naming them |
--json | JSON output |
Pass --task, --label or both. Name episodes or pass --filter, not both.
qualia dataset link-task
Section titled “qualia dataset link-task”Set the Task an upload was recorded against. Every episode with no link of its
own reads it, in one request. On a merged dataset it is set on every upload the
dataset holds. A link, not a label: labels.task stays as it is, and a mixture
can follow every upload linked to the task.
Episodes that link the old Task themselves keep it. Pass --relink to move them
too.
qualia dataset link-task <DATASET_UUID> <TASK_UUID>qualia dataset link-task <DATASET_UUID> <TASK_UUID> --relinkqualia dataset link-task <DATASET_UUID> --unlink| Option | Description |
|---|---|
--unlink | Remove the upload’s task link (omit the task) |
--relink | Also move the episodes linked to the old task themselves |
--etag | The dataset’s etag as read; refuse the change if it moved since |
--json | JSON output |
qualia dataset link-episode
Section titled “qualia dataset link-episode”Link one episode to a Task, or remove its own link. A link, not an edit: the
episode’s task label, revisions and versions stay as they are. Unlinked, the
episode reads the Task of the dataset that holds it again. To label and link many
episodes, use assign-task; to link a whole upload, link-task.
qualia dataset link-episode <EPISODE_UUID> -d <DATASET_UUID> --task <TASK_UUID>qualia dataset link-episode accounts/…/datasets/…/episodes/… --unlink --json| Option | Description |
|---|---|
--dataset, -d | The dataset the episode is read through (with a bare id) |
--task, -t | Task to link: id or accounts/.../tasks/... |
--unlink | Remove the episode’s own link |
--etag | The episode’s etag as read; refuse the link if it changed since |
--json | JSON output |
Pass --task or --unlink, one of them.
qualia dataset preparation
Section titled “qualia dataset preparation”What the newest prepare run did to an upload, as the dataset page’s Tasks tab shows it: its state, error and warnings; the tasks discovery found, each with its episode count, health and the Task its episodes are checked against (a draft until published); and the dataset’s own task names, with their keys and the decisions on them. A merged dataset or a mixture has no run of its own.
qualia dataset preparation <DATASET_UUID>qualia dataset preparation my-upload-slug --jsonA found task with no Task prints the qualia task create line that makes one
from its name and picked reference episodes, and the link-task (one task) or
link-episode line that links its episodes. A Task id it prints is read with
qualia task get and published with qualia task publish.
| Option | Description |
|---|---|
--json | JSON output |
qualia dataset confirm-task-names
Section titled “qualia dataset confirm-task-names”Decide which of the dataset’s own task names become tasks, as the Tasks tab’s
Use these tasks. Every usable name gets a decision: the ones you pass with
--use (or every one with --all) are used, the rest are recorded as a
person’s no. Read-only names (outcome words, a code, already a task label) are
never sent. The confirmed names start task discovery again, which drafts a Task
for each; read it with qualia dataset preparation.
qualia dataset confirm-task-names <DATASET_UUID> --use ts_3f9a0c1b2d4equalia dataset confirm-task-names <DATASET_UUID> --all --name "ts_3f9a0c1b2d4e=Fold the towel"| Option | Description |
|---|---|
--use, -u | Use this task name as a task, by its key (repeatable) |
--all | Use every task name that can be used |
--name | KEY=NAME: the Task name, at most 32 characters. Default: the earlier one, else the first six words |
--run | The run you read; refused when a newer run replaced it |
--json | JSON output |
A personal API key decides as the person who made it. A workspace’s service key is refused.
qualia dataset history
Section titled “qualia dataset history”List an episode’s edits, newest first, then the recording as revision 0. Each row names who edited, when, the note, and the fields the edit changed against the revision before it. Rulings (keep, reject) are not edits, and an episode nobody edited lists nothing. The history is the take’s: the same through every dataset that holds it.
qualia dataset history <EPISODE_UUID> -d <DATASET_UUID>qualia dataset history <EPISODE_UUID> -d <DATASET_UUID> -n 10 --cursor <CURSOR> --json| Option | Description |
|---|---|
--dataset, -d | The dataset the episode is read through (with a bare id) |
--limit, -n | Revisions per page, 1–500 (default 50) |
--cursor | Next-page cursor from the previous page |
--json | JSON output: episodeRevisions and nextPageToken |
Each revision in --json holds the take’s whole content after that edit.
qualia dataset videos
Section titled “qualia dataset videos”Sign each camera’s video of an episode, or download them. Each link is short-lived and stops working at its expiry; run the command again for fresh ones. When a camera file holds more than the take, the take’s window in it is shown.
qualia dataset videos <EPISODE_UUID> -d <DATASET_UUID>qualia dataset videos <EPISODE_UUID> -d <DATASET_UUID> --version stable --download ./videos| Option | Description |
|---|---|
--dataset, -d | The dataset the episode is read through (with a bare id) |
--version | The take as this version holds it: a tag, stable, v0 or a digest prefix |
--download | Save each camera’s video into this directory |
--json | JSON output; with --download, a downloads list of saved files |
--download DIR creates DIR if needed and saves the whole file of each camera
as DIR/<camera>.mp4, replacing a file of that name. A file is written under a
temporary name and renamed once complete, so it is whole or absent. The links go
to storage directly; your API key is never sent there. A take in no published
version yet has no videos, and --download then exits 1.
qualia dataset episodes
Section titled “qualia dataset episodes”List a dataset’s episodes, in recording order unless --order-by. The filter
is the one the dataset page’s filter bar writes. Each line is one episode: its
id (what the commands below take), index, standing, length after its trim, open
issues and task label. Pass - as the dataset to read every dataset of the
account; each line then starts with the episode’s full name.
qualia dataset episodes <DATASET_UUID>qualia dataset episodes <DATASET_UUID> --filter 'state = UNREVIEWED AND open_issue_codes:"jerky"'qualia dataset episodes <DATASET_UUID> --order-by 'metrics.duration_seconds desc' -n 20 --json| Option | Description |
|---|---|
--filter | Episode filter, e.g. state = KEPT, metrics.duration_seconds < 20 |
--order-by | index (default), record_time, metrics.<field> desc, open_issue_count desc |
--view | basic, or analysis to add each episode’s analysis |
--version | Read the episodes as this version froze them: a tag, stable or a digest prefix |
--limit, -n | Page size, 1 to 1000 (default 50) |
--cursor | Cursor from the previous page |
--json | JSON output: episodes, nextPageToken, totalSize |
--version needs a qualia-sdk whose episode reads take version=; with an
older one the command says so and exits 1.
qualia dataset episode
Section titled “qualia dataset episode”Show one episode as its dataset sees it: standing and who ruled, task, labels,
length, trim, subtasks, open issues, and who is editing it in the studio. Pass
--dataset/-d with a bare episode id, or the full name
accounts/…/datasets/…/episodes/….
qualia dataset episode <EPISODE_UUID> -d <DATASET_UUID>qualia dataset episode accounts/<ACCOUNT>/datasets/<DATASET_UUID>/episodes/<EPISODE_UUID> --json| Option | Description |
|---|---|
--dataset, -d | The dataset it is read through (with a bare id) |
--view | basic, or analysis to add its analysis curves |
--version | Read it as this version froze it |
--json | JSON output: the episode, including its etag |
qualia dataset summary
Section titled “qualia dataset summary”Count what a filter leaves: episodes, recorded time and frames, how many episodes carry each value of a field, and each metric’s quantiles, histogram and outlier fences. This is what the dataset page’s overview and outliers tab show.
qualia dataset summary <DATASET_UUID> --facet state --facet open_issue_codesqualia dataset summary <DATASET_UUID> --filter 'state != REJECTED' --metric metrics.duration_seconds --bins 10| Option | Description |
|---|---|
--filter | Episode filter |
--facet | Count per value of this field, e.g. state, task, outcome, open_issue_codes (repeats; default state) |
--metric | Describe this metric’s spread, e.g. metrics.duration_seconds (repeats) |
--bins | Histogram bins per metric (default 30); printed only when given |
--json | JSON output, every count included even when 0; an unfenced metric’s fences are "NaN" |
qualia dataset keep
Section titled “qualia dataset keep”Keep episodes in the dataset’s scope, closing their open issues there. Name the
episodes, or pass --filter to keep everything it leaves, as the dataset page’s
Keep does. Through a mixture the keep is the mixture’s own, and episodes its
uploads do not keep are skipped.
qualia dataset keep <DATASET_UUID> <EPISODE_UUID> <EPISODE_UUID> --reason "checked by hand"qualia dataset keep <DATASET_UUID> --filter 'state = UNREVIEWED AND open_issue_codes:"jerky"'| Option | Description |
|---|---|
--filter | Keep every episode this filter leaves, not names |
--reason | Words for the record |
--json | JSON output: every count of the result, and locked |
The command prints how many episodes changed, were already kept, and were
skipped, and how many open issues it closed. Name episodes or pass a filter, not
both. An empty --filter "" is refused, so a blank shell variable never selects
every episode.
A take a person has open in the studio is left as it was: their edit lease
wins over a key. Those takes are listed on stderr with who holds them, and the
command still exits 0. Run it again once they are done. --json puts the same
list under locked (the first 100) beside lockedCount.
qualia dataset reject
Section titled “qualia dataset reject”Reject episodes in the dataset’s scope: they leave training there. Nothing is
deleted, and qualia dataset reset withdraws it. Same selection, output and
locked takes as keep.
qualia dataset reject <DATASET_UUID> <EPISODE_UUID> --reason "operator in frame"qualia dataset reject <DATASET_UUID> --filter 'metrics.duration_seconds < 2'| Option | Description |
|---|---|
--filter | Reject every episode this filter leaves, not names |
--reason | Words for the record |
--json | JSON output |
qualia dataset reset
Section titled “qualia dataset reset”Withdraw the keep or reject made in the dataset’s scope, as Ctrl+Z does in the studio. Each episode then stands as derived: unreviewed while a blocking issue is open on it, kept otherwise. Issues the withdrawn keep closed open again. A reset carries no reason.
qualia dataset reset <DATASET_UUID> <EPISODE_UUID>qualia dataset reset <DATASET_UUID> --filter 'metrics.duration_seconds < 2'| Option | Description |
|---|---|
--filter | Reset every episode this filter leaves, not names |
--json | JSON output |
qualia dataset restore
Section titled “qualia dataset restore”Put back episodes ingest validation rejected, with the reason the check was wrong. Made in the upload only. Episodes that are not validation rejects are skipped.
qualia dataset restore <DATASET_UUID> <EPISODE_UUID> --reason "the fps metadata was right"| Option | Description |
|---|---|
--reason | Why the check was wrong (required) |
--json | JSON output |
qualia dataset issues list
Section titled “qualia dataset issues list”List a dataset’s issues and notes, oldest first. An issue blocks a keep until
it is dismissed or its episode is ruled; a note never blocks. Through a mixture
the list includes the issues upstream of it, under their own names; filter on
dataset = "<the mixture's name>" for its own.
qualia dataset issues list <DATASET_UUID> --filter 'state = OPEN AND blocks = true'qualia dataset issues list <DATASET_UUID> --episode <EPISODE_UUID> --json| Argument / option | Description |
|---|---|
DATASET | Dataset id or full name (required) |
--filter | AIP-160 over episode, code, kind, state, blocks, … |
--episode, -e | Only this episode’s issues (id or full name) |
--order-by | create_time (default), create_time desc, code, episode |
--limit, -n | Rows per page, 1-1000 (default 50) |
--cursor | Pagination cursor, as the previous page printed |
--json | JSON output |
qualia dataset issues summary
Section titled “qualia dataset issues summary”Count issues per code: open, the distinct episodes with an open one, and
dismissed. The dataset page’s issues table. A person’s own words show as
(own words).
qualia dataset issues summary <DATASET_UUID>qualia dataset issues summary <DATASET_UUID> --filter 'blocks = true' --json| Argument / option | Description |
|---|---|
DATASET | Dataset id or full name (required) |
--filter | Same language as list |
--json | JSON output |
qualia dataset issues dismiss
Section titled “qualia dataset issues dismiss”Settle open issues by name or by filter: seen, and the episode wanted as it stands. No ruling moves. Notes and issues already dismissed are left alone. Issues on takes another person is editing stay open; the command prints how many it dismissed, then those takes and who holds them.
qualia dataset issues dismiss <DATASET_UUID> --filter 'code = "idle_tail"' --reason "fine for this task"qualia dataset issues dismiss <DATASET_UUID> <ISSUE_UUID> <ISSUE_UUID>| Argument / option | Description |
|---|---|
DATASET | Dataset id or full name: the scope (required) |
ISSUES | Issue ids or full names; omit to select with —filter |
--filter | Issues matching this filter |
--reason, -r | Words for the record |
--cause | MANUAL (default), or TRIM when a trim cut it away |
--json | JSON output |
Name issues or pass --filter, not both. Through a mixture only its own issues
are dismissed.
qualia dataset issues reopen
Section titled “qualia dataset issues reopen”Reopen dismissed issues by name or by filter. A person’s ruling on an episode whose blocking issue reopens is withdrawn: the episode is unreviewed again in this dataset. Takes another person is editing are left as they were and listed.
qualia dataset issues reopen <DATASET_UUID> --filter 'code = "idle_tail" AND state = DISMISSED'| Argument / option | Description |
|---|---|
DATASET | Dataset id or full name: the scope (required) |
ISSUES | Issue ids or full names; omit to select with —filter |
--filter | Issues matching this filter |
--json | JSON output |
qualia dataset issues add
Section titled “qualia dataset issues add”Raise an issue, or with --note write a note, in your own words, on an episode
or the whole dataset. An issue on an episode withdraws a person’s ruling on it
in this dataset; deleting the issue puts the ruling back.
qualia dataset issues add <DATASET_UUID> "Gripper slips at the second grasp" -e <EPISODE_UUID> --at 12.5qualia dataset issues add <DATASET_UUID> "Recorded on the new rig" --note| Argument / option | Description |
|---|---|
DATASET | Dataset id or full name: the scope (required) |
TEXT | One sentence; its first line is the title (required) |
--episode, -e | The episode it is about; omit for the whole dataset |
--note | Write a note, which never blocks a keep |
--at | A moment in the episode, seconds from its start |
--body | More than the sentence says |
--request-id | Idempotency key: a retry with it returns the first issue |
--json | JSON output |
qualia dataset issues delete
Section titled “qualia dataset issues delete”Withdraw an issue or note you raised. An API key withdraws only what it raised
itself. An issue others replied to needs --force, which deletes their replies
too.
qualia dataset issues delete <ISSUE_UUID> -d <DATASET_UUID> --yes| Argument / option | Description |
|---|---|
ISSUE | Issue id or full name (required) |
--dataset, -d | The dataset it is read through; needed with an id |
--force | Also delete replies others wrote under it |
--yes, -y | Skip the confirmation (required without a terminal) |
--json | JSON output |
qualia dataset issues replies
Section titled “qualia dataset issues replies”List the replies under an issue or note, oldest first.
qualia dataset issues replies <ISSUE_UUID> -d <DATASET_UUID>| Argument / option | Description |
|---|---|
ISSUE | Issue id or full name (required) |
--dataset, -d | The dataset it is read through; needed with an id |
--limit, -n | Rows per page, 1-500 (default 50) |
--cursor | Pagination cursor, as the previous page printed |
--json | JSON output |
qualia dataset issues reply
Section titled “qualia dataset issues reply”Reply under an issue or note.
qualia dataset issues reply <ISSUE_UUID> "Trimmed it away" -d <DATASET_UUID>| Argument / option | Description |
|---|---|
ISSUE | Issue id or full name (required) |
TEXT | What to say (required) |
--dataset, -d | The dataset it is read through; needed with an id |
--request-id | Idempotency key: a retry with it returns the first reply |
--json | JSON output |
qualia dataset get
Section titled “qualia dataset get”Show one dataset: its kind, episode counts, robots, task link, tags, reach
settings and etag. DATASET is an id, a full name or a slug
(the dashboard address, /datasets/<slug>).
qualia dataset get kitchen-runqualia dataset get <DATASET_UUID> --json--json prints the qualia.v1 Dataset.
qualia dataset update
Section titled “qualia dataset update”Change a dataset’s name, description, target robot or reach settings. Only what you pass changes. A merged dataset writes its target robot and reach settings to every upload it holds.
qualia dataset update kitchen-run --name "Kitchen, day 2" --description ""qualia dataset update kitchen-run --target-robot <ROBOT_UUID>qualia dataset update kitchen-run --reach-solver dls --reach-base 0,0.1,0 --reach-heading 0.5qualia dataset update kitchen-run --reach-reset| Option | Description |
|---|---|
--name | New display name |
--description | New description; '' clears it |
--target-robot | The robot it plays on: a robot id or accounts/.../robots/...; '' clears |
--reach-solver | Reach check IK solver: pyroki, dls, or auto (the robot model’s) |
--reach-base | x,y,z metres from the grippers’ midpoint in the robot’s frame, or auto |
--reach-heading | Rotate both hand paths around world up, radians (within ±π) |
--reach-reset | Clear all three reach settings |
--etag | Refuse if the dataset changed since this etag |
The reach flags change one value at a time: the command reads the stored settings, changes what you passed and writes them back under the etag it read. Saving them starts nothing; the next reach check uses them.
qualia dataset merge
Section titled “qualia dataset merge”Merge uploads into one dataset, or add uploads to a merged one. A merge is
final: it cannot be undone. Preview it with --dry-run, which writes nothing.
qualia dataset merge day-1 day-2 --name "Bench" --dry-runqualia dataset merge day-1 day-2 --name "Bench" --resolve target_robot=accounts/<a>/robots/<r>qualia dataset merge day-3 --into bench --yes| Option | Description |
|---|---|
--name | Name of the new merged dataset (or pass --into) |
--into | Add the uploads to this merged dataset |
--description | Description of the new merged dataset |
--resolve | Answer a conflict: FIELD=VALUE, or channel_key:CHANNEL=KEY; repeatable |
--dry-run | List what differs between the uploads |
--yes, -y | Skip the confirmation (required without a terminal) |
A blocking conflict (features, cameras, channel names, fps, where the poses
are) settles only by leaving uploads out. The others take one value each:
answer them with --resolve; labels and the task default to the uploads’
commonest.
qualia dataset remap
Section titled “qualia dataset remap”Map native channel names onto canonical keys where the automatic grammar got them wrong, then derive the robot interface again. Renames add to earlier ones.
qualia dataset remap kitchen-run --rename /arm/joint_0=left.joint_0.pos --rename /arm/joint_1=NATIVE= resets that channel to the key read from its name. A key another
channel holds is refused and nothing is written: rename both to swap them.
qualia dataset reingest
Section titled “qualia dataset reingest”Ingest an MCAP upload’s recordings again under a new meta/ingest.toml, or read
a re-ingest that this command or resolve-poses started.
qualia dataset reingest kitchen-run --config ./ingest.toml --waitqualia dataset reingest kitchen-run --status <REINGEST_ID> --wait| Option | Description |
|---|---|
--config | The complete meta/ingest.toml; it replaces the published one |
--status | Read this re-ingest (its id or full name) instead |
--wait | Wait until it succeeds or fails |
--timeout | Seconds --wait waits (default 3600) |
The upload’s next generation is published; the old one stays readable and
versions cut earlier keep what they pinned. The published config again runs
nothing. A config with [episodes] spans re-cuts the upload and is refused
while any episode holds a person’s ruling, issue, note or edit. Mixtures,
merged datasets and LeRobot uploads are refused.
qualia dataset resolve-poses
Section titled “qualia dataset resolve-poses”Resolve a handheld upload’s poses at each hand’s tool centre point, with a
gripper’s tracker-to-TCP calibration, or undo that with --root.
qualia dataset resolve-poses kitchen-run --gripper <GRIPPER_UUID> --waitqualia dataset resolve-poses kitchen-run --rootThe calibration is read and sent as it stands now; a gripper without one is
refused before anything is sent. The work re-derives the whole upload, which
takes as long as checking its video again. Without --wait, follow it with
qualia dataset reingest <DATASET> --status <ID> --wait.
The same action as qualia dataset poses --at, which also
finds the upload’s capture gripper.
qualia dataset dismiss-upload
Section titled “qualia dataset dismiss-upload”Stop the upload feed reporting a failed or finished upload. The record of why it failed and the uploaded bytes are kept. A live upload is never hidden.
qualia dataset dismiss-upload <REPO_ID>qualia dataset dismiss-upload <REPO_ID> --through <UPDATED_AT_UNIX>REPO_ID is repo_id in qualia dataset uploads --json. --through is the
updated_at_unix you saw, so a failure recorded after it stays. Organization
keys only.
qualia dataset cancel-upload
Section titled “qualia dataset cancel-upload”Cancel an upload in progress, from any machine. The uploading process is refused its next step and stops; server-side work stops on its next heartbeat. Nothing is published. Refused once the upload has published. Organization keys only.
qualia dataset cancel-upload <REPO_ID>qualia dataset imports
Section titled “qualia dataset imports”List the account’s server-side Hugging Face imports, show one, or cancel one. Organization keys only.
qualia dataset importsqualia dataset imports <IMPORT_ID> --jsonqualia dataset imports <IMPORT_ID> --cancelqualia dataset copy
Section titled “qualia dataset copy”Copy a dataset into another workspace, of this organization or another one. The copy is a new dataset whose history starts at the copied version, and it records where it came from. It shares the source’s content, so inside one organization no media bytes are written. It prints what it did:
qualia dataset copy fold-bench --to Bench# Copied 4.0 GiB, 34 episodes in 0.8 s# Fold bench: accounts/<account>/datasets/<copy-id>qualia dataset copy <DATASET_UUID> --to "Partner Lab/Bench" --version v3 --name "Fold bench"# Copied 4.0 GiB (12 MiB written), 34 episodes in 1.4 sThe dataset is found in the CLI’s workspace (--workspace or
QUALIA_WORKSPACE, else the key’s own), by id, full name, slug or display
name. --to <workspace> is a workspace of the key’s organization, by name or
id. --to <org>/<workspace> names an organization and a workspace, each by name
or id. An organization named by name resolves through the places this key can
transfer to from the CLI’s workspace, so set --workspace or
QUALIA_WORKSPACE for it; without one, name it by ids. A target the rule
refuses prints the reason before anything is called.
Inside one organization you need read on the source and Contributor or higher in the target. Into another organization you need Admin or Owner in the source organization, and Contributor or higher in the target. A personal API key acts as its creator. A workspace or service key reaches only its own organization, and a key limited to some workspaces can target only those. A refusal prints the server’s reason and exits 1.
A tagged version that left episodes out is copied with new episode numbers, so the files that mix kept and left-out episodes are rewritten: tables always, and video too when the copy leaves the organization. A video that can’t be cut cleanly is re-encoded, and the result says its pixels changed.
qualia dataset copy fold-bench --to "Partner Lab/Bench" --version v3# Request id 3f1c…: if this stops, run it again within 24 hours with --request-id 3f1c…# Copying 26 episodes: 4 of 9 files.# Copied 1.6 GiB (1.5 GiB rewritten, 3.0 GiB written), 26 episodes in 3 minSuch a copy can run past its call. The command waits and prints how far it got
on stderr. Stopping the command stops nothing. The request id prints before the
first request: run the same command with --request-id to pick the copy up
again, within 24 hours of the first call. --request-id never starts a copy: if
the server no longer holds that id, the command says the copy stopped and
exits with status 1. Run it without --request-id to start again.
| Option | Description |
|---|---|
--to | Target workspace: <workspace> or <org>/<workspace> (required) |
--version | Version tag to copy; default the current version |
--name | Name of the copy; default the source’s, or <name> (copy) if taken |
--no-wait | Return at once with how far a running copy got |
--request-id | Pick up a copy by the id it printed, with the same options, within 24 hours |
--json | JSON output: the dataset, counts, bytes and seconds |
qualia dataset move
Section titled “qualia dataset move”Move a dataset to another workspace of this organization. It keeps its id, name, history, versions, checks and flags. You need Admin or Owner in the source workspace and Contributor or higher in the target. A move is refused across organizations (copy instead), while a mixture in the source workspace reads the dataset, and when its name is taken in the target.
qualia dataset move fold-bench --to Bench# Moved 4.0 GiB, 34 episodes in 0.1 s| Option | Description |
|---|---|
--to | Target workspace of this organization: name or id |
--json | JSON output: the dataset, counts, bytes and seconds |
qualia dataset setup
Section titled “qualia dataset setup”Set a dataset up for the reach solver: the robot it plays on, the solver and the placement. It does what the dashboard’s Setup strip does, so a handheld (UMI) dataset can be set up from a terminal or a pipeline. Only what you pass is written; the rest of the reach settings are kept, and repeating a command writes nothing.
qualia dataset setup <DATASET_UUID> --robot <ROBOT_UUID> --solver pyrokiqualia dataset setup <DATASET_UUID> --base 0 0 0 --heading 0qualia dataset setup <DATASET_UUID> --robot <ROBOT_UUID> --waitqualia dataset setup <DATASET_UUID> --run-solverFor a handheld upload, picking a robot with --robot also starts the resolve
at the TCP, when all of this holds:
- the dataset is an upload with handheld poses (not a mixture or a merged dataset);
- every arm of the robot has a TCP (a robot with one bare arm would leave one hand at the gripper root and the other at the TCP);
- the workspace has a gripper for the upload’s rig (the capture gripper, usually the UMI handheld) with a tracker-to-TCP calibration;
- the poses are not at the TCP yet, or are there with another calibration.
The resolve uses the capture gripper’s calibration, not the robot’s own
gripper’s: the robot only decides when. It re-derives the whole upload, so it
takes as long as ingesting it did. Without --wait the command prints the
operation and how to follow it (qualia dataset poses --follow). When nothing
starts, the command says why and leaves the poses where they are.
The solver is never started by itself. --run-solver presses Run solver once,
after waiting for a resolve this command started; follow the run with
qualia check reach-status.
| Option | Description |
|---|---|
DATASET | Dataset id or full name (required) |
--robot, -r | The robot it plays on: id or accounts/.../robots/...; '' clears it |
--solver | pyroki, dls, or robot to follow the robot’s model |
--base X Y Z | Where the takes’ start sits from the grippers’ midpoint: metres in the robot’s base frame, within 5 m |
--heading | Rotate the paired paths around up, degrees (+/- 180) |
--resolve / --no-resolve | Resolve the poses at the TCP whatever the robot / never (default: by the rules above) |
--wait, -w | Wait for a resolve to finish (minutes to hours) |
--run-solver | Press Run solver afterwards |
--json | JSON output |
Progress of a wait goes to stderr, so --json stays one document on stdout.
qualia dataset poses
Section titled “qualia dataset poses”Show where a handheld upload’s poses are, or move them. Without --at it
prints root (the gripper root’s poses), tcp (each hand’s TCP too) or
recorded (a raw recording, which a resolve converts), the rig, the capture
gripper, the calibration the poses were resolved with, and whether that gripper’s
calibration has changed since.
qualia dataset poses <DATASET_UUID>qualia dataset poses <DATASET_UUID> --at tcp --waitqualia dataset poses <DATASET_UUID> --follow <OPERATION_ID>qualia dataset poses <DATASET_UUID> --at root--at tcp re-derives the upload with the capture gripper’s calibration (the
same command again after the gripper’s calibration changed; with the same one it
changes nothing), --at root goes back. A ruling or trim made while it runs
fails it: run it again.
| Option | Description |
|---|---|
DATASET | Dataset id or full name (required) |
--at | tcp or root: move the poses (without it: show where they are) |
--wait, -w | With --at: wait for the re-derive to finish |
--follow | Wait for a resolve you started without --wait: its id or operation name |
--gripper | With --at tcp: resolve with this gripper’s calibration instead of the capture gripper’s |
--json | JSON output |
qualia mixture
Section titled “qualia mixture”A mixture is a dataset kept up to date from other datasets. It reads sources: a
dataset by name, every upload with one label value, or every upload linked to a
Task. A dataset source follows stable (its newest tag, the default), head
(what it yields now), or is pinned to one tag. Tag a mixture with
qualia dataset version create; delete one
with qualia dataset delete.
qualia mixture create
Section titled “qualia mixture create”Make a mixture with its sources, or from a version.
qualia mixture create "Folding, all rigs" \ --source dataset=rig-a-folding \ --source dataset=rig-b-folding@1.2 \ --source label=task:fold@head \ --source task=<TASK_UUID>
# a mixture that reads the dataset as version 1.0 froze it, to curate furtherqualia mixture create --from rig-a-folding:1.0| Option | Description |
|---|---|
NAME | Display name; with --from optional |
--source, -s | Repeatable: dataset=<id, name or slug>[@stable|@head|@<tag>], label=<task|robot|operator|method|scene>:<value>[@stable|@head], task=<task>[@stable|@head] |
--from | <dataset>:<tag>: the dashboard’s Curate from this version. Not with --source |
--description | Free text |
--json | {"mixture": {...}, "sources": [...]} |
The sources are added together, or none of them. When they are refused, the mixture made stays and the error names it.
qualia mixture sources
Section titled “qualia mixture sources”List a mixture’s sources in panel order: what each reads, how it follows it, its episodes and a newer tag when a pinned source has one.
qualia mixture sources folding-all-rigs --jsonqualia mixture remove-source
Section titled “qualia mixture remove-source”Remove a source from its mixture. Asks first; --yes skips the question.
qualia mixture remove-source accounts/…/datasets/…/sources/… --yesqualia mixture remove-source <SOURCE_ID> --mixture folding-all-rigs --yesqualia mixture pin-source
Section titled “qualia mixture pin-source”Keep a dataset source on one tag of what it reads. A pinned source holds its dataset out of no merge, so an upload a mixture reads can then be merged.
qualia mixture pin-source <SOURCE_ID> --mixture folding-all-rigsqualia mixture pin-source <SOURCE_ID> --mixture folding-all-rigs --tag 1.0Without --tag it pins the dataset’s newest tag. It refuses when the source
follows head and the dataset changed since that tag, since the pin would drop
those changes; tag them first, or pass --tag to pin anyway.
qualia mixture readers
Section titled “qualia mixture readers”The mixtures that read a dataset directly, each with how it follows it.
qualia mixture readers rig-a-folding --jsonqualia robot
Section titled “qualia robot”Register robots, import their models and give them a gripper. A robot owns its
gripper: attaching one copies a gripper’s URDF, TCP and jaw into a gripper of
the robot’s own, so lining it up or editing its TCP changes that robot only, and
the copy is a snapshot (recalibrating the handheld later does not change it). A
robot that carries a gripper never swaps it: to try another gripper, copy the
robot. Every command takes --json, and a robot is an id, accounts/.../robots/...
or its display name, looked up among robots only (show also finds gripper
designs).
qualia robot list
Section titled “qualia robot list”qualia robot listqualia robot list --gripperRobots oldest first (the first is the default target of a dataset). --gripper
lists the workspace’s gripper designs, such as the handheld’s, and the copies robots
own (each named like its source; the Owner column names the robot) instead. --limit
(-n) and --cursor page.
qualia robot show
Section titled “qualia robot show”qualia robot show <ROBOT_UUID>The robot’s type, serial number, whether it has a model, the gripper it carries
and where it sits on each arm (guessed until you set the mounts). For a gripper:
its TCP, the calibration file and date, and the rig it was copied from.
qualia robot get
Section titled “qualia robot get”The same as qualia robot show, for a caller that wants a robot: a gripper is
refused, a display name is looked up among robots only, and the etag is printed.
qualia robot get <ROBOT> --jsonqualia robot create
Section titled “qualia robot create”qualia robot create "Lab arm" --type franka_fr3 --serial SN-1qualia robot create "Lab arm" --urdf lab_arm.zip--urdf also imports a file in one step, as New embodiment does: a .urdf, a .zip of
the URDF and its meshes, or a directory. When the file never reaches an import,
the robot made for it is deleted again; an import that starts and then fails keeps
the robot, and the error names it. With --request-id the robot is kept, and running
the command again follows the import instead of uploading again.
| Option | Description |
|---|---|
NAME | Display name, unique in the account (required) |
--type, -t | Robot type key (franka_fr3, so101_follower); none for URDF-only |
--serial | Serial number, free text |
--request-id | Idempotency key (a UUID4) for a retry |
--urdf | Import this file in one step |
--wait, --no-wait | With --urdf: wait for the conversion (default on) |
--timeout | With --urdf: seconds to wait (default 1800) |
qualia robot import
Section titled “qualia robot import”qualia robot import <ROBOT_UUID> lab_arm.urdfqualia robot import <ROBOT_UUID> ./rizon_description # a directory is zippedqualia robot import <ROBOT_UUID> rizon.zip --no-waitReplaces the robot’s model with a .urdf, a .zip of the URDF and its meshes,
or a directory (hidden VCS folders are left out). The file is uploaded (at most
256 MiB) and the server converts the meshes: a second for a URDF, minutes for a
large mesh package. The command waits and prints each state on stderr;
--no-wait returns once the import is accepted, and --timeout bounds the wait
(seconds, default 1800). A URDF the server cannot use ends failed and the
command exits 1 with the server’s reason. A file symlinked within a directory is
zipped with its content; a link to a file outside it, a link to a directory or a
broken link is refused by name.
qualia robot model
Section titled “qualia robot model”qualia robot model <ROBOT_UUID>qualia robot model <ROBOT_UUID> --solver dls --reach-base 0 0 0qualia robot model <ROBOT_UUID> --arms-file arms.jsonWithout an option it prints the model: the import state, solver, each arm’s hand link and TCP, the jaw and the reach base. Options change only what they name.
| Option | Description |
|---|---|
--solver | pyroki or dls |
--arms-file | A JSON list of arms {"side": "left", "hand_link": "...", "tool": {"xyz": [], "rpy": []}, "start_posture": []}; replaces all |
--reach-base X Y Z | Where a dataset’s reach check starts when it names no base: metres in the robot’s base frame, within 5 m |
--clear-reach-base | Remove it |
--etag | Refuse if the model changed since this etag |
qualia robot copy
Section titled “qualia robot copy”qualia robot copy <ROBOT_UUID>qualia robot copy <ROBOT_UUID> --name "Lab arm, parallel gripper" --gripper <GRIPPER_UUID>Makes a new robot from an existing one, to try another gripper or a mount without
touching the original. The copy takes the robot’s type, URDF and meshes, arms,
solver, jaw, reach base and capsules and a gripper of its own, and shares nothing
with it afterwards; its serial number, datasets, reach results and history are not
copied. --gripper is keep (the default: a copy of the gripper it carries, with
its mounts), none, or a gripper or robot to copy a gripper from instead (mounted
at each arm’s hand link: line it up with qualia robot gripper mount). keep and
none are matched in any case; any other value must be a robot id (a UUID) or
resource name, and is checked before the copy is made. A copy is refused while the
model is being imported or the capsules fitted: try again in a minute.
With another gripper this is two calls, the copy and then the attach. If the attach
fails, the gripper-less copy stays: the command exits 1 with the attach’s own error
and a note naming the copy, which you can give a gripper with
qualia robot gripper attach <COPY> --copy-from ... or delete. Run again with the
same --request-id to retry; a copy that already carries a gripper is returned as
it is.
qualia robot rename and qualia robot delete
Section titled “qualia robot rename and qualia robot delete”qualia robot rename <ROBOT_UUID> "Lab arm 2"qualia robot delete <ROBOT_UUID> --force --yesDeleting a robot deletes the gripper it owns, files included. It is refused while
the robot has a model unless --force; datasets that played on it keep a dangling
reference. It asks first, or pass --yes. With --json it prints
{"robot": ..., "deleted": true, "force": ...}.
qualia robot update
Section titled “qualia robot update”Edit a robot’s name, type or serial number. '' clears a type or serial. For
the name, qualia robot rename is the same action.
qualia robot update <ROBOT> --name "Lab arm 2" --serial SN-0042| Option | Description |
|---|---|
--name | New name |
--type | Robot type key, e.g. franka_fr3 |
--serial | Serial number |
--etag | Refuse if changed since this etag |
--json | JSON output |
qualia robot configure
Section titled “qualia robot configure”Correct what the import guessed. Only what you pass changes. The command reads
the model and saves under its etag, so a change made meanwhile is refused.
qualia robot model edits the arms and solver too, and qualia robot gripper jaw
the jaw.
The jaw lives in the model of the gripper the robot carries, so --jaw-* and
--no-jaw write there: a second write when you also change the arms or solver.
--etag covers the robot’s model only. With --json a command that wrote both
adds the gripper’s model as carriedGripperModel.
Moving an arm’s hand link starts its posture at rest unless --home sets it,
and moves the carried gripper’s mount on that arm along, as the Embodiments page
does.
qualia robot configure <ROBOT> --arm left=left_link7 --arm right=right_link7qualia robot configure <ROBOT> --home right=0.2,0,0,0,0,0qualia robot configure <ROBOT> --solver dls --jaw-joint '{side}_finger_joint1' --jaw-open 0.8 --jaw-closed 0| Option | Description |
|---|---|
--arm | An arm’s hand link: left=LINK or right=LINK (repeatable) |
--home | An arm’s home posture, radians, one per turning joint: left=a,b,… |
--solver | IK solver: pyroki or dls |
--jaw-joint | The joint that opens the jaw; {side} is left or right |
--jaw-open | Its position fully open |
--jaw-closed | Its position shut |
--jaw-home | Its position at home |
--no-jaw | Clear the jaw joint |
--etag | Refuse if the robot’s model changed since this etag |
--json | JSON output |
qualia robot carry
Section titled “qualia robot carry”Give a robot a gripper, set the mounts of the one it carries, or take it off, in
one command. It does what qualia robot gripper attach --copy-from, mount and
detach do.
On a robot that carries none, GRIPPER is copied and the copy is the robot’s own.
With no --mount or --baked, it creates a mount at each
arm’s hand link with no offset, for each hand the gripper has a TCP in a link for.
A gripper with no such TCP gets no mount; set one with qualia robot gripper tcp
or calibration, then qualia robot gripper mount.
Naming the gripper the robot carries sets its mounts; without --mount each arm
keeps a mount that still hangs on its hand link. Any other gripper is refused: a
robot never swaps its gripper, so qualia robot copy it with the other one.
--none deletes the robot’s own gripper: it asks first, or pass --yes.
qualia robot carry <ROBOT> <GRIPPER>qualia robot carry <ROBOT> <ITS_GRIPPER> --mount left=left_link7:left-mount.json --baked rightqualia robot carry <ROBOT> --none --yes| Option | Description |
|---|---|
--none | Take the gripper off, which deletes it |
--mount | left=LINK or left=LINK:matrix.json: the gripper’s hand link in LINK’s frame, 16 numbers row-major, metres (default identity). Repeatable |
--baked | left or right: the robot’s URDF has the gripper built in on that arm |
--etag | Refuse if changed since this etag |
--yes, -y | With --none: skip the confirmation |
--json | JSON output |
qualia robot datasets
Section titled “qualia robot datasets”List the datasets played on a robot (their target robot). Takes --limit,
--cursor and --json.
qualia robot datasets <ROBOT>Two names for one action
Section titled “Two names for one action”Some actions have two commands. Both work; the last column says what differs.
| Command | Also | What differs |
|---|---|---|
qualia robot show | qualia robot get | get refuses a gripper and prints the etag |
qualia robot rename | qualia robot update --name | update also takes --type, --serial and --etag |
qualia robot model with options | qualia robot configure | configure sets one arm at a time, the jaw, and moves mounts with an arm |
qualia robot gripper jaw | qualia robot configure --jaw-* | configure changes one jaw field at a time |
qualia robot gripper attach --copy-from, mount, detach | qualia robot carry | One command; see above |
qualia robot gripper tcp --file | qualia gripper tcp | gripper tcp takes a design or a robot, by name among designs |
qualia robot gripper calibration | qualia gripper calibrate | The same |
qualia robot list --gripper | qualia gripper list | The same rows, with the TCP state and rig key |
qualia robot show <GRIPPER_ID> | qualia gripper get | get refuses a robot and looks a name up among designs |
qualia robot import <GRIPPER_ID> FILE | qualia gripper import | gripper import refuses a robot and looks a name up among designs |
qualia robot delete <GRIPPER_ID> --force | qualia gripper delete | gripper delete refuses a robot, always forces and looks a name up among designs |
qualia dataset poses --at | qualia dataset resolve-poses | poses also finds the capture gripper |
qualia robot gripper
Section titled “qualia robot gripper”The robot’s own gripper. Each command takes the robot that carries it.
qualia robot gripper attach <ROBOT_UUID> --copy-from <GRIPPER_UUID>qualia robot gripper attach <ROBOT_UUID> --urdf ./parallel_gripperqualia robot gripper mount <ROBOT_UUID> -m left:left_hand:0,0,0.02 -m right:right_hand:0,0,0.02qualia robot gripper jaw <ROBOT_UUID> --joint '{side}_finger_joint' --open 0.04 --shut 0qualia robot gripper tcp <ROBOT_UUID> --hand 'left:gripper_{side}_ee:0,0,0.12' --hand 'right:gripper_{side}_ee:0,0,0.12'qualia robot gripper calibration <ROBOT_UUID> tcp_calibration.jsonqualia robot gripper detach <ROBOT_UUID>attach gives a robot that carries none a gripper. --copy-from copies a
gripper design (the handheld’s, a library gripper) or another robot’s own gripper:
its URDF and meshes, TCP and jaw as they are now. --urdf uploads a gripper of the
robot’s own (a .urdf, .zip or directory) and imports it; it has no TCP yet, so
set one before you mount it. A robot that carries a gripper is refused:
qualia robot copy it with the other gripper, or detach first.
mount sets where the gripper sits on each arm and replaces all mounts, one per
arm at most. A mount is SIDE:LINK[:X,Y,Z[:ROLL,PITCH,YAW]], the position in metres
and the rotation in radians (URDF convention) of the gripper’s hand link in LINK’s
frame, where LINK is a link of the robot joined to the arm’s hand link by fixed
joints only; SIDE:baked says the robot’s own URDF already has the gripper built in.
The gripper’s hand needs a TCP in a link first. attach --copy-from takes --mount
too; without it the copy is mounted at each arm’s hand link with no offset, guessed.
jaw names the joint that opens the gripper ({side} stands for left or right)
and its position open and shut, checked against the URDF’s limits, and optionally
--home, its position at the arm’s home (never inferred; left out, the home the
model already has for the same joint is kept). It edits the model the jaw lives in:
the carried gripper’s, or the robot’s own when its URDF has the gripper built in or
it carries none.
tcp sets the TCP of each hand, SIDE:LINK:X,Y,Z[:ROLL,PITCH,YAW] in a link of
the gripper’s URDF ({side} in a link stands for the side); a hand keeps its link
once set, and hands not named keep theirs. Or --file a JSON of
{"left": {"link": "...", "matrix": [... 16 numbers ...]}, "right": {...}}.
calibration replaces the TCPs with a tcp_calibration.json. detach takes
the gripper off, which deletes it: its URDF, meshes, TCP and jaw.
On a workspace that has not been migrated yet, a robot may still carry a gripper
shared with other robots. jaw, tcp and calibration refuse to edit it by way of
the robot (the error names the gripper), because the edit would change every robot
that carries it; pass the gripper’s id instead of the robot’s to edit it for all of
them. mount is not affected: mounts are the robot’s own.
| Option | Description |
|---|---|
--copy-from / --urdf | attach: where the gripper comes from (exactly one) |
--name | attach --urdf: the gripper’s name |
--mount, -m | attach --copy-from, mount: a mount, repeat per arm |
--joint, --open, --shut, --home | jaw: the joint and its positions |
--hand, --file | tcp: the hands’ TCPs |
--filename | tcp, calibration: the name recorded with the TCP |
--etag | Refuse if it changed since this etag |
--yes, -y | detach: skip the confirmation |
qualia gripper
Section titled “qualia gripper”Gripper designs: one gripper’s URDF and the tool centre point (TCP) of each hand
on it. A robot takes a copy of its own (qualia robot gripper attach --copy-from,
qualia robot carry), so changing a design reaches no robot that already has a
copy. A gripper with a model and a calibration can be a handheld rig, whose
uploads are resolved at its TCP. A display name is looked up among designs only, never
among the copies robots own (they are named like their source): name a copy by its
id, or use qualia robot gripper.
qualia gripper list
Section titled “qualia gripper list”List the workspace’s gripper designs, oldest first, with whether each has a TCP.
The copies robots own are listed too, named like their source; Owner is the robot
that carries one. Same list as qualia robot list --gripper.
Takes --limit, --cursor and --json.
qualia gripper get
Section titled “qualia gripper get”Show a gripper: its rig key, whether uploads resolve with it, the calibration file and date, and each hand’s link and tracker-to-TCP.
qualia gripper get <GRIPPER>qualia gripper create
Section titled “qualia gripper create”Register a gripper design from its URDF or .zip, as ”+ gripper” does. The name
defaults to the file name; a taken name is refused. When the file never reaches
an import, the gripper made for it is deleted again. Takes --name,
--wait/--no-wait, --timeout (default 600) and --json.
qualia gripper create parallel_gripper.urdfqualia gripper import
Section titled “qualia gripper import”Import a new URDF onto a gripper. A TCP set in one of its links goes stale
until you set it again. Takes --wait/--no-wait, --timeout and --json.
qualia gripper delete
Section titled “qualia gripper delete”Delete a gripper design and its model (account owners only). Robots that copied
it keep their copy. A robot’s own gripper, named by its id, can be deleted too:
it comes off its robot, as qualia robot gripper detach does, unless a live dataset
still plays back with it. A workspace’s “UMI handheld” is an ordinary gripper: a
delete removes it for good. Pass --yes when there is no terminal.
qualia gripper tcp
Section titled “qualia gripper tcp”Set where the TCP is on each hand: a 4x4 matrix in one of the gripper’s URDF
links. Hands the file leaves out keep theirs. At most 64 KiB. Same action as
qualia robot gripper tcp --file, which takes the robot.
qualia gripper tcp <GRIPPER> tcp.json{ "left": { "link": "{side}_ee_base_link", "matrix": [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0.1, 0, 0, 0, 1] }, "right": { "link": "{side}_ee_base_link", "matrix": [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0.1, 0, 0, 0, 1] }}matrix is 16 numbers, row-major, metres, or a nested 4x4. {side} in a link
is replaced by left or right.
| Option | Description |
|---|---|
--filename | What to call the calibration; default tcp-matrix:<gripper> |
--etag | Refuse if the TCP changed since this etag |
--json | JSON output |
qualia gripper calibrate
Section titled “qualia gripper calibrate”Import a handheld rig’s tcp_calibration.json: each hand’s tracker-to-TCP, and
the TCP in the gripper’s end-effector link where the file gives it. It replaces
the gripper’s TCP. Takes --filename, --etag and --json. Same action as
qualia robot gripper calibration, which takes the robot.
qualia gripper calibrate <GRIPPER> tcp_calibration.jsonqualia task
Section titled “qualia task”Manage tasks: what a robot should do and how success shows. A task is a draft of five fields (description, scene, steps, success, failure) and an optional procedure, published as numbered revisions that never change. The Robots and Tasks guide walks through it.
Every qualia task command acts in the API key’s own account; a key acts in no
other, so --account and QUALIA_ACCOUNT are not needed. See
Authentication. A task is named by its id or
its full name, accounts/<ACCOUNT_UUID>/tasks/<TASK_ID>.
qualia task list
Section titled “qualia task list”List the account’s tasks, newest first, with their latest revision and whether the draft has unpublished changes.
A key restricted to workspaces reads no tasks.
qualia task listqualia task list -n 100| Option | Description |
|---|---|
--limit, -n | Page size, 1–500 (default: 20) |
--cursor | Pagination cursor |
--json | JSON output |
qualia task get
Section titled “qualia task get”Show a task with its draft, or one of its published revisions. --json prints
the task as the API returns it; edit that file and pass it to qualia task edit.
qualia task get <TASK_ID>qualia task get <TASK_ID> -r 2qualia task get <TASK_ID> --json > task.json| Option | Description |
|---|---|
--revision, -r | Show this published revision instead |
--json | JSON output |
qualia task create
Section titled “qualia task create”Create a task. Its draft comes from a file or from --description. Nothing is
published. A task needs a name: --name, or displayName in the file.
qualia task create --name "Cube in box" -d "Pick the cube off the table and put it in the box"qualia task create task.yaml --name "Cube in box"The file is YAML or JSON. It holds either a task as qualia task get --json
prints it (displayName, draft, references), or only the draft fields:
description: Pick the cube off the table and put it in the boxscene: A cube and an open box on a table; the cube's start position variessteps: | Grasp the cube Move it over the box Release itsuccess: The cube rests inside the boxfailure: The cube falls outside the box| Option | Description |
|---|---|
--name | Display name (overrides the file) |
--description, -d | What the robot should do |
--success | A picked success reference episode (repeatable, 1–3) |
--failure | A picked failure reference, MODE=<episode> (repeatable) |
--recovery | A picked recovery reference, MODE=<episode> (repeatable) |
--json | JSON output |
Reference episodes are full names, accounts/.../datasets/.../episodes/....
Pick them in the file or with options, not both.
qualia task edit
Section titled “qualia task edit”Save a task’s draft from a file, or single fields from options. A file replaces
the whole draft, procedure included. An option replaces only that field, and
"" clears it. Published revisions never change.
qualia task edit <TASK_ID> --success "The cube rests inside the box"qualia task edit <TASK_ID> --steps $'Grasp the cube\nRelease it over the box'qualia task edit <TASK_ID> task.json| Option | Description |
|---|---|
--name | New display name |
--description | What the robot should do |
--scene | The scene the task runs in |
--steps | The steps, one per line |
--success | How success shows |
--failure | How it fails |
--etag | Refuse if the task changed since this etag |
--json | JSON output |
Pass a draft file or field options, not both. A file from
qualia task get --json carries the task’s etag, so the save is refused if
someone changed the task since.
qualia task publish
Section titled “qualia task publish”Publish the draft as the next revision. It needs a description and a success; the other fields are optional. A procedure, when there is one, must have one start, a success outcome, every step reachable and no loops. Publishing also links the unlinked episodes and uploads whose task label is exactly the task’s name.
qualia task publish <TASK_ID> -m "First revision"| Option | Description |
|---|---|
--note, -m | What changed |
--etag | Publish only the draft as read at this etag |
--json | JSON output |
qualia task revisions
Section titled “qualia task revisions”List a task’s published revisions, newest first: number, note, content hash, who published it and when.
qualia task revisions <TASK_ID>| Option | Description |
|---|---|
--limit, -n | Page size, 1–500 (default: 20) |
--cursor | Pagination cursor |
--json | JSON output |
qualia task link-episodes
Section titled “qualia task link-episodes”Link the unlinked episodes and uploads whose task label names the task. It lists
the labels that match exactly beside the near misses (case, spacing,
punctuation) in your workspace. Without --label it links the exact matches;
with it, the labels you pass. A link already set is never changed, and labels
stay as they are.
qualia task link-episodes <TASK_ID> --dry-runqualia task link-episodes <TASK_ID> -l "cube in box" -l "Cube in box."| Option | Description |
|---|---|
--label, -l | A label to link, exactly as listed (repeatable) |
--dry-run | List the matching labels and link nothing |
--json | JSON output |
qualia task delete
Section titled “qualia task delete”Delete a task. Only account owners can. A task with a published revision is
refused unless you pass --force, which deletes its revisions too. It asks for
confirmation; pass --yes when there is no terminal.
qualia task delete <TASK_ID>qualia task delete <TASK_ID> --force --yes| Option | Description |
|---|---|
--force | Delete its published revisions too |
--etag | Refuse if changed since this etag |
--yes, -y | Skip the confirmation |
qualia task references
Section titled “qualia task references”Show the episodes a person picked for a task as references: each one’s id, role (success, failure, recovery), mode and episode.
qualia task references <TASK_ID>| Option | Description |
|---|---|
--limit, -n | Page size, 1–500 |
--cursor | Pagination cursor |
--json | JSON output |
qualia task reference add
Section titled “qualia task reference add”Pick an episode as one of the task’s references, as yourself. A task holds 1 to 3 success references and any number of failure and recovery modes, each with 1 or 2. A failure or recovery names its mode; a success has none. You need read access to the episode’s dataset.
qualia task reference add <TASK_ID> accounts/<ACCOUNT_UUID>/datasets/<DATASET_ID>/episodes/<EPISODE_ID>qualia task reference add <TASK_ID> <EPISODE_NAME> --role failure --mode slip --start 1.5 --end 4| Option | Description |
|---|---|
--role | success (default), failure or recovery |
--mode | The failure or recovery it shows (1–80 characters) |
--start | Range start, seconds into the episode (with --end) |
--end | Range end, seconds (with --start) |
--json | JSON output |
The episode is its full name, as qualia task references --json or
Episode.upload names it.
qualia task reference rm
Section titled “qualia task reference rm”Remove a reference from the task. The episode is untouched. It asks for
confirmation; pass --yes when there is no terminal.
qualia task reference rm <TASK_ID> <REFERENCE_ID> --yes| Option | Description |
|---|---|
--yes, -y | Skip the confirmation |
--json | JSON output ({} on success) |
qualia task draft
Section titled “qualia task draft”Ask a VLM to draft the task’s fields from exactly its picked references. It
never publishes. --estimate prices it and starts nothing.
qualia task draft <TASK_ID> --estimatequalia task draft <TASK_ID> --wait| Option | Description |
|---|---|
--model | VLM model |
--max-cost | Credit cap |
--estimate | Price the whole selection; start nothing |
--wait | Wait for the stored proposal |
--json | JSON output |
A draft needs a signed-in person: with an API key, --estimate and the draft
are refused (a person must draft a Task).
qualia task draft-get <DRAFT> reads a stored proposal and changes nothing.
qualia task draft-apply <DRAFT> saves it as the task’s draft; pass
--file <spec.yaml> to save your reviewed version instead. Publish it with
qualia task publish after review.
qualia task drafts
Section titled “qualia task drafts”List a task’s VLM drafts: each run’s id, state, model, credits, and error.
qualia task drafts <TASK_ID>| Option | Description |
|---|---|
--limit, -n | Page size, 1–500 (default: 20) |
--cursor | Pagination cursor |
--json | JSON output |
qualia task linked
Section titled “qualia task linked”List the datasets linked to a task, or with --episodes its episodes from every
dataset. An episode with no link of its own reads its dataset’s link; the
Link column says which. The global --workspace picks the workspace.
qualia task linked <TASK_ID>qualia task linked <TASK_ID> --episodes -n 100| Option | Description |
|---|---|
--episodes | List the linked episodes instead of datasets |
--limit, -n | Page size, 1–500 (default: 20) |
--cursor | Pagination cursor |
--json | JSON output |
qualia task link
Section titled “qualia task link”Link one episode to a task. A link, not an edit: the episode’s label, revisions
and versions stay as they are. --unlink removes the episode’s own link only if
it is to this task, and the episode then reads its dataset’s link again. To link
a whole upload, use qualia dataset link-task.
qualia task link <TASK_ID> --episode <EPISODE_NAME>qualia task link <TASK_ID> --episode <EPISODE_ID> --dataset <DATASET_ID>qualia task link <TASK_ID> --episode <EPISODE_NAME> --unlink| Option | Description |
|---|---|
--episode, -e | Episode id (with --dataset) or full name |
--dataset, -d | The dataset an episode id is read through |
--unlink | Remove the episode’s own link to this task |
--json | JSON output |
qualia git
Section titled “qualia git”qualia git install
Section titled “qualia git install”Enable fast large-file transfer for a cloned Qualia dataset repo. Run it once
inside the clone; it configures the Git filter and adds the tracked patterns to
.gitattributes, after which large files sync chunk-by-chunk instead of moving
whole.
git clone https://dev-api.qualiastudios.dev/git/<org>/<name>.gitcd <name>qualia git install| Option | Description |
|---|---|
--path | Path to the cloned dataset repo (default .) |
Tracked by default: *.safetensors, *.gguf, *.parquet, *.mp4, *.mcap,
*.bag, *.npz, *.npy, *.pt, *.bin, *.tar, *.zip. Patterns already
present in .gitattributes are left alone.
The clone’s origin must be the same endpoint the CLI is configured against —
the filter refuses a repo whose remote points somewhere other than the
configured base URL, so a repo cloned from one environment cannot be pushed to
another by changing the URL.
Without an API key the filter cannot move data; qualia git install says so
rather than failing later inside a git command.
qualia status
Section titled “qualia status”Running work and what ended recently, as the dashboard’s Running page shows
it: ingests, check runs, training jobs and pipeline runs. A status is named
under its workspace (accounts/<A>/workspaces/<W>/statuses/<OPERATION>), or
under the organization for the organization’s own work.
qualia status list
Section titled “qualia status list”List running work and work that ended within --recent, most recently
changed first. The default is the workspace the CLI acts in (--workspace,
else your key’s own).
qualia status listqualia status list --runningqualia status list --org --recent 7d --jsonqualia status list <WORKSPACE_ID> --filter 'service = "pipeline" AND state != FAILED'| Argument / Option | Description |
|---|---|
PARENT | Workspace ID or resource name (default: the workspace the CLI acts in) |
--org | The whole organization: every workspace’s work and its own |
--running | Only work that is queued or running |
--recent | How far back ended work goes: 90s, 30m, 24h, 7d (default 24h, max 90 days) |
--filter | AIP-160 filter on state, kind and service; OR binds tighter than AND |
--limit, -n | Page size, 1–500 (default 50) |
--cursor | Pagination cursor printed by the previous page |
Each line is the operation ID, kind, state, progress, target and last change,
and cancellable when qualia status cancel can stop it. A key restricted to
workspaces cannot read or cancel statuses.
qualia status cancel
Section titled “qualia status cancel”Ask the service running the work to stop it. Needs jobs:write and a
contributor role on the work’s workspace. The status turns CANCELLED a
moment after the service accepts; ended work, or a kind that cannot be
cancelled, is refused.
qualia status cancel <OPERATION_ID>qualia status cancel accounts/<A>/workspaces/<W>/statuses/<OPERATION_ID> --jsonqualia check
Section titled “qualia check”Run a check over a dataset and read what it found. The default check is the
VLM check (vlm): a model reads each episode against the Task it is linked
to. Confident failures become issues; uncertain readings become notes. Issues
are flags on episodes. A check never keeps, rejects or deletes an episode.
The VLM check costs credits. Run qualia check estimate first: it shows the
price and starts nothing. A run never spends more than it reserved.
qualia check also reads the thresholds the episode rules judge against
(ranges) and the reach check’s status and results (reach-status,
reach-cancel, results).
qualia check speaks qualia.v1, so it needs your account (--account or
QUALIA_ACCOUNT; see Authentication).
qualia check runs one check by its slug. To run several checks from the
catalog in one go, use qualia dataset checks.
qualia check estimate
Section titled “qualia check estimate”What a VLM check would read and reserve. Starts and charges nothing. It prints the credits, the episode count (and how many are left out because they are not linked to a published Task), the model it would use and every model offered. It also fails the way the run would, for example when no episode is linked to a published Task.
qualia check estimate <DATASET_UUID>qualia check estimate <DATASET_UUID> --max-episodes 50 --max-cost 200| Argument / option | Description |
|---|---|
DATASET | Dataset id or full name (required) |
--episode, -e | Check only this episode (repeatable) |
--filter | Check only episodes matching this filter |
--model, -m | VLM model; one of the models estimate lists as offered |
--max-episodes | Sample at most N episodes |
--max-cost | Credit ceiling |
--json | JSON output |
Pass the same --max-episodes and --max-cost to qualia check run to
reserve the same amount.
qualia check run
Section titled “qualia check run”Start a check over a dataset. Without --check it runs the VLM check. It
prints the name of each run it started (one per upload of a merged dataset);
--wait waits for each run to end and prints its result.
--check reach presses Run solver on a dataset: set the robot first with
qualia dataset setup, and follow the run with
qualia check reach-status.
qualia check run <DATASET_UUID> --max-episodes 50 --max-cost 200 --waitqualia check run <DATASET_UUID> --check reach| Argument / option | Description |
|---|---|
DATASET | Dataset id or full name (required) |
--check, -c | Check slug (default vlm); - runs the dataset’s defaults |
--episode, -e | Check only this episode (repeatable) |
--filter | Check only episodes matching this filter |
--model, -m | VLM model; one of the models estimate lists as offered |
--max-episodes | Sample at most N episodes |
--max-cost | Credit ceiling |
--wait, -w | Wait for each run to end; exits 1 if one failed |
--json | JSON output |
qualia check status
Section titled “qualia check status”Show where a run stands: its state, how many issues it raised and resolved, and for the VLM check the model, the episodes read and the pass, fail and uncertain counts.
qualia check status accounts/<ACCOUNT>/checks/vlm/runs/<RUN_ID>| Argument / option | Description |
|---|---|
RUN | Run name, accounts/.../checks/.../runs/..., as run prints |
--json | JSON output |
qualia check runs
Section titled “qualia check runs”List check runs, newest first.
qualia check runs --dataset <DATASET_UUID>qualia check runs --check vlm --state RUNNING| Option | Description |
|---|---|
--check, -c | Check slug; - for all (default -) |
--dataset, -d | Only this dataset’s runs |
--state | QUEUED, RUNNING, SUCCEEDED or FAILED |
--limit, -n | Rows per page, 1-1000 (default 20) |
--cursor | Pagination cursor, as the previous page printed |
--json | JSON output |
qualia check findings
Section titled “qualia check findings”The issues and notes a check raised on a dataset, with the model’s reading:
the episode, the verdict, the confidence, the moments in seconds it points at,
and the text. For what catalog checks wrote per episode, passes included, use
qualia dataset checks findings.
qualia check findings <DATASET_UUID>qualia check findings <DATASET_UUID> --limit 100 --json| Argument / option | Description |
|---|---|
DATASET | Dataset id or full name (required) |
--check, -c | Check slug (default vlm) |
--filter | More issue filter, ANDed |
--limit, -n | Rows per page, 1-1000 (default 20) |
--cursor | Pagination cursor, as the previous page printed |
--json | JSON output |
qualia check get
Section titled “qualia check get”One check: its kind, what it checks, the dataset kinds it runs on, and whether
this deployment can run it. qualia check get vlm says whether the VLM check
is set up here.
qualia check getqualia check get reach --json| Argument / option | Description |
|---|---|
CHECK | vlm, episode-rules, mixture or reach (default vlm) |
--json | JSON output |
qualia check ranges
Section titled “qualia check ranges”The reference ranges the episode rules judge against, in your workspace. Each
range is one metric on one robot interface (or one robot): its quantiles and
the fences an episode is judged against. An upload’s interface is its
robotInterface.interfaceHash (SDK client.datasets.get).
qualia check ranges --interface-hash b3:<HEX>qualia check ranges --metric duration_seconds --json| Option | Description |
|---|---|
--check, -c | Check slug (default episode-rules) |
--interface-hash | Only this robot interface (b3:…) |
--robot | Only ranges narrowed to this robot (id or name) |
--metric | Only this metric |
--filter | More range filter (interface_hash, robot, metric) |
--limit, -n | Rows per page, 1-1000 (default 20) |
--cursor | Pagination cursor, as the previous page printed |
--json | JSON output |
qualia check reach-status
Section titled “qualia check reach-status”Where a dataset’s reach check (Run solver) stands: the robot, the settings a run would use now, the last run with how many takes it solved, and whether it is stale (the robot, model, placement or poses changed since). It reads only; nothing runs by itself. A dataset with no usable robot has no key, and a run would start nothing.
qualia check reach-status <DATASET_UUID>| Argument / option | Description |
|---|---|
DATASET | Dataset id or full name (required) |
--json | JSON output |
Press Run solver with qualia check run <DATASET> --check reach or
qualia dataset setup <DATASET> --run-solver.
qualia check reach-cancel
Section titled “qualia check reach-cancel”Stop the Run solver press that is under way. Takes not yet sent to the solver are dropped and takes already solved keep their results: the next run answers them from storage and solves the rest. It prints the status after the cancel.
qualia check reach-cancel <DATASET_UUID>| Argument / option | Description |
|---|---|
DATASET | Dataset id or full name (required) |
--json | JSON output |
qualia check results
Section titled “qualia check results”What the reach check stored per take: for each handheld or egocentric take on
the dataset’s target robot, its state (NOT_RUN where nothing is solved under
the current key yet), how many stretches the robot cannot follow and the
longest, in seconds.
qualia check results <DATASET_UUID>qualia check results <DATASET_UUID> --state SUCCEEDED --json| Argument / option | Description |
|---|---|
DATASET | Dataset id or full name (required) |
--check, -c | Check slug (default reach; only reach stores results) |
--episode, -e | Only this episode |
--state | PENDING, SUCCEEDED, FAILED or NOT_RUN |
--robot | Only results on this robot (id or name) |
--filter | More result filter, e.g. reach.longest_seconds > 1 |
--limit, -n | Rows per page, 1-1000 (default 20) |
--cursor | Pagination cursor, as the previous page printed |
--json | JSON output |
qualia dataset checks
Section titled “qualia dataset checks”The checks catalog on one dataset. Catalog checks are versioned checks with an
id such as task.graph or task.criteria, grouped by category.
qualia dataset checks run runs a selection of them as one run;
qualia dataset checks findings reads what they found.
qualia dataset checks list <DATASET_UUID>qualia dataset checks run <DATASET_UUID> --category heuristic --validate-onlyqualia dataset checks run <DATASET_UUID> --all --max-cost 200 --waitqualia dataset checks findings <DATASET_UUID> --verdict FAILlist shows every catalog check by category: whether it can run on this
dataset (or why not) and its last result.
run runs the union of --check, --category and --all. Name at least one.
A run reads one kind of check: the kind --check names, else VLM when a VLM
check can run here, else the heuristics. It lists the checks it leaves out, with
why, but not graph.observe and graph.evaluate: they run only inside
qualia check run. A run needs --max-cost covering its bound: see the bound
first with --validate-only, which starts nothing.
Option (run) | Description |
|---|---|
DATASET | Dataset id or full name (required) |
--check, -c | A catalog check id, e.g. task.graph (repeatable) |
--category | Every runnable check of this category (repeatable) |
--all | Every catalog check that can run here |
--episode, -e | Check only this episode (repeatable) |
--filter | Check only episodes matching this filter |
--model, -m | VLM model for the VLM checks in the selection |
--max-episodes | Sample at most N episodes |
--max-cost | Credit ceiling; required unless --validate-only |
--validate-only | Resolve the selection and its bound; start nothing |
--wait, -w | Wait for the run to end; exits 1 if it failed |
--json | JSON output |
qualia dataset checks findings
Section titled “qualia dataset checks findings”What catalog checks found on a dataset, newest first: per check, episode and
finding, the verdict (PASS, FAIL or UNKNOWN), what it raised (ISSUE,
NOTE or NONE) and a title.
qualia dataset checks findings <DATASET_UUID>qualia dataset checks findings <DATASET_UUID> --check task.graph --verdict FAILqualia dataset checks findings <DATASET_UUID> --run accounts/<ACCOUNT>/checks/vlm/runs/<RUN_ID> --json| Argument / option | Description |
|---|---|
DATASET | Dataset id or full name (required) |
--check, -c | A catalog check id; - for all (default) |
--run | Only this run’s findings (its full name) |
--episode, -e | Only this episode |
--verdict | PASS, FAIL or UNKNOWN |
--limit, -n | Rows per page, 1-1000 (default 20) |
--cursor | Pagination cursor, as the previous page printed |
--json | JSON output |