Data & Sensors
Generate simulation datasets as tracked runs, keep them inspectable and portable, discover the sensors attached to your machine, and verify the computer-vision stack — all without Caasi ever importing a single heavy library.
caasi dataset
| Subcommand | What it does |
|---|---|
list | List datasets under the datasets base directory. |
generate | Generate a dataset from an experiment. |
inspect | Inspect a dataset. |
convert | Convert a dataset into a portable index (jsonl/csv). |
validate | Validate a dataset. |
download | Download a dataset (Hugging Face, NGC or URL) as a tracked run. |
Descriptions are the CLI's own — caasi dataset --help prints this list. For datasets
generated by Isaac Sim Replicator see caasi synth;
for fetching existing ones see dataset download below
and its extended treatment in
synthetic.html.
What a dataset is
A dataset is a directory with a metadata.json plus any of the known data
subdirectories:
wave-100-20260905-170412/
├── metadata.json
├── episodes/ # per-episode recordings
├── observations/ # agent observations
├── actions/
├── rewards/
├── poses/
├── images/ # RGB frames (--record-images)
├── depth/ # depth frames (--record-depth)
└── lidar/ # point clouds (--record-lidar)
Datasets are looked for in the project's datasets/ directory when you are inside
a project, otherwise in paths.datasets (default ~/.caasi/datasets).
Directory names follow <name-slug>-<YYYYmmdd-HHMMSS>.
The QUERY argument
inspect, convert and validate accept:
- a path to any directory containing
metadata.json; latest/last/newest;- a dataset name or unique name prefix
(
caasi dataset inspect wave).
Unknown or ambiguous → Error: No dataset matching '<query>'. (exit 1).
caasi dataset list
caasi dataset list [--limit|-n N] [--json]
Every dataset under the base directory — the project's datasets/ when you are inside
a project, else paths.datasets — newest first. A directory counts only when it holds a
metadata.json; --limit defaults to 20 (and
--limit 0 means “none”).
shellcaasi dataset list
Name Status Files Size
wave-100-20260905-170412 generating 1301 81.3 KiB
aloha-sim-20260905-180233 downloading 13 877 B
caasi dataset list --limit 1 --json | jq '.datasets[0]'
{
"name": "wave-100-20260905-170412",
"path": "/home/you/.caasi/datasets/wave-100-20260905-170412",
"status": "generating",
"source": null,
"files": 1301,
"size": 83269
}
Status and source come straight from metadata.json
(unknown / null when absent), while Files and
Size are counted on disk, recursively and including metadata.json — the
same scan inspect reports. The JSON payload is
{"base": "<datasets dir>", "datasets": [{"name", "path", "status", "source", "files",
"size"}]}.
An empty base directory is data, not an error — No datasets found. in yellow, exit
0 ({"base": …, "datasets": []} in JSON):
shellcaasi dataset list
No datasets found.
caasi dataset list --json
{
"base": "/home/you/.caasi/datasets",
"datasets": []
}
caasi dataset generate
caasi dataset generate CONFIG_PATH [--episodes N] [--workers N] [--record-images]
[--record-depth] [--record-lidar] [--name NAME] [--dry-run] [-- SCRIPT_ARGS…]
| Parameter | Kind | Type | Default | Description |
|---|---|---|---|---|
CONFIG_PATH | argument | path | required | The experiment YAML whose script collects the data. |
--episodes | option | int | — | → script arg --episodes N. |
--workers | option | int | — | → script arg --workers N. |
--record-images | option | flag | off | → script arg --record-images. |
--record-depth | option | flag | off | → script arg --record-depth. |
--record-lidar | option | flag | off | → script arg --record-lidar. |
--name | option | str | experiment name | Dataset name (dir name gets a timestamp suffix). |
--dry-run | option | flag | off | Show the command; create nothing. |
What happens on launch:
- The dataset directory is created and
metadata.jsonis written withstatus: "generating", the experiment path, backend, episodes/workers, the record flags and the linkedrun_id. - The script receives
--dataset-dir <dir>and the environment variableCAASI_DATASET_DIR— write your collected files there. - A detached run (
kind: dataset) is started exactly likesim run.
shellcaasi dataset generate experiments/collect.yaml --episodes 100 --record-images
Dataset generation started: /home/you/.caasi/datasets/wave-100-20260905-170412
Run: 20260905-170412-wave — follow it with 'caasi logs 20260905-170412-wave -f'
caasi dataset inspect
caasi dataset inspect QUERY [--json]
Shows the metadata, the linked run's live status, and what is actually on disk (file counts per subdirectory, total size):
shellcaasi dataset inspect latest
wave-100-20260905-170412
/home/you/.caasi/datasets/wave-100-20260905-170412
name wave-100
created 2026-09-05T17:04:12+08:00
experiment /home/you/demo/experiments/collect.yaml
backend sim
episodes 100
record images=True depth=False lidar=False
status generating
Run: 20260905-170412-wave (succeeded)
Directory Files
episodes 100
images 1200
caasi dataset inspect latest --json | jq '.run'
{ "id": "20260905-170412-wave", "status": "succeeded" }
JSON payload: {"path", "metadata", "contents": {"files", "size", "dirs"}, "run"};
run is null when unlinked, or {"id", "status": "unknown"}
if the run was deleted.
caasi dataset convert
caasi dataset convert QUERY [--to jsonl|csv] [--output PATH]
Builds a portable index of every file in the dataset (relative path + size,
excluding metadata.json and previous indexes) — handy for training pipelines that
just need a file list:
shellcaasi dataset convert latest --to csv
Index written to /home/you/.caasi/datasets/wave-100-20260905-170412/index.csv (1300 file(s)).
head -3 /home/you/.caasi/datasets/wave-100-20260905-170412/index.csv
path,size
episodes/ep_000.json,4213
images/frame_00000.png,184322
Defaults: --to jsonl (one {"path": …, "size": …} object per line),
output <dataset>/index.<fmt>. Unknown format →
Error: unknown index format '…' (expected one of jsonl, csv) (exit 1).
caasi dataset validate
caasi dataset validate QUERY [--json]
Structural validation:
metadata.jsonexists, is valid JSON and an object;nameis present;- if
episodesis an integer andepisodes/exists, the file count must match the declared number.
shellcaasi dataset validate latest --json
{
"path": "/home/you/.caasi/datasets/wave-100-20260905-170412",
"valid": false,
"issues": ["metadata declares 100 episode(s) but episodes/ contains 97"]
}
exit code: 1
Exit 0 valid / 1 any issue — in both human and JSON mode.
caasi dataset download
caasi dataset download REF [--backend hf|ngc|url] [--name NAME] [--dry-run] [-- EXTRA…]
Fetches a dataset that already exists instead of generating one. The backend is auto-detected
from the reference's scheme; --backend forces one (and then a bare
org/name is accepted too). Caasi resolves an upstream downloader and delegates the
whole transfer to it — no HTTP client, no SDK, nothing imported:
| Reference | Backend | Tool (first found on PATH) | Command built |
|---|---|---|---|
hf://org/name | hf | hf, then huggingface-cli | <tool> download org/name [EXTRA…] --local-dir <dataset-dir> |
ngc://org/name:version | ngc | ngc | <tool> registry dataset download-version org/name:version [EXTRA…] --dest <dataset-dir> |
http(s)://…/file | url | curl, then wget | curl -L [EXTRA…] -o <dataset-dir>/file <url> (wget [EXTRA…] -O …) |
The destination is a fresh dataset directory named --name or the source's last path
segment, plus the usual timestamp suffix. The transfer starts as a detached run —
kind: dataset, backend = the detected backend, extra: {source,
dataset} in the manifest — and metadata.json is written at launch with
status: "downloading" and the run_id, so
caasi run status and caasi logs follow it like any
other run:
shellcaasi dataset download hf://lerobot/aloha_sim --dry-run
Dry run — nothing was started:
command: hf download lerobot/aloha_sim --local-dir /home/you/.caasi/datasets/aloha-sim-20260905-180233
dest: /home/you/.caasi/datasets/aloha-sim-20260905-180233
caasi dataset download https://example.com/data.tar.gz --dry-run
Dry run — nothing was started:
command: /usr/bin/curl -L -o /home/you/.caasi/datasets/data-tar-gz-20260905-180411/data.tar.gz https://example.com/data.tar.gz
dest: /home/you/.caasi/datasets/data-tar-gz-20260905-180411
caasi dataset download https://example.com/data.tar.gz
Dataset download started: /home/you/.caasi/datasets/data-tar-gz-20260905-180512
Run: 20260905-180512-data-tar-gz — follow it with 'caasi logs 20260905-180512-data-tar-gz -f'
Unrecognized flags pass straight through to the tool, between the source and the destination
flags — --revision main yields
hf download lerobot/aloha_sim --revision main --local-dir <dataset-dir>. A
--dry-run needs no downloader installed (the command is printed with the backend's
default tool name) and leaves no directory behind.
Both refusals happen before anything is created, and both exit 1:
shell# neither hf nor huggingface-cli on PATH
caasi dataset download hf://lerobot/aloha_sim
Error: No download tool found for backend 'hf'.
exit code: 1
caasi dataset download ftp://example.com/x
Error: Cannot detect a download backend for 'ftp://example.com/x' (use hf://, ngc://, http(s):// or --backend hf|ngc|url).
exit code: 1
Once the files land the directory is an ordinary dataset: dataset
list shows it with its source and status, and
inspect / convert / validate all work on it. Cache behaviour
and the Replicator-side workflow are covered in
synthetic.html.
caasi sensor
Discovers sensors by scanning /dev, sysfs and pip metadata — vendor SDKs are
never imported. Five sensors are known:
| Name | Kind | Detected via | If missing |
|---|---|---|---|
cameras | video4linux | /dev/video* + /sys/class/video4linux/*/name | hint: v4l2-ctl --list-devices |
realsense | depth-camera | pip package pyrealsense2 | hint: pip install pyrealsense2 |
zed | depth-camera | directory /usr/local/zed | hint: install the ZED SDK |
lidar | serial | /dev/ttyUSB*, /dev/ttyACM* | hint: connection/udev rules |
isaacsim | simulation | the usual Isaac Sim detection chain | hint: caasi setup isaacsim |
caasi sensor list
caasi sensor list [--json]
shellcaasi sensor list
Sensor Kind Status Detail
cameras video4linux detected 1 device(s)
realsense depth-camera not detected pyrealsense2 not installed
zed depth-camera not detected ZED SDK not found
lidar serial not detected 0 serial device(s)
isaacsim simulation detected Isaac Sim 6.0 at /opt/isaac-sim-6.0
caasi sensor list --json | jq '.[0]'
{ "name": "cameras", "kind": "video4linux", "detected": true,
"detail": "1 device(s)", "devices": ["/dev/video0 (Integrated Webcam)"],
"hint": "check the device with 'v4l2-ctl --list-devices'" }
Always exits 0 — missing sensors are data, not errors.
caasi sensor inspect
caasi sensor inspect NAME [--json]
Detail for one sensor (devices list, hint). Exit 0 even when not detected;
1 for an unknown name (Error: Unknown sensor '<n>'. Valid: cameras,
realsense, zed, lidar, isaacsim).
caasi sensor test
caasi sensor test NAME [--json]
Gating version of inspect: exits 0 when the sensor is detected,
1 when not — for scripts like:
shellcaasi sensor test cameras || echo "no camera — using sim sensors"
Sensor 'cameras' is available: 1 device(s)
caasi sensor test lidar --json
{ "name": "lidar", "ok": false, "detail": "0 serial device(s)" }
exit code: 1
caasi vision
Diagnoses the computer-vision Python stack. “Installed” means pip metadata is present — the
package is never imported by status/inspect. Six components, each
mapped to its import module and candidate distributions:
| Component | Module | Distributions checked (in order) |
|---|---|---|
opencv | cv2 | opencv-python, opencv-python-headless, opencv-contrib-python |
open3d | open3d | open3d, open3d-cpu |
onnxruntime | onnxruntime | onnxruntime-gpu, onnxruntime |
tensorrt | tensorrt | tensorrt |
pytorch | torch | torch |
pillow | PIL | pillow |
caasi vision status
caasi vision status [--json]
shellcaasi vision status
Component Status Version Module
opencv installed 4.10.0 cv2
open3d installed 0.18.0 open3d
onnxruntime installed 1.19.0 onnxruntime
tensorrt missing — tensorrt
pytorch installed 2.4.0 torch
pillow installed 10.4.0 PIL
Install missing components with 'pip install <package>'.
JSON: array of {"name", "installed", "version", "module"}. Always exits
0.
caasi vision inspect
caasi vision inspect COMPONENT [--json]
One component in detail, with an install hint when missing. Exit 0 for known
names (installed or not); 1 for unknown names.
caasi vision test
caasi vision test [COMPONENT…] [--python PATH] [--json]
The real proof: imports each component — in a subprocess, with a 30-second timeout,
optionally using a different interpreter (--python, default: the CLI's own). This
catches broken installs that pip metadata alone would happily report as fine.
shellcaasi vision test
opencv: 4.10.0
open3d: 0.18.0
onnxruntime: 1.19.0
tensorrt: missing
pytorch: 2.4.0
pillow: 10.4.0
exit code: 1
caasi vision test opencv pytorch --python /opt/IsaacLab/_isaac_sim/python.sh --json
[ { "name": "opencv", "ok": true, "detail": "4.10.0" },
{ "name": "pytorch", "ok": true, "detail": "2.4.0" } ]
Exit 0 only if every tested component imports successfully;
1 if any fails, times out, or the name is unknown. No arguments = all six.