cli-to-py
Turn CLI binaries into Python APIs for applications and LLM agents.
cli-to-py reads a command's help output, builds a callable Python wrapper, and
lets you run subcommands with keyword arguments instead of hand-built shell
strings.
Full documentation: https://oneryalcin.github.io/cli-to-py/
Install
pip install cli-to-py
or:
uv add cli-to-py
Requires Python 3.11 or newer.
Quick Start
import asyncio
from cli_to_py import convert
async def main():
git = await convert("git")
result = await git.status(short=True)
print(result.stdout)
branch = await git.branch(show_current=True).text()
changed = await git("diff", name_only=True, _=["HEAD~1"]).lines()
print(branch)
print(changed)
asyncio.run(main())
Flags use Python names and are converted to CLI flags:
await git.commit(message="fix", all=True)
# runs: git commit --message fix --all
Use _ for positional arguments:
await git("diff", name_only=True, _=["HEAD~1"])
# runs: git diff --name-only HEAD~1
Use _global for options that must come before the subcommand
(git -C, docker --context, kubectl --namespace):
await git("log", _global={"C": "/path/to/repo"}, max_count=15)
# runs: git -C /path/to/repo log --max-count 15
Nested command trees dispatch fluently, or as a space-separated string:
uv = await convert("uv")
await uv.pip.install(upgrade=True, _=["httpx"])
# runs: uv pip install --upgrade httpx
await uv("pip install", upgrade=True, _=["httpx"]) # equivalent
Why It Exists
Traditional tool calling makes agents call tools one step at a time. That is awkward when a task needs loops, branching, arithmetic, retries, filtering, or many repeated CLI calls.
cli-to-py gives those CLIs a function-shaped Python interface. An agent can
write code that coordinates commands directly:
git = await convert("git")
changed = await git("diff", name_only=True, _=["HEAD~1"]).lines()
for path in changed:
if path.endswith(".py"):
print(await git("log", oneline=True, n=1, _=["--", path]).text())
That pairs naturally with code-mode interpreters such as Monty, where host applications expose a controlled set of functions and the agent writes Python to orchestrate them.
Why Use It
- Convert CLIs into async Python APIs with no runtime dependencies.
- Expose command-line tools as functions for agent code-mode workflows.
- Validate flags and arguments before spawning a subprocess.
- Keep subprocess output ergonomic with
.text(),.lines(), and.json(). - Stream output, inherit stdio, set timeouts, pass env/cwd, and cancel work.
- Generate standalone wrapper modules for tools you want to check into a project.
Documentation
- Installation
- Quick start
- Agent code mode
- Validation
- Runtime control
- Code generation
- Parser limits
- Public API
CLI Wrapper Generation
Generate a dependency-free Python wrapper from a CLI:
cli-to-py git -o git_wrapper.py
The generated .py module and .pyi stub can be committed to another project
without depending on cli-to-py at runtime.
Development
make test # unit and integration tests
make ci # full CI path, including package build
make docs # strict MkDocs build
make build # source distribution and wheel
See the release checklist for publishing steps.
Status
This project parses common --help formats pragmatically. It is useful for many
CLIs, but it is not a formal parser for every help style. See
parser limits
before relying on generated wrappers for unusual CLIs.
Release files for cli-to-py 0.2.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 | |
|---|---|---|---|
| cli_to_py-0.2.0.tar.gz | 66.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| cli_to_py-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 108.5 kB
Release files / cli_to_py-0.2.0.tar.gz
| Download URL | cli_to_py-0.2.0.tar.gz |
|---|---|
| Size | 66.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
0d97734f4c896df552bc57bac0c76a64356749f1fa9adebb7607ec3d7616572a
|
|
BLAKE2b-256 checksum How to use checksums |
312f9cf832df2c80f900e0465b7ca7dd05169ce8ebe44c62509102feda663ff7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.21 {"installer":{"name":"uv","version":"0.11.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / cli_to_py-0.2.0-py3-none-any.whl
| Download URL | cli_to_py-0.2.0-py3-none-any.whl |
|---|---|
| Size | 41.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
cc055dd7bbc216c9621aecc1b715e50a53eea07579387e20a692ab05911749f9
|
|
BLAKE2b-256 checksum How to use checksums |
02ed9d0f65f4d9ab42bc988f96209d572338151f62bdaf7de85d250e522a3ec9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.21 {"installer":{"name":"uv","version":"0.11.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|