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

cerulion [--verbose] <command> [args...]
FlagLongTypeDefaultMeaning
verbose--verboseboolfalseEnable debug-level logging. Long form only; there is no -v. Applies to every subcommand.
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.
cerulion workspace create <name>
Arg / flagValue nameTypeDefaultMeaning
name (positional)<name>StringRequired. Workspace directory to create at ./<name>/.
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>.
cerulion workspace create my_robot
Initialize a workspace in place.
cerulion workspace init [location]
Arg / flagValue nameTypeDefaultMeaning
location (positional)[location]String.Directory to initialize in place (defaults to the current directory).
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>.
cerulion workspace init .

node

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

cerulion node create

Create a node type.
cerulion node create <node_type> [-o SCHEMA NAME] [-i SCHEMA NAME] [-T SCHEMA NAME] [--policy SPEC] [--raw-ffi]
FlagShort/LongValue namesTypeDefaultMeaning
node type(positional)<node_type>StringRequired. Becomes folder nodes/<node_type>/ and (PascalCased) the struct name. Validated: non-empty, alphanumeric/underscore, must not start with a digit.
output port-o / --outputSCHEMA NAME2 valuesAdd one output port. Both SCHEMA and NAME required. At most one -o per create.
input port-i / --inputSCHEMA NAME2 valuesAdd one regular input. Both required. At most one -i per create.
trigger input-T / --trigger-inputSCHEMA NAME2 valuesAdd a trigger input β†’ field emitted as #[input(trigger)], policy set to data_trigger=<NAME>. Both required. At most one -T per node.
policy--policySPECString(defaulting rules)Trigger policy. See Trigger policies.
raw FFI--raw-ffiboolfalseGenerate the raw extern "C" FFI template instead of the #[cerulion_node] macro template.
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.
cerulion node create detector -T sensor_msgs/Image image -o geometry_msgs/PoseArray detections
Delete a node type.
cerulion node delete <node_type>
ArgValue nameTypeMeaning
node type (positional)<node_type>StringRequired. Node type to delete.
Removes nodes/<node_type>/ (recursive) and the workspace member entry. Errors NodeNotFound if absent. Prints Deleted node type '<node_type>'.
cerulion node delete detector
Modify an existing node type in place.
cerulion node modify <node_type> [-i SCHEMA NAME] [-T SCHEMA NAME] [-o SCHEMA NAME] [--policy SPEC]
FlagShort/LongValue namesNotes
node type(positional)<node_type>Required. Node type to modify.
input port-i / --inputSCHEMA NAMEAdd a regular input. At most one per call.
trigger input-T / --trigger-inputSCHEMA NAMEAdd a trigger input (#[input(trigger)]) and set policy data_trigger=<NAME>, clearing conflicting node-level policy args. At most one per call.
output port-o / --outputSCHEMA NAMEAdd an output. At most one per call.
policy--policySPECSet/replace the trigger policy. data_trigger=NAME requires NAME to be an existing input or one added in the same call.
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.
cerulion node modify detector -i sensor_msgs/Imu imu --policy period_ms=33
Build a node crate.
cerulion node build <node_type> [--release]
FlagLongTypeDefaultMeaning
node type(positional)<node_type>Required. Node type to build.
release--releaseboolfalseBuild in release mode.
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.
cerulion node build detector --release
Append a node instance to a graph YAML file.
cerulion node stage <node_type> [-i ID] [-g GRAPH] [-p PREFIX] [-I NAME SOURCE]...
FlagShort/LongValue namesTypeDefaultMeaning
node type(positional)<node_type>StringRequired. Node type to stage.
id-i / --idOption<String>node_typeNode instance ID (defaults to the node type).
graph-g / --graphOption<String>autoTarget graph. If omitted: auto-selects the sole graph; errors if 0 or more than 1 exist.
prefix-p / --prefixOption<String>Accepted for forward compatibility; topic prefix resolution lives on the graph, so this flag has no effect here.
input binding-INAME SOURCE2 values, repeatableWire input NAME to SOURCE. [node,port] form β†’ node/port; node/port passes through.
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>'.
cerulion node stage detector -g perception -I image [camera,image]
Smoke-run a single node.
cerulion node run <node_type> [-p PREFIX] [-i ID] [--release] [--no-cpu-dma-lock] [--no-monitor-wait]
FlagShort/LongTypeDefaultMeaning
node type(positional)StringRequired. Node type to run.
prefix-p / --prefixOption<String>standaloneTopic prefix.
id-i / --idOption<String>node_typeInstance ID.
release--releaseboolfalseForce the release-profile cdylib (target/release). Without this flag the freshest built cdylib between target/debug and target/release is auto-selected by modification time β€” the profile you most recently built wins.
no-cpu-dma-lock--no-cpu-dma-lockboolfalseDisable the automatic CPU C-state cap (Linux only). Pass this on laptops or power-sensitive dev boxes. See graph run for environment variable overrides.
no-monitor-wait--no-monitor-waitboolfalseOpt out of the live-loop CPU park (Linux only). By default 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. Pass this to disable it. See graph run for environment variable overrides.
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.
cerulion node run detector -p standalone
List node types.
cerulion node list
No arguments. Prints a table with columns TYPE INPUTS OUTPUTS POLICY (counts plus a short policy label). Empty workspace prints No nodes found.
cerulion node list
Show details for a node type.
cerulion node info <node_type>
ArgValue nameTypeMeaning
node type (positional)<node_type>StringRequired. Node type to inspect.
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).
cerulion node info detector

graph

Subcommands: create, run, validate, list.

cerulion graph create

Create a graph file.
cerulion graph create <name> [-n PREFIX]
FlagShort/LongTypeDefaultMeaning
name(positional)StringRequired. Graph name β†’ graphs/<name>.yaml.
prefix-n / --prefixOption<String>Topic prefix. If omitted, the prefix: line is omitted from the file and resolved to the hostname (without .local) at load time.
Creates graphs/<name>.yaml. Errors if the graph already exists. Prints Created graph '<name>'.
cerulion graph create perception -n robot1
Run a graph.
cerulion graph run <name> [--time-source CLOCK] [--no-validate] [--release] [--no-cpu-dma-lock] [--no-monitor-wait]
FlagFormDefaultMeaning
name(positional)Required. Graph to run.
time-source--time-source real|virtual|externalrealClock mode. real: live event-driven loop β€” wakes on each incoming message. virtual: deterministic 1 ms step loop for replay and benchmarking. external: accepted but not yet functional.
no validate--no-validateoffSkip pre-run workspace validation.
release--releaseoffForce release-profile cdylibs (target/release). Without this flag the freshest built cdylib between target/debug and target/release is auto-selected by modification time β€” the profile you most recently built wins. The pre-run validation uses the same mode.
no-cpu-dma-lock--no-cpu-dma-lockoffDisable the automatic CPU C-state cap (Linux only). No effect under --time-source virtual. Pass this on laptops or power-sensitive dev boxes.
no-monitor-wait--no-monitor-waitoffOpt out of the live-loop CPU park (Linux only). By default 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. Pass this to disable the park. No effect under --time-source virtual.
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.
# Default: live mode
cerulion graph run perception

# Deterministic mode (replay / benchmarking)
cerulion graph run perception --time-source virtual
Validate a graph.
cerulion graph validate <name> [--release]
FlagFormTypeDefaultMeaning
name(positional)StringRequired. Graph to validate.
release--releaseboolfalseForce release-profile cdylibs (target/release) when resolving node libraries. Without this flag the freshest built cdylib between target/debug and target/release is auto-selected by modification time. The report shows which profile was found.
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.
cerulion graph validate perception
List graphs.
cerulion graph list
No arguments. Lists graph names (file stems of *.yaml), sorted. Empty prints No graphs found.
cerulion graph list

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.
cerulion topic list
Lists active topic names (sorted). Header TOPIC. Empty prints No active topics.
cerulion topic list
Show topic info.
cerulion topic info <topic>
ArgValue nameTypeMeaning
topic (positional)<topic>StringRequired. Topic to inspect.
Prints the topic info string.
cerulion topic info robot1/camera/image
Print messages from a topic.
cerulion topic echo <topic>
ArgValue nameTypeMeaning
topic (positional)<topic>StringRequired. Topic to subscribe to.
Subscribes and prints messages until Ctrl+C. Pretty-prints std_msgs/String and sensor_msgs/Image (by FNV-1a schema hash); hex preview otherwise.
cerulion topic echo robot1/camera/image
Measure publish rate.
cerulion topic hz <topic>
ArgValue nameTypeMeaning
topic (positional)<topic>StringRequired. Topic to measure.
Measures the publish rate until Ctrl+C.
cerulion topic hz robot1/camera/image

schema

Subcommands: create, delete, info.

cerulion schema create

Create a schema file.
cerulion schema create <name>
ArgValue nameTypeMeaning
name (positional)<name>StringRequired. Schema name β†’ schemas/<PascalName>.yaml.
Creates schemas/<PascalName>.yaml with a schemas: skeleton (description plus a fields: comment). Errors if the schema exists. Prints Created schema '<name>'.
cerulion schema create Reading
Delete a schema file.
cerulion schema delete <name>
ArgValue nameTypeMeaning
name (positional)<name>StringRequired. Schema to delete.
Removes schemas/<name>.yaml. Errors SchemaNotFound. Prints Deleted schema '<name>'.
cerulion schema delete Reading
Show schema details.
cerulion schema info <name>
ArgValue nameTypeMeaning
name (positional)<name>StringRequired. Schema name. Accepts qualified ROS2 names like sensor_msgs::Image.
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...).
cerulion schema info sensor_msgs::Image

tui

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

trace inspect

cerulion trace inspect <dir> [-t TOPIC] [-n N] [-r]
FlagShort/LongValue nameTypeDefaultMeaning
dir(positional)<dir>StringRequired. Directory of trace_*.jsonl bag files.
filter-t / --filterTOPICOption<String>Filter by exact topic.
limit-n / --limitNOption<usize>Limit the number of records.
reverse-r / --reverseboolfalseReverse order (most-recent first).
Reads trace_*.jsonl bag files (lexicographic order) and prints <topic> seq=<N> t=<ts>ns schema=0x<HASH> per record.
cerulion trace inspect ./traces -t robot1/camera/image -n 100 -r

clean

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