xbp 10.40.1

XBP is a zero-config build pack that can also interact with proxies, kafka, sockets, synthetic monitors.
Documentation
use tracing::info;
use tracing_subscriber::{fmt, EnvFilter};

use xbp_cli::{api, cli, commands};

/// Windows defaults to a ~1MB main-thread stack. Long `version release` /
/// `publish` async graphs (plus stream capture) have overflowed that after
/// multi-minute `cargo publish` runs. Run the runtime on a larger stack.
const MAIN_THREAD_STACK_SIZE: usize = 8 * 1024 * 1024;

fn main() {
    let result = std::thread::Builder::new()
        .name("xbp-main".into())
        .stack_size(MAIN_THREAD_STACK_SIZE)
        .spawn(|| {
            let runtime = tokio::runtime::Builder::new_multi_thread()
                .enable_all()
                .thread_name("xbp-worker")
                .build()
                .expect("failed to build tokio runtime");
            runtime.block_on(async_main())
        })
        .expect("failed to spawn xbp main thread")
        .join();

    match result {
        Ok(Ok(())) => {}
        Ok(Err(code)) => std::process::exit(code),
        Err(_) => {
            eprintln!("xbp main thread panicked");
            std::process::exit(1);
        }
    }
}

async fn async_main() -> Result<(), i32> {
    let background_tray = commands::is_tray_background_child();
    if background_tray {
        commands::prepare_background_tray_process();
        let _ = fmt()
            .with_writer(std::io::sink)
            .with_ansi(false)
            .with_env_filter(EnvFilter::from_default_env())
            .try_init();
    } else {
        fmt()
            .with_env_filter(EnvFilter::from_default_env())
            .with_ansi(cli::ui::should_emit_ansi())
            .init();
    }

    if std::env::var("PORT_XBP_MCP").is_ok() {
        info!("Starting XBP MCP server mode");
        if let Err(e) = xbp_mcp::serve_from_env().await {
            eprintln!("MCP server error: {}", e);
            return Err(1);
        }
    } else if std::env::var("PORT_XBP_API").is_ok() {
        info!("Starting XBP API server mode");
        if let Err(e) = api::start_api_server().await {
            eprintln!("API server error: {}", e);
            return Err(1);
        }
    } else if let Err(e) = cli::run().await {
        if background_tray {
            let _ = tracing::error!("{e}");
        } else {
            eprintln!("{}", e);
        }
        return Err(1);
    }
    Ok(())
}