xbp 0.9.3

XBP is a zero-config build pack that can also interact with proxies, kafka, sockets, synthetic monitors.
Documentation
use clap::{Args, Parser, Subcommand};

#[derive(Parser, Debug)]
#[command(
    name = "xbp",
    version,
    about = "XBP CLI",
    disable_help_subcommand = false
)]
pub struct Cli {
    #[arg(long, global = true)]
    pub debug: bool,
    #[arg(short = 'l', help = "List pm2 processes")]
    pub list: bool,
    #[arg(short = 'p', long = "port", help = "Filter by port number")]
    pub port: Option<u16>,
    #[arg(long, help = "Open logs directory")]
    pub logs: bool,

    #[command(subcommand)]
    pub command: Option<Commands>,
}

#[derive(Subcommand, Debug)]
pub enum Commands {
    Ports(PortsCmd),
    Setup,
    Redeploy {
        #[arg(
            help = "Service name to redeploy (optional, uses legacy redeploy.sh if not provided)"
        )]
        service_name: Option<String>,
    },
    RedeployV2(RedeployV2Cmd),
    Config,
    Install {
        package: String,
    },
    Logs(LogsCmd),
    List,
    Curl {
        #[arg(help = "URL to fetch, e.g. https://example.com/api")]
        url: Option<String>,
    },
    Services,
    Service {
        #[arg(help = "Command to run: build, install, start, dev, or --help")]
        command: Option<String>,
        #[arg(help = "Service name")]
        service_name: Option<String>,
    },
    Nginx(NginxCmd),
    Diag(DiagCmd),
    Monitor(MonitorCmd),
    Tail(TailCmd),
    Start {
        #[arg(trailing_var_arg = true, allow_hyphen_values = true)]
        args: Vec<String>,
    },
}

#[derive(Args, Debug)]
pub struct PortsCmd {
    #[arg(short = 'p', long = "port")]
    pub port: Option<u16>,
    #[arg(long = "kill")]
    pub kill: bool,
    #[arg(short = 'n')]
    pub nginx: bool,
}

#[derive(Args, Debug)]
pub struct RedeployV2Cmd {
    #[arg(short = 'p', long = "password")]
    pub password: Option<String>,
    #[arg(short = 'u', long = "username")]
    pub username: Option<String>,
    #[arg(short = 'h', long = "host")]
    pub host: Option<String>,
    #[arg(short = 'd', long = "project-dir")]
    pub project_dir: Option<String>,
}

#[derive(Args, Debug)]
pub struct LogsCmd {
    #[arg()]
    pub project: Option<String>,
}

#[derive(Args, Debug)]
pub struct NginxCmd {
    #[command(subcommand)]
    pub command: NginxSubCommand,
}

#[derive(Subcommand, Debug)]
pub enum NginxSubCommand {
    Setup {
        #[arg(short, long, help = "Domain name")]
        domain: String,
        #[arg(short, long, help = "Port to proxy to")]
        port: u16,
    },
    List,
    Update {
        #[arg(short, long, help = "Domain name to update")]
        domain: String,
        #[arg(short, long, help = "New port to proxy to")]
        port: u16,
    },
}

#[derive(Args, Debug)]
pub struct DiagCmd {
    #[arg(long, help = "Check Nginx configuration")]
    pub nginx: bool,
    #[arg(long, help = "Check specific ports (comma-separated)")]
    pub ports: Option<String>,
    #[arg(long, help = "Skip internet speed test")]
    pub no_speed_test: bool,
}

#[derive(Args, Debug)]
pub struct MonitorCmd {
    #[command(subcommand)]
    pub command: Option<MonitorSubCommand>,
}

#[derive(Subcommand, Debug)]
pub enum MonitorSubCommand {
    Check,
    Start,
}

#[derive(Args, Debug)]
pub struct TailCmd {
    #[arg(long, help = "Tail Kafka topic instead of log files")]
    pub kafka: bool,
    #[arg(long, help = "Ship logs to Kafka")]
    pub ship: bool,
}