Files
agent-manager/src/cli.rs
T

255 lines
9.2 KiB
Rust

//! 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<PathBuf>,
/// 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<String>,
#[command(subcommand)]
pub command: Option<Command>,
}
#[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<String>,
},
/// 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:<name>
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<u64>,
},
/// 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<u64>,
},
/// Show the state of one agent, or of every installed agent
Status {
/// Agent name or alias (omit to show all installed agents)
agent: Option<String>,
},
/// List the sessions of every agent (and of the interactive shell)
Sessions {
/// Only sessions of this agent
agent: Option<String>,
/// Only sessions of this project
#[arg(long, value_name = "PROJECT")]
project: Option<String>,
/// Only sessions with this status (running, stopped, failed, interrupted)
#[arg(long, value_name = "STATUS")]
status: Option<String>,
/// Show one session in detail (summary + log excerpt)
#[arg(long, value_name = "ID")]
show: Option<String>,
},
/// 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<String>,
/// 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<String>,
/// 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<String>,
},
/// 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<String>,
/// Search through all help commands table
#[arg(long, value_name = "TEXT")]
find: Option<String>,
},
/// 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<std::ffi::OsString>,
},
/// 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<PathBuf>,
},
/// 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:<name>
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<String>,
/// Set an environment variable for the agent (repeatable): --env KEY=VALUE
#[arg(long, value_name = "KEY=VALUE", action = ArgAction::Append)]
pub env: Vec<String>,
/// 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,
},
}