Skip to main content
The cerulion binary groups all functionality under top-level commands: workspace, node, graph, topic, schema, tui, trace, and clean. Synopsis notation uses <required>, [optional], {a|b} (choice), and ... (repeatable). Synopsis lines are not directly runnable; each command includes a separate runnable example.

Global

On error, cerulion prints Error: <msg> to stderr and exits with a failure code. Most commands require a workspace, discovered by walking upward for a Cargo.toml containing [workspace] plus a graphs/ directory. workspace create/init, tui, trace, and clean do not require discovery. topic * uses iceoryx2 discovery and needs no workspace.

workspace

cerulion workspace create

Create a new workspace directory.
Creates ./<name>/ with graphs/, nodes/, schemas/, Cargo.toml ([workspace], members=["nodes/*"], resolver="2", workspace dependencies for cerulion_core and native_ros2_messages), and .cargo/config.toml. Errors if ./<name> already exists. Prints Created workspace at <path>.
Initialize a workspace in place.
Initializes a workspace at location. Errors if a Cargo.toml with [workspace] already exists there. The workspace name is the directory’s file name (fallback cerulion_ws). Prints Initialized workspace at <path>.

node

Subcommands: create, delete, modify, build, stage, run, list, info. All require workspace discovery.

cerulion node create

Create a node type.
Schema is accepted in both sensor_msgs/Image (slash, canonical) and sensor_msgs::Image (colon) forms; canonicalized to slash. Output prints Created node type '<node_type>'.Generated files: nodes/<type>/Cargo.toml (cdylib, cdylib feature default) and nodes/<type>/src/lib.rs (macro or raw-FFI). Nothing is added to the workspace Cargo.toml if it already uses the "nodes/*" glob (the default).Validation errors (clean messages, no panic): passing a flag twice; -T name colliding with -i name; --policy data_trigger=NAME not matching a declared input; a source-only node (no -i/-T) without an explicit non-data --policy.
Delete a node type.
Removes nodes/<node_type>/ (recursive) and the workspace member entry. Errors NodeNotFound if absent. Prints Deleted node type '<node_type>'.
Modify an existing node type in place.
Mutates the node’s src/lib.rs in place (preserves the tick body, comments, and other fields). -T and --policy data_trigger=NAME are equivalent; supplying both requires they agree. Prints per-action lines, e.g. Added input 'image' to 'detector' as the data trigger, Set policy=period_ms=33 on 'detector', Promoted existing input 'x' to data trigger on 'detector'.
The only user surface for setting external triggering is --policy external.
Build a node crate.
Runs cargo build -p <node_type> (adds --release if set) in the workspace root. Errors BuildFailed (with cargo stderr) on failure. Prints Built '<node_type>'.
Requires cargo on PATH; the CLI shells out to it.
Append a node instance to a graph YAML file.
Outputs (with schemas) are auto-derived from the node’s source metadata. A duplicate node ID is an error. The modified graph is validated. Prints Staged '<type>' into graph '<graph>'.
Smoke-run a single node.
Creates a hidden temp graph __temp_<type>, stages the node, runs it in live mode (validation skipped), and deletes the temp graph YAML on exit. Ctrl+C stops it.
List node types.
No arguments. Prints a table with columns TYPE INPUTS OUTPUTS POLICY (counts plus a short policy label). Empty workspace prints No nodes found.
Show details for a node type.
Prints Node type, Policy, and Inputs:/Outputs: (name plus schema or (untyped)). Metadata is parsed from src/lib.rs; the source is the single source of truth.Policy short labels: period <N>ms, deadline <N>ms, sync <N>ms, sync ∞ (unbounded), external, trigger:<input>, - (none).

graph

Subcommands: create, run, validate, list.

cerulion graph create

Create a graph file.
Creates graphs/<name>.yaml. Errors if the graph already exists. Prints Created graph '<name>'.
Run a graph.
Loads cdylibs, builds the runtime, and runs the graph until Ctrl+C or a node requests shutdown. In the default live mode (--time-source real) the graph wakes and processes messages as they arrive. Validation failures only warn and continue; they do not block run.In live mode, Cerulion automatically applies a CPU C-state cap for timing-sensitive graphs to reduce wake latency (Linux only; best-effort β€” warns on failure if the cap cannot be acquired). Pass --no-cpu-dma-lock to disable it. Environment variable overrides: CERULION_CPU_DMA_LOCK=1 forces a full C0 pin; CERULION_CPU_DMA_LOCK=0 disables the cap; CERULION_CPU_DMA_LOCK_US=N sets an explicit N-Β΅s cap. The --no-cpu-dma-lock flag takes precedence over all env vars.On Linux x86_64 and Linux aarch64 in live mode, Cerulion uses a per-core CPU park to reduce idle wake latency. When the park is active, the graph-derived auto C-state cap is not applied (an explicit CERULION_CPU_DMA_LOCK=1 or CERULION_CPU_DMA_LOCK_US=N override still takes effect). To opt out of the park entirely, pass --no-monitor-wait. Environment variable overrides (only honored when --no-monitor-wait is absent): CERULION_MONITOR_WAIT=1 force-enables the park; CERULION_MONITOR_WAIT=0 disables it; any other non-empty value warns and uses the auto default. CERULION_DOORBELL=1 enables waking on incoming data as well as on the timer deadline; CERULION_DOORBELL=0 restricts to timer-only wakes; any other non-empty value warns and uses the auto default.CERULION_FIRE_THREADS=N sets the number of threads used for within-level parallel node execution (must be a positive integer; if unset or invalid, auto-sizes to min(available_parallelism, max_level_width); read once at graph build). CERULION_LIVE_SPIN_US=N controls how long (Β΅s) the live loop busy-waits for an incoming message before yielding the core (--time-source real/external only; no effect with virtual). =0 disables busy-waiting; =N (N > 0) caps it at N Β΅s (max 100,000; larger values are clamped with a warning). When unset, the duration is auto-sized to the graph’s timing requirements β€” a tight-period graph polls briefly, a quiescent graph yields immediately. graph run also runs an iceoryx2 dead-node cleanup at start.
run loads compiled cdylibs from the cargo target directory. The default is target/{debug,release}/ in the workspace root. If CARGO_TARGET_DIR is set in your shell, both cerulion node build and cerulion graph run use it, so a shared or custom target directory works without any extra flags.
Validate a graph.
Runs the validation report (topology, node crate exists, ports parse, cdylib exists, input bindings and schema match, data_trigger bindings). Prints the report and exits non-zero if any check fails.
List graphs.
No arguments. Lists graph names (file stems of *.yaml), sorted. Empty prints No graphs found.

topic

Uses iceoryx2 service discovery: enumerates services ending in /data (Cerulion creates {topic}/data and {topic}/event per topic). No workspace required.

cerulion topic list

List active topics.
Lists active topic names (sorted). Header TOPIC. Empty prints No active topics.
Show topic info.
Prints the topic info string.
Print messages from a topic.
Subscribes and prints messages until Ctrl+C. Pretty-prints std_msgs/String and sensor_msgs/Image (by FNV-1a schema hash); hex preview otherwise.
Measure publish rate.
Measures the publish rate until Ctrl+C.

schema

Subcommands: create, delete, info.

cerulion schema create

Create a schema file.
Creates schemas/<PascalName>.yaml with a schemas: skeleton (description plus a fields: comment). Errors if the schema exists. Prints Created schema '<name>'.
Delete a schema file.
Removes schemas/<name>.yaml. Errors SchemaNotFound. Prints Deleted schema '<name>'.
Show schema details.
First tries a ROS2 .msg lookup at ../native_ros2_messages/msg/<pkg>/<Type>.msg (for qualified names); prints fields, Rust types, and min wire size. Falls back to a workspace YAML schema (prints Schema, Description, Fields, Hash: 0x...).

tui

Launches the interactive ratatui dashboard. Logging is suppressed in TUI mode.

trace inspect

Reads trace_*.jsonl bag files (lexicographic order) and prints <topic> seq=<N> t=<ts>ns schema=0x<HASH> per record.

clean

Removes iceoryx2 on-disk bookkeeping for dead nodes only (live sibling processes are untouched). Prints cleanup counts plus per-cause remediation.