Skip to main content

A CLI toolkit

Project description

Piou logo

Piou

Python versions Latest PyPI version CI Latest conda-forge version

A CLI tool to build beautiful command-line interfaces with type validation.

Quick Example

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

Installation

pip install piou

Or with uv:

uv add piou

Or with conda:

conda install piou -c conda-forge

Raw Formatter

By default, Piou uses Rich for beautiful terminal output. If you prefer plain text output, you can use the raw formatter:

# Force raw output via environment variable
PIOU_FORMATTER=raw python your_cli.py --help

Documentation

Full documentation is available at 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
  • Customization of the interface (to build a CLI similar to Poetry)
  • Type validation / casting

Typer is the closest alternative but lacks the possibility to format the output in a custom way using external libraries (like 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:

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. This provides a rich terminal experience with command suggestions, history, and inline completions.

Installation

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:

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:

python my_cli.py --tui

Or via the PIOU_TUI=1 environment variable:

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:

pip install piou[tui-reload]

Then use the --tui-reload flag:

python my_cli.py --tui-reload

Or via environment variable:

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:

@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 for the full implementation using TuiContext and custom widgets.

Development

Running Tests

uv run pytest

Generating Documentation

# 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. Install it first:

# 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:

vhs docs/static/tui-demo.tape

Tape files are located in docs/static/ and define scripted terminal sessions that produce GIFs.

Project details


Release history Release notifications | RSS feed

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

piou-0.35.0.tar.gz (1.6 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

piou-0.35.0-py3-none-any.whl (55.1 kB view details)

Uploaded Python 3

File details

Details for the file piou-0.35.0.tar.gz.

File metadata

  • Download URL: piou-0.35.0.tar.gz
  • Upload date:
  • Size: 1.6 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.18 {"installer":{"name":"uv","version":"0.11.18","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for piou-0.35.0.tar.gz
Algorithm Hash digest
SHA256 9037976ef529cea6afdd2f2b0a8aa7ddbb2f709468966e9d4d995d71a1ac3a78
MD5 874e0b7b81bdec2c4c7a364e8a51252c
BLAKE2b-256 cbdb1e5d5ac514d71fc7bdbebe6183e065bd0ede4fa13aea97d7f4ac1778adfe

See more details on using hashes here.

File details

Details for the file piou-0.35.0-py3-none-any.whl.

File metadata

  • Download URL: piou-0.35.0-py3-none-any.whl
  • Upload date:
  • Size: 55.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.18 {"installer":{"name":"uv","version":"0.11.18","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for piou-0.35.0-py3-none-any.whl
Algorithm Hash digest
SHA256 1b2b98edde3bab426c493b2fd95f40bd3eb4f8a5fc2010cc4b77a5f6353fdc7a
MD5 fb896fc8aab2a4f7e515aeabe5b10f04
BLAKE2b-256 11d555bb32388529a3087456e894280d91dce60185599e745c7a7f5911dc5b2c

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page