Task orchestration with a cache you can trust, on a core you can extend. Each task is one shell command with declared inputs and outputs; vx runs them in dependency order and replays results from a content-addressed cache.
Quick start
In a git repo:
bunx @vzn/vx init # installs vx, writes an empty root vx.config.ts and the lockfile plugin
A prebuilt binary for Linux (glibc, not Alpine's musl) and macOS, x64 and arm64. Windows: run vx inside WSL2.
A task runs its tool directly, never through a package script. Cache one by saying what it reads and writes:
// packages/app/vx.config.ts
import { defineProject } from '@vzn/vx/config'
export default defineProject({
tasks: {
build: {
exec: { command: 'tsc -b' },
dependsOn: ['^build'], // dependencies build first
inputs: { files: ['src/**', 'tsconfig.json'] },
cache: {
outputs: { files: ['dist/**'] },
},
},
},
})
vx run build --all # builds, in dependency order; stores the results
vx run build --all # nothing changed: up-to-date, in milliseconds
rm -rf packages/*/dist
vx run build --all # restored from the cache, not rebuilt
When to run vx lock
init also writes .vx/projects.lock.json, every project's config as it evaluated.
Commit it. Every run reads its configs from the lock, so run
vx lock and commit the lock again after you:
- edit any
vx.config.tsor.vx/workspace.ts, - update dependencies or plugins,
- change a file a config imports.
Otherwise runs keep the old configs. On CI, vx lock --check fails a
stale lock before any task runs.
Starters: examples/basic, and
examples/ci with a GitHub Actions workflow; CI runs both
on every commit. The CI guide
explains the workflow.
More: Quickstart ·
Configure ·
CLI · every config field.
A foundation you own
- A cache you can trust: TypeScript configs are evaluated before hashing, so imports and computed values are in the key. Outputs are wiped before every run and restore: no stale file survives.
- Sandboxed tasks: opt in per task; a workspace file the task did not declare is out of its reach, so it cannot poison the cache.
- Clean exits: Ctrl-C reaps each task's process group.
- Plugins at every stage (15 hooks,
commandsincluded): remote cache, remote execution, telemetry, CLI verbs. Core ships none and needs none. - Free: MIT. No paywall, no cloud, no account.
Plugins
What vx can do, not what it is limited to. Declared in .vx/workspace.ts; without any, vx runs and caches locally.
Hosting the three servers: servers docs.
Write your own: plugin guide · architecture.
Coming from Turbo or Nx
Beside turbo.json or nx.json, bunx @vzn/vx init runs @vzn/vx-migrate:
it writes a vx.config.ts per package from turbo.json or the Nx graph,
and you keep those and delete the old config. vx init --keep writes only
a .vx/workspace.ts that maps the old config instead, and its lock: a temporary start,
not a way to run the repo. The benchmark below uses native vx config.
Migration guide.
How it compares
Every gap, and when another tool is the better pick: comparison · vx, Turborepo, Nx, Bazel.
Fast, without trading correctness
- Nothing boots per task: no daemon, no Node process; vx spawns your command.
- No source-file reads to hash: on a clean tree, keys come from git's index; each project's
package.jsonand the lockfile are still read. - One pass: one git walk per run; each stat and lookup happens once.
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-25 on linux x64, 4 cores: vx at commit 9abdfb52c, Turborepo 2.11.10, Nx 24.0.1, Vite Task (vite-plus) 1.4.0.
Same graph, commands and concurrency: how it is measured.
Status
Pre-alpha, dogfooded: this repo lints, tests and builds itself with vx. The schema may still change; 1.0's promise: versioning-1.0.md.
Issues
vx is maintained by VZN and takes issues, not pull requests: report a bug or ask for a feature in issues.
License
vx is MIT licensed. The prebuilt binaries embed Bun and a few npm packages under permissive licenses; their notices ship as THIRD_PARTY_NOTICES.txt in each platform package and GitHub release.