Pronounced /ˈtuːlər/ (tool-er)
ToolR is a Python task runner that boots in milliseconds because the front-end is a Rust binary.
Python only runs when you invoke a command, inside a per-repo uv-managed venv.
| Tool runner | -h steady-state |
First run | Second run |
|---|---|---|---|
| toolr | 10.4 ms | 277.0 ms | 21.8 ms |
| doit | 83.4 ms | 143.0 ms | 88.9 ms |
| invoke | 84.6 ms | 101.7 ms | 77.4 ms |
| nox | 91.8 ms | 395.9 ms | 115.3 ms |
| duty | 166.4 ms | 188.5 ms | 252.4 ms |
| python-tools-scripts | 252.2 ms | 340.3 ms | 189.0 ms |
<tool> -h, 20 runs, steady-state = mean of last 18. Measured on Apple M3 Pro / macOS 26.5 / arm64.
Reproduce locally with python3 scripts/bench.py (stdlib-only; emits the table above to stdout).
- Sub-millisecond discovery. The CLI is a Rust binary.
--helpand Tab completion read a cached static manifest; Python never boots for non-execute paths. - No system-Python dependency. Toolr resolves a per-repo Python venv via
uvon first invocation. The host OS doesn't need Python at all to install toolr — it's a single static binary. - Write Python, not framework boilerplate. Drop a
tools/*.pyfile with acommand_groupand a@commanddecorator. Type hints become CLI arguments; Google-style docstrings become--helptext. - First-class third-party command packages. Plugins ship a static
toolr-manifest.jsoninside the wheel. Discovery is a glob + JSON parse; no Python import to find them. - Signed releases. Every release archive ships with a SLSA build-provenance attestation. The
install scripts verify it by default (requires the
ghCLI); pass--verify-attestation=skipto bypass, accepting the supply-chain risk.
| Package | What it is | Where it lives |
|---|---|---|
toolr |
The Rust CLI binary you run from the shell. | On $PATH, installed once. |
toolr-py |
The Python runtime your tools/*.py import. |
In your tools/pyproject.toml. |
Most projects want both: the CLI installed globally, toolr-py declared in the per-repo
tools/pyproject.toml so from toolr import Context, command_group works when your commands run.
Five first-class install paths.
mise use aqua:s0undt3ch/ToolR@latestPulls toolr from the aqua registry
via mise's built-in aqua backend — no plugin to register. For projects that already pin tool versions via
.mise.toml, toolr's version becomes part of your project's reproducible tool set.
See docs/installation/mise/.
pip install toolr # Rust CLI binaryThis installs the toolr binary into whatever venv pip is pointing at.
Do not pip install toolr-py into that same venv — toolr-py is the Python runtime your
tools/*.py files import, and it belongs in the per-repo tools venv that toolr project init
scaffolds for you (where it's declared in tools/pyproject.toml and materialised via uv sync).
See "Two wheels, two roles" above for the split.
curl -fsSL https://raw.githubusercontent.com/s0undt3ch/ToolR/main/installation/install.sh | shVerifies the SLSA attestation by default (requires the gh CLI; pass --verify-attestation=skip
to bypass). Pin a version with sh -s -- --version X.Y.Z.
Custom prefix: sh -s -- --prefix /opt/toolr/bin.
irm https://raw.githubusercontent.com/s0undt3ch/ToolR/main/installation/install.ps1 | iexDownload toolr-<version>-<target-triple>.tar.gz (or .zip for Windows) from
https://github.com/s0undt3ch/ToolR/releases, verify the .sha256 sibling and the SLSA
attestation, drop the binary on $PATH. Useful in locked-down environments that audit binaries
before allowing them on a machine.
After the binary is on $PATH:
toolr project init # writes tools/{pyproject.toml,.gitignore,example.py}
toolr example hello # run the generated example
toolr self completion install bash # or zsh / fishThe full install matrix (per-OS notes, attestation flags, prefix overrides) lives in docs/installation/.
# tools/example.py
"""Example commands."""
from toolr import Context, command_group
example = command_group("example", title="Example", description=__doc__)
@example.command
def hello(ctx: Context, name: str = "world") -> None:
"""Say hello to <name>.
Args:
name: who to greet.
"""
ctx.print(f"Hello, {name}!")$ toolr example hello --name Pedro
Hello, Pedro!toolr project init writes a richer four-command starter than this two-liner — open it and edit,
or delete it and start from scratch.
- Quickstart
- Writing commands
- Third-party packages
- Agent skills (for LLM coding assistants)
- Internals (manifest, freshness, cache)
- CLI reference
ToolR is pre-1.0. The on-disk manifest is versioned (schema_version in
tools/.toolr-manifest.json); the binary refuses to load a higher version than it understands. The
public Python surface is toolr.__all__; anything not listed there is implementation detail.
Backwards-incompatible changes will be explicit in the changelog (generated by git-cliff on
release).
See CONTRIBUTING.md.
