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--template option

  • Docstring → 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

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"