Piou logo # Piou [![Python versions](https://img.shields.io/pypi/pyversions/piou)](https://pypi.python.org/pypi/piou) [![Latest PyPI version](https://img.shields.io/pypi/v/piou?logo=pypi)](https://pypi.python.org/pypi/piou) [![CI](https://github.com/Andarius/piou/actions/workflows/ci.yml/badge.svg)](https://github.com/Andarius/piou/actions/workflows/ci.yml) [![Latest conda-forge version](https://img.shields.io/conda/vn/conda-forge/piou?logo=conda-forge)](https://anaconda.org/conda-forge/piou) A CLI tool to build beautiful command-line interfaces with type validation. ## Quick Example ```python from piou import Cli, Option cli = Cli(description='A CLI tool') @cli.command(cmd='foo', help='Run foo command') def foo_main( bar: int = Option(help='Bar positional argument (required)'), baz: str = Option('-b', '--baz', help='Baz keyword argument (required)'), foo: str | None = Option(None, '--foo', help='Foo keyword argument'), ): """ A longer description on what the function is doing. """ pass if __name__ == '__main__': cli.run() ``` ![example](https://github.com/Andarius/piou/raw/master/docs/static/simple-output.svg) ## Installation ```bash pip install piou ``` Or with [uv](https://docs.astral.sh/uv/): ```bash uv add piou ``` Or with [conda](https://docs.conda.io/): ```bash conda install piou -c conda-forge ``` ### Raw Formatter By default, Piou uses [Rich](https://github.com/Textualize/rich) for beautiful terminal output. If you prefer plain text output, you can use the raw formatter: ```bash # Force raw output via environment variable PIOU_FORMATTER=raw python your_cli.py --help ``` ## Documentation Full documentation is available at **[andarius.github.io/piou](https://andarius.github.io/piou)**. ### Features - FastAPI-like developer experience with type hints - Custom formatters (Rich-based by default) - Nested command groups / sub-commands - Derived options for reusable argument patterns - Async command support - Type validation and casting - **Interactive TUI mode** with command suggestions and history - **Structured JSON help** (`--help-json`) for tooling and programmatic CLI discovery ## Why Piou? I could not find a library that provided: - The same developer experience as [FastAPI](https://fastapi.tiangolo.com/) - Customization of the interface (to build a CLI similar to [Poetry](https://python-poetry.org/)) - Type validation / casting [Typer](https://github.com/tiangolo/typer) is the closest alternative but lacks the possibility to format the output in a custom way using external libraries (like [Rich](https://github.com/Textualize/rich)). **Piou** provides all these possibilities and lets you define your own Formatter. ## Async Commands Commands can be `async` functions — piou detects coroutines and runs them automatically, no manual `asyncio.run()` needed: ```python from piou import Cli, Option cli = Cli(description='Async example') @cli.command(cmd='fetch', help='Fetch data') async def fetch(url: str = Option(help='URL to fetch')): import niquests async with niquests.AsyncSession() as client: r = await client.get(url) print(r.status_code) if __name__ == '__main__': cli.run() ``` This works the same way for commands inside command groups. ## Interactive TUI Mode Piou includes an optional interactive TUI (Text User Interface) mode powered by [Textual](https://textual.textualize.io/). This provides a rich terminal experience with command suggestions, history, and inline completions. ### Installation ```bash pip install piou[tui] # With auto-reload support for development pip install piou[tui-reload] ``` ### Usage Enable TUI mode by setting `tui=True` when creating your CLI: ```python from piou import Cli, Option cli = Cli(description='My Interactive CLI', tui=True) @cli.command(cmd='hello', help='Say hello') def hello(name: str = Option(..., help='Name to greet')): print(f'Hello, {name}!') if __name__ == '__main__': cli.run() ``` Or via the `--tui` flag: ```bash python my_cli.py --tui ``` Or via the `PIOU_TUI=1` environment variable: ```bash PIOU_TUI=1 python my_cli.py ``` ### TUI Features - **Command suggestions**: Type `/` to see available commands with descriptions - **Subcommand navigation**: Use `:` to navigate subcommands (e.g., `/stats:uploads`) - **Inline completions**: See argument placeholders as you type - **Command history**: Navigate previous commands with up/down arrows (persisted across sessions) - **Rich output**: ANSI colors and formatting preserved in output - **Keyboard shortcuts**: - `Tab` - Confirm selected suggestion - `Up/Down` - Navigate suggestions or history - `Ctrl+C` - Clear input (press twice to exit) - `Escape` - Quit - **Dev mode**: Auto-reload commands when source files change (see below) TUI Demo ### Dev Mode with Auto-Reload For faster development iteration, enable dev mode to automatically reload your commands when source files change: ```bash pip install piou[tui-reload] ``` Then use the `--tui-reload` flag: ```bash python my_cli.py --tui-reload ``` Or via environment variable: ```bash PIOU_TUI_DEV=1 python my_cli.py --tui ``` When enabled, Piou watches your command source files and hot-reloads them on save. You can also toggle reload mode at runtime with the `/tui-reload` command. To run custom code after each reload (e.g., refresh cached data), use the `@cli.tui_on_reload` decorator: ```python @cli.tui_on_reload def on_reload(): print('Code reloaded!') ``` ### Advanced Example: HTTP Benchmark The TUI mode supports mounting custom Textual widgets for rich interactive displays. This example benchmarks HTTP libraries with live progress grids: HTTP Benchmark TUI See [examples/http_bench_tui.py](examples/http_bench_tui.py) for the full implementation using `TuiContext` and custom widgets. ## Development ### Running Tests ```bash uv run pytest ``` ### Generating Documentation ```bash # Build docs uv run --group docs mkdocs build # Serve locally uv run --group docs mkdocs serve ``` ### Generating Screenshots and GIFs Terminal recordings are created with [VHS](https://github.com/charmbracelet/vhs). Install it first: ```bash # Ubuntu/Debian sudo apt install vhs ttyd # macOS brew install vhs # Or via Go go install github.com/charmbracelet/vhs@latest ``` Then generate recordings from tape files: ```bash vhs docs/static/tui-demo.tape ``` Tape files are located in `docs/static/` and define scripted terminal sessions that produce GIFs.