Running & filtering tasks
vx run <task> is the command you’ll type most. By default it runs the
task in the current package plus its dependency graph. Flags let you
widen, narrow, and target the run.
Scope: where the task runs
Section titled “Scope: where the task runs”vx run build # current package (by cwd) + its depsvx run build --all # every package that declares buildvx run build --filter "@app/*" # packages matching a filtervx run test --affected # only packages changed vs the base branch--all, --filter, and --affected switch vx into a broad run;
with none of them, it’s a focused run on the current package and
streams that task’s output live.
Multiple tasks at once
Section titled “Multiple tasks at once”Pass several task names and vx runs them in one shared graph (so shared dependencies build only once):
vx run lint test build --allTargeting a specific package’s task
Section titled “Targeting a specific package’s task”Use pkg#task to address one package directly, regardless of cwd:
vx run app#buildvx run app#build api#testFiltering with --filter
Section titled “Filtering with --filter”vx speaks the pnpm/Turborepo filter DSL:
vx run build --filter "@app/web" # one package by namevx run build --filter "@app/*" # a glob over package namesvx run build --filter "./packages/ui" # by pathvx run build --filter "...@app/web" # a package and its dependency graphvx run build --filter "[origin/main]" # packages changed since a git refThe ... expansion pulls in related packages across the dependency
graph; see the CLI reference for the exact table. Combine
multiple --filter flags to union selections.
Selecting only what changed: --affected
Section titled “Selecting only what changed: --affected”vx run test --affected # vs the default base branchvx run test --affected=origin/main # vs an explicit refvx asks git which files changed, maps them to packages, and runs the task only for those packages (and the ones that depend on them). This is the flag that keeps CI fast — pair it with remote caching and most PRs touch a handful of packages.
How --affected narrows the run: it starts from git, not from your
task graph. A PR that touches one file in @acme/web selects only
@acme/web plus anything that depends on it — the rest of the monorepo
is skipped entirely, never even scheduled. On a big repo that’s the
difference between building 3 packages and building 300:
flowchart LR base["git diff vs base<br/>(origin/main)"] --> changed["Changed files"] changed --> owners["Map each file<br/>to its package"] owners --> dependents["+ packages that<br/>depend on those"] dependents --> scope["Run the task only<br/>in this set"] skipped["Every other package"] -.->|"never scheduled"| scope classDef step fill:#1e293b,stroke:#38bdf8,color:#e2e8f0 classDef skip fill:#1f2328,stroke:#6b7280,color:#9ca3af class base,changed,owners,dependents,scope step class skipped skip
Forwarding arguments with --
Section titled “Forwarding arguments with --”Everything after -- is appended to the task’s command:
vx run test -- --bail --testNamePattern auth# the child sees: bun test "--bail" "--testNamePattern" "auth"Forwarded args are part of the cache key, so different args form distinct cache entries — no stale hits across argument changes.
Preview without executing
Section titled “Preview without executing”vx run build --all --dry # predicted hits/misses + the planvx run build --all --dry=json # same, as JSONvx run build --graph # the task graph (text)vx run build --graph=g.dot # Graphviz DOT--dry is the fastest way to answer “what will this run do, and what’s
already cached?” before committing to it. It prints the plan and the
predicted cache verdict per task, then exits without running anything:
would run: ◉ @acme/api#build cache hit (local) 8625b603 ◉ @acme/ui#build cache hit (local) 71e5d9a0 ◉ @acme/web#build cache hit (local) 42e9b39d
3 task(s) planned, 3 cache hits (3 local).Prove a cache entry is safe: --verify
Section titled “Prove a cache entry is safe: --verify”vx is the only runner that can prove a cached result is safe to
reuse instead of hoping. Every other cache trusts that identical inputs
produce identical outputs; --verify checks it. It runs the task,
saves the outputs, runs it again, and content-compares — so a build
that quietly depends on a timestamp, a random seed, or an unlisted file
is caught before it ever poisons a shared cache:
flowchart LR
run1["Run the task<br/>→ save outputs"] --> run2["Run it again<br/>(same inputs)"]
run2 --> cmp{"Outputs<br/>byte-identical?"}
cmp -->|"yes"| proven["proven-deterministic ✓<br/>safe to cache & share"]
cmp -->|"no"| fail["nondeterministic ✗<br/>run FAILS + names the<br/>files that changed"]
classDef step fill:#1e293b,stroke:#38bdf8,color:#e2e8f0
classDef decide fill:#1e293b,stroke:#a78bfa,color:#e2e8f0
classDef good fill:#12261b,stroke:#34d399,color:#d1fae5
classDef bad fill:#2a1416,stroke:#ef4444,color:#fecaca
class run1,run2 step
class cmp decide
class proven good
class fail bad
Pair it with --force to re-verify a warm graph. It’s a CI / merge-queue
gate, not an every-run default (it costs ~2× because it runs each task
twice).
See the CLI reference for
--verify=inputs (proves your declared inputs are complete) and
--verify=fingerprint (catches machine-dependent outputs across a CI
matrix).
Useful run flags
Section titled “Useful run flags”| Flag | Effect |
|---|---|
--no-cache (--force) | Ignore the cache for this run (don’t read or write). |
--concurrency <n> | Cap parallel tasks (default: your CPU count). |
--output-logs <mode> | full · errors-only · none — control per-task logging. |
--summarize[=<path>] | Write a per-run JSON summary. |
--profile[=<path>] | Write a Chrome-trace timeline of the run. |
--frozen | Run from the committed vx-lock.json (CI; see below). |
Re-run on change: vx watch
Section titled “Re-run on change: vx watch”vx watch test # initial run, then re-run on every file changevx watch runs the task, then watches the relevant files and re-runs on
change (debounced, with bursty edits collapsed into one run). Great for a
test or typecheck loop. See Dev & long-running tasks for
dev servers, which are a different mechanism (persistent).
Other handy commands
Section titled “Other handy commands”vx show # list projects and their tasksvx show app#build # the live resolved config for one taskvx info # doctor printout: versions, cache size, run statsvx cache prune --older-than 7d --max-size 5gbNext steps
Section titled “Next steps”- Continuous integration —
--affected+ remote cache in CI. - Caching tasks — why a run hit or missed.
- CLI reference — every flag, exit code, and the full filter table.