use std::process::ExitCode; use clap::{Parser, error::ErrorKind}; use bsk::cli::error::{CliError, Format, render}; use bsk::cli::status::Output; use bsk::{Cli, Command, cli}; fn main() -> ExitCode { let cli = match Cli::try_parse() { Ok(cli) => cli, Err(err) => { let exit = match err.kind() { ErrorKind::DisplayHelp | ErrorKind::DisplayVersion => 0, _ => 1, }; let _ = err.print(); return ExitCode::from(exit); } }; // The daemon installs its own subscriber (with the rolling file // appender); CLI tracing would race with it and silently win, so // only init the CLI-side stderr subscriber for client commands. if !matches!(cli.command, Command::Daemon(_)) { init_cli_tracing(&cli.flags); } cli::update::print_update_hint_from_cache(&cli.flags, &cli.command); let format = if cli.flags.json { Format::Json } else { Format::Human }; match dispatch(cli, format) { Ok(()) => ExitCode::SUCCESS, Err(err) => render(&err, format), } } fn dispatch(cli: Cli, format: Format) -> Result<(), CliError> { match cli.command { Command::Daemon(cmd) => cli::daemon::dispatch(cmd).map_err(CliError::Local), Command::Status => { let output = if cli.flags.json { Output::Json } else { Output::Human }; cli::status::run(output).map(|_| ()) } Command::Doctor => { let output = if cli.flags.json { Output::Json } else { Output::Human }; let checks = cli::doctor::run(output).map_err(CliError::Local)?; if cli::doctor::has_failures(&checks) { Err(CliError::RenderedExit { exit_code: 1 }) } else { Ok(()) } } Command::InstallSkill(args) => { let output = if cli.flags.json { Output::Json } else { Output::Human }; cli::install_skill::dispatch(args, output) } Command::Update(args) => cli::update::dispatch(args, format), Command::Logs(cmd) => cli::logs::run(cli::logs::LogsArgs { follow: cmd.follow, lines: cmd.lines, }) .map_err(CliError::Local), Command::Session(cmd) => cli::session::dispatch(cmd, format), Command::Browsers => cli::browsers::dispatch(format), Command::Tab(cmd) => cli::tab::dispatch(cmd, format), Command::Window(cmd) => cli::window::dispatch(cmd, format), Command::Emulate(args) => cli::emulate::dispatch(args, format), Command::Screenshot(args) => cli::screenshot::dispatch(args, format), Command::Snapshot(args) => cli::snapshot::dispatch(args, format), Command::Observe(args) => cli::observe::dispatch(args, format), Command::Console(args) => cli::console::dispatch(args, format), Command::Network(args) => cli::network::dispatch(args, format), Command::GetHtml(args) => cli::get_html::dispatch(args, format), Command::Navigate(args) => cli::navigate::dispatch_navigate_command(args, format), Command::NavigateBack(args) => cli::navigate::dispatch_navigate_back(args, format), Command::NavigateForward(args) => cli::navigate::dispatch_navigate_forward(args, format), Command::Reload(args) => cli::navigate::dispatch_reload(args, format), Command::Click(args) => cli::interaction::dispatch_click(args, format), Command::Hover(args) => cli::interaction::dispatch_hover(args, format), Command::Fill(args) => cli::interaction::dispatch_fill(args, format), Command::Press(args) => cli::interaction::dispatch_press(args, format), Command::Select(args) => cli::interaction::dispatch_select(args, format), Command::Upload(args) => cli::upload::dispatch(args, format), Command::Download(args) => cli::download::dispatch(args, format), Command::Evaluate(args) => cli::evaluate::dispatch(args, format), Command::WaitForNavigation(args) => cli::waits::dispatch_wait_for_navigation(args, format), Command::WaitMs(args) => cli::waits::dispatch_wait_ms(args, format), Command::RequestHelp(args) => cli::human_loop::dispatch(args, format), Command::Record(cmd) => cli::record::dispatch(cmd, format), } } fn init_cli_tracing(flags: &bsk::cli::GlobalFlags) { use tracing_subscriber::EnvFilter; let level = if flags.quiet { "warn" } else { match flags.verbose { 0 => "info", 1 => "debug", _ => "trace", } }; let filter = EnvFilter::try_from_default_env() .unwrap_or_else(|_| EnvFilter::new(format!("bsk={level}"))); let _ = tracing_subscriber::fmt() .with_env_filter(filter) .with_writer(std::io::stderr) .try_init(); }