//! Command line interface definition (clap v4, derive API). use clap::{ArgAction, Args, Parser, Subcommand}; use clap_complete::Shell; use std::path::PathBuf; /// Manage local AI coding agents: install, start, stop, update. #[derive(Parser, Debug, Clone)] #[command( name = "am", bin_name = "am", version, // The help subcommand is provided by the custom Nushell-style help // (cli::Command::Help) instead of clap's generated one. disable_help_subcommand = true, about = "agent-manager (am) — manage local AI coding agents", long_about = "agent-manager (am) — a CLI to manage local AI coding agents. Install, uninstall, start, stop, restart and update AI agents from a YAML catalog. Handles dependencies (Node, Python, Go, Rust, Bun), binaries from GitHub Releases, install scripts, and git repositories. All state lives under your user directories; nothing pollutes the system." )] pub struct Cli { /// Use an alternate configuration file #[arg(short = 'c', long, global = true, value_name = "FILE")] pub config: Option, /// Verbose output: show every command executed and its details #[arg(short = 'v', long, global = true, action = ArgAction::SetTrue)] pub verbose: bool, /// Quiet mode: only errors are printed #[arg(short = 'q', long, global = true, conflicts_with = "verbose", action = ArgAction::SetTrue)] pub quiet: bool, /// Answer yes to every confirmation prompt #[arg(short = 'y', long, global = true, action = ArgAction::SetTrue)] pub yes: bool, /// Simulate the action without changing anything #[arg(long, global = true, action = ArgAction::SetTrue)] pub dry_run: bool, /// Emit machine-readable JSON on stdout (for scripts) #[arg(long, global = true, action = ArgAction::SetTrue)] pub json: bool, /// Disable ANSI colors #[arg(long, global = true, action = ArgAction::SetTrue)] pub no_color: bool, /// Color theme for the output (see 'am help theme' for the list) #[arg(long, global = true, value_name = "THEME")] pub theme: Option, #[command(subcommand)] pub command: Option, } #[derive(Subcommand, Debug, Clone)] pub enum Command { /// List installed agents (default); use --all for the whole catalog List { /// Show every agent known to the catalog, not only the installed ones #[arg(long)] all: bool, /// Only show agents of this category #[arg(long, value_name = "CATEGORY")] category: Option, }, /// Start an agent (foreground by default, or detached with --background) Start(StartArgs), /// Stop a background agent (SIGTERM, then SIGKILL after the timeout) Stop { /// Agent name, alias, or group: agent: String, /// Kill immediately instead of terminating gracefully #[arg(long)] force: bool, /// Grace period in seconds before killing (default: from config, 5s) #[arg(long, value_name = "SECS")] timeout: Option, }, /// Restart an agent: stop, then start with the same options Restart { #[command(flatten)] start: StartArgs, /// Kill immediately instead of terminating gracefully #[arg(long)] force: bool, /// Grace period in seconds before killing (default: from config, 5s) #[arg(long, value_name = "SECS")] timeout: Option, }, /// Show the state of one agent, or of every installed agent Status { /// Agent name or alias (omit to show all installed agents) agent: Option, }, /// List the sessions of every agent (and of the interactive shell) Sessions { /// Only sessions of this agent agent: Option, /// Only sessions of this project #[arg(long, value_name = "PROJECT")] project: Option, /// Only sessions with this status (running, stopped, failed, interrupted) #[arg(long, value_name = "STATUS")] status: Option, /// Show one session in detail (summary + log excerpt) #[arg(long, value_name = "ID")] show: Option, }, /// Install an agent and its dependencies Install { /// Agent name or alias agent: String, /// Select the install method (index, or type: npm, pip, uv, cargo, go, bun, curl, binary, git) #[arg(long, value_name = "METHOD")] method: Option, /// Reinstall even if already installed #[arg(long)] force: bool, }, /// Uninstall an agent (managed or external) and clean its files Uninstall { /// Agent name or alias agent: String, /// Also remove logs and the agent entry from the user config file #[arg(long)] purge: bool, }, /// Update an installed agent to the latest available version Update { /// Agent name or alias (required unless --all) agent: Option, /// Update every installed managed agent #[arg(long)] all: bool, }, /// Search the catalog by keyword (name, description, category, tags) Search { /// Keyword to search for (case-insensitive substring) keyword: String, /// Restrict to this category #[arg(long, value_name = "CATEGORY")] category: Option, }, /// Show detailed information about one agent Info { /// Agent name or alias agent: String, }, /// Display help: the overview, a command, the command list, or a search Help { /// Command name (also accepts an agent name or alias); "commands" lists every command command: Option, /// Search through all help commands table #[arg(long, value_name = "TEXT")] find: Option, }, /// Display version and build information Version, /// Manage the configuration file #[command(subcommand)] Config(ConfigCmd), /// Check the environment: tools, config validity, paths, permissions Doctor { /// Attempt to repair problems (create directories, fix the state file) #[arg(long)] fix: bool, }, /// Run the agent command directly with the given arguments (no process management) Run { /// Agent name or alias agent: String, /// Arguments passed through to the agent command #[arg(trailing_var_arg = true, allow_hyphen_values = true, value_name = "ARGS...")] args: Vec, }, /// Generate a shell completion script Completion { /// Shell to generate completions for #[arg(value_enum, value_name = "SHELL")] shell: Shell, }, /// Update agent-manager itself from GitHub Releases SelfUpdate { /// Only check whether a newer version exists #[arg(long)] check: bool, /// Download the new binary to this path instead of replacing the current one #[arg(long, value_name = "FILE")] to: Option, }, /// Remove agent-manager and everything it created from this machine /// /// Stops every managed background agent, then deletes the data, state and /// configuration directories, and finally the executable itself. Combine /// with --yes for a fully automated one-liner. SelfUninstall, /// Export the configuration and installation state (backup) Export { /// Output file (default: am-export.json) #[arg(long, value_name = "FILE", default_value = "am-export.json")] output: PathBuf, }, /// Import a previously exported configuration and state Import { /// File exported by the export command file: PathBuf, }, } /// Arguments shared by start and restart. #[derive(Args, Debug, Clone, Default)] pub struct StartArgs { /// Agent name, alias, or group: pub agent: String, /// Run detached in the background; output goes to the agent log file #[arg(short = 'b', long, conflicts_with = "foreground", action = ArgAction::SetTrue)] pub background: bool, /// Run in the foreground, attached to this terminal (the default) #[arg(short = 'f', long, action = ArgAction::SetTrue)] pub foreground: bool, /// Extra arguments passed to the agent (repeatable; quoted strings are split on spaces) #[arg(long, value_name = "ARGS", num_args = 0.., action = ArgAction::Append)] pub args: Vec, /// Set an environment variable for the agent (repeatable): --env KEY=VALUE #[arg(long, value_name = "KEY=VALUE", action = ArgAction::Append)] pub env: Vec, /// Send a desktop notification once the agent has started #[arg(long, action = ArgAction::SetTrue)] pub notify: bool, } /// Configuration management subcommands. #[derive(Subcommand, Debug, Clone)] pub enum ConfigCmd { /// Print the effective (merged) configuration as YAML Show, /// Print the location of the configuration file(s) Path, /// Open the user configuration file in your editor Edit, /// Validate the configuration file(s) Validate, /// Add another agent definition file to the user configuration Add { /// YAML (or JSON) file defining agents to include file: PathBuf, }, }