Module

commands

CLI application with command decorator and dispatch.

Classes

CLI 65
Command-line application with typed commands and nested groups. Each @command becomes a CLI subcom…

Command-line application with typed commands and nested groups.

Each @command becomes a CLI subcommand, an MCP tool, and a help entry. Groups create nested command namespaces.

Usage::

cli = CLI(name="myapp", description="My tool", version="1.0.0")

@cli.command("greet", description="Say hello")
def greet(name: str, loud: bool = False) -> str:
    msg = f"Hello, {name}!"
    return msg.upper() if loud else msg

site = cli.group("site", description="Site operations")

@site.command("build", description="Build the site")
def build(output: str = "_site") -> str:
    return f"Building to {output}"

cli.run()

CLI::

myapp greet --name Alice
myapp site build --output _site
myapp --llms-txt
myapp --mcp

Methods

commands 0 dict[str, CommandDef | L…
All registered top-level commands (eager and lazy).
property
def commands(self) -> dict[str, CommandDef | LazyCommandDef]
Returns
dict[str, CommandDef | LazyCommandDef]
groups 0 dict[str, Group]
All registered top-level groups.
property
def groups(self) -> dict[str, Group]
Returns
dict[str, Group]
global_option 6
Register a global option available to all commands via Context. Usage:: c…
def global_option(self, name: str, *, short: str = '', option_type: type = str, default: Any = None, description: str = '', is_flag: bool = False) -> None

Register a global option available to all commands via Context.

Usage::

cli.global_option("environment", short="-e", default="local",
                  description="Config environment")
Parameters
Name Type Description
name
short Default:''
option_type Default:str
default Default:None
description Default:''
is_flag Default:False
root_option_specs 0 tuple[RootOptionSpec, ..…
Return immutable metadata for built-in and user-defined root options.
def root_option_specs(self) -> tuple[RootOptionSpec, ...]
Returns
tuple[RootOptionSpec, ...]
before_command 1 Callable
Register a hook that runs before every command. The hook receives (ctx, comman…
def before_command(self, fn: Callable) -> Callable

Register a hook that runs before every command.

The hook receives (ctx, command_name, kwargs) and can modify kwargs.

Usage::

@cli.before_command
def check_auth(ctx, command_name, kwargs):
    if not os.environ.get("API_KEY"):
        raise SystemExit("API_KEY not set")
Parameters
Name Type Description
fn
Returns
Callable
after_command 1 Callable
Register a hook that runs after every command. The hook receives (ctx, command…
def after_command(self, fn: Callable) -> Callable

Register a hook that runs after every command.

The hook receives (ctx, command_name, result).

Usage::

@cli.after_command
def log_result(ctx, command_name, result):
    ctx.log(f"{command_name} completed", level=1)
Parameters
Name Type Description
fn
Returns
Callable
command 12 Callable
Register a function as a CLI command. The function's type annotations drive: -…
def command(self, name: str, *, description: str = '', aliases: tuple[str, ...] | list[str] = (), tags: tuple[str, ...] | list[str] = (), hidden: bool = False, surfaces: tuple[CommandSurface, ...] | list[CommandSurface] = ('cli', 'mcp', 'llms'), examples: tuple[dict[str, Any], ...] | list[dict[str, Any]] = (), confirm: str = '', annotations: dict[str, Any] | None = None, ui: MCPAppToolMeta | None = None, display_result: bool = True, terminal_renderer: Callable[[Any, Context], str] | None = None) -> Callable

Register a function as a CLI command.

The function's type annotations drive:

  • argparse argument generation
  • MCP tool schema
  • help text
Parameters
Name Type Description
name
description Default:''
aliases Default:()
tags Default:()
hidden Default:False
surfaces

Discovery and invocation surfaces where the command is visible.

Default:('cli', 'mcp', 'llms')
examples Default:()
confirm

If set, prompt user with this message before executing.

Default:''
annotations

MCP tool annotations (readOnlyHint, destructiveHint, idempotentHint, openWorldHint).

Default:None
ui

Stable MCP Apps metadata linking this tool to aui://resource.

Default:None
display_result

If False, suppress plain-format output while still returning data for--format json or --output-file.

Default:True
terminal_renderer

Render structured results for plain terminal output only.

Default:None
Returns
Callable
lazy_command 14 LazyCommandDef
Register a lazy-loaded command. The handler module is not imported until the c…
def lazy_command(self, name: str, import_path: str, *, description: str = '', schema: dict[str, Any] | None = None, aliases: tuple[str, ...] | list[str] = (), tags: tuple[str, ...] | list[str] = (), hidden: bool = False, surfaces: tuple[CommandSurface, ...] | list[CommandSurface] = ('cli', 'mcp', 'llms'), examples: tuple[dict[str, Any], ...] | list[dict[str, Any]] = (), confirm: str = '', annotations: dict[str, Any] | None = None, ui: MCPAppToolMeta | None = None, display_result: bool = True, terminal_renderer: Callable[[Any, Context], str] | None = None) -> LazyCommandDef

Register a lazy-loaded command.

The handler module is not imported until the command is invoked. This keeps CLI startup fast for large command sets.

When providing a pre-computed schema, include"default"fields in properties for optional parameters so argparse receives the correct defaults without importing the handler module.

Parameters
Name Type Description
name
import_path
description Default:''
schema Default:None
aliases Default:()
tags Default:()
hidden Default:False
surfaces Default:('cli', 'mcp', 'llms')
examples Default:()
confirm Default:''
annotations Default:None
ui Default:None
display_result Default:True
terminal_renderer Default:None
Returns
LazyCommandDef
resource 4 Callable
Register a function as an MCP resource. Usage:: @cli.resource("config://a…
def resource(self, uri: str, *, name: str = '', description: str = '', mime_type: str = 'text/plain') -> Callable

Register a function as an MCP resource.

Usage::

@cli.resource("config://app", description="App config")
def get_config() -> dict: ...
Parameters
Name Type Description
uri
name Default:''
description Default:''
mime_type Default:'text/plain'
Returns
Callable
ui_resource 4 Callable
Register an HTML resource for the stable MCP Apps extension.
def ui_resource(self, uri: str, *, name: str = '', description: str = '', meta: MCPAppResourceMeta | None = None) -> Callable
Parameters
Name Type Description
uri
name Default:''
description Default:''
meta Default:None
Returns
Callable
prompt 3 Callable
Register a function as an MCP prompt. Usage:: @cli.prompt("deploy-checkli…
def prompt(self, name: str, *, description: str = '', arguments: tuple[dict[str, Any], ...] | list[dict[str, Any]] = ()) -> Callable

Register a function as an MCP prompt.

Usage::

@cli.prompt("deploy-checklist", description="Pre-deploy steps")
def checklist(environment: str) -> list[dict]: ...
Parameters
Name Type Description
name
description Default:''
arguments Default:()
Returns
Callable
middleware 1 Callable
Register a middleware function. Usage:: @cli.middleware def log_calls…
def middleware(self, fn: Callable) -> Callable

Register a middleware function.

Usage::

@cli.middleware
def log_calls(ctx, call, next_fn):
    result = next_fn(call)
    return result
Parameters
Name Type Description
fn
Returns
Callable
group 4 Group
Create and register a command group. Returns the Group for registering command…
def group(self, name: str, *, description: str = '', aliases: tuple[str, ...] | list[str] = (), hidden: bool = False) -> Group

Create and register a command group.

Returns the Group for registering commands within it::

site = cli.group("site", description="Site operations")

@site.command("build", description="Build the site")
def build(output: str = "_site") -> str: ...
Parameters
Name Type Description
name
description Default:''
aliases Default:()
hidden Default:False
Returns
Group
add_group 1
Register an externally-created Group.
def add_group(self, group: Group) -> None
Parameters
Name Type Description
group
mount 2
Mount another CLI as a command group. In-process, no subprocess. Usage:: …
def mount(self, prefix: str, other: CLI) -> None

Mount another CLI as a command group. In-process, no subprocess.

Usage::

main = CLI(name="main")
sub = CLI(name="sub")
main.mount("sub", sub)
# sub's commands are now at main.sub.*
Parameters
Name Type Description
prefix
other
get_command 1 CommandDef | LazyCommand…
Look up a command by name, alias, or dotted path. Dotted paths traverse groups…
def get_command(self, name: str) -> CommandDef | LazyCommandDef | None

Look up a command by name, alias, or dotted path.

Dotted paths traverse groups:get_command("site.build") resolves to thebuild command inside the sitegroup.

Parameters
Name Type Description
name
Returns
CommandDef | LazyCommandDef | None
walk_commands 0
Yield all commands in the tree as (dotted_path, CommandDef) tuples. Top-level …
def walk_commands(self)

Yield all commands in the tree as (dotted_path, CommandDef) tuples.

Top-level commands have simple names. Group commands use dots::

[("greet", greet_cmd), ("site.build", build_cmd), ...]
walk_resources 0 list[tuple[str, Resource…
Walk all registered resources.
def walk_resources(self) -> list[tuple[str, ResourceDef]]
Returns
list[tuple[str, ResourceDef]]
walk_ui_resources 0 list[tuple[str, MCPAppRe…
Walk registered MCP Apps UI resources in registration order.
def walk_ui_resources(self) -> list[tuple[str, MCPAppResourceDef]]
Returns
list[tuple[str, MCPAppResourceDef]]
walk_prompts 0 list[tuple[str, PromptDe…
Walk all registered prompts.
def walk_prompts(self) -> list[tuple[str, PromptDef]]
Returns
list[tuple[str, PromptDef]]
build_parser 0 argparse.ArgumentParser
Build argparse parser from registered commands and groups.
def build_parser(self) -> argparse.ArgumentParser
Returns
argparse.ArgumentParser
run 1 Any
Parse args and dispatch to the appropriate command.
def run(self, argv: list[str] | None = None) -> Any
Parameters
Name Type Description
argv Default:None
Returns
Any
invoke 1 InvokeResult
Run a command and capture output for testing. Stdout and stderr are captured s…
def invoke(self, argv: list[str]) -> InvokeResult

Run a command and capture output for testing.

Stdout and stderr are captured separately.outputcontains stdout (command results),stderrcontains log/error messages.

Usage::

result = cli.invoke(["greet", "--name", "Alice"])
assert result.exit_code == 0
assert "Alice" in result.output
assert result.stderr == ""  # no warnings
Parameters
Name Type Description
argv
Returns
InvokeResult
call 3 Any
Programmatically call a command by name or dotted path. Used by MCP server and…
def call(self, command_name: str, *, ctx: Context | None = None, **kwargs: Any) -> Any

Programmatically call a command by name or dotted path.

Used by MCP server and for programmatic invocation::

cli.call("greet", name="Alice")
cli.call("site.build", output="_site")

Arguments are validated and string inputs are coerced against the command's generated schema before hooks or handlers run.

A host-providedctxcan route output and approvals without touching process-global streams. Context remains invisible to command schemas and is injected into the handler as usual.

Parameters
Name Type Description
command_name
ctx Default:None
**kwargs
Returns
Any
call_raw 3 Any
Call a command without consuming generators. Like `call`(), but returns the ra…
def call_raw(self, command_name: str, *, ctx: Context | None = None, **kwargs: Any) -> Any

Call a command without consuming generators.

Likecall(), but returns the raw result — if the handler returns a generator, it is not consumed. The MCP server uses this to streamProgressyields as notifications. Arguments use the same schema validation and coercion ascall().

Parameters
Name Type Description
command_name
ctx Default:None
**kwargs
Returns
Any
suggest_command 1 str | None
Suggest the closest command name for typo correction.
def suggest_command(self, name: str) -> str | None
Parameters
Name Type Description
name
Returns
str | None
generate_help_all 0 str
Generate a full command tree reference in markdown.
def generate_help_all(self) -> str
Returns
str
Internal Methods 38
__init__ 5
def __init__(self, *, name: str = '', description: str = '', version: str = '', version_flags: tuple[str, ...] | list[str] = ('--version',), version_report: Callable[[], str] | None = None) -> None
Parameters
Name Type Description
name Default:''
description Default:''
version Default:''
version_flags Default:('--version',)
version_report Default:None
_bump_command_version 0
Mark command discovery caches stale.
def _bump_command_version(self) -> None
_resolve_dotted 1 CommandDef | LazyCommand…
Resolve a dotted command path like 'site.config.show'.
def _resolve_dotted(self, path: str) -> CommandDef | LazyCommandDef | None
Parameters
Name Type Description
path
Returns
CommandDef | LazyCommandDef | None
_new_root_parser 0 _MiloArgumentParser
Create a root parser from the public root-option metadata.
def _new_root_parser(self) -> _MiloArgumentParser
Returns
_MiloArgumentParser
_add_root_options 1
Add root options using `root_option_specs`() as the source of truth.
def _add_root_options(self, parser: argparse.ArgumentParser) -> None
Parameters
Name Type Description
parser
_build_navigation_parser 0 argparse.ArgumentParser
Build a schema-free parser for root options and command selection.
def _build_navigation_parser(self) -> argparse.ArgumentParser
Returns
argparse.ArgumentParser
_add_navigation_commands 2
Add leaf metadata without touching command schemas.
def _add_navigation_commands(self, subparsers: argparse._SubParsersAction, commands: dict[str, CommandDef | LazyCommandDef]) -> None
Parameters
Name Type Description
subparsers
commands
_add_navigation_groups 2
Add group metadata recursively without touching leaf schemas.
def _add_navigation_groups(self, subparsers: argparse._SubParsersAction, groups: dict[str, Group]) -> None
Parameters
Name Type Description
subparsers
groups
_build_selected_parser 2 argparse.ArgumentParser
Build a parser containing only one selected command path.
def _build_selected_parser(self, groups: tuple[Group, ...], command: CommandDef | LazyCommandDef) -> argparse.ArgumentParser
Parameters
Name Type Description
groups
command
Returns
argparse.ArgumentParser
_add_commands_to_subparsers 2
Add command parsers to a subparsers action.
def _add_commands_to_subparsers(self, subparsers: argparse._SubParsersAction, commands: dict[str, CommandDef | LazyCommandDef]) -> None
Parameters
Name Type Description
subparsers
commands
_add_groups_to_subparsers 2
Recursively add group parsers to a subparsers action.
def _add_groups_to_subparsers(self, subparsers: argparse._SubParsersAction, groups: dict[str, Group]) -> None
Parameters
Name Type Description
subparsers
groups
_add_arguments_from_schema 3
Add argparse arguments from a command's JSON schema. Uses the handler's signat…
def _add_arguments_from_schema(self, parser: argparse.ArgumentParser, schema: dict[str, Any], cmd: CommandDef | LazyCommandDef) -> None

Add argparse arguments from a command's JSON schema.

Uses the handler's signature for defaults when available (eager commands), or falls back to schema-only mode (lazy commands).

Parameters
Name Type Description
parser
schema
cmd
_dispatch_parsed_args 1 Any
Execute a fully parsed command namespace.
def _dispatch_parsed_args(self, args: argparse.Namespace) -> Any
Parameters
Name Type Description
args
Returns
Any
_selected_command_path 1 tuple[tuple[Group, ...],…
Return the selected group path and leaf from a navigation namespace.
def _selected_command_path(self, args: argparse.Namespace) -> tuple[tuple[Group, ...], CommandDef | LazyCommandDef] | None
Parameters
Name Type Description
args
Returns
tuple[tuple[Group, ...], CommandDef | LazyCommandDef] | None
_resolve_builtin_mode 1 BuiltinMode | None
Return the selected built-in top-level mode, if any.
def _resolve_builtin_mode(self, args: argparse.Namespace) -> BuiltinMode | None
Parameters
Name Type Description
args
Returns
BuiltinMode | None
_run_builtin_mode 2
Execute a built-in top-level mode.
def _run_builtin_mode(self, args: argparse.Namespace, mode: BuiltinMode) -> None
Parameters
Name Type Description
args
mode
_resolve_command_execution 1 CommandExecution | None
Resolve parsed args to an executable command or handle help cases.
def _resolve_command_execution(self, args: argparse.Namespace) -> CommandExecution | None
Parameters
Name Type Description
args
Returns
CommandExecution | None
_build_run_kwargs 3 dict[str, Any]
Build handler kwargs from parsed args, injecting the active context.
def _build_run_kwargs(self, args: argparse.Namespace, ctx: Context, command: CommandDef) -> dict[str, Any]
Parameters
Name Type Description
args
ctx
command
Returns
dict[str, Any]
_build_handler_kwargs_from_namespace 3 dict[str, Any]
Build handler kwargs from an argparse namespace.
def _build_handler_kwargs_from_namespace(self, args: argparse.Namespace, ctx: Context, command: CommandDef) -> dict[str, Any]
Parameters
Name Type Description
args
ctx
command
Returns
dict[str, Any]
_get_resolved_command 1 tuple[CommandDef | LazyC…
Resolve a command name to the registered definition and eager command. Raises …
def _get_resolved_command(self, command_name: str) -> tuple[CommandDef | LazyCommandDef, CommandDef]

Resolve a command name to the registered definition and eager command.

Raises a structuredMiloErrorif a lazy command fails to import.

Parameters
Name Type Description
command_name
Returns
tuple[CommandDef | LazyCommandDef, CommandDef]
_lazy_import_error 1
Convert an import implementation detail into Milo's public error contract.
staticmethod
def _lazy_import_error(exc: LazyImportError)
Parameters
Name Type Description
exc
_validate_command_kwargs 2 dict[str, Any]
Validate user arguments and preserve injected Context parameters.
def _validate_command_kwargs(self, command: CommandDef, kwargs: dict[str, Any]) -> dict[str, Any]
Parameters
Name Type Description
command
kwargs
Returns
dict[str, Any]
_build_call_kwargs 3 dict[str, Any]
Build handler kwargs for programmatic/MCP calls, injecting context.
def _build_call_kwargs(self, command: CommandDef, kwargs: dict[str, Any], ctx: Context) -> dict[str, Any]
Parameters
Name Type Description
command
kwargs
ctx
Returns
dict[str, Any]
_new_call_context 0 Context
Create a default context for programmatic command calls.
def _new_call_context(self) -> Context
Returns
Context
_execute_command 6 Any
Execute a command with context setup, hooks, middleware, and error handling.
def _execute_command(self, command: CommandDef, ctx: Context, kwargs: dict[str, Any], *, method: str = 'command', call_name: str | None = None, raise_on_error: bool = False) -> Any
Parameters
Name Type Description
command
ctx
kwargs
method Default:'command'
call_name Default:None
raise_on_error Default:False
Returns
Any
_run_before_command_hooks 3
Execute before-command hooks.
def _run_before_command_hooks(self, ctx: Context, command_name: str, kwargs: dict[str, Any]) -> None
Parameters
Name Type Description
ctx
command_name
kwargs
_run_after_command_hooks 3
Execute after-command hooks.
def _run_after_command_hooks(self, ctx: Context, command_name: str, result: Any) -> None
Parameters
Name Type Description
ctx
command_name
result
_consume_result 2 Any
Consume generator-based command results.
def _consume_result(self, result: Any, *, emit_progress: bool = True) -> Any
Parameters
Name Type Description
result
emit_progress Default:True
Returns
Any
_write_command_output 4
Write command output to stdout or a file. When *output_file* already exists an…
def _write_command_output(self, result: Any, fmt: str, output_file: str, *, force: bool = False) -> None

Write command output to stdout or a file.

When output_file already exists and force is False, prints an error and exits instead of silently overwriting.

Parameters
Name Type Description
result
fmt
output_file
force Default:False
_build_context 1 Context
Build a Context from parsed global options.
def _build_context(self, args: argparse.Namespace) -> Context
Parameters
Name Type Description
args
Returns
Context
_format_root_help 0
Render root help from command, group, and root-option metadata.
def _format_root_help(self) -> None
_format_group_help 2
Render group metadata through an overrideable application hook.
def _format_group_help(self, group: Group, prog: str) -> None
Parameters
Name Type Description
group
prog
_format_command_help 2
Render one leaf schema through an overrideable application hook.
def _format_command_help(self, command: CommandDef | LazyCommandDef, prog: str) -> None
Parameters
Name Type Description
command
prog
_resolve_command_from_args 1 ResolveResult
Walk the parsed args to find the leaf command, group, or nothing.
def _resolve_command_from_args(self, args: argparse.Namespace) -> ResolveResult
Parameters
Name Type Description
args
Returns
ResolveResult
_resolve_group_command 4 ResolveResult
Recursively resolve a command within a group from parsed args.
def _resolve_group_command(self, group: Group, args: argparse.Namespace, fmt: str, prog: str = '') -> ResolveResult
Parameters
Name Type Description
group
args
fmt
prog Default:''
Returns
ResolveResult
_resolve_call_context 2 Context
Validate a host context while rejecting protocol attempts to spoof one.
def _resolve_call_context(self, ctx: Context | None, *, method: str) -> Context
Parameters
Name Type Description
ctx
method
Returns
Context
_mcp_install 0
Register this CLI in the milo gateway.
def _mcp_install(self) -> None
_mcp_uninstall 0
Remove this CLI from the milo gateway.
def _mcp_uninstall(self) -> None