Skip to main content

Command

Command represents one executable operation in a CLI. Commands live directly inside an Application and are the main way to expose named actions to the user.

Application
└── Command ← you are here
├── Argument
├── Option
└── Subcommand
├── Argument
└── Option

Subcommand inherits from Command and is used for nested command trees. It behaves identically to a Command but is attached under a parent command rather than directly under the Application.

What a command contains

  • a public command name
  • help text (explicit or derived from a docstring)
  • positional argument definitions
  • named option definitions
  • optional nested subcommand definitions
  • one handler callable

Responsibilities

A command parses tokens that belong to it, validates the parsed values against resource definitions, binds values to the handler signature, and executes the handler.

Naming behavior

Commands are registered under unique names. Function names are normalized by replacing underscores with hyphens when a name is not explicitly provided.

Basic command example

from quickli import Application, Argument, Option

app = Application(name="demo")


@app.command(
help_text="Greet someone.",
arguments=[Argument("name")],
options=[Option("shout", is_flag=True)],
)
def greet(name: str, shout: bool = False) -> str:
msg = f"Hello, {name}!"
return msg.upper() if shout else msg


print(app.run(["greet", "Alice"])) # Hello, Alice!
print(app.run(["greet", "Alice", "--shout"])) # HELLO, ALICE!

Nested subcommands example

Use Subcommand when a command naturally groups further actions, such as env create and env delete.

from quickli import Application, Argument, Subcommand

app = Application(name="demo")


@app.command(
name="env",
subcommands=[
Subcommand(
name="create",
arguments=[Argument("name")],
handler=lambda name: f"created:{name}",
)
],
)
def env() -> str:
return "env"


print(app.run(["env", "create", "dev"]))

Tips

:::tip Command vs. Subcommand Use a top-level @app.command for actions that are independent of each other, such as build and clean. Use a Subcommand when actions logically share a namespace, such as env create, env list, and env delete. :::

:::tip Help text from docstrings If you do not pass help_text, quickli automatically uses the function's docstring. This keeps your handler code self-documenting.

@app.command()
def build() -> str:
"""Build the project and produce a release artefact."""
return "building…"

:::

Where to go next

  • Add Arguments to accept positional input.
  • Add Options to accept named flags and values.
  • Go back to Application to understand how commands are dispatched.