Caasi v0.2.0 Physics & foundation models: physics · warp · groot · cosmos

Physics & Foundation Models

Four Tier-4 groups wrap the physics engines and the foundation-model stacks — physics, warp, groot and cosmos — plus scene reconstruct, which hands a capture to a neural-reconstruction CLI. Caasi implements none of them: every command resolves an upstream tool from the catalog, starts it as a tracked run, and — when nothing is installed — fails honestly and names the config key that would point at it.

GroupCatalog domainCommandsWhat it delegates
caasi physicsphysics — kind sim, tool isaacsimstatus · list · run · benchmarkPhysX, Newton, Warp, MuJoCo, Gazebo: a launcher choice plus CAASI_PHYSICS_ENGINE.
caasi warpwarp — kind pythonstatus · test · benchmarkNVIDIA Warp: a device probe in a subprocess, your benchmark script as a run.
caasi grootgroot — kind python, tool grootstatus · setup · run · train · evaluateThe Isaac GR00T repo's own installer, module and scripts, through its own interpreter.
caasi cosmoscosmos — kind pythonstatus · run · datasetThe Cosmos CLI (or -m cosmos_predict1) with your arguments forwarded verbatim.
caasi scene reconstructcapability nurec of usdA NuRec CLI that turns a capture into OpenUSD.

Shared conventions:

caasi physics

The physics “interface” is deliberately thin: a launcher choice and one environment variable, nothing more. Caasi picks the engine the catalog resolves, exports CAASI_PHYSICS_ENGINE=<engine> to the run, and — when that engine ships its own launcher script — swaps it into the command's first position. PhysX runs through Isaac Sim's python.sh; Newton runs through the Newton launcher when one exists (isaac-sim.newton.sh, shipped next to python.sh). Five engines are known:

EngineDetected viaCoreLauncher used
physxpaths extsPhysics/*physx*, exts/omni.physx* under the Isaac Sim rootyesthe experiment's own (Isaac Sim python.sh)
newtonpath isaac-sim.newton.sh; modules newton-physics, newtonnoisaac-sim.newton.sh when it resolved as a .sh path
warpmodules warp, warp-langnothe experiment's own
mujocomodule mujoconothe experiment's own
gazebobinaries gz, gazebonothe experiment's own

caasi physics status

caasi physics status [--json]

Reports the five engines plus the engine that would be used by default (physics.default, else physx). On a machine with no Isaac Sim this is the real output:

shellcaasi physics status
Physics Engines
  Engine         physx
Capability  State    Detail
physx       missing  not installed
newton      absent   not installed
warp        absent   not installed
mujoco      absent   not installed
gazebo      absent   not installed
0 of 5 capabilities installed.

The core capability shows missing, the optional ones absent; exit 0 — this is a report, not a gate. The Root and Launcher rows appear only once Isaac Sim is registered in the tool registry (or ISAACSIM_PATH is set), because the physics domain is a sim domain and has no Python fallback:

shellcaasi physics status
Physics Engines
  Root           /opt/isaac-sim-6.0
  Launcher       /opt/isaac-sim-6.0/python.sh
  Engine         physx
Capability  State      Detail
physx       installed  /opt/isaac-sim-6.0/extsPhysics/omni.physx
newton      installed  /opt/isaac-sim-6.0/isaac-sim.newton.sh
warp        absent     not installed
mujoco      absent     not installed
gazebo      installed  /usr/bin/gz
3 of 5 capabilities installed.

JSON carries the standard status payload (domain, kind, tool, root, total, installed, capabilities, launcher, running) plus this group's own engine key:

shellcaasi physics status --json | jq '{domain, kind, tool, root, total, installed, engine, running}'
{
  "domain": "physics",
  "kind": "sim",
  "tool": "isaacsim",
  "root": null,
  "total": 5,
  "installed": 0,
  "engine": "physx",
  "running": []
}

caasi physics list

caasi physics list [--json]

The engine table with the how of each detection — package, binary, module, env or path — and the default engine note:

shellcaasi physics list
Engine  State  Found via  Detail
physx   •      —          not installed
newton  •      —          not installed
warp    •      —          not installed
mujoco  •      —          not installed
gazebo  •      —          not installed
Default engine: physx — change it with: caasi config set physics.default <engine>

On a machine with Isaac Sim registered the same command reports the path detections from the install tree (physx under extsPhysics/, newton through isaac-sim.newton.sh) and any gz/gazebo binary as binary. In the JSON payload the per-engine launcher is set only for an engine that resolves to a launcher script of its own — newton:

shellcaasi physics list --json | jq '.default, .engines[1]'
"physx"
{
  "engine": "newton",
  "installed": true,
  "how": "path",
  "value": "/opt/isaac-sim-6.0/isaac-sim.newton.sh",
  "launcher": "/opt/isaac-sim-6.0/isaac-sim.newton.sh"
}

JSON shape: {"domain", "default", "engines": [{"engine", "installed", "how", "value", "launcher"}]}how, value and launcher are null for an engine that was not detected. Always exits 0.

caasi physics run

caasi physics run CONFIG_PATH [--engine KEY] [--name NAME] [--dry-run] [--json] [ARGS…]
ParameterKindTypeDefaultDescription
CONFIG_PATHargumentpathrequiredExperiment YAML (.yaml/.yml) — the same file sim run consumes; extra arguments pass through to it.
--engineoptionstrphysics.default, else physxPhysics engine to use: physx, newton, warp, mujoco, gazebo.
--nameoptionstrexperiment nameName for the tracked run.
--dry-runoptionflagoffPrint the command without starting it.
--jsonoptionflagoffEmit the run record as JSON.
trailing argspass-throughAppended to the script's argv, after --headless when the experiment declares it.

What happens, in order:

  1. The experiment YAML is loaded. A missing file is an honest failure — even for --dry-run.
  2. The engine is picked: --enginephysics.defaultphysx. An unknown key or an engine that is not detected on this machine fails and names the catalog key that would point at it.
  3. The command is built from the experiment (backend sim, lab or python) and the engine is applied: CAASI_PHYSICS_ENGINE=<engine> in the environment, plus the engine's launcher in first position when it has one.
  4. --dry-run prints command, cwd and engine; otherwise a detached run (kind: run, the experiment's backend) is started and its manifest records the experiment path and the engine.
shellcaasi physics run /tmp/nope.yaml --dry-run
Error: experiment config not found: /tmp/nope.yaml
exit code: 1
caasi physics run experiments/stack_cubes.yaml --dry-run
Error: 'physx' is not available (extsPhysics/*physx*, exts/omni.physx*). Install it, or point Caasi at the renamed upstream with `caasi config set catalog.physics.physx.paths [...]`.
exit code: 1
caasi physics run experiments/stack_cubes.yaml --engine nope --dry-run
Error: Unknown physics engine 'nope'. Known: physx, newton, warp, mujoco, gazebo
exit code: 1

On a machine where the engines resolve, the dry run shows the launcher that each engine brings — python.sh for PhysX, isaac-sim.newton.sh for Newton:

shellcaasi physics run experiments/stack_cubes.yaml --dry-run
Dry run — nothing was started:
  command: /opt/isaac-sim-6.0/python.sh /home/you/demo/scripts/stack_cubes.py --steps 1000 --headless
  cwd:     /home/you/demo/experiments
  engine:  physx (CAASI_PHYSICS_ENGINE)
caasi physics run experiments/stack_cubes.yaml --engine newton --dry-run
Dry run — nothing was started:
  command: /opt/isaac-sim-6.0/isaac-sim.newton.sh /home/you/demo/scripts/stack_cubes.py --steps 1000 --headless
  cwd:     /home/you/demo/experiments
  engine:  newton (CAASI_PHYSICS_ENGINE)
caasi physics run experiments/stack_cubes.yaml --engine newton --name newton-stack
Started run 20260907-211734-newton-stack.
  Follow it with: caasi logs 20260907-211734-newton-stack -f

caasi physics benchmark

caasi physics benchmark CONFIG_PATH [--engine KEY] [--name NAME] [--dry-run] [--json] [ARGS…]

Exactly physics run with kind: benchmark and one extra line after launch — the reminder that the run's stdout can be parsed for metrics (caasi benchmark report):

shellcaasi physics benchmark experiments/stack_cubes.yaml --dry-run
Error: 'physx' is not available (extsPhysics/*physx*, exts/omni.physx*). Install it, or point Caasi at the renamed upstream with `caasi config set catalog.physics.physx.paths [...]`.
exit code: 1
# on a machine where the newton engine resolves:
caasi physics benchmark experiments/stack_cubes.yaml --engine newton --name newton-bench
Started run 20260907-211734-newton-bench.
  Follow it with: caasi logs 20260907-211734-newton-bench -f
  When finished: caasi benchmark report 20260907-211734-newton-bench
Two config keys, one env var

caasi config set physics.default <engine> changes the engine used when --engine is absent. caasi config set physics.engines.<engine>.launcher <path> overrides the launcher for one engine — an absolute path, or a path relative to the Isaac Sim tool root, e.g. caasi config set physics.engines.newton.launcher isaac-sim.newton.sh. A launcher that is not a file is ignored, and an engine detected through a .sh path uses that path. The run's environment always carries CAASI_PHYSICS_ENGINE=<engine> so the experiment can branch on it. Caasi never imports a physics engine.

caasi doctor --component physics

The same probes as one doctor section, Physics Engines. physx is the only core capability, so it is the only row that can fail (exit 1); every other engine is optional and is skipped. The warp domain reports into this section too, which is why Warp appears here as well as under caasi warp:

shellcaasi doctor --component physics
Environment Diagnostics

Physics Engines
  ✗ PhysX — not found (extsPhysics/*physx*, exts/omni.physx*)
      ↳ Install it, or point Caasi at the renamed upstream with `caasi config set
catalog.physics.physx.paths [...]`.
  • Newton — not found (newton-physics, newton, isaac-sim.newton.sh)
  • Warp — not found (warp, warp-lang)
  • MuJoCo — not found (mujoco)
  • Gazebo — not found (gz, gazebo)
✘ 1 issue(s) found, 0 warning(s). Run with --verbose for hints.
exit code: 1
caasi doctor --component physics --json | jq '{summary, exit_code}'
{ "summary": { "fail": 1, "skip": 4 }, "exit_code": 1 }

caasi warp

One capability — warp in the warp domain, detected through the modules warp / warp-lang, and marked core. Caasi never imports Warp in-process: test runs a probe in a subprocess and benchmark starts your script as a detached run. The interpreter is the physics domain's launcher — Isaac Sim's python.sh when a tool is registered (Warp ships inside the Isaac Sim install, so its interpreter is the one that can see it), otherwise the CLI's own Python.

caasi warp status

caasi warp status [--json]

The capability plus the interpreter that test and benchmark would use, as the Launcher row (JSON key launcher):

shellcaasi warp status
NVIDIA Warp
  Launcher       /home/you/demo/.venv/bin/python3
Capability  State    Detail
warp        missing  not installed
0 of 1 capabilities installed.
caasi warp status --json | jq '{domain, kind, tool, total, installed, launcher, running}'
{
  "domain": "warp",
  "kind": "python",
  "tool": null,
  "total": 1,
  "installed": 0,
  "launcher": "/home/you/demo/.venv/bin/python3",
  "running": []
}

With Isaac Sim registered the Launcher row becomes its python.sh — that is the interpreter Warp is looked for in.

caasi warp test

caasi warp test [--json]

The real proof: a subprocess runs

import warp; warp.init(); print(warp.get_devices())

with a 120-second timeout (the first init can compile kernels). The capability is resolved first, so a machine without Warp gets an honest failure instead of a Python traceback:

shellcaasi warp test
Error: No warp capability is installed. Install it, or point Caasi at the renamed upstream with `caasi config set catalog.warp.<capability>.<field> [...]`.
exit code: 1
# with Warp installed, the probe runs in a subprocess:
caasi warp test
Warp initialized. Devices:
  ['cpu', 'cuda:0']

If the probe itself fails, the last line of its stderr (or stdout) is reported: Error: Warp test failed: <detail> (exit 1). JSON always carries the whole probe — {"domain", "python", "returncode", "devices", "stdout", "stderr"} — with devices being the non-empty stdout lines, and exits 0 only when the subprocess did:

shellcaasi warp test --json | jq '{python, returncode, devices}'
{
  "python": "/opt/isaac-sim-6.0/python.sh",
  "returncode": 0,
  "devices": ["['cpu', 'cuda:0']"]
}

caasi warp benchmark

caasi warp benchmark [--name NAME] [--dry-run] [--json] [ARGS…]

A pure pass-through: the command is [<resolved interpreter>, ARGS…], so ARGS must say what to run — a script path or -m <module>. Caasi adds no Warp flags of its own, and with nothing to run it refuses rather than guessing:

shellcaasi warp benchmark
Error: Nothing to benchmark — pass a script or `-m <module>`, e.g. `caasi warp benchmark bench.py`.
exit code: 1
caasi warp benchmark benchmarks/warp_bench.py --dry-run
Dry run — nothing was launched:
  command: /home/you/demo/.venv/bin/python3 benchmarks/warp_bench.py
caasi warp benchmark -m warp.tests.test_bench --dry-run
Dry run — nothing was launched:
  command: /home/you/demo/.venv/bin/python3 -m warp.tests.test_bench

Launched for real it is a tracked run (backend: python, kind: benchmark, default name warp) with the benchmark-report reminder:

shellcaasi warp benchmark benchmarks/warp_bench.py --name warp-bench
Started run 20260907-211734-warp-bench.
  Follow it with: caasi logs 20260907-211734-warp-bench -f
  When finished: caasi benchmark report 20260907-211734-warp-bench
caasi run status warp-bench --json | jq '{id, backend, kind, status}'
{
  "id": "20260907-211734-warp-bench",
  "backend": "python",
  "kind": "benchmark",
  "status": "succeeded"
}

Metrics are parsed from the run's stdout by caasi benchmark report — Caasi does not interpret them itself.

caasi groot

Isaac GR00T is a repository, not a package Caasi installs: everything here runs the repo's own installer, module and scripts through the repo's own interpreter. The repository is discovered as the catalog's repo capability — the GR00T_PATH environment variable first, then the common paths ~/Isaac-GR00T, ~/gr00t and ~/workspaces/Isaac-GR00T, plus anything you add with caasi config set catalog.groot.repo.paths [...]. The tools.groot registry entry (falling back to $GR00T_PATH) supplies the root used for the repo's python.sh and for the relative script paths:

CapabilityDetected viaCoreUsed by
repoenv GR00T_PATH; paths ~/Isaac-GR00T, ~/gr00t, ~/workspaces/Isaac-GR00Tyesevery groot command
modulemodule gr00tnogroot run (the default capability)
trainscript scripts/finetune.py under the repo rootnogroot train, groot run --backend train
evaluatescript scripts/eval.py under the repo rootnogroot evaluate, groot run --backend evaluate
datascript scripts/data.py under the repo rootnogroot run --backend data

The three script capabilities carry no probe of their own: they always read absent in status, but their resolved script path is what train/evaluate run. An upstream release that moves a file is a config edit — caasi config set catalog.groot.train.script <path>.

caasi groot status

caasi groot status [--json]

Without the repo there is nothing to delegate to, and the core capability says so:

shellcaasi groot status
Isaac GR00T
  Launcher       /home/you/demo/.venv/bin/python3
Capability  State    Detail
repo        missing  not installed
module      absent   not installed
train       absent   not installed
evaluate    absent   not installed
data        absent   not installed
0 of 5 capabilities installed.

With GR00T_PATH set (or the repo in one of the common paths) the Root row appears, the launcher is the repo's own python.sh, and the script capabilities resolve against that root:

shellcaasi groot status
Isaac GR00T
  Root           /home/you/Isaac-GR00T
  Launcher       /home/you/Isaac-GR00T/python.sh
Capability  State      Detail
repo        installed  /home/you/Isaac-GR00T
module      absent     not installed
train       absent     not installed
evaluate    absent     not installed
data        absent     not installed
1 of 5 capabilities installed.
caasi groot status --json | jq '.capabilities[2]'
{
  "key": "train",
  "label": "catalog.groot.train",
  "group": null,
  "core": false,
  "found": false,
  "how": null,
  "value": null,
  "launch": null,
  "script": "/home/you/Isaac-GR00T/scripts/finetune.py",
  "nodes": []
}

caasi groot setup

caasi groot setup [--execute] [--name NAME] [--dry-run] [--json]
ParameterKindTypeDefaultDescription
--executeoptionflagoffActually run the install steps as a tracked run.
--nameoptionstrgroot-setupName for the tracked run.
--dry-runoptionflagoffPrint the steps without executing them — it wins over --execute.
--jsonoptionflagoffEmit machine-readable JSON output.

The steps are the repo's own: post_install.sh when the repo has one, otherwise <repo python> -m pip install -e .. By default they are only printed — installing a foundation-model repo changes environments, so Caasi does not do it unless you say so:

shellcaasi groot setup
Error: The GR00T repository was not found (GR00T_PATH, ~/Isaac-GR00T, ~/gr00t, ~/workspaces/Isaac-GR00T). Clone it, set GR00T_PATH, or point Caasi at it with `caasi config set catalog.groot.repo.paths [...]`.
exit code: 1
# with the repo present — GR00T_PATH set, or one of the common paths:
caasi groot setup
GR00T install steps (/home/you/Isaac-GR00T) — not executed:
  command: /home/you/Isaac-GR00T/post_install.sh
  cwd:     /home/you/Isaac-GR00T
  Execute them as a tracked run with: caasi groot setup --execute
caasi groot setup --json
{
  "domain": "groot",
  "executed": false,
  "command": ["/home/you/Isaac-GR00T/post_install.sh"],
  "cwd": "/home/you/Isaac-GR00T"
}
caasi groot setup --execute
Started run 20260907-211738-groot-setup.
  Follow it with: caasi logs 20260907-211738-groot-setup -f

The executed form is a detached run with backend: python, kind: setup and the repo root in its manifest, so caasi run status latest shows the command that ran.

caasi groot run

caasi groot run [--backend|-b CAPABILITY] [--name NAME] [--dry-run] [--json] [ARGS…]

Delegates to one capability of the repo — module by default, or whatever catalog.groot.default names. module becomes <repo python> -m gr00t ARGS…; any other key becomes <repo python> <repo script> ARGS…. The working directory is always the repo root, and the run is recorded with backend: groot, kind: groot:

shellcaasi groot run --dry-run
Error: The GR00T repository was not found (GR00T_PATH, ~/Isaac-GR00T, ~/gr00t, ~/workspaces/Isaac-GR00T). Clone it, set GR00T_PATH, or point Caasi at it with `caasi config set catalog.groot.repo.paths [...]`.
exit code: 1
# with the repo present but the gr00t module not installed:
caasi groot run --dry-run
Error: 'module' is not available (gr00t). Install it, or point Caasi at the renamed upstream with `caasi config set catalog.groot.module.modules [...]`.
exit code: 1
# a script capability needs no module — only the repo:
caasi groot run --backend train --dry-run
Dry run — nothing was launched:
  command: /home/you/Isaac-GR00T/python.sh /home/you/Isaac-GR00T/scripts/finetune.py
  cwd:     /home/you/Isaac-GR00T
caasi groot run --backend train --name finetune -- configs/a.yaml
Started run 20260907-211734-finetune.
  Follow it with: caasi logs 20260907-211734-finetune -f

caasi groot train / caasi groot evaluate

caasi groot train CONFIG_PATH [--name NAME] [--dry-run] [--json] [ARGS…]
caasi groot evaluate CONFIG_PATH [--name NAME] [--dry-run] [--json] [ARGS…]

Both take the config file the GR00T script expects and hand it to the repo's own script through the repo's own interpreter — scripts/finetune.py for train, scripts/eval.py for evaluate, each path taken from the catalog. The config is checked before anything is resolved, the run is detached (backend: groot, kind: train/evaluate, default name = the config file's stem) and its manifest records the config path:

shellcaasi groot train /tmp/nope.yaml --dry-run
Error: config not found: /tmp/nope.yaml
exit code: 1
# with the repo present:
caasi groot train configs/gr00t_finetune.yaml --dry-run
Dry run — nothing was launched:
  command: /home/you/Isaac-GR00T/python.sh /home/you/Isaac-GR00T/scripts/finetune.py configs/gr00t_finetune.yaml
  cwd:     /home/you/Isaac-GR00T
caasi groot evaluate configs/gr00t_eval.yaml --dry-run
Dry run — nothing was launched:
  command: /home/you/Isaac-GR00T/python.sh /home/you/Isaac-GR00T/scripts/eval.py configs/gr00t_eval.yaml
  cwd:     /home/you/Isaac-GR00T
caasi groot train configs/gr00t_finetune.yaml --name finetune-v2
Started run 20260907-211734-finetune-v2.
  Follow it with: caasi logs 20260907-211734-finetune-v2 -f

A script the repo does not have (or has moved) is reported with the exact key that fixes it:

shellcaasi groot train configs/gr00t_finetune.yaml --dry-run
Error: /home/you/Isaac-GR00T has no scripts/finetune.py. Fix the path with: caasi config set catalog.groot.train.script <path>
exit code: 1
Whose interpreter?

GR00T ships a python.sh of its own, and that is what runs its scripts: the tools.groot registry entry first, then $GR00T_PATH, then this process' Python as a last resort. Nothing is installed into the environment Caasi itself runs in.

caasi cosmos

The lowest-priority group and the thinnest one: caasi cosmos resolves a Cosmos entry point and forwards your arguments to it verbatim. Two capabilities, neither core — module (cosmos_predict1, cosmos1) and cli (binaries cosmos, ngc). A CLI found as a binary wins and is run directly (the run's backend is the binary's basename); otherwise the module is run as <caasi python> -m <module>. Caasi knows no Cosmos flags and invents none.

caasi cosmos status

caasi cosmos status [--json]
shellcaasi cosmos status
NVIDIA Cosmos
  Launcher       /home/you/demo/.venv/bin/python3
Capability  State   Detail
module      absent  not installed
cli         absent  not installed
0 of 2 capabilities installed.
caasi cosmos status --json | jq '{domain, kind, total, installed, launcher, running}'
{
  "domain": "cosmos",
  "kind": "python",
  "total": 2,
  "installed": 0,
  "launcher": "/home/you/demo/.venv/bin/python3",
  "running": []
}

caasi cosmos run

caasi cosmos run [--name NAME] [--dry-run] [--json] [ARGS…]

With nothing to forward there is nothing to delegate, and with nothing installed the failure names the key that would point at a CLI:

shellcaasi cosmos run
Error: Nothing to forward — pass the arguments for the Cosmos CLI, e.g. `caasi cosmos run <args>`.
exit code: 1
caasi cosmos run predict --dry-run
Error: No cosmos capability is installed. Install it, or point Caasi at the renamed upstream with `caasi config set catalog.cosmos.cli.binaries [...]`.
exit code: 1

Once a CLI resolves, the arguments are the command — backend is the binary's basename and kind is cosmos (default run name cosmos):

shellcaasi cosmos run predict --checkpoint /models/cosmos_predict1.pt --dry-run
Dry run — nothing was launched:
  command: /usr/local/bin/cosmos predict --checkpoint /models/cosmos_predict1.pt
caasi cosmos run predict --checkpoint /models/cosmos_predict1.pt --name cosmos-predict
Started run 20260907-211737-cosmos-predict.
  Follow it with: caasi logs 20260907-211737-cosmos-predict -f

caasi cosmos dataset

caasi cosmos dataset [--name NAME] [--dry-run] [--json] [ARGS…]

The same pass-through for Cosmos dataset work — kind: dataset, default run name cosmos-dataset, and the same two honest failures:

shellcaasi cosmos dataset
Error: Nothing to forward — pass the arguments for the Cosmos CLI, e.g. `caasi cosmos dataset <args>`.
exit code: 1
caasi cosmos dataset prepare --input /data/raw --dry-run
Dry run — nothing was launched:
  command: /usr/local/bin/cosmos prepare --input /data/raw

caasi scene reconstruct

Neural reconstruction is delegated, like everything else on this page: scene reconstruct resolves the nurec capability of the usd catalog domain (binary nurec) and hands it a capture — a ros2 bag directory recorded by caasi scene capture, or any dataset path. Caasi implements no reconstruction and reads no frames; the run is tracked like any other (backend: nurec, kind: reconstruct).

Usage

caasi scene reconstruct CAPTURE [--dry-run] [ARGS…]
ParameterKindTypeDefaultDescription
CAPTUREargumentpathrequiredCapture to reconstruct (ros2 bag directory or dataset path).
--dry-runoptionflagoffShow the command without starting a run.
trailing argspass-throughAppended after the capture path, for the NuRec CLI to interpret.

The two gates run in order — the capture must exist, then a reconstruction tool must resolve — and on a machine without NuRec this is the real output:

shellcaasi scene reconstruct /tmp/nope --dry-run
Error: Capture '/tmp/nope' not found.
exit code: 1
caasi scene reconstruct datasets/kitchen-capture --dry-run
Error: No neural reconstruction tool detected (nurec). Install NuRec, or point Caasi at its CLI: caasi config set catalog.usd.nurec.binaries "[<cli>]".
exit code: 1

With a CLI resolved — its own, or one you named with caasi config set catalog.usd.nurec.binaries "[<cli>]" — the command is [<nurec>, <capture>, ARGS…]:

shellcaasi scene reconstruct datasets/kitchen-capture --dry-run
Dry run — nothing was started:
  command: /usr/local/bin/nurec datasets/kitchen-capture
caasi scene reconstruct datasets/kitchen-capture --output kitchen.usd
Reconstruction started for datasets/kitchen-capture.
  Follow it with: caasi logs 20260907-213012-kitchen-capture -f

The run is named after the capture's directory name, and its manifest carries the capture path, so caasi run list shows which capture produced which reconstruction. Note that --output above is not a Caasi option: it is forwarded to the NuRec CLI, which decides what it means.

caasi doctor --component platform

One doctor section — Foundation Models & Teleop — covers GR00T, Cosmos, NuRec and the two teleop stacks. The GR00T repo capability is the only core row here, so it is the only one that fails the check; the packages, the CLIs and NuRec are optional and are skipped:

shellcaasi doctor --component platform
Environment Diagnostics

Foundation Models & Teleop
  ✗ GR00T repository — not found (GR00T_PATH, ~/Isaac-GR00T, ~/gr00t, ~/workspaces/Isaac-GR00T)
      ↳ Install it, or point Caasi at the renamed upstream with `caasi config set
catalog.groot.repo.env [...]`.
  • gr00t package — not found (gr00t)
  • Cosmos package — not found (cosmos_predict1, cosmos1)
  • Cosmos CLI — not found (cosmos, ngc)
  • NuRec (neural reconstruction) — not found (nurec)
  ✗ Keyboard teleop — not found (teleop_twist_keyboard)
      ↳ Install it, or point Caasi at the renamed upstream with `caasi config set
catalog.teleop.keyboard.packages [...]`.
  • Joystick teleop — not found (teleop_twist_joy, joy)
✘ 2 issue(s) found, 0 warning(s). Run with --verbose for hints.
exit code: 1
caasi doctor --component platform --json | jq '[.checks[] | {name, status}]'
[ { "name": "GR00T repository", "status": "fail" },
  { "name": "gr00t package", "status": "skip" },
  { "name": "Cosmos package", "status": "skip" },
  { "name": "Cosmos CLI", "status": "skip" },
  { "name": "NuRec (neural reconstruction)", "status": "skip" },
  { "name": "Keyboard teleop", "status": "fail" },
  { "name": "Joystick teleop", "status": "skip" } ]

A resolved row reads ✓ NuRec (neural reconstruction) — /usr/local/bin/nurec and carries the hint detected via binary (shown by --verbose). The two teleop rows need the ros2 CLI: on a machine without one they report • Keyboard teleop — skipped (ROS 2 CLI unavailable) with the hint Install ROS 2 to enable Nav2 / MoveIt 2 / ros2_control checks. — they never fail for a missing ROS 2.

Nothing here is Caasi's own

No engine, no kernel, no model and no reconstruction is implemented by Caasi. What it adds is detection (the catalog), a launcher choice, tracked runs with logs, and honest failures that name the config key to fix. Every name on this page — engine keys, package names, binaries, script paths — is catalog data: caasi config catalog physics, caasi config catalog groot, caasi config catalog cosmos and caasi config catalog usd print it.