Sayer
Fast. Scalable. Elegant. Command the CLI like a boss. 🧙♂️
Documentation: https://sayer.dymmond.com 📚
Source Code: https://github.com/dymmond/sayer
The official supported version is always the latest released.
🤔 What is Sayer?
Sayer is a modern, async-native Python CLI framework built for developers who want more:
- More structure.
- More power.
- More expressiveness.
Less boilerplate. Less headache. Less "why doesn't this just work?".
Designed to scale from weekend scripts to enterprise-grade CLI suites — with a touch of magic.
📦 Installation
Using pip:
pip install sayer
Or with uv (blazing fast):
uv pip install sayer
🧩 Features
- ✅ Fully async support out-of-the-box
- ✅ Param metadata via
Option(...),Argument(...),Env(...)— inspired by the best - ✅ Declarative CLI building with decorators
- ✅ Built-in middleware system (yes, for CLI!)
- ✅ Shared app state and lifecycle management
- ✅ Terminal-rich output via
rich - ✅ Easy testing with
SayerTestClient - ✅ Flexible help and docs rendering
- ✅ Clean project scaffolding, sensible defaults
- ✅ 100% type annotated.
🔥 Why Sayer?
| Feature | Sayer | Notes |
|---|---|---|
| Async Support | ✅ Yes | Truly async from top to bottom |
| Param Metadata | ✅ Yes | With rich options, env vars, etc. |
| Middleware Support | ✅ Yes | Per-command, app-wide, scoped |
| Lifecycle Hooks | ✅ Yes | on_startup, on_shutdown |
| State Management | ✅ Yes | Like a Flask g but better |
| Testability | ✅ Yes | CLI client for unit tests |
| Output Styling | ✅ Yes | Built-in rich integration |
| Based on Modern Tools | ✅ Hatch + UV | Modern dev setup from day 1 |
| Full Typing | ✅ Yes | Ty + Ruff compliant |
| Fun to Use? | 🕺 Extremely | Let the code dance with you |
🚀 Getting Started
Create your first CLI app:
from sayer import Sayer, Option
app = Sayer()
@app.command()
def hello(name: str = Option(..., help="Your name")):
"""Say hello to someone"""
print(f"Hello, {name}!")
if __name__ == "__main__":
app()
Run it:
$ python app.py hello --name Ada
Hello, Ada!
🧪 Testing
hatch run test:test
Or with pytest:
pytest -v
📚 Documentation
Full docs available at: https://sayer.dymmond.com
You'll find:
- Full API reference
- Command examples
- Parameter deep dives
- Middleware patterns
- Configuration strategies
- ... and some fun easter eggs 🐣
Release files for sayer 0.7.7
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| sayer-0.7.7.tar.gz | 65.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| sayer-0.7.7-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 145.9 kB
Release files / sayer-0.7.7.tar.gz
| Download URL | sayer-0.7.7.tar.gz |
|---|---|
| Size | 65.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
61631e3ea3b15990cbf6762467bafa10afa61a6c04c3796d0602001d102d3db9
|
|
BLAKE2b-256 checksum How to use checksums |
9b4e3add9a30d8859ba7dc2817b4dda902689b48bcf1ad1aaf8a0bbcd5769db7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
Hatch/1.16.5 cpython/3.10.19 HTTPX/0.28.1
|
Release files / sayer-0.7.7-py3-none-any.whl
| Download URL | sayer-0.7.7-py3-none-any.whl |
|---|---|
| Size | 80.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
f3008aa9222cfd0a28b2914a694c5c35e65425be13a19ba132919cea85296593
|
|
BLAKE2b-256 checksum How to use checksums |
5f94e8ac18557aa1b5a982fb79845f3926d8cb1a3869cb5a4d9e89f2e4eac90e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
Hatch/1.16.5 cpython/3.10.19 HTTPX/0.28.1
|