vx init maps a root package.json's repo-wide scripts, a bare --affected takes its base from affectedBase, and Turbo and Nx commands, flags and cache switches now land where you expect.
vx 0.0.243 to 0.0.325 all shipped on 2026-10-01. The theme is adoption:
moving from Turbo or Nx to vx has fewer surprises, from the
first vx init to the CI job that must not write the shared cache.
vx run lint used to find no project in many repos, because the root’s
lint, test and format scripts were never mapped. vx init now turns
a root script that checks the whole repo into a root task. A script that
runs the members (pnpm -r, --filter, --cwd, --prefix, vp run, a
runner, or vx itself) stays unmapped, and init names it. A run scoped
to a project that lacks a task others declare now says so and names
--all.
Terminal window
acme (the workspace root): its scripts that check the whole repo are its tasks; left out as running the members (`pnpm -r`, `--filter`, a runner): build
A bare --affected compared with origin/HEAD, so a git-flow repo diffed
against the wrong branch. affectedBase in vx.workspace.ts now names
the ref, and --affected=<base> still wins. nx() and turbo() set it
from Nx’s defaultBase and NX_BASE, and from Turbo’s TURBO_SCM_BASE.
Turbo spells a root task //#lint. vx read // as a project name and
refused it in vx run, vx show, vx why and in dependsOn. All four
now take it as the root project’s task, from any directory.
Turbo’s and Nx’s run flags and verbs used to stop at “unknown flag” or
“unknown command”. Now -F is --filter, three Nx options are aliases,
and the rest (--env-mode, --global-deps, nx graph,
nx show projects and more) say what does it in vx. A flag cut short (--dry)
or --json on a verb that takes --format json gets a hint too.
Terminal window
$ vx run build --env-mode=strict
vx run: --env-mode (turbo): vx passes only the variables a task declares (strict): list the rest in `exec.env.passThrough` (see `vx run --help`)
$ vx graph
`nx graph` is `vx run <task> --graph[=<file>.dot]` here: the task graph as Graphviz DOT
$ vx info --json
vx info: unknown flag: --json (did you mean --format json?) (see `vx info --help`)
A CI keeps an untrusted pull request from writing the shared cache with
Turbo’s TURBO_CACHE and TURBO_REMOTE_CACHE_READ_ONLY, or Nx’s
NX_SKIP_REMOTE_CACHE. vx ignored them, so such a job wrote what main
would restore. turboCache() and nxCache() now honour each one. A
switch can only narrow the run’s --cache policy, never widen it.
turboCache() declined on Vercel and in a turbo linked repo. It now
reads VERCEL_ARTIFACTS_TOKEN and _OWNER, and .turbo/config.json.
It honours Turbo’s timeouts, signs only where turbo.json turns signing
on, and sends teamId only in Vercel’s team_ form. vx init declares
it in a linked repo, and says when nx.json uses Nx Cloud, which vx
cannot share.
nx() now caps the local cache at maxCacheSize (or
NX_MAX_CACHE_SIZE), and lets NX_PARALLEL win over nx.json’s
parallel, as Nx 23 does. nxCache() keeps reads on when a read-only
token’s upload is refused. bunx @vzn/vx-migrate --from nx exports the
graph itself when none is on disk.
turbo() left a task uncached when its outputs glob might reach a
source file. It now proves more globs safe: **/dist/** with no tracked
dist directory, a pattern like dist-*/** that matches no tracked
top-level entry, and top-level artifacts like *.xml. vercel/ai’s 69
builds and tldraw’s 35 now cache. nx() shares the same rules.
Every vx an npm user runs starts in a small Node launcher. It is now
CommonJS, not ESM: vx --version went from 65.5 ms to 57.0 ms. On Node
22.15 and newer the launcher replaces itself with the binary instead of
spawning it: from 54.2 ms to 45.3 ms. The binary itself answers
--version before loading the dispatcher, from 20.1 ms to 16.4 ms.
bun.lock records a patch by path, so editing the patch leaves the
lockfile byte-identical while bun install applies the new one. Without
the bun() plugin, vx replayed the old outputs. Core now folds each
patch bun.lock names into the key, and --affected widens on its edit.
Terminal window
# after editing patches/left-pad@1.3.0.patch and running bun install
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.
turbo() now runs root tasks, single-package repos and with sidecars as Turbo does, nx() finds every project in an integrated repo, and the CLI starts 2× faster.
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.
Turborepo, Nx and other product names are trademarks of their owners. vx is not affiliated with or endorsed by them.