mod service;
fn main() {
let args: Vec<String> = std::env::args().collect();
let code = match args.get(1).map(String::as_str) {
Some("--version") | Some("-v") | Some("version") => {
println!("{}", env!("CARGO_PKG_VERSION"));
0
}
Some("service") => service::run(args.get(2).map(String::as_str)),
Some("dashboard") => dashboard(&args[2..]),
Some("mcp") => mcp_serve(),
Some("help") | Some("--help") | Some("-h") | None => {
print_help();
0
}
Some(other) => {
eprintln!("Unknown command: {other}");
print_help();
1
}
};
std::process::exit(code);
}
fn mcp_serve() -> i32 {
let rt = match tokio::runtime::Runtime::new() {
Ok(rt) => rt,
Err(e) => {
eprintln!("[RuntimeScope] could not start the async runtime: {e}");
return 1;
}
};
match rt.block_on(runtimescope_mcp::run()) {
Ok(()) => 0,
Err(e) => {
eprintln!("[RuntimeScope] mcp server exited with error: {e}");
1
}
}
}
fn dashboard(args: &[String]) -> i32 {
let network = args.iter().any(|a| a == "--network");
let port = service::http_port(); if network {
let host = local_ip().unwrap_or_else(|| "<your-LAN-IP>".to_string());
println!(" LAN access needs the collector bound to 0.0.0.0:");
println!(" RUNTIMESCOPE_HOST=0.0.0.0 runtimescope service install");
println!(" Then open: http://{host}:{port}/dashboard");
return 0;
}
if !service::ensure_running() {
eprintln!(" Could not start the collector. Try `runtimescope service install` and check the logs.");
return 1;
}
let url = format!("http://127.0.0.1:{port}/dashboard");
println!(" Opening {url}");
open_browser(&url)
}
fn open_browser(url: &str) -> i32 {
let opener = if cfg!(target_os = "macos") { "open" } else { "xdg-open" };
match std::process::Command::new(opener).arg(url).status() {
Ok(s) if s.success() => 0,
_ => {
eprintln!(" Could not launch a browser. Open this URL manually: {url}");
0 }
}
}
fn local_ip() -> Option<String> {
let sock = std::net::UdpSocket::bind("0.0.0.0:0").ok()?;
sock.connect("8.8.8.8:80").ok()?;
sock.local_addr().ok().map(|a| a.ip().to_string())
}
fn print_help() {
println!("runtimescope {} — runtime monitoring for Claude Code", env!("CARGO_PKG_VERSION"));
println!();
println!("USAGE:");
println!(" runtimescope <command>");
println!();
println!("COMMANDS:");
println!(" service <sub> Manage the background collector service");
println!(" (install | stop | start | restart | status | uninstall)");
println!(" dashboard Start the collector if needed + open the dashboard (--network for the LAN URL)");
println!(" mcp Run the MCP server over stdio (for Claude Code: claude mcp add runtimescope -- runtimescope mcp)");
println!(" version Print the version");
println!(" help Show this help");
}