#![forbid(unsafe_code)]
mod app;
mod commands;
mod render;
mod ui;
use std::path::PathBuf;
use clap::{Parser, Subcommand};
use crate::ui::{ColorChoice, Ui};
#[derive(Debug, Parser)]
#[command(
name = "agentlink",
version,
about,
long_about = None,
after_help = "Learn more: https://github.com/fialhosoft/agentlink"
)]
struct Cli {
#[arg(short = 'C', long = "dir", global = true, value_name = "PATH")]
dir: Option<PathBuf>,
#[arg(long, global = true, value_enum, default_value_t = ColorChoice::Auto)]
color: ColorChoice,
#[arg(short, long, global = true)]
quiet: bool,
#[command(subcommand)]
command: Command,
}
#[derive(Debug, Subcommand)]
enum Command {
Init,
#[command(alias = "sync")]
Apply {
#[arg(long)]
dry_run: bool,
#[arg(long)]
adopt: bool,
},
Status {
#[arg(long)]
check: bool,
},
Adopt {
#[arg(long)]
dry_run: bool,
},
Doctor,
Providers,
Clean {
#[arg(long)]
dry_run: bool,
},
}
fn main() -> std::process::ExitCode {
let cli = Cli::parse();
let ui = Ui::new(cli.color, cli.quiet);
let result = match cli.command {
Command::Init => commands::init(ui, cli.dir),
Command::Apply { dry_run, adopt } => commands::apply(ui, cli.dir, dry_run, adopt),
Command::Status { check } => commands::status(ui, cli.dir, check),
Command::Adopt { dry_run } => commands::adopt(ui, cli.dir, dry_run),
Command::Doctor => commands::doctor(ui, cli.dir),
Command::Providers => commands::providers(ui, cli.dir),
Command::Clean { dry_run } => commands::clean(ui, cli.dir, dry_run),
};
match result {
Ok(code) => std::process::ExitCode::from(u8::try_from(code).unwrap_or(1)),
Err(err) => {
eprintln!("{} {err}", ui.red("error:"));
for cause in err.chain().skip(1) {
eprintln!(" {}", ui.dim(&cause.to_string()));
}
std::process::ExitCode::FAILURE
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use clap::CommandFactory;
#[test]
fn cli_definition_is_valid() {
Cli::command().debug_assert();
}
}