npx skills add vznjs/vx
One skill teaches any coding agent the CLI: run tasks, read failures and history, ask why.
vx runvx last --failedvx last --statsvx whyvx docs
vx runs and caches your task graph correctly, and every stage after that is a seam you can fill.
// ai first
npx skills add vznjs/vxOne skill teaches any coding agent the CLI: run tasks, read failures and history, ask why.
vx runvx last --failedvx last --statsvx whyvx docsvx whyA re-run names its cause, down to the file that changed.
$ vx why @demo/web#build
verdict cache key changed: upstream @demo/ui#build
root cause:
@demo/web#build ← @demo/ui#build ← file packages/ui/src/index.tsHow vx why works →--format jsonEvery report verb prints JSON with a published schema, and failures keep their full log.
vx showvx infovx lastvx why--dry=json// extensibility is king
Every plugin below is a separate package on core’s public seams, and yours can be too.
@vzn/vx-reapiAny Bazel REAPI server: NativeLink, BuildBuddy, your own.
@vzn/vx-migrateKeep Turbo’s or Nx’s remote cache while you move to native config.
@vzn/vx-otelEvery run and task in any OpenTelemetry backend.
@vzn/vx-ciGitHub job summary and Checks.
@vzn/vx-schedule-historyOrder by the critical path learned from your run history.
@vzn/vx-lockfileEach task keyed on its own dependency closure: pnpm, bun, npm, yarn.
definePlugin()Fill any of the 15 stages: where tasks run, where the cache lives, who watches, what the terminal draws, which commands exist.
// 9,603 tasks · 1,601 projects · 30 levels · identical commands, identical concurrency
Time each tool adds over the ideal run; lower is better.
Benchmark workload: a synthetic monorepo of 1,601 projects and 9,603 tasks in 30 dependency levels, five core libraries a quarter of the projects use; build 300 ms, test and typecheck 150 ms, lint 75 ms, publish 30 ms; real repos with uneven task times will differ.
Run 2026-10-12 on linux x64, 4 cores: vx at commit 126d60a93, Turborepo 2.11.7, Nx 23.3.0, Vite Task (vite-plus) 1.1.0.
// shipping every day
// vx vs Turborepo vs Nx
| vx | Turborepo | Nx | |
|---|---|---|---|
| A file sandbox for every task | Local and free, Linux and macOS | None | Nx Cloud add-on |
| Remote execution you host | Bazel’s open REAPI protocol | None | Nx Agents on Nx Cloud |
| A remote cache on any backend | REAPI, Turborepo’s or Nx’s wire, by plugin | Its own HTTP API | Nx Cloud or its own API |
| Config is code | TypeScript, evaluated and hashed | JSON | JSON, merged with inferred tasks |
| No background daemon | None | None for turbo run | On by default |
// four commands
npm install -D @vzn/vx
npx @vzn/vx init # a vx.config.ts per package; add the cache block each TODO shows
npx @vzn/vx run build --all # builds in dependency order; stores what is cached
npx @vzn/vx run build --all # again: the cached tasks are up-to-dateComing from Turbo or Nx: the same vx init writes the native vx config from it.
// one run, after you edit app
app builds after what it uses.ui and api build at once.app; only app runs.// what you can count on
A task’s cache key covers every file, setting and env var it declares.
Caching in depth →A sandboxed task cannot read a workspace file it did not declare.
Sandboxing →Plugins decide where tasks run, where the cache lives and who watches.
Writing a plugin →MIT, no paywall, no cloud, no account.
Migrate →// 116 features, a page each

An undeclared read or write fails the task and names the path.

Ask why a task re-ran, and get the input that changed.

A module you deleted never comes back from the cache.

--affected follows task edges from the change, and nothing else runs.

A server is ready when it prints a line, not after sleep 5.

Every change takes the same path as vx run, and the key decides what re-runs.

Distributed builds over Bazel’s open Remote Execution API.

An installable skill teaches an agent to run, debug and query vx.