Runs & Logs
A run is Caasi's unit of long-running work: a simulation, a training job, a ROS launch, an SSH batch job or a container. Runs are started detached — the CLI returns immediately and the process survives your terminal — and every run keeps its own logs, metadata and lifecycle state on disk.
The run model
Where runs live
All runs are stored under paths.runs (default ~/.caasi/runs), one
directory per run:
~/.caasi/runs/
└── 20260905-142301-wave/ # run id: <timestamp>-<name-slug>
├── manifest.yaml # metadata (written after the process spawns)
├── run.sh # bash wrapper that records the exit code
├── stdout.log # everything the process prints
├── stderr.log
├── exit_code # appears when the process finishes
└── … # any artifacts the process itself writes here
The run id is YYYYmmdd-HHMMSS-<slug> — a local timestamp plus
the run name, lowercased with non-alphanumeric runs replaced by -. Because ids are
timestamp-prefixed, sorting them sorts by time.
How a run is started
- The run directory and the
run.shwrapper are created. The wrapper executes the command and writes its exit code intoexit_codewhen it finishes. - The process is spawned with
start_new_session=True(its own process group) andstdindetached, stdout/stderr redirected into the log files. The CLI never waits for it. manifest.yamlrecords everything: id, name, backend, kind, full command, working directory, creation time, PID, and the paused/stopped flags.
Manifest fields
| Field | Content |
|---|---|
id / name | Run id and human name. |
backend | What executes it: python, sim, lab, ros, ssh, container. |
kind | What it is: run, experiment, train, benchmark, dataset, test, ros, nav, moveit, remote, container. |
command | Full argv list. |
cwd | Absolute working directory. |
created | ISO-8601 timestamp with timezone. |
pid | PID of the wrapper process (its whole process group is controlled). |
paused / stopped | Lifecycle flags set by pause/stop. |
extra | Command-specific metadata (experiment path, image, remote, …). Visible only in the manifest file, not in JSON output. |
Status: derived, not remembered
Status is computed on every query, in strict precedence:
| Status | Meaning | Derived from |
|---|---|---|
| succeeded | Finished with exit code 0. | exit_code file = 0 |
| failed | Finished with non-zero exit code. | exit_code file ≠ 0 |
| running | Alive and executing. | No exit code + PID alive |
| paused | Frozen with SIGSTOP. | No exit code + PID alive + paused flag |
| stopped | Terminated by caasi run stop. | No exit code + PID dead + stopped flag |
| lost | Vanished without recording an exit code (SIGKILL, reboot). | No exit code + PID dead + no flags |
A stopped run may report failed instead of stopped: if the wrapper
survived long enough to record the SIGTERM exit code (typically 143), the exit code wins.
Both mean “terminated by you”.
Referring to a run: the QUERY argument
Every command that takes a run accepts a flexible QUERY:
latest,lastornewest→ the most recent run;- an exact run id → that run;
- a unique id prefix or exact run name → that run
(
caasi logs 20260905-14,caasi logs wave).
Ambiguous prefixes and unknown queries fail with
Error: No run matching '<query>'. (exit 1).
caasi run
caasi run list
caasi run list [--limit|-n N] [--json]
| Option | Short | Type | Default | Description |
|---|---|---|---|---|
--limit | -n | int | 20 | Number of runs to show (newest first). |
--json | flag | off | Array of run records. |
shellcaasi run list
ID Name Backend Status Created PID
20260905-151207-ant ant lab running 2026-09-05T15:12:07+08:00 51244
20260905-142301-wave wave sim succeeded 2026-09-05T14:23:01+08:00 —
20260905-091544-nav2 nav2-bringup ros stopped 2026-09-05T09:15:44+08:00 —
Always exits 0; an empty history prints No runs recorded yet.
The run record (JSON shape)
All --json outputs of run commands share this shape:
{
"id": "20260905-142301-wave",
"name": "wave",
"backend": "sim",
"kind": "experiment",
"command": ["/opt/isaac-sim-6.0/python.sh", "/home/you/demo/scripts/wave.py", "--steps", "10000"],
"cwd": "/home/you/demo/experiments",
"created": "2026-09-05T14:23:01+08:00",
"pid": 48213,
"paused": false,
"stopped": false,
"directory": "/home/you/.caasi/runs/20260905-142301-wave",
"status": "succeeded"
}
caasi run status
caasi run status QUERY [--json]
shellcaasi run status latest
wave (20260905-142301-wave)
Status succeeded
Backend sim
Kind experiment
Created 2026-09-05T14:23:01+08:00
PID 48213
Directory /home/you/.caasi/runs/20260905-142301-wave
Command /opt/isaac-sim-6.0/python.sh /home/you/demo/scripts/wave.py --steps 10000
Exit 0 when found, 1 when not.
caasi run stop
caasi run stop QUERY
Terminates the whole process group: resumes it first if paused, sends SIGTERM,
waits up to 5 seconds, escalates to SIGKILL, and marks the manifest
stopped. Already-finished runs are a no-op success.
shellcaasi run stop ant
Run 20260905-151207-ant stopped.
Exit 1 if the run is unknown or the PID somehow survives SIGKILL.
caasi run pause / resume
caasi run pause QUERY # SIGSTOP to the process group — only when running
caasi run resume QUERY # SIGCONT — only when paused
Pause freezes the process in place (it holds its GPU memory — check with
caasi gpu memory); resume continues exactly where it stopped. Wrong-state calls fail
with e.g. Error: Run <id> is not running (status: succeeded). (exit 1).
caasi run delete
caasi run delete QUERY [--force]
| Option | Type | Default | Description |
|---|---|---|---|
--force | flag | off | Stop the run first if it is still active. |
Removes the whole run directory (logs, manifest, artifacts). Refuses while the run is
running or paused unless --force. Terminal, stopped and lost
runs are always deletable.
caasi run inspect
caasi run inspect QUERY [--json]
Lists every artifact file inside the run directory with human-readable sizes. JSON adds a
files array to the run record:
shellcaasi run inspect latest --json | jq '.files'
[
{ "path": "manifest.yaml", "size": 412 },
{ "path": "run.sh", "size": 118 },
{ "path": "stdout.log", "size": 28413 },
{ "path": "stderr.log", "size": 0 },
{ "path": "metrics/result.json", "size": 1024 }
]
Your scripts can write outputs into $CAASI_RUN_DIR (set for viewers) or simply
print to stdout — everything lands in the run directory, and replay treats all
files beyond the five bookkeeping files as recorded data.
caasi logs
caasi logs QUERY is a top-level alias of caasi run logs QUERY — the
command you will use most.
caasi logs QUERY [--lines|-n N] [--follow|-f] [--stream|-s stdout|stderr]
| Option | Short | Type | Default | Description |
|---|---|---|---|---|
--lines | -n | int | 50 | Number of trailing lines to show. |
--follow | -f | flag | off | Tail the log until the run ends; Ctrl+C stops following (the run keeps going). |
--stream | -s | str | stdout | Which log file: stdout or stderr. |
shellcaasi logs latest -n 3
[14:41:02] step 9000/10000 fps 241.3
[14:41:07] step 10000/10000 fps 244.1
[14:41:07] done.
caasi logs latest -f -s stderr
…follows stderr live until the run ends…
Follow mode stops automatically when the run reaches succeeded,
failed or stopped. Errors (exit 1): unknown run, unknown
--stream value, or the log file does not exist. No --json — logs are
already plain text.
caasi run attach
caasi run attach QUERY
Attaches to a run's live output: both logs are read from the beginning and then followed together, each line tagged with its stream. Ctrl+C detaches — the run keeps going, as always.
shellcaasi run attach ant
Attached to run 20260905-151207-ant — Ctrl+C detaches, the run keeps going.
[stdout] Loading extension: omni.kit.viewport.window
[stderr] [Warning] deprecated API used at frame 12
[stdout] learning iteration 12/1500 mean reward 87.2
# Ctrl+C
Detached from run 20260905-151207-ant; the run keeps going.
caasi run status ant --json | jq -r .status
running
caasi logs -f | caasi run attach | |
|---|---|---|
| Streams | one at a time — --stream stdout|stderr | both, interleaved, each line prefixed [stdout] / [stderr] |
| History | the last --lines N (default 50), then follows from the end of the file | everything from the start of both logs, then follows |
| Options | -n, -f, -s | none beyond QUERY — no --json |
| Ctrl+C | stops following, silently | detaches and says so |
Like follow mode, attach returns on its own once the run reaches succeeded,
failed or stopped — attaching to a finished run replays its logs and
exits. Exit 1 for an unknown run or a run directory without log files
(Error: No log files found for this run.). There is no top-level alias;
caasi view attach is the unrelated viewer
command.
Typical lifecycle
shellcaasi sim run experiments/wave.yaml
Run 20260905-142301-wave started in the background.
caasi run pause latest
Run 20260905-142301-wave paused.
caasi run resume latest
Run 20260905-142301-wave resumed.
caasi run stop latest && caasi run inspect latest && caasi run delete latest
Run 20260905-142301-wave stopped.
Run 20260905-142301-wave deleted.