Skip to main content

Cli

Struct Cli 

Source
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

InputBehavior
--help / -h anywherePrint help for the most-specific resolved command; return Ok(()).
--version / -VPrint "<app_name> <version>" (or just the version); return Ok(()).
Empty argument listPrint the top-level command listing; return Ok(()).
Unrecognized commandPrint 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

Source

pub fn new(commands: Vec<Command>) -> Self

Create a new Cli from a list of top-level commands.

§Arguments
  • commands — The fully-built top-level command list. Ownership is transferred to an internal Registry.
Source

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.

Source

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.

Source

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);
Source

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);
Source

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 line

The 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`.
Source

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 defined

This 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.
Source

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:

  • --help or -h anywhere → print help for the most-specific matched command and return Ok(()).
  • --version or -V → print version string and return Ok(()).
  • 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
§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(())));
Source

pub fn run_env_args(&self) -> Result<(), CliError>

Convenience: run with std::env::args().skip(1).

Equivalent to self.run(std::env::args().skip(1)). Skipping element 0 is required because std::env::args includes the program name.

§Errors

Same as Cli::run.

Source

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.

Source

pub fn run_env_args_and_exit(&self) -> !

Convenience: run_and_exit using std::env::args().skip(1).

Source

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]).

Source

pub async fn run_env_args_async_and_exit(&self) -> !

Convenience: run_async_and_exit using std::env::args().skip(1).

Source

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.

Source

pub async fn run_env_args_async(&self) -> Result<(), CliError>

Convenience: run_async using std::env::args().skip(1).

Auto Trait Implementations§

§

impl Freeze for Cli

§

impl !RefUnwindSafe for Cli

§

impl Send for Cli

§

impl Sync for Cli

§

impl Unpin for Cli

§

impl UnsafeUnpin for Cli

§

impl !UnwindSafe for Cli

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.