Skip to content
vxvx
GitHubBlueskydev.toRSS

Config support for Turbo and Nx

Every key turbo.json, nx.json and project.json accept, read from the upstream schemas (@turbo/types 2.11.10, nx 23.2.1), and what @vzn/vx-migrate’s turbo() or nx(), a temporary start before native config, does with it. A key a new upstream release adds fails vx’s tests until it has a row here.

  • supported: vx honours it with the same meaning.
  • mapped, with a note: vx honours it through a translation; the note says how it differs.
  • not supported: vx ignores or refuses it; the note says which.
  • not applicable: it configures something outside a task runner and its cache.
Key vx Note
$schema not applicable Editor schema hint only; the mapper never reads it.
agentGuidance not applicable Guidance for AI agents, not task or cache config; vx ignores it.
boundaries not applicable Turbo’s import-rule checker; vx has no module-boundary rules and ignores it.
cacheDir not supported Ignored without a warning; vx uses its own cache.dir in .vx/workspace.ts.
cacheMaxAge not supported Ignored without a warning, as is TURBO_CACHE_MAX_AGE; no vx run evicts, vx cache clean --older-than does.
cacheMaxSize not supported Ignored without a warning, as is TURBO_CACHE_MAX_SIZE; no vx run evicts, vx cache clean --max-size does.
concurrency mapped, with a note turbo() fills the workspace’s run.concurrency when .vx/workspace.ts sets none ("50%" of the cores too); TURBO_CONCURRENCY wins over it, as in Turbo.
daemon not applicable vx has no daemon by design.
dangerouslyDisablePackageManagerCheck not applicable Turbo’s package-manager check; vx has none.
envMode mapped, with a note Strict is vx’s behaviour; loose gets a note, since vx passes only declared variables, and so do the tasks a Turbo 1 pipeline config’s inferred mode ran loose (no pass-through list); under turbo() TURBO_ENV_MODE wins over it.
extends supported Package configs’ extends chains are followed as Turbo does; cycles and missing parents are refused.
futureFlags mapped, with a note The flags are not read; what they gate (global, structured inputs) is detected by shape.
global mapped, with a note inputs, env and passThroughEnv are read as the global* fields they replace; envMode: loose gets a note.
globalDependencies mapped, with a note Becomes inputs.workspaceFiles; $NAME entries become env inputs. Under turbo() every package’s microfrontends.json (or .jsonc, or the name VC_MICROFRONTENDS_CONFIG_FILE_NAME gives) joins them, as in Turbo, unless it is a child’s partOf, and so do the files of every package the root depends on, transitively, as in Turbo 2’s global hash (Turbo 1, a pipeline turbo.json, leaves them out, and so does the mapping). A path git ignores (config.local.json) is keyed by a inputs.workspaceRuntime probe of its name and bytes, as Turbo hashes it; a glob reaches only files git reports.
globalEnv mapped, with a note Added to every task’s inputs.env and passthrough; under turbo() a * name expands over the run’s environment, as Turbo does; otherwise a wildcard is dropped with a note. Turbo’s default keyed names (VERCEL_ANALYTICS_ID, VERCEL_TARGET_ENV, and VERCEL_DEPLOYMENT_ID on a Next package when VERCEL_SKEW_PROTECTION_ENABLED=1; written configs key it always) join it, and a ! entry takes them back. A $NAME entry is refused, as Turbo refuses it.
globalPassThroughEnv mapped, with a note Added to every task’s exec.env.passThrough, not hashed; under turbo() a * name expands over the run’s environment; otherwise a wildcard is dropped with a note. The literal names of Turbo’s builtin pass-through list (TZ, CI, the Vercel, Docker and IDE names) join it, under turbo() as in written configs, so both key alike; its wildcard families (GITHUB_*, DOCKER_*, …) are a note. A $NAME entry is refused, as Turbo refuses it.
noUpdateNotifier not applicable Turbo CLI update notice.
remoteCache mapped, with a note turboCache() reads apiUrl, teamId, teamSlug, enabled, signature, preflight, timeout and uploadTimeout, below env vars and options.
tags supported A package’s own tags (Turbo 2.11.6) become its vx project tags, so --filter tag:<label> selects its tasks as Turbo’s does; the root’s label the root project, and none is inherited.
tasks supported Each task (or Turbo 1 pipeline) becomes a vx task for the packages that declare the script, and a key-only one where a ^ edge reaches a package without it (dependsOn, below); a task no package has a script for is a group task in each package that defines it, as Turbo runs a no-op node there and exits 0. A script that names $npm_package_name, $npm_package_version or $npm_lifecycle_event gets it defined, as the package manager Turbo runs it through sets it. A task’s key holds its own mapped definition, not all of turbo.json: an edit to another task’s definition keeps its hits, where Turbo’s global hash misses every task.
ui not applicable Terminal UI choice.
tasks.*.cache supported cache: false stays cache: false: the task always runs.
tasks.*.dependsOn mapped, with a note Same syntax; edges to tasks nobody runs are dropped; $TURBO_ROOT$ deps get a TODO; $NAME becomes env. A package without the script of a ^ task others run keys it as Turbo’s no-op node does: a cached true task with no outputs, its own edges kept. A task name no package has a script for (ci: { dependsOn: ["lint", "build"] }) is a group wherever it has an edge, so vx run ci runs them as turbo run ci does. Written sorted, as Turbo sorts it before hashing, so a reorder keeps the hit.
tasks.*.description supported Copied to the task’s description.
tasks.*.env mapped, with a note Goes to inputs.env and exec.env.passThrough; under turbo() a * name expands over the run’s environment, as Turbo does; the CLI lists the names the package’s files spell, and a wildcard nothing spells gets a TODO. A $NAME entry is refused, as Turbo refuses it.
tasks.*.inputs mapped, with a note Globs translated; $TURBO_DEFAULT$ becomes **/*, $TURBO_ROOT$ workspace files; the package’s own package.json joins an explicit list, as Turbo keys it, unless a glob names it, and a negation that matches it (!**/*.json) is dropped, as Turbo keys it whatever the negations; unsafe globs get a TODO; a path git ignores is keyed by a inputs.workspaceRuntime probe, as for globalDependencies; a glob that reaches a workspace package nested in the task’s package is also listed in inputs.workspaceFiles, since Turbo hashes the nested package’s files with its parent’s.
tasks.*.interactive mapped, with a note true becomes exec.interactive: true, uncached (Turbo requires cache: false of it): the task holds the terminal when vx’s stdin is one.
tasks.*.interruptible not applicable Maps to nothing, silently: vx watch stops and re-spawns every persistent task each cycle.
tasks.*.outputLogs mapped, with a note new-only is vx’s default; other values get a TODO pointing at --output-logs. Turbo 1’s outputMode is read as it.
tasks.*.outputs mapped, with a note Become cache.outputs, negations kept, sorted with the negations last, as Turbo sorts them before hashing, so a reorder keeps the hit; vx cleans outputs, so a wildcard first segment (*/**) stays cached with a note that the clean deletes the untracked files it reaches (without git, the task runs uncached with a TODO); core never cleans a file git tracks, committed or only git added; the project’s own package.json or vx.config is taken back with ! (a build that writes package.json also gets inputStability: { strategy: 'mutable' }).
tasks.*.passThroughEnv mapped, with a note Goes to exec.env.passThrough, not hashed; under turbo() a * name expands over the run’s environment; the CLI lists the names the package’s files spell, and a wildcard nothing spells gets a TODO. A $NAME entry is refused, as Turbo refuses it.
tasks.*.persistent mapped, with a note An uncached exec.persistent task, with a readyWhen TODO when something depends on it.
tasks.*.with mapped, with a note An edge to each persistent sidecar, which vx starts beside the task (ready on spawn); a sidecar that ends is a todo, and a pair naming each other keeps one edge. A task with no script is a group that starts its persistent sidecars.
tasks.*.inputs[].from not supported Ignored; vx folds each dependency’s cache key instead of its outputs.
tasks.*.inputs[].globs mapped, with a note For startup and jit entries, keyed like plain input strings.
tasks.*.inputs[].mode mapped, with a note startup and jit are keyed alike (no separate pass); dependencyOutputs adds nothing.
tasks.*.inputs[].withDefaults mapped, with a note true adds $TURBO_DEFAULT$: every package file.
remoteCache.apiUrl supported The cache URL when neither the option nor TURBO_API is set, as in Turbo.
remoteCache.enabled mapped, with a note false turns turboCache() off unless its options name a cache.
remoteCache.loginUrl not applicable Used only by turbo login; vx has no login.
remoteCache.preflight supported true sends Turbo’s OPTIONS preflight and follows its Location (http(s) only; never plain http with the token from an https URL), below TURBO_PREFLIGHT (1 or 0) and turboCache({ preflight }).
remoteCache.signature supported true signs and verifies with TURBO_REMOTE_CACHE_SIGNATURE_KEY, as in Turbo; with signing off the env key is not read. turboCache({ signatureKey }) signs either way. Signing with no key is no remote (a warning), as in Turbo; no team id signs as ''.
remoteCache.teamId supported Used when neither the option nor TURBO_TEAMID is set.
remoteCache.teamSlug supported Used when neither the option nor TURBO_TEAM is set.
remoteCache.timeout supported Whole seconds, below TURBO_REMOTE_CACHE_TIMEOUT and turboCache({ timeoutMs }); 0 is no deadline, as in Turbo.
remoteCache.uploadTimeout supported Whole seconds, below TURBO_REMOTE_CACHE_UPLOAD_TIMEOUT and turboCache({ uploadTimeoutMs }); 0 is no deadline.
futureFlags.affectedUsingTaskInputs not supported Ignored; --affected selects projects from vx’s own git diff.
futureFlags.errorsOnlyShowHash not supported Ignored.
futureFlags.experimentalCargoWorkspaces not supported Ignored; vx discovers projects from package.json workspaces only.
futureFlags.experimentalGoWorkspaces not supported Ignored; vx discovers projects from package.json workspaces only.
futureFlags.experimentalObservability not applicable Turbo telemetry export; vx’s is a telemetry plugin.
futureFlags.experimentalPythonWorkspaces not supported Ignored; vx discovers projects from package.json workspaces only.
futureFlags.filterUsingTasks not supported Ignored; --filter keeps vx’s semantics.
futureFlags.githubActionsRemoteBaseRefFallback supported turbo() follows it on GitHub Actions: a pull request’s base ref the checkout lacks is compared as origin/<ref>, as in Turbo.
futureFlags.globalConfiguration supported The global block is read whenever present, flag or not.
futureFlags.longerSignatureKey supported turboCache() refuses a TURBO_REMOTE_CACHE_SIGNATURE_KEY under 32 bytes, as Turbo does; without it a short key warns and signs. The signatureKey option needs 32 bytes either way.
futureFlags.pruneIncludesGlobalFiles not applicable Affects only turbo prune; vx has none.
futureFlags.strictTaskEntrypointSelection not supported Ignored.
futureFlags.watchUsingTaskInputs not supported Ignored; vx watch re-runs on any change in a watched project but a declared output, and the cache keys decide what executes.
boundaries.dependencies not applicable A Turbo boundaries import rule.
boundaries.dependents not applicable A Turbo boundaries import rule.
boundaries.implicitDependencies not applicable A Turbo boundaries import rule.
boundaries.tags not applicable A Turbo boundaries tag rule.
setup not applicable turbo setup’s toolchain provisioning policy; vx provisions no toolchain and ignores it.
tasks.*.tags not supported Ignored: vx tags are a project’s, so a tag: filter selects by a package’s own tags, never a task’s.
futureFlags.experimentalSetup not applicable Gates turbo setup, which vx has no counterpart for.
Key vx Note
implicitDependencies not supported The top-level map is not read.
affected mapped, with a note Its defaultBase (before Nx 20) is baseBranch when the top-level key is absent; nothing else in it is read.
extends supported The chain is followed and merged as Nx does, before named inputs are read.
defaultBase mapped, with a note nx() sets baseBranch, the branch a bare --affected compares with; NX_BASE wins over it as the base commit, as in Nx.
tasksRunnerOptions mapped, with a note Only default.options.cacheableOperations is read, as the legacy cached-targets list.
namedInputs mapped, with a note Expanded per project (project entries win) into each task’s inputs; vx has no named inputs.
targetDefaults mapped, with a note Applied by Nx while it builds the graph vx reads; vx sees the merged targets.
workspaceLayout not applicable Where generators create projects; vx has no generators.
cli not applicable Nx CLI and generator defaults.
generators not applicable Generator defaults; vx has no generators.
plugins mapped, with a note Targets Nx plugins infer arrive in the graph; bunx @vzn/vx-migrate freezes them as written.
tui not applicable Nx terminal UI.
defaultProject not supported Ignored; name tasks as pkg#task or select with --filter.
nxCloudAccessToken not applicable Nx Cloud credential; nxCache() talks to self-hosted /v1/cache servers.
nxCloudUrl not applicable Nx Cloud endpoint; nxCache() talks to self-hosted /v1/cache servers.
nxCloudEncryptionKey not applicable Nx Cloud artifact encryption.
neverConnectToCloud not applicable Nx Cloud opt-out; vx never connects to Nx Cloud.
parallel mapped, with a note nx() fills the workspace’s run.concurrency when .vx/workspace.ts sets none; NX_PARALLEL wins over it, as in Nx.
cacheDirectory not supported Ignored; vx uses its own cache.dir.
useDaemonProcess not applicable vx has no daemon; Nx’s setting still applies when vx asks Nx for the graph.
useInferencePlugins mapped, with a note Applied by Nx when it builds the graph; vx sees the targets that result.
analytics not applicable Nx usage analytics.
release not applicable Nx versioning and publishing; nx-release-publish targets still run through nx-exec.
sync not supported Global sync generators never run; under nx() vx lock warns to run nx sync, and a migration notes keeping their output by hand.
migrate not applicable Settings for nx migrate.
conformance not applicable Nx Powerpack conformance rules.
owners not applicable Nx Powerpack CODEOWNERS generation.
targetDefaults.*.filter mapped, with a note Applied by Nx while it builds the graph vx reads.
targetDefaults.*.executor mapped, with a note Merged into targets by Nx, then mapped as targets.*.executor.
targetDefaults.*.command mapped, with a note Merged into targets by Nx, then run as targets.*.command.
targetDefaults.*.metadata mapped, with a note Merged into targets by Nx, then read as targets.*.metadata.
targetDefaults.*.options mapped, with a note Merged into targets by Nx, then passed on as targets.*.options.
targetDefaults.*.outputs mapped, with a note Merged into targets by Nx, then mapped as targets.*.outputs.
targetDefaults.*.defaultConfiguration mapped, with a note Merged into targets by Nx, then read as targets.*.defaultConfiguration.
targetDefaults.*.configurations mapped, with a note Merged into targets by Nx, then one task per configuration.
targetDefaults.*.continuous mapped, with a note Merged into targets by Nx, then a persistent, uncached task.
targetDefaults.*.parallelism not supported parallelism: false gets a TODO to run with --concurrency 1.
targetDefaults.*.inputs mapped, with a note Merged into targets by Nx, then expanded as targets.*.inputs.
targetDefaults.*.dependsOn mapped, with a note Merged into targets by Nx, then mapped as targets.*.dependsOn.
targetDefaults.*.cache mapped, with a note Merged into targets by Nx, then read as targets.*.cache.
targetDefaults.*.syncGenerators not supported One workspace note per generator list, counting its tasks, says to run nx sync (a migration: keep their output by hand); vx never runs sync generators.
Key vx Note
name mapped, with a note Used in nx-exec lines and project:target edges; the vx project takes the package.json name.
root supported Graph nodes are matched to workspace packages by root directory.
sourceRoot mapped, with a note Not read by the mapper; executors still see it through nx-exec.
projectType not applicable App-or-library metadata for generators and tooling.
generators not applicable Per-project generator defaults; vx has no generators.
namedInputs mapped, with a note Merged over nx.json’s and expanded into each task’s cache inputs.
targets mapped, with a note Each target becomes a vx task, plus one per non-default configuration.
tags supported Become the project’s vx tags (a vx.config’s own win), so --filter tag:<name> or --projects tag:<name> selects as nx run-many -p tag:<name> does; tag: patterns in dependsOn resolve against them, and @nx/enforce-module-boundaries depConstraints become run.rules.dependencies, which vx lock checks (vx-migrate README § Module boundaries).
implicitDependencies mapped, with a note Graph edges without a package.json link become explicit pkg#target edges for ^target.
metadata mapped, with a note Only targetGroups is read, to find non-atomized targets’ .env files.
release not applicable Nx release settings.
targets.*.executor mapped, with a note run-commands and run-script become shell lines, noop a group task; every other executor runs through nx-exec, under nx() and in the migrator’s written config alike (the migrator translates no executor).
targets.*.options mapped, with a note Rendered into run-commands, or passed as nx-exec’s --options; {args.*} forwarding gets a TODO.
targets.*.outputs mapped, with a note Tokens and {options.x} resolved, Nx 24’s {options.x ?? fallback} included; paths outside the project become workspace files, and one outside the workspace is dropped with a TODO; negations kept; vx cleans outputs before a run but never a file git tracks, committed or only git added; the project’s own package.json or vx.config is taken back with !; a wildcard first segment stays cached under git and leaves the task uncached with a TODO without it.
targets.*.defaultConfiguration supported The base task carries the default configuration’s options, as nx run does.
targets.*.configurations mapped, with a note One task per configuration (build:ci); own, named and ^ edges take the configuration where declared, else the default (a ^ edge becomes one edge per dependency Nx links).
targets.*.inputs mapped, with a note Expanded into inputs; none means default and ^default; forms without an equivalent get TODOs.
targets.*.dependsOn mapped, with a note project:target becomes pkg#target; project patterns and tags resolved; a target glob (test:e2e--*) expands over the workspace’s target names, as Nx 19.5+ does, a same-project one over its own; params: forward gets a TODO.
targets.*.command mapped, with a note Run as the run-commands shorthand: one POSIX sh line.
targets.*.cache supported cache: true (or cacheableOperations) stays cache: true; persistent tasks stay uncached.
targets.*.continuous supported An uncached exec.persistent task, ready on spawn: Nx starts its dependents once it has started, and so does vx. A run-commands readyWhen becomes exec.persistent.readyWhen.
targets.*.parallelism not supported parallelism: false gets a TODO to run with --concurrency 1; vx has no per-task exclusivity.
targets.*.metadata mapped, with a note Only nonAtomizedTarget is read, to find .env files.
targets.*.syncGenerators not supported One workspace note per generator list, counting its tasks, says to run nx sync (a migration: keep their output by hand); vx never runs sync generators.
Key vx Note
a string mapped, with a note Named inputs expanded, token paths made project or workspace globs, ^name folded over dependencies.
{fileset, dependencies} mapped, with a note The fileset becomes a glob; with dependencies: true it is folded through the dependencies.
{projects, dependencies, input} mapped, with a note Folded through the named projects’ inputs (a superset); unknown project names get a TODO.
{runtime} supported Becomes inputs.workspaceRuntime, run at the workspace root as Nx does.
{env} supported Goes to inputs.env and exec.env.passThrough.
{externalDependencies} mapped, with a note Core keys no lockfile. With a @vzn/vx-lockfile plugin, which keys the project’s and the root’s dependencies, dropped: silent for names the root package.json declares, a TODO names any other. With no plugin claiming the lockfile, the task keys the whole file, as does a target with no such input of its own whose executor is not an @nx/ or @nrwl/ one (Nx hashes every external dependency there).
{dependentTasksOutputFiles, transitive} supported vx folds each dependency’s cache key (its inputs, transitively) through dependsOn, and a cached task’s output follows from its inputs. An uncached producer’s matching files are an inputs.workspaceRuntime probe, answered after it ran; with transitive, one behind an nx:noop group or another task too. A ^ edge with no Nx dependency reads nothing and stays cached.
{json, fields, excludeFields} mapped, with a note The whole file is hashed, a superset of the selected fields.
Turborepo, Nx and other product names are trademarks of their owners. vx is not affiliated with or endorsed by them.