rhiza-task¶
The rhiza developer tasks, as a pinned CLI β not a synced make layer.
Quick links: π¦ PyPI β’ π Repository β’ π Issues β’ π± rhiza β’ π§ͺ pytest-rhiza
π Overview¶
There is nothing to install and nothing to sync. One command runs a project's gates, and
which gates those are is decided by the manifest in the repository β pyproject.toml,
Cargo.toml or go.mod.
rhiza-task is the sibling of pytest-rhiza,
which did the same thing for .rhiza/tests.
π― The problem it deletes¶
The pain was never make's syntax β it was distribution by copying, which make
structurally cannot fix, because include cannot reach a remote file. Every consumer got a
full copy of the task layer at a template tag, and everything downstream was damage
control.
Version pinning becomes a dependency pin, which is a real mechanism instead of "copy files at tag v1.3.3 and hope nobody edited them."
| before, per consumer repo | after |
|---|---|
.rhiza/rhiza.mk β 200 lines, synced |
gone |
.rhiza/make.d/*.mk β 1023 lines in 15 files, synced |
gone |
exclude: entries in template.yml, because a deletion alone is undone by the next sync |
not needed |
targets shadowed in the repo Makefile |
[tool.rhiza-task] |
| ~40 lines of GNU-make guard and Windows POSIX-shell probe | gone β no make, no shell |
install-uv β 30 lines of bootstrap.mk shell |
gone β uvx provisions the runtime |
Makefile |
repo-owned, if a repo wants one |
π Three commands¶
-
See what is available
Tasks, grouped by section, with prerequisites and a one-line description.
-
Run every gate
The aggregate CI runs: format, deps, test, docs, security, licence, types.
-
Read a resolved setting
Six configuration layers, collapsed to the one value a task will actually see.
π§© One set of names, three languages¶
test is pytest in a Python project, cargo nextest in a crate and go test in a
module. That gate-parity contract is what lets a reusable workflow call typecheck
without knowing the language.
flowchart LR
M{which manifest?}
M -- "pyproject.toml" --> P[python layer]
M -- "Cargo.toml" --> R[rust layer]
M -- "go.mod" --> G[go layer]
P --> T["test Β· typecheck Β· coverage<br/>security Β· deps Β· license"]
R --> T
G --> T
The make layer answered "which one?" at sync time, by copying exactly one of
python.mk, rust.mk and go.mk into a repository. A pinned CLI carries all three, so
the answer is the manifest that is present β and the layers you do not have stay
addressable as rhiza-task rust:test.
π Why it is small¶
Reading all ten make fragments back to back, every recipe has the same three parts: a
guard on a folder existing, a provision via uv run --with or uvx, and a long, mostly
static argument list. So the model is declarative, with an escape hatch for the three
recipes that genuinely are not.
β The design Β· β Adding your own task
π Where to go next¶
| If you want to⦠| Read |
|---|---|
| run this against your project for the first time | Getting Started |
| know what every task does, and when it skips | Tasks |
| change a threshold, a folder or a typechecker | Configuration |
understand polyglot repositories and rust:test |
Language Layers |
| add a project-specific gate | Adding a Task |
| retire a synced make layer | Migrating from make |
| know why it is not a Taskfile | FAQ |