1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
// RLX — versatile ML compiler + runtime.
// Copyright (C) 2026 Eugene Hauptmann, Nataliya Kosmyna.
//
// Demonstrates plugging custom subcommands into `rlx-cli`'s dispatch
// registry from a downstream crate (no changes to `rlx-models` required).
//
// 1. Implement `ModelRunner` for your model.
// 2. `register_runner(Box::new(YourRunner))` early in `main`.
// 3. `dispatch(&argv)` — routes by first argv token.
//
// Running:
// cargo run -p rlx-models --example register_custom_runner -- echo hello
// cargo run -p rlx-models --example register_custom_runner -- adder 3 4
//
// A production binary would depend on `rlx-cli` directly, register its
// own runners, and optionally call `register_cli` for built-ins (see
// `rlx-models/src/bin/rlx_run.rs`).
use anyhow::{Context, Result};
use rlx_cli::{ModelRunner, dispatch, dispatch_help, register_runner};
/// `echo <args...>` — prints its arguments back. Useful as a
/// no-deps sanity test of the dispatch path.
struct EchoRunner;
impl ModelRunner for EchoRunner {
fn name(&self) -> &'static str {
"echo"
}
fn description(&self) -> &'static str {
"Print the supplied arguments back to stdout"
}
fn run(&self, args: &[String]) -> Result<()> {
println!("echo: {}", args.join(" "));
Ok(())
}
}
/// `adder <a> <b>` — parses two integers and prints the sum.
/// Shows how a real runner does its own arg parsing inside `run`.
struct AdderRunner;
impl ModelRunner for AdderRunner {
fn name(&self) -> &'static str {
"adder"
}
fn description(&self) -> &'static str {
"Add two integers (demonstrates per-runner arg parsing)"
}
fn run(&self, args: &[String]) -> Result<()> {
let a: i64 = args
.first()
.context("adder: missing first integer")?
.parse()
.context("adder: first arg not an integer")?;
let b: i64 = args
.get(1)
.context("adder: missing second integer")?
.parse()
.context("adder: second arg not an integer")?;
println!("{a} + {b} = {}", a + b);
Ok(())
}
}
fn main() -> Result<()> {
register_runner(Box::new(EchoRunner));
register_runner(Box::new(AdderRunner));
eprintln!("[register_custom_runner] registered subcommands:");
eprintln!("{}", dispatch_help());
let argv: Vec<String> = std::env::args().skip(1).collect();
if argv.is_empty() {
eprintln!(
"[register_custom_runner] no subcommand given; try `echo hi` or `adder 3 4` or `help`"
);
return Ok(());
}
dispatch(&argv)
}