Skip to content
vznjsPublic

About

Resources

Contributing

Security policy

Stars

4 stars

Watchers

0 watching

Forks

Repository files navigation

vx logo

vx

The fastest task runner for JS monorepos.
Measured against Turborepo and Nx, each in its own native config.

npm CI MIT license Documentation

1,090 packages, 3,270 tasks vx Turborepo Nx Vite Task
Cold build: time the runner adds 2 s 1 min 21 s (vx 34× faster) 11 s (vx 4.7× faster) 1 min 11 s (vx 30× faster)
Cold build: CPU burned 17 s 21 s (vx 1.2× faster) 52 s (vx 3× faster) 12 s (vx 1.4× slower)
Fully cached run (restored) 650 ms 997 ms (vx 1.5× faster) 6.25 s (vx 9.6× faster) 2.64 s (vx 4× faster)
Fully cached run (up-to-date) 393 ms 463 ms (vx 1.1× faster) 6.45 s (vx 16× faster) 2.49 s (vx 6.3× faster)

vx N× faster: that tool takes N times as long as vx (theirs ÷ vx); N× slower: vx takes N times as long (vx ÷ theirs).

Time added is the wall time over the tasks' own ideal schedule (3 min 38 s). Same graph, commands and concurrency: how it is measured.

What vx is

A task runner and build cache for JavaScript monorepos. 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.

Install

npm install -D @vzn/vx     # or: pnpm add -D -w · yarn add -D (-W on Yarn 1) · bun add -d

A prebuilt binary for Linux (glibc, not Alpine's musl) and macOS, x64 and arm64; no Bun needed. The release binary needs no Node either. Windows: use WSL.

Quick start

In a git repo with a package.json workspace:

npx vx init               # a vx.config.ts per package, from its scripts

Give a task a cache block, 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
      cache: {
        inputs: { files: ['src/**', 'tsconfig.json'] },
        outputs: { files: ['dist/**'] },
      },
    },
  },
})
npx vx run build --all    # builds, in dependency order; stores the results
npx vx run build --all    # nothing changed: up-to-date, in milliseconds
rm -rf packages/*/dist
npx vx run build --all    # restored from the cache, not rebuilt

vx run ci --all on examples/basic: cold, three tasks run; again, three up-to-date.

Starter: examples/basic, run by CI on every commit. More: Quickstart · Configure · CLI · every config field · playground (the planner, in your browser).

Coming from Turbo or Nx

bunx @vzn/vx-migrate writes a vx.config.ts per package from turbo.json or the Nx graph; you keep those and delete the old config. Beside turbo.json or nx.json, vx init writes only a vx.workspace.ts that maps the old config until then: a temporary start, not a way to run the repo. The numbers above are native vx config. @vzn/vx-migrate's first npm publish is pending. Migration guide.

Why it is faster

  • 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.json and the lockfile are still read.
  • One pass: one git walk per run; each stat and lookup happens once.

More than speed

  • 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 (14 hooks, commands included): remote cache, remote execution, telemetry, CLI verbs. Core ships none and needs none.
  • Free: MIT. No paywall, no cloud, no account.

How it compares

vx Turborepo Nx
Config TypeScript, evaluated into the cache key JSON (static) JSON (static)
Output ownership Strict: wiped before exec and restore Additive (stale files survive) Additive
Clean-tree hashing No source reads (git index OIDs) git OIDs re-hash / daemon
Daemon None None for turbo run On by default
Per-task sandbox Yes: kernel-level, opt-in No No
Plugin API Yes: every pipeline stage No Yes (TS-tied)
Install Single binary; no Bun, Node optional npm + Node npm + Node

Every gap, and when another tool is the better pick: comparison · vx, Turborepo, Nx, Bazel.

Plugins

Declared in vx.workspace.ts; without any, vx runs and caches locally.

Package What it adds
@vzn/vx-migrate Migrate from Turbo or Nx: write native configs, keep its remote cache
@vzn/vx-reapi Remote cache and remote execution over Bazel's REAPI (NativeLink, BuildBuddy)
@vzn/vx-lockfile Key each project on its own lockfile slice: pnpm, bun, npm, yarn
@vzn/vx-otel OpenTelemetry traces, metrics and logs, no SDK
@vzn/vx-ci GitHub Actions job summary and Checks API
@vzn/vx-mcp vx mcp: a read-only MCP server for AI coding agents
@vzn/vx-schedule-history Schedule by the critical path learned from past runs

Write your own: plugin guide · architecture.

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.

Contributing

git clone https://github.com/vznjs/vx && cd vx
bun install
bun packages/vx/src/bin.ts run ci --all     # lint, test, docs build: every package

Needs Bun ≥ 1.4. Every dev task is a vx task; no package.json scripts. Start with CONTRIBUTING.md and STATUS.md.

License

MIT

About

Resources

Contributing

Security policy

Stars

4 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages