# SimEngine CLI reference

> The complete command-line interface of SimEngine's public tools, taken from their `--help` text. Every command except `--help` and `--session` prints exactly one JSON document to stdout, including on failure. Diagnostics go to stderr as JSON Lines (`simengine.diagnostic`, version 1).

Last updated: 2026-10-29 (pre-release build `0.0.0-dev`).

## simengine_host

The runtime host: build and device report, and the headless scenario runner.

```text
simengine_host --report [--no-validation] [--device INDEX]
simengine_host --version
simengine_host --help
simengine_host --capabilities
simengine_host --load FILE
simengine_host --run FILE --out DIR [--ticks N] [--max-wall-ms MS] [--trace-every N]
simengine_host --session [--max-wall-ms MS]
```

| Command | What it does |
| --- | --- |
| `--report` | Opens the Vulkan backend headless (no window), prints one JSON report of build, settings, device and a core runtime self-check (clocks, jobs, handles, telemetry), then shuts down. `runtime.modules` lists the build-selected modules. |
| `--version` | Prints build identity as JSON without touching Vulkan. |
| `--capabilities` | Prints the machine-readable capability document: scenario schema, units, frames, components, commands, limits, exit codes and an example scenario valid for this build's modules. No Vulkan. |
| `--load FILE` | Validates a scenario (all-or-nothing) and prints its initial state. No Vulkan. |
| `--run FILE --out DIR` | Loads, steps and checks expectations. DIR must be new or empty. `--ticks` overrides the scenario's run length, `--max-wall-ms` bounds the run (default 30000), `--trace-every N` records a state digest every N ticks. |
| `--session` | JSON Lines control on stdin/stdout: `load`, `step`, `inspect`, `command` (dry run, expected state version), `expectations`, `capabilities`, `quit`. Bounded by `--max-wall-ms`. |

Options for `--report`: `--no-validation` (do not enable `VK_LAYER_KHRONOS_validation`), `--device INDEX` (physical device by enumeration index; default selection is discrete, then integrated, virtual, CPU), `--inject-fault invalid-queue-priority` (negative control: with validation enabled the run must end with exit 8).

Environment: `SIMENGINE_VULKAN_LOADER` sets an explicit Vulkan loader path (diagnostic override).

### Exit codes

| Code | Name | Meaning |
| --- | --- | --- |
| 0 | ok | Success |
| 1 | internal_error | Unexpected exception inside the host |
| 2 | usage_error | Invalid command line |
| 3 | vulkan_loader_unavailable | No Vulkan loader library on this machine |
| 4 | vulkan_driver_unavailable | Loader present, no driver supporting Vulkan 1.3 |
| 5 | no_vulkan_device | Instance created, zero physical devices |
| 6 | no_suitable_device | Devices exist, none meets the requirements |
| 7 | backend_initialization_failed | Other instance or device creation failure |
| 8 | validation_errors | Backend opened, the validation layer reported errors |
| 9 | runtime_self_check_failed | Backend fine, core runtime self-check failed |
| 10 | scenario_invalid | Validation failed; nothing ran |
| 11 | scenario_timeout | The wall-time bound stopped the run or session |
| 12 | scenario_expectation_failed | Run completed, an expectation failed |
| 13 | scenario_io_error | Input unreadable or output directory unusable |
| 14 | simulation_fault | A tick produced non-finite state (rolled back) |
| 15 | module_startup_failed | Optional modules could not be initialized |

A process killed by a signal (crash) prints no document; supervisors classify it.

## simengine_capture

Offscreen render and capture with the forward PBR path.

```text
simengine_capture --scene FILE --out-dir DIR [options]
simengine_capture --check-scene FILE
simengine_capture --version
simengine_capture --help
```

| Command | What it does |
| --- | --- |
| `--scene FILE` | Loads a `.sescene` file and its `.seasset` files, renders offscreen, writes `DIR/<scene_id>.png` and `DIR/<scene_id>.capture.json`, prints the manifest (`simengine.capture.manifest`, version 1). |
| `--check-scene FILE` | Validates the scene and its assets only (units, axes, PBR subset, provenance, geometry). No Vulkan. Prints the manifest. |

Options for `--scene`: `--out-dir DIR` (required, created if missing), `--width N --height N` (default 2560 x 1440), `--warmup N` (timed warm-up frames excluded from steady statistics, default 3), `--frames N` (measured steady frames, default 30), `--label TEXT` (free-form machine label recorded in the manifest, not verified), `--no-validation`, `--no-sync-validation`, `--device INDEX`, `--inject-fault skip-layout-barrier|black-output` (negative controls: exit 8 and exit 12 respectively).

### Exit codes

| Code | Name | Meaning |
| --- | --- | --- |
| 0 | ok | Success |
| 1 | internal_error | Unexpected exception |
| 2 | usage_error | Invalid command line |
| 3 | vulkan_loader_unavailable | No Vulkan loader library on this machine |
| 4 | vulkan_driver_unavailable | Loader present, no driver supporting Vulkan 1.3 |
| 5 | no_vulkan_device | Instance created, zero physical devices |
| 6 | no_suitable_device | Devices exist, none meets the requirements |
| 7 | backend_initialization_failed | Other instance or device creation failure |
| 8 | validation_errors | Rendered, but the validation layer reported errors |
| 10 | scene_invalid | Scene or asset rejected by the import path |
| 11 | render_failed | A Vulkan call failed or the device lacks a format |
| 12 | capture_content_invalid | The image is black, empty or background-only |
| 13 | output_write_failed | The PNG or manifest could not be written |

## simengine_desktop (Windows only)

A scene playground using the same persistent renderer: explore a generic PBR scene, select and move objects, save snapshots that `simengine_capture` reproduces. It is not a game-authoring API.

```text
simengine_desktop --scene FILE [--out DIR] [--width N] [--height N]
```

`--out` must be new or empty; omitting it disables saved captures. `--width`/`--height` set the internal render resolution (default 1280 x 720). Requires Vulkan 1.3, one graphics/present queue, SRGB blit support and `VK_EXT_swapchain_maintenance1`; failures are explicit JSON. Controls: W/A/S/D and Q/E move the camera, right-drag looks, Tab selects an object, arrows and Page Up/Down move it in metres, Space pauses, R resets, F12 saves a PNG and a replayable `.sescene`, Escape exits. There is no collision response.

## first_scene.py (example driver)

```text
python first_scene.py new DEST [--name NAME] [--no-skills]
python first_scene.py check [--project P] [--build B | --host H --capture C] [--scenario S]
python first_scene.py run   [--project P] [--build B | --host H --capture C] [--scenario S] [--out DIR] [--timeout SEC] [--label TEXT] [--skip-capture]
python first_scene.py verify [MANIFEST] [--project P] [--scenario S] [--expect-outcome PASS|FAIL|BLOCKED_ENVIRONMENT]
```

`run` executes the full journey (load, run twice, pose, capture, verify, manifest). With `--skip-capture` the render check is `NOT_RUN`, never `PASS`. The driver exits 21 (`incompatible_engine`) when the engine's interface versions differ from the ones its skills were written for.
