
Ready for Docker and pull requests
vx prune cuts a workspace and its lockfile for a Docker build, projects take tags you can filter on, and remote cache writes can be scoped per pull request.
vx 0.0.326 to 0.0.360 migrate Nx executor targets as the commands they run, accept the --filter and flag spellings Turbo, pnpm and Nx users already type, and cut a scoped run on 1,000 projects from 181 ms to 113 ms.

vx 0.0.326 to 0.0.360 all shipped on 2 October 2026. The theme is moving in: migrations write configs that run without Nx or Turbo installed, the CLI takes the selections you already know, and long-running dev servers behave. Windows is now supported through WSL only.
In this release
bunx @vzn/vx-migrate used to write every Nx executor target as an
nx-exec line, so the migrated config still needed Nx to run. It now
writes the command the executor drives, with the defaults Nx applies:
jest, vitest, vite build, eslint, tsc, playwright, esbuild, swc, Next.js,
Cypress, Storybook, and the Vite dev and preview servers. @nx/js:node
becomes node on the build output, as a persistent task. Webpack and
Rollup targets name Nx’s convert-to-inferred generator in their TODO,
and nx-release-publish gets one note instead of a failing task per
package. nx() still runs executors through nx-exec.
bunx @vzn/vx-migratevx run build --allA task env that several packages share is now one export in
vx-preset.ts instead of a copy in every config: vercel/ai’s output
is 2× smaller, with every key unchanged. The .env probes are named exports
too (dotenvFiles). Framework variables Turbo infers, such as Next’s
NEXT_PUBLIC_*, are written out from the names your source and its
workspace dependencies spell, so a migrated Next build no longer inlines
them empty. The report also names the @vzn/vx-lockfile plugin your
lockfile needs, and says when turbo() is redundant once the configs
are written.
npx @vzn/vx-migratePRs #2207, #2217, #2218, #2225, #2319. Guide: Turborepo.
--filter now reads Turbo’s <name>...[ref] and ...x... forms as Turbo
does, matches a name without its scope as pnpm does (cart finds
@shop/cart), and lets a trailing ** in a path match its base
directory. vx run takes Nx’s camelCase flags (--skipNxCache,
--nxBail) and Nx short project names in cart:build. Every flag in
Turbo 2.11’s run help now either works or is refused with the vx way to
do it.
$ vx run build --heapvx run: --heap (turbo): use `--profile[=<path>]` for vx's own trace (see `vx run --help`)PRs #2015, #2016, #2017, #2018, #2041, #2055.
With no origin/HEAD (no remote, or the fetch actions/checkout does),
a bare --affected compared with HEAD~1 and saw only a branch’s last
commit. It now compares with the first trunk branch that is not HEAD, as
Turbo and Nx do. On a one-commit shallow clone, vx says the history is
missing instead of only that the ref did not resolve. Under turbo() on
GitHub Actions, the base is the pull request’s base or the push’s
before, as Turbo picks it.
vx run test --affectedA server vx keeps after the summary now streams its output line by line
instead of showing nothing. One that crashes after the summary counts as
failed in --summarize and --report. When another task in the run
fails, vx stops the servers and exits 1 instead of holding them forever.
vx run app#dev over a dependsOn: ['^dev'] group now keeps the
servers it stands for.
vx run dev --allPRs #2030, #2039, #2054, #2096. Deep dive: Dev servers in the graph.
A run scoped to one package no longer walks git over its whole
dependency closure, only over the projects that own a task, and it finds
that closure by search instead of building it for the whole graph. On
1,000 projects, a warm vx run build --filter pkg-500 went from 181 ms
to 113 ms. A plain repository’s git facts are read off the disk instead
of from a git rev-parse spawn, and a cold load imports 128 configs at a
time.
A warm frozen run also keeps its lock check from one run to the next.
vx run build --filter pkg-500PRs #2035, #2241, #2306, #2323, #2329.
The invocation line vx stores and vx last prints kept a secret passed
after -- whole, while the task’s own output masked it. It is now masked
with the same rule before it is recorded. --tag values, stored on the
history row and sent to telemetry, are masked too.
vx run publish -- --token=$NPM_TOKENvx lastvx init now maps a script that runs a server as a persistent task, so
a dependent no longer waits on it forever. A build’s output directory is
guessed from its own command when no framework rule names one. The
next: line it prints is runnable, naming git init first when needed.
It names Yarn Plug’n’Play when that is why a config cannot load, and
vx.config.cjs and vx.config.cts are read as configs.
vx initPRs #2070, #2098, #2100, #2169, #2290, #2308.
A strace that warns it cannot check the seccomp filter order still works, but vx read the warning as a tracer failure and ran every sandboxed task twice. vx now uses such a strace only when it is quiet, and otherwise runs tasks untraced. A task with a port bridge also waits for its host listener before it starts, so a server’s port no longer refuses its first connection under load.
vx run test --allPRs #2121, #2130. Deep dive: The sandbox.
Git 2.45 can store refs as a reftable (--ref-format=reftable). vx read
HEAD from the ref files, which a reftable repository does not keep, and
vx-migrate missed branch moves. Both now handle it; keys, cache hits and
--affected match a normal repository.
git init --ref-format=reftablePR #2318.
SYSTEMROOT, APPDATA and the other Windows env vars
(#2227).See Upgrading.
npm install -D @vzn/vx@latestA standalone binary updates itself with vx upgrade.