larzcli
Define a function, get a CLI. Pure Python, zero dependencies.
Write a normal type-annotated function and larzcli builds the command-line
interface from its signature — arguments, types, defaults, boolean flags, and
--help. The CLI and the code can't drift apart, and there's no parser to
configure.
from larzcli import command, run
@command
def greet(name: str, count: int = 1, shout: bool = False):
"""Greet someone."""
for _ in range(count):
print(("HI " if shout else "Hi ") + name)
if __name__ == "__main__":
run(greet)
$ greet Ada --count 3 --shout
HI Ada
HI Ada
HI Ada
What makes it different
Function-first CLIs aren't new — larzcli's edge is layered configuration built in. Options resolve as command line → environment variable → default, so the same command is 12-factor-configurable with zero extra code:
from larzcli import App
app = App("tool", env_prefix="TOOL_")
@app.command
def serve(host: str = "127.0.0.1", port: int = 8080):
"""Run the server."""
...
app.run()
$ tool serve --port 9000 # explicit
$ TOOL_PORT=9000 tool serve # from the environment
$ tool serve # default 8080
The --help even documents which env var backs each option. It pairs naturally
with larzconf for the same layering
philosophy across your whole app.
Why else
- Zero dependencies. No
click, notyper, noargparseboilerplate. - Types drive everything.
int/float/str/bool/listannotations become parsing and validation;boolbecomes a--flag/--no-flag; params without a default become required positionals. - Subcommands with one decorator (
@app.command), auto-generated help. - Testable.
command.parse(argv, env=...)returns the resolved kwargs andcommand.invoke(...)calls the function — nosys.exit, no globals, so unit testing a CLI is trivial.
Install
pip install larzcli
Usage
from larzcli import command, App, run
# single command
@command
def build(target: str, jobs: int = 4, verbose: bool = False):
"""Build a target."""
...
run(build) # build app --jobs 8 --verbose
# multi-command app
app = App("git-ish", help="A tiny VCS.")
@app.command
def add(path: str):
"""Stage a file."""
...
@app.command(name="commit")
def do_commit(message: str, amend: bool = False):
"""Record changes."""
...
app.run() # git-ish add file.py ; git-ish commit --message "wip"
Testing a CLI
build.parse(["main", "--jobs", "8"]) # {"target": "main", "jobs": 8, ...}
build.invoke(["main", "--verbose"]) # actually calls build(...)
app.invoke(["add", "file.py"], env={...})
Tests
python -m unittest discover -s tests -v # 21 tests, zero deps
The Larz stack
Pure-Python, zero-dependency building blocks: larz · larzchain · larzmoney · larzcrypt · larzdb · larzagent · larzchart · larzmark · larztask · larzvault · larzvm · larzcache · larzvalidate · larzid · larzrpc · larzstate · larzhttp · larzconf · larzcron · larzlimit · larzlog · larzcli
License
MIT © larz-scripter
Metadata
Release files for larzcli 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| larzcli-0.1.0.tar.gz | 8.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| larzcli-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 16.3 kB
Release files / larzcli-0.1.0.tar.gz
| Download URL | larzcli-0.1.0.tar.gz |
|---|---|
| Size | 8.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
657ca14c8feb212c7e96b5b5bc5d6a1b02059a9c78bb00bcebe06ff010472d1c
|
|
BLAKE2b-256 checksum How to use checksums |
1d717198c17b000165eb3af42f45f300a31c6fd1f3fda77a665f28b0da1fe932
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.13
|
Release files / larzcli-0.1.0-py3-none-any.whl
| Download URL | larzcli-0.1.0-py3-none-any.whl |
|---|---|
| Size | 8.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e2e6fb717b9d40809ed9308fce973081ad6bf44800185b7a8569ff550953c372
|
|
BLAKE2b-256 checksum How to use checksums |
1ecd1432088692f0e23c031d53f4aa19dbcd1213a2f29b25fc00de681411cdb5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.13
|