Caasi v0.2.0 Configuration: files, precedence, tool registry, environment variables

Configuration

Caasi is configured with layered YAML files. There is no database, no daemon and nothing hidden: caasi config show always prints exactly what the CLI will use, and every command reads the same merged result.

Config files & precedence

Four file locations are merged, lowest precedence first:

#SourceLocationPurpose
1Built-in defaultscompiled into CaasiSane starting point (see below).
2Global config~/.config/caasi/config.yaml
(or $XDG_CONFIG_HOME/caasi/config.yaml)
Your machine: tool registry, paths, remotes.
3Project config./caasi.yaml (current directory)Per-project overrides. Inside a project this is also the project marker file — see Projects.
4CAASI_CONFIGany path from the env varCI / experiment-specific config.
5--config <path>any path from the flagHighest precedence, one-shot override.

Merging is a recursive dict merge: a project file that sets one key under tools: does not wipe the rest of the global registry. After merging, the CAASI_LANG, CAASI_LAYOUT and CAASI_HELP_ORDER environment variables (if set) override language, layout and help_order.

Malformed files

A config file that is unreadable, invalid YAML, or whose top level is not a mapping is silently treated as empty. If your settings seem ignored, run caasi config path and caasi config show.

Built-in defaults

language: en
layout: rich                   # 'rich' (bordered tables) or 'plain' (aligned columns)
help_order: grouped            # 'grouped' (titled panels), 'core' or 'alpha' (flat a–z)
defaults:
  output: table
paths:
  runs: ~/.caasi/runs          # where tracked runs live
  datasets: ~/.caasi/datasets  # where generated datasets go
tools: {}                      # the tool registry (see below)

A complete global config example

# ~/.config/caasi/config.yaml
language: en
paths:
  runs: /data/caasi-runs        # big disk for logs and artifacts
tools:
  isaacsim:
    default: "6.0"
    versions:
      "6.0": { path: /opt/isaac-sim-6.0 }
      "5.1": { path: /opt/isaac-sim-5.1 }
  isaaclab:
    versions:
      "2.0": { path: /opt/IsaacLab, python: /opt/IsaacLab/_isaac_sim/python.sh }
remotes:
  gpu-box:
    host: 10.0.0.5
    user: robot
    port: 2222
    identity: ~/.ssh/id_ed25519
    path: ~/experiments          # remote working directory

The tool registry

The registry is how you tell Caasi where your installs are — and which version to use when you have several side by side (very common with Isaac Sim). It lives under the top-level tools: key.

Multi-version form

tools:
  isaacsim:
    default: "6.0"              # which version commands resolve to
    versions:
      "6.0": { path: /opt/isaac-sim-6.0 }
      "5.1": { path: /opt/isaac-sim-5.1, python: /opt/isaac-sim-5.1/python.sh }

Single-install form

tools:
  isaaclab:
    path: /opt/IsaacLab
    python: /opt/IsaacLab/_isaac_sim/python.sh   # optional interpreter override

How a tool is resolved

  1. With the multi-version form, the requested version is used; without one, default; without a default, the first version key in file order.
  2. Version keys are compared as strings, so a float 6.0 default matches the key "6.0". Quoting version keys in YAML is recommended.
  3. Resolution produces {name, version, path, python}; commands then derive their launchers from path: Isaac Sim → <path>/python.sh, Isaac Lab → <path>/isaaclab.sh (unless python is set).

Set registry entries with dotted keys (quote version segments):

shellcaasi config set tools.isaacsim.versions."6.0".path /opt/isaac-sim-6.0
Set tools.isaacsim.versions."6.0".path = /opt/isaac-sim-6.0 (saved to /home/you/.config/caasi/config.yaml)
caasi config set tools.isaacsim.default "6.0"
caasi config tools
Tool      Default  Versions  Resolved path
isaacsim  6.0      6.0       /opt/isaac-sim-6.0

Registry vs. environment variables

If a tool is not in the registry, Caasi falls back to detection (ISAACSIM_PATH/ISAACLAB_PATH env vars, common install locations, pip metadata — see Architecture). The registry always wins when present, and is the only way to manage multiple versions.

Capability catalog

Caasi is a layer over tools it does not own, so no upstream package name, binary or launch file is hardcoded in the CLI. They are rows in a capability catalog: domains (isaacros, slam, motion, physics, teleop, sdg, …) hold capabilities (slam.visual, physics.gazebo, …), and every capability lists the probes that can find it on this machine. The catalog is overridable from config under the top-level catalog: key, so an upstream rename is a config edit rather than a Caasi release. Print the effective table with caasi config catalog.

Probe order

Probing is subprocess, pip-metadata and filesystem only — the CLI never imports the ecosystem it detects. A capability's fields are tried in this order and the first hit wins:

#FieldProbeReported as
1packagesros2 pkg prefix <name> (skipped entirely when there is no ros2 CLI)package → the install prefix
2binaries<name> found on PATHbinary → the executable path
3modulespip metadata of the first listed distribution that exists (never imported)module → its version
4envthe variable is set and non-emptyenv → its value
5pathsglob under the capability's tool root; a pattern starting with ~ or / is globbed from its own parent directory insteadpath → the first match in sorted order

Two fields sit outside that chain. script is resolved on its own — an absolute path is used when the file exists, a relative one is joined to the tool root — and is attached to the result whether or not the capability was found. launch is a [package, file] pair handed to ros2 launch. The tool root itself comes from the tool registry first and from the tool's environment variable (ISAACSIM_PATH, ISAACLAB_PATH, GR00T_PATH) second.

Overriding a capability

The override path is catalog.<domain>.<capability>.<field>, and the rule is deliberately the only one: an override replaces that field wholesale — lists are not appended to. An override may also add a capability, or a whole domain, that the built-ins do not know about. default is reserved at domain level: it names the capability a group uses when you omit --backend.

catalog:
  slam:
    default: toolbox                 # used when `caasi slam launch` gets no --backend
    visual:
      label: "Visual SLAM (v4)"      # row label in status / doctor output
      packages: [isaac_ros_visual_slam_v4]
      launch: [isaac_ros_visual_slam_v4, visual_slam.launch.py]
      topics: [/tf, /map]
      group: slam                    # the caasi group that wraps it
      core: true                     # absent = a doctor failure, not a skip
  physics:
    newton:
      paths: [isaac-sim.newton.sh]   # relative to the domain's tool root (isaacsim)
      modules: [newton-physics, newton]

Overridable fields: label, packages, binaries, modules, env, paths, topics (lists), launch (a two-element pair), script, group, tool and core. Unknown fields are ignored, and key comes from the mapping key. A domain that ships a tool root (perception, physics, groot, usd, data, teleop, sdg) forces it on every capability it contains, so tool only takes effect on domains that have none.

Set it from the CLI

Every field is reachable through caasi config set — list values are parsed as YAML: caasi config set catalog.slam.visual.packages "[isaac_ros_visual_slam_v4]". See the version-churn firewall for the full walkthrough.

Physics engine keys

The physics domain doubles as the engine registry, and two keys outside catalog: steer it (see caasi physics):

KeyDefaultEffect
physics.defaultphysxEngine used by physics run / physics benchmark when --engine is absent. It must be a capability key of the physics domain; anything else exits 1 with Error: Unknown physics engine '<key>'. Known: ….
physics.engines.<key>.launcherScript that replaces the experiment's own launcher for that engine. A relative value is resolved against the isaacsim tool root, and it is only used when the resulting file exists; otherwise a launcher the catalog found through paths that ends in .sh is used.
physics:
  default: gazebo
  engines:
    gazebo:
      launcher: ~/bin/gz-run.sh

Whichever engine is applied, the run also receives CAASI_PHYSICS_ENGINE=<key>. synth and teleop read no keys of their own: synth generate resolves the sdg domain's replicator capability, teleop start resolves catalog.teleop.default and then keyboardjoyxr, and both write under paths.datasets — see synth & teleop.

Remotes

The remotes: section defines SSH machines for the remote commands:

remotes:
  <name>:
    host: 10.0.0.5            # required — entries without host are ignored
    user: robot               # optional
    port: 2222                # optional
    identity: ~/.ssh/id_ed25519  # optional, ~ is expanded
    path: ~/experiments       # optional remote working directory

Commands accept the exact name or any unique prefix (caasi remote run gpu nvidia-smi matches gpu-box when unambiguous). Caasi only builds ssh command lines — keys, agents and ~/.ssh/config are honored because the system ssh client does the work.

caasi config

Inspect and edit the configuration from the command line.

caasi config show

caasi config show [--json]

Prints the merged effective configuration (human mode renders YAML; --json emits the same object). This is the ground truth of what Caasi will do.

shellcaasi config show
language: en
layout: rich
help_order: grouped
defaults:
  output: table
paths:
  runs: ~/.caasi/runs
  datasets: ~/.caasi/datasets
tools:
  isaacsim:
    default: '6.0'
    versions:
      '6.0':
        path: /opt/isaac-sim-6.0

caasi config get

caasi config get KEY

Reads one dotted key. Dicts and lists are printed as YAML, scalars as plain text. A missing (or null) key exits 1 with Error: Key '<key>' is not set.

shellcaasi config get paths.runs
~/.caasi/runs
caasi config get tools.isaacsim.versions
'6.0':
  path: /opt/isaac-sim-6.0

caasi config set

caasi config set KEY VALUE

caasi config path

caasi config path

Shows the four possible sources, which of them are active, and the effective merge order — the fastest way to debug “why is my setting ignored?”.

shellcaasi config path
  ✓ --config                     (not set)
  ✓ CAASI_CONFIG                 (not set)
  ✓ Global config file           /home/you/.config/caasi/config.yaml
  • Project config file          ./caasi.yaml
Effective sources in merge order:
  /home/you/.config/caasi/config.yaml

caasi config tools

caasi config tools [--json]

Lists every registered tool with its default version, all versions, and the resolved {version, path, python} (or null when unresolvable). With no registry entries it prints a usage hint. Always exits 0.

shellcaasi config tools --json | jq '.isaacsim.resolved'
{
  "version": "6.0",
  "path": "/opt/isaac-sim-6.0",
  "python": null
}

caasi config catalog

caasi config catalog [DOMAIN] [--json]

Prints the effective capability catalog — the built-in domains merged with your catalog: overrides — so you can see exactly which upstream names Caasi will probe. Omit DOMAIN to print every domain; an unknown one exits 1 with Error: Unknown catalog domain: <name>. Known domains: …. See Capability catalog.

Argument / optionTypeDefaultDescription
DOMAINstrevery domainCatalog domain to show (omit to show every domain).
--jsonflagoffMachine-readable output.
shellcaasi config catalog slam
SLAM slam · ros
capability    upstream targets       launch file                                  caasi group
visual        isaac_ros_visual_slam  isaac_ros_visual_slam visual_slam.launch.py  —
toolbox       slam_toolbox           slam_toolbox online_async_launch.py          —
cartographer  cartographer_ros       cartographer_ros cartographer.launch.py      —

Every field is overridable: `caasi config set catalog.<domain>.<capability>.<field> <value>`
caasi config catalog nope
Error: Unknown catalog domain: nope. Known domains: isaacros, perception, slam, mapping, motion, nitros, physics, warp, groot, cosmos, usd, data, teleop, sdg

When the domain has a default, the heading carries it — SLAM (default: toolbox) slam · ros. --json emits one object per domain, or a single object when DOMAIN is given:

shellcaasi config catalog teleop --json
{
  "key": "teleop",
  "title": "catalog.domain.teleop",
  "kind": "ros",
  "verbs": ["start", "record", "stop", "replay"],
  "tool": "isaacsim",
  "capabilities": [
    {
      "key": "keyboard",
      "label": "catalog.teleop.keyboard",
      "packages": ["teleop_twist_keyboard"],
      "binaries": [],
      "modules": [],
      "env": [],
      "paths": [],
      "launch": ["teleop_twist_keyboard", "teleop-launch.py"],
      "script": null,
      "topics": [],
      "group": null,
      "tool": "isaacsim",
      "core": true
    }
    … one object per capability, in catalog order …
  ],
  "default": null,
  "overrides": {}
}

overrides is the raw catalog.<domain> mapping from your config, so what you changed and what is built-in stays visible at a glance.

Environment variables

Consumed by Caasi

VariableEffect
CAASI_CONFIGPath to an extra config file (merged above global/project).
CAASI_LANGOverrides language after merging (e.g. en).
CAASI_LAYOUTOverrides layout after merging: rich (bordered tables) or plain (space-aligned columns). The --layout flag wins over both.
CAASI_HELP_ORDEROverrides help_order after merging: grouped (titled panels, default), core (entry points first, then a–z) or alpha (flat a–z). Applies to the root listing only; there is no flag, because --help exits before flags are stored.
XDG_CONFIG_HOMERelocates the global config dir ($XDG_CONFIG_HOME/caasi/config.yaml).
ISAACSIM_PATHFallback Isaac Sim location when the registry has none.
ISAACLAB_PATHFallback Isaac Lab location when the registry has none.
ROS_DISTROSelects the ROS 2 distro (otherwise /opt/ros is scanned).
RMW_IMPLEMENTATIONReported by caasi ros status (not modified).
ISAAC_ROS_WSIsaac ROS workspace root, tried before the tools.isaacros registry entry and the common paths — see isaac-ros.
GR00T_PATHGR00T repository root: the catalog.groot.repo probe and the fallback for the tools.groot registry entry — see groot.
AMENT_PREFIX_PATHWith COLCON_PREFIX_PATH and PYTHONPATH, proves the ROS 2 environment is already sourced. When none of them names the distro root, Caasi wraps ros2 commands in a shell that sources setup.bash first.
ROS_DOMAIN_IDReported by caasi doctor -c accelerated (not modified).
ROS_DISABLE_NITROSProbed as the nitros.disable capability and reported by caasi doctor -c accelerated (not modified).

Any capability can also be found through its own env field — see Capability catalog.

Produced for child processes

Caasi sets these in the environment of everything it launches — your scripts can rely on them:

VariableSet byContent
CAASI_EXPERIMENTsim run, train, benchmark start, dataset generateAbsolute path of the experiment YAML.
ISAACSIM_PATH / ISAACLAB_PATHsim run, train, … (sim/lab backends)Resolved install path.
CAASI_DATASET_DIRdataset generateDataset directory the script should write into (also passed as --dataset-dir).
CAASI_RUN_DIRreplay, view attachRun directory for the viewer.
CAASI_REPLAY_SPEED, CAASI_REPLAY_EPISODEreplayReplay parameters exported to the viewer.
CAASI_PHYSICS_ENGINEphysics run, physics benchmarkKey of the engine that was applied (physx, gazebo, …) — see Capability catalog.
Tip — CI

Feed a per-job config without touching the machine setup: CAASI_CONFIG=ci/caasi-gpu.yaml caasi sim run exp.yaml, or caasi --config ci/caasi-gpu.yaml sim run exp.yaml for highest precedence.