Quick Start¶
This page walks you through building a minimal Xclif CLI from scratch.
Step 1: Define your routes¶
Your directory structure is your command tree:
myapp/
├── __init__.py
├── __main__.py
└── routes/
├── __init__.py → myapp
├── greet.py → myapp greet
└── server/
├── __init__.py → myapp server
├── start.py → myapp server start
└── stop.py → myapp server stop
Step 2: Write commands as functions¶
# routes/greet.py
from xclif import command
@command()
def _(name: str, template: str = "Hello, {}!") -> None:
"""Greet someone by name."""
print(template.format(name))
The mapping rules are simple:
No default → positional argument (
name)Has default →
--templateoptionDocstring → help text (rendered as Markdown in
--help)Type annotation → parser and type coercion
The function signature is the CLI contract.
Step 3: Three-line entry point¶
# __main__.py
from xclif import Cli
from . import routes
cli = Cli.from_routes(routes)
if __name__ == "__main__":
cli()
Run it:
python -m myapp greet Alice
# Hello, Alice!
python -m myapp greet Alice --template "Hi, {}!"
# Hi, Alice!
python -m myapp --help
Flat API (not recommended)¶
Xclif also has a flat API that lets you build the command tree imperatively without file-based routing. It is not recommended for most projects — if you wanted to wire commands up by hand, you probably did not need Xclif in the first place. See Flat (Imperative) API for details.
Testing¶
Commands can be tested without mocking sys.argv:
def test_greet(capsys):
cli.root_command.execute(["greet", "Alice"])
assert capsys.readouterr().out == "Hello, Alice!\n"