rngo-cli 0.32.0

CLI for running rngo simulations
mod init;
mod sim;
mod skills;
mod ui;

use clap::{Parser, Subcommand};

/// Simulate code usage, record everything and analyze the results
#[derive(Parser)]
#[command(name = "rngo", version)]
struct Cli {
    #[command(subcommand)]
    command: Commands,
}

#[derive(Subcommand)]
enum Commands {
    /// Initialize a directory for rngo
    ///
    /// Creates a `.rngo` directory, a starter `.rngo/spec.yml`, and
    /// updates `.gitignore`.
    Init {
        /// Directory to initialize
        #[arg(long, default_value = ".")]
        dir: std::path::PathBuf,
    },
    /// Run a simulation
    ///
    /// Loads a spec, runs the simulation, routes events to systems,
    /// and records everything.
    Run {
        /// Write  events to stdout (instead of routing to systems)
        #[arg(long)]
        stdout: bool,
        /// Path to a spec file (instead of building from the `.rngo` directory)
        #[arg(long)]
        spec: Option<std::path::PathBuf>,
        /// Path to the `.rngo` directory
        #[arg(long, default_value = ".")]
        dir: std::path::PathBuf,
    },
    /// Manage rngo agent skills
    Skills {
        #[command(subcommand)]
        command: SkillsCommands,
    },
}

#[derive(Subcommand)]
enum SkillsCommands {
    /// Download the latest rngo agent skills and install them
    ///
    /// Idempotent: any previously installed `rngo-` skills in the target
    /// directory are replaced with the latest release.
    Install {
        /// Where to install skills. Skips the interactive location prompt.
        #[arg(long)]
        path: Option<std::path::PathBuf>,
    },
}

fn main() {
    let cli = Cli::parse();

    match cli.command {
        Commands::Init { dir } => {
            if let Err(e) = init::init(&dir) {
                eprintln!("error: {e}");
                std::process::exit(1);
            }
        }
        Commands::Run { stdout, dir, spec } => match sim::run(&dir, stdout, spec.as_deref()) {
            Ok(true) => {}
            Ok(false) => std::process::exit(1),
            Err(e) => {
                eprintln!("error: {e}");
                std::process::exit(1);
            }
        },
        Commands::Skills { command } => match command {
            SkillsCommands::Install { path } => {
                if let Err(e) = skills::install(std::path::Path::new("."), path) {
                    eprintln!("error: {e}");
                    std::process::exit(1);
                }
            }
        },
    }
}