Each case is a small workspace and the outcome a user would see. All six
tools run the same 984 cases, each in a sandbox.
vx 747b26f · Turborepo 2.11.10 · Nx 24.0.2 · Vite Task 1.4.0 · moon 2.6.5 · Nix 2.34.6 · 2026-11-07 · every case
The cases come from every tool's own tests
The cases are compiled from the test suites of Nx, Turborepo, Vite
Task, moon, Nix and vx. A case names no tool's config. It says which
projects exist, what each task runs, and what must hold afterwards.
A thin adapter turns the case into each tool's own config. The harness
marks each command as it starts and ends, so "ran" means it ran.
Where the scores split
| Group | Cases | vx | Nx | Turborepo | moon | Vite Task | Nix |
|---|---|---|---|---|---|---|---|
| graph | 149 | 149 | 113 | 91 | 84 | 86 | 57 |
| inputs | 302 | 302 | 186 | 187 | 192 | 177 | 175 |
| outputs | 223 | 223 | 156 | 160 | 122 | 139 | 158 |
| affected | 97 | 97 | 57 | 68 | 69 | 0 | 0 |
| watch | 31 | 31 | 27 | 28 | 0 | 0 | 0 |
| sandbox | 18 | 18 | 0 | 1 | 0 | 1 | 15 |
A case a tool cannot express counts as not passed. Its users cannot get
that behaviour either.
Each case says why it matters
Args forwarded to a server reach it as typed, never expanded by a shell vx pass moon pass Nx fail seen.txt is "<0><0>…", expected "<$(id -u)><`id -u`>…" Every case carries three or four sentences on what goes wrong without
it. Here a second shell ran $(id -u), a command nobody typed.
vx misses 2 cases. Both need programs a dependency puts on PATH, which
vx left to the tools you already have.
All cases, filters and each tool's detail: Conformance.
More at vznjs.github.io/vx.
Originally published on the vx blog. vx is open-source (MIT) task orchestration with a build cache: vznjs.github.io/vx · GitHub.
Written with AI assistance.
