Skip to content
vxvx
GitHubBlueskydev.toRSS

dependsOn

Tasks that must complete successfully before this task runs. Turbo/Nx-style micro-syntax — a flat array of strings:

dependsOn?: readonly string[]
Form Meaning
'name' Same-project task name.
'^name' The name task in the nearest project deps (a plugin’s edges) that declare it.
'pkg#name' The name task in a specific other package (cross-project edge).
'name.*' Every OTHER same-project task matching the pattern (* = any).
'^name.*' All matching tasks of the nearest deps that declare any (pattern).

Examples:

dependsOn: ['build'] // same-project build first
dependsOn: ['^build'] // build in every workspace dep first
dependsOn: ['codegen', '^build'] // both
dependsOn: ['lib#build', 'shared#test'] // cross-project edges
dependsOn: ['lint.*'] // every lint.<x> task in this project
dependsOn: ['^build.*'] // all build.<x> tasks of the nearest deps

Semantics:

  • Same-project ('name') — name must exist in this project’s tasks map; missing is a hard error at graph-build time. When the config is authored through defineProject, a bare entry is also type-checked against this config’s task keys — a typo is a compile error ('^name' / 'pkg#name' reference other projects and stay free strings).
  • '^name' — nearest-holder frontier. Walk the project graph from this project’s direct deps: the edges a plugin’s discover returns as deps (the lockfile plugins bun() / pnpm() / npm() / yarn() return what the package manager installed; core reads no edge from a package.json) and the cross-project pkg#task edges. With no plugin returning deps the workspace has no edge source and a '^name' is refused (VX_E_DEPENDS_ON: “^build needs project edges; add pnpm()/bun()/npm()/yarn() and install so its lockfile exists, or a plugin that returns deps”): it would resolve to nothing and fold no upstream into the key. With one, a project with no deps is a leaf; each path stops at the first dep that declares the task and an edge is added to it (Turbo/Nx direct-deps parity). The holder’s own dependsOn is responsible for anything deeper — chain '^name' in the holder to keep the cascade going (the universal pattern). Deps that don’t declare the task are passed through, so a sparse dep doesn’t break ordering to deeper packages that do (sparse tasks across a workspace are normal — not every package has a lint). Finding no holder at all is legal too, as long as SOME project in the workspace declares name: a preset spreads '^build' over packages whose deps have no build. A '^name' that no project in the whole workspace declares is a hard error at graph-build time, since it can only be a typo: “app#test: dependsOn ^biuld but no project in the workspace declares biuld. Did you mean ^build?” (a same-project name that is not declared names the project’s nearest task the same way). Until 2026-09-24 it resolved to no edges and the run went green (Nx#32779 is the same bug). A scoped run (an anchored app#test, --filter, a project directory) loads only its projects and their dependency closure; when a '^name' there finds no holder and nothing loaded declares it, vx evaluates the remaining configs to decide, and if one of them fails to load the name is let through rather than failing the scoped run. A '^name.*' pattern matching nothing anywhere stays legal, as 'name.*' does.
  • 'pkg#name' — missing pkg or task is a hard error (you named them explicitly). '//#name', Turbo’s spelling of the root package, names the root project (D-39) here and in inputs.tasks; with no root project it is refused as such.
  • Patterns ('name.*' / '^name.*') — * matches any run of characters in a task NAME; everything else is literal (the dotted namespace convention needs no escaping). A same-project pattern expands to every other matching task (the declaring task never matches itself); zero matches is legal — a preset-spread pattern needn’t match in every project. A '^pattern' walks the same nearest-holder frontier as '^name', where a holder is a dep declaring at least one matching task; the holder receives edges to ALL its matches and stops the walk. Patterns are not supported in the 'pkg#task' form. (Nx 19.5 build-* parity.)
  • No bare wildcards or negation here. '*' / '^*' / '!form' belong in inputs.tasks (filtering which upstream hashes participate in this task’s cache key), not in dependsOn (declaring graph edges). The micro-syntax parser rejects them in this position.
  • Cycle detection runs across the resolved graph at the end of buildTaskGraph. Cycles throw with a path-formatted message.
Turborepo, Nx and other product names are trademarks of their owners. vx is not affiliated with or endorsed by them.