363 lines
13 KiB
Rust
363 lines
13 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>,
|
|
/// Only show running agents
|
|
#[arg(long)]
|
|
running: bool,
|
|
/// Sort by name, version or status (default: name)
|
|
#[arg(long, value_name = "KEY")]
|
|
sort: Option<String>,
|
|
},
|
|
/// Tail the log file of an agent (--follow for a live view)
|
|
Logs {
|
|
/// Agent name or alias
|
|
agent: String,
|
|
/// Number of lines to show (default: 20)
|
|
#[arg(long, value_name = "N", default_value = "20")]
|
|
lines: usize,
|
|
/// Follow the log as it grows
|
|
#[arg(long)]
|
|
follow: bool,
|
|
},
|
|
/// Open an agent's installation directory in the file manager
|
|
Open {
|
|
/// Agent name or alias
|
|
agent: String,
|
|
},
|
|
/// Manage command aliases (cc -> claude-code)
|
|
#[command(subcommand)]
|
|
Alias(AliasCmd),
|
|
/// 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>,
|
|
},
|
|
/// Show usage statistics computed from the event journal
|
|
Stats {
|
|
/// Agent name or alias (omit for the global view)
|
|
agent: Option<String>,
|
|
/// Only events of the last period (7d, 30d, 90d, all)
|
|
#[arg(long, value_name = "PERIOD")]
|
|
period: Option<String>,
|
|
},
|
|
/// Show which agent works on which project
|
|
Projects {
|
|
/// Project name (omit to list every project)
|
|
name: Option<String>,
|
|
},
|
|
/// Read the event journal: everything am did
|
|
Log {
|
|
/// Only events of this agent
|
|
agent: Option<String>,
|
|
/// Only these event kinds (comma separated: start,stop,run,install,...)
|
|
#[arg(long, value_name = "KINDS")]
|
|
kind: Option<String>,
|
|
/// Only events at or after this date (YYYY-MM-DD or RFC 3339)
|
|
#[arg(long, value_name = "DATE")]
|
|
since: Option<String>,
|
|
/// Maximum number of events (default: 50)
|
|
#[arg(long, value_name = "N", default_value = "50")]
|
|
limit: usize,
|
|
},
|
|
/// 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>,
|
|
},
|
|
/// Search the command history (am and shell commands)
|
|
History {
|
|
/// Only commands of this kind (am or shell)
|
|
#[arg(long, value_name = "KIND")]
|
|
kind: Option<String>,
|
|
/// Only commands run in this directory
|
|
#[arg(long, value_name = "DIR")]
|
|
cwd: Option<String>,
|
|
/// Full-text search in the command line
|
|
#[arg(long, value_name = "TEXT")]
|
|
search: Option<String>,
|
|
/// Only failed commands
|
|
#[arg(long)]
|
|
failed: bool,
|
|
/// Only commands of this session
|
|
#[arg(long, value_name = "ID")]
|
|
session: Option<String>,
|
|
/// Maximum number of entries (default: 100)
|
|
#[arg(long, value_name = "N", default_value = "100")]
|
|
limit: usize,
|
|
/// Re-run the Nth most recent entry (with confirmation)
|
|
#[arg(long, value_name = "N")]
|
|
rerun: Option<usize>,
|
|
},
|
|
/// Show detailed information about one agent
|
|
Info {
|
|
/// Agent name or alias
|
|
agent: String,
|
|
},
|
|
/// Generate a local agent-manager.yaml for the current directory
|
|
Init {
|
|
/// Overwrite an existing agent-manager.yaml
|
|
#[arg(long)]
|
|
force: bool,
|
|
},
|
|
/// 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> (defaults to the project's default agent)
|
|
pub agent: Option<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,
|
|
}
|
|
|
|
/// Alias management subcommands.
|
|
#[derive(Subcommand, Debug, Clone)]
|
|
pub enum AliasCmd {
|
|
/// Add an alias (am alias add cc claude-code)
|
|
Add {
|
|
/// Short name of the alias
|
|
name: String,
|
|
/// Agent name (or another alias) it points to
|
|
target: String,
|
|
},
|
|
/// Remove an alias
|
|
Remove {
|
|
/// Alias to remove
|
|
name: String,
|
|
},
|
|
/// List every alias
|
|
List,
|
|
}
|
|
|
|
/// 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,
|
|
},
|
|
/// Set one configuration key without an editor (config set settings.default_shell pwsh)
|
|
Set {
|
|
/// Dotted key path, e.g. settings.default_shell
|
|
key: String,
|
|
/// New value (booleans and integers keep their type)
|
|
value: String,
|
|
},
|
|
}
|