Quickstart
Run your first cached task in five minutes.
You need a git repository on Linux or macOS (on Windows, use WSL). vx is
one prebuilt binary. The release binary alone needs neither Node nor Bun;
installed from npm, the vx command is a small Node script that runs
that binary.
Install
Section titled “Install”- Install it at the workspace root:
npm install -D @vzn/vx(in a pnpm workspace,pnpm add -D @vzn/vx: npm refusesworkspace:*). - Run
npx vx init. It writes avx.config.tsper package from its scripts, and avx.workspace.ts. No task gets acacheblock, so nothing is cached yet: add the one eachbuild’s TODO shows. - Or write one by hand, beside a package’s
package.json.
Config
Section titled “Config”import { defineProject } from '@vzn/vx'
export default defineProject({ tasks: { build: { dependsOn: ['^build'], // my dependencies' build first exec: { command: 'tsc -b' }, cache: { inputs: { files: ['src/**', 'tsconfig.json'] }, outputs: { files: ['dist/**'] }, }, }, test: { dependsOn: ['build'], // my own build first exec: { command: 'bun test' }, cache: { inputs: { files: ['src/**', 'tests/**'] }, outputs: { files: [] } }, }, },})vx run build --all # every package, in dependency ordervx run build # ⇢ success local — a hit; restores dist/ if deletedvx run test --affected # what changed, and its dependentsvx run build --all --dry # the plan; runs nothingvx run build --graph # the task graph as Graphviz DOTThe first run stores the result. The second finds nothing changed and
dist/ still as stored, so it restores nothing: the task’s frame closes
up-to-date (► success fresh in the --output-logs full row). Delete
dist/ and the next run restores it from the cache: restored-local, the
⇢ success local row.
An existing repo
Section titled “An existing repo”Start with one package and leave the rest of your tooling as it is.
- Give one package a
vx.config.tswith the command itsbuildscript runs. - Run
vx run buildtwice in it. The second run is a cache hit. - Edit a file the build reads.
vx run build --drynow predicts a miss. - Add configs to more packages.
^buildorders them by yourpackage.jsondependencies.
Want the whole repo under vx first? turbo() or nx() runs a Turborepo
or Nx repo as it is: Migrate.
Common problems
Section titled “Common problems”- Only one package ran.
vx run buildruns the package you are in. Add--all. - The editor cannot resolve
@vzn/vx. Add it as a devDependency. vx itself runs a config without it. vx requires git. Rungit initat the workspace root.- A package has no
vx.config.ts. It has no tasks, and^buildreaches through it to the nearest package that has one. - A package has nothing to build, but others depend on it. Give it
build: { dependsOn: [] }, so their^buildwaits on nothing.
Known limits
Section titled “Known limits”- Running from source needs Bun ≥ 1.4. The binary needs nothing.
- The Linux sandbox needs
bubblewrap,socatandripgrep, and no root in a container, or setsandbox.weakerWhenNested: true(Sandboxing). - No native Windows build: use WSL.
- On macOS the sandbox’s report can miss records under load. Enforcement holds.
- A cache hit replays the first and last 8 MiB of a task’s output.
- A
workspaceFilesglob stops at a git submodule’s edge. - A
kill -9of vx leaves its persistent tasks running, except a server that exits when its stdin closes (esbuild--watch).