pub struct Cli { /* private fields */ }Expand description
A batteries-included entry point that wires together Registry, Parser,
and the render layer so callers do not have to do it themselves.
Build a Cli with Cli::new, optionally configure it with
Cli::app_name and Cli::version, then call Cli::run (or
Cli::run_env_args for the common case of reading from
std::env::args).
§Built-in behaviors
| Input | Behavior |
|---|---|
--help / -h anywhere | Print help for the most-specific resolved command; return Ok(()). |
--version / -V | Print "<app_name> <version>" (or just the version); return Ok(()). |
| Empty argument list | Print the top-level command listing; return Ok(()). |
| Unrecognized command | Print error + help to stderr; return Err(CliError::Parse(...)). |
§Examples
let cli = Cli::new(vec![
Command::builder("ping")
.summary("Check connectivity")
.handler(Arc::new(|_| { println!("pong"); Ok(()) }))
.build()
.unwrap(),
])
.app_name("myapp")
.version("0.1.0");
// Invoking with no args prints the command list (does not error).
assert!(cli.run(std::iter::empty::<&str>()).is_ok());Implementations§
Source§impl Cli
impl Cli
Sourcepub fn app_name(self, name: impl Into<String>) -> Self
pub fn app_name(self, name: impl Into<String>) -> Self
Set the application name (shown in version output and top-level help).
If not set, the version string is printed without a prefix.
Sourcepub fn version(self, version: impl Into<String>) -> Self
pub fn version(self, version: impl Into<String>) -> Self
Set the application version (shown by --version / -V).
If not set, "(no version set)" is printed.
Sourcepub fn with_middleware<M: Middleware + 'static>(self, m: M) -> Self
pub fn with_middleware<M: Middleware + 'static>(self, m: M) -> Self
Register a middleware that hooks into the parse-and-dispatch lifecycle.
Middlewares are invoked in registration order. Multiple middlewares can
be added by calling with_middleware repeatedly.
§Examples
use argot_cmd::{Cli, Command, middleware::Middleware};
struct Audit;
impl Middleware for Audit {
fn before_dispatch(&self, parsed: &argot_cmd::ParsedCommand<'_>) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
eprintln!("audit: {}", parsed.command.canonical);
Ok(())
}
}
let cli = Cli::new(vec![Command::builder("run").build().unwrap()])
.with_middleware(Audit);Sourcepub fn with_renderer<R: Renderer + 'static>(self, renderer: R) -> Self
pub fn with_renderer<R: Renderer + 'static>(self, renderer: R) -> Self
Replace the default renderer with a custom implementation.
The renderer is used for all help text, Markdown, subcommand listings,
and ambiguity messages produced by this Cli instance.
§Examples
struct MyRenderer;
impl Renderer for MyRenderer {
fn render_help(&self, cmd: &argot_cmd::Command) -> String { format!("HELP: {}", cmd.canonical) }
fn render_markdown(&self, cmd: &argot_cmd::Command) -> String { String::new() }
fn render_subcommand_list(&self, cmds: &[argot_cmd::Command]) -> String { String::new() }
fn render_ambiguity(&self, input: &str, _: &[String]) -> String { format!("bad: {}", input) }
}
let cli = Cli::new(vec![Command::builder("run").build().unwrap()])
.with_renderer(MyRenderer);Sourcepub fn with_query_support(self) -> Self
pub fn with_query_support(self) -> Self
Enable agent-discovery query support.
When enabled, the CLI recognises a built-in query command:
tool query commands # list all commands as JSON
tool query commands --stream # NDJSON: one object per line
tool query commands --fields canonical,summary
tool query commands --stream --fields canonical,summary
tool query <name> # get structured JSON for one command
tool query <name> --stream # single compact JSON lineThe query command is also injected into the registry so that it
appears in --help output and in Registry::iter_all_recursive.
§Examples
use argot_cmd::{Cli, Command};
let cli = Cli::new(vec![Command::builder("deploy").build().unwrap()])
.with_query_support();
// Now: `tool query commands` and `tool query deploy` work.
// Also: `tool query commands --stream` and `tool query deploy --stream`.Sourcepub fn warn_missing_dry_run(self, enabled: bool) -> Self
pub fn warn_missing_dry_run(self, enabled: bool) -> Self
Enable advisory warnings for mutating commands that have no --dry-run flag.
When enabled (default: off), Cli::run (and Cli::run_async) will emit a
warning to stderr before dispatching a mutating command that has no --dry-run
flag defined on it:
warning: mutating command 'delete' has no --dry-run flag definedThis is an advisory lint, not a hard error. It helps developers notice missing safety flags while building CLIs with argot.
§Examples
use std::sync::Arc;
use argot_cmd::{Cli, Command};
let cli = Cli::new(vec![
Command::builder("delete")
.summary("Delete a resource")
.mutating()
.handler(Arc::new(|_| Ok(())))
.build()
.unwrap(),
])
.warn_missing_dry_run(true);
// Running `delete` will now emit a warning to stderr.Sourcepub fn run(
&self,
args: impl IntoIterator<Item = impl AsRef<str>>,
) -> Result<(), CliError>
pub fn run( &self, args: impl IntoIterator<Item = impl AsRef<str>>, ) -> Result<(), CliError>
Parse and dispatch a command from an iterator of string arguments.
The iterator should not include the program name (argv[0]).
Built-in behaviors:
--helpor-hanywhere → print help for the most-specific matched command and returnOk(()).--versionor-V→ print version string and returnOk(()).- Empty input → print top-level command list and return
Ok(()). - Parse error → print the error to stderr, then help if possible; return
Err(CliError::Parse(...)). - No handler registered → return
Err(CliError::NoHandler(...)).
§Arguments
args— Iterator of argument strings, not including the program name.
§Errors
CliError::Parse— the argument list could not be parsed.CliError::NoHandler— the resolved command has no handler.CliError::Handler— the handler returned an error.
§Examples
let cli = Cli::new(vec![
Command::builder("hello")
.handler(Arc::new(|_| Ok(())))
.build()
.unwrap(),
]);
assert!(cli.run(["hello"]).is_ok());
assert!(matches!(cli.run(["--help"]), Ok(())));Sourcepub fn run_env_args(&self) -> Result<(), CliError>
pub fn run_env_args(&self) -> Result<(), CliError>
Sourcepub fn run_and_exit(&self, args: impl IntoIterator<Item = impl AsRef<str>>) -> !
pub fn run_and_exit(&self, args: impl IntoIterator<Item = impl AsRef<str>>) -> !
Parse, dispatch, and exit the process with an appropriate exit code.
On success exits with code 0. On any error, prints the error to stderr
and exits with code 1.
This is the recommended entry point for binary crates that want main
to be a one-liner:
use argot_cmd::{Cli, Command};
use std::sync::Arc;
fn main() {
Cli::new(vec![
Command::builder("run")
.handler(Arc::new(|_| Ok(())))
.build()
.unwrap(),
])
.run_env_args_and_exit();
}§Panics
Does not panic; all errors are handled by printing to stderr and exiting.
Sourcepub fn run_env_args_and_exit(&self) -> !
pub fn run_env_args_and_exit(&self) -> !
Convenience: run_and_exit using std::env::args().skip(1).
Sourcepub async fn run_async_and_exit(
&self,
args: impl IntoIterator<Item = impl AsRef<str>>,
) -> !
pub async fn run_async_and_exit( &self, args: impl IntoIterator<Item = impl AsRef<str>>, ) -> !
Async version of run_and_exit.
Must be called from an async context (e.g., #[tokio::main]).
Sourcepub async fn run_env_args_async_and_exit(&self) -> !
pub async fn run_env_args_async_and_exit(&self) -> !
Convenience: run_async_and_exit using std::env::args().skip(1).
Sourcepub async fn run_async(
&self,
args: impl IntoIterator<Item = impl AsRef<str>>,
) -> Result<(), CliError>
pub async fn run_async( &self, args: impl IntoIterator<Item = impl AsRef<str>>, ) -> Result<(), CliError>
Parse and dispatch a command asynchronously.
Behaves identically to Cli::run but also invokes
AsyncHandlerFn handlers
registered with crate::CommandBuilder::async_handler.
Must be called from an async context (e.g., inside #[tokio::main]).
Dispatch priority: async handler → sync handler → CliError::NoHandler.
§Feature
Requires the async feature flag.
§Errors
Same variants as Cli::run.
Sourcepub async fn run_env_args_async(&self) -> Result<(), CliError>
pub async fn run_env_args_async(&self) -> Result<(), CliError>
Convenience: run_async using std::env::args().skip(1).