Skipping Tasks
Purpose and Scope
Skipping work is the fastest form of optimization in a Turborepo pipeline. Caching avoids repeating completed tasks, but a cache hit still requires the CI provider to start a job, check out the repository, install dependencies, and invoke the task runner. The skipping workflow asks an earlier question: is the target workspace or task affected by this change at all? If the answer is no, the job can terminate before those heavier setup steps happen. This page focuses on that early decision point for package builds, tests, deploy previews, and other workspace-scoped checks.
Sources: apps/docs/content/docs/guides/skipping-tasks.mdx, apps/docs/content/docs/crafting-your-repository/running-tasks.mdx
The current first-party guidance centers on the affected query command. It is designed for CI and deployment gates where a workspace such as a web application should only build or test when its own files, or the packages it depends on, changed. Remote Caching remains important because affected work can still reuse artifacts across machines, but affected querying can prevent entire jobs from running. Treat the two features as complementary: querying reduces the amount of work considered, while caching accelerates the work that still needs to execute.
Sources: apps/docs/content/docs/guides/skipping-tasks.mdx, apps/docs/content/blog/free-vercel-remote-cache.mdx
Relevant Source Files
- apps/docs/content/docs/guides/skipping-tasks.mdx — Defines the guide’s recommended workflow, affected query examples, base and head customization, exit-code behavior, and the deprecation notice for the legacy ignore package.
- apps/docs/content/blog/free-vercel-remote-cache.mdx — Explains why Remote Caching matters in CI, how Vercel Remote Cache is linked, and which environment variables authenticate other CI providers.
- apps/docs/content/blog/joining-vercel.mdx — Provides historical context that Turborepo’s CLI became open source and that Vercel provides zero-configuration remote caching.
- apps/docs/content/docs/crafting-your-repository/configuring-tasks.mdx — Defines tasks as scripts registered in the root configuration and explains dependencies, parallelization, and outputs that affect task execution.
- apps/docs/content/docs/crafting-your-repository/running-tasks.mdx — Shows how teams run registered tasks through package manager scripts, global commands, filters, and CI workflows.
- apps/docs/content/docs/guides/ci-vendors/github-actions.mdx — Supplies a concrete CI workflow shape with checkout, package-manager setup, dependency installation, build, test, and optional Remote Caching environment variables.
Core Primitives
A skip decision depends on three primitives: workspaces, tasks, and the source-control comparison. A workspace is a package in the repository graph, typically an app or shared package. A task is a script that Turborepo can run when it is registered in the root configuration. The comparison is the range of commits used to decide whether the selected workspace or task is affected. When those pieces are aligned, the query can answer a targeted question, such as whether the web workspace needs its unit tests on this branch.
Sources: apps/docs/content/docs/crafting-your-repository/configuring-tasks.mdx, apps/docs/content/docs/guides/skipping-tasks.mdx
Task configuration still matters even when the goal is skipping. The configuration guide describes a task as a script that Turborepo runs, with relationships expressed through the root configuration and the package graph. Those relationships are important because a workspace may be affected by a direct file change or by a dependency that must build before it. Skipping should therefore be based on Turborepo’s understanding of the repository rather than a handwritten path check that only watches one directory and misses shared package changes.
Sources: apps/docs/content/docs/crafting-your-repository/configuring-tasks.mdx
Recommended Workflow with Affected Queries
Place the affected check immediately after checkout and before dependency installation whenever your CI provider allows it. The guide’s example stores the query result, counts the affected packages, and exits successfully when the selected workspace is not affected. That sequencing is the main benefit: the pipeline avoids provisioning cost beyond the minimal checkout and query step. If the count is positive, continue with the normal install, build, test, or deploy workflow. If the count is zero, exit cleanly so the skipped job is not treated as a failure.
Sources: apps/docs/content/docs/guides/skipping-tasks.mdx
affected=$(turbo query affected --packages web)
count=$(echo "$affected" | jq '.data.affectedPackages.length')
if [ "$count" -gt 0 ]; then
echo "web is affected, proceeding with build"
else
echo "web is not affected, skipping"
exit 0
fiThe query output is useful beyond a yes or no answer. The guide shows structured data that includes affected package entries, package paths, and a reason for the result. That lets a pipeline log why work proceeded, branch into different build strategies, or collect diagnostics when a workspace unexpectedly appears affected. For task-specific gates, the workflow can query affected tasks rather than only affected packages. That is useful when a workspace changed, but a particular task is not relevant to the change set or when a deploy step should be stricter than a lint step.
Sources: apps/docs/content/docs/guides/skipping-tasks.mdx
affected=$(turbo query affected --tasks test --packages web)
count=$(echo "$affected" | jq '.data.affectedTasks.length')Git History, Base and Head, and Exit Codes
The most important edge case is checkout depth. The affected comparison requires the relevant commits between base and head to exist locally. If the checkout is too shallow, the guide warns that all packages will be considered changed. That failure mode is intentionally conservative because running too much work is safer than skipping required work. In CI, configure checkout so the comparison has enough history. The docs call out a full enough Git checkout, such as using blob filtering with complete depth, when the query must compare against the branch base accurately.
Sources: apps/docs/content/docs/guides/skipping-tasks.mdx
By default, the affected query compares against the merge base with the default branch, so it detects all changes across the branch rather than only the latest commit. That default is a good fit for pull request jobs because it answers whether the branch as a whole affects the workspace. For release jobs, backports, or custom deployment flows, set the base and head explicitly. The command flags take precedence over environment variables, while the environment variables are convenient when a CI template wants to share comparison settings across multiple query commands.
Sources: apps/docs/content/docs/guides/skipping-tasks.mdx
turbo query affected --packages web --base main --head HEAD
turbo query affected --packages web --exit-codeThe shorthand exit-code mode is appropriate when the pipeline only needs a binary signal and does not need to parse JSON. The documented behavior is distinct from many Unix commands: an affected result exits with one, no affected result exits with zero, and errors exit with two. That makes it easy to wire into shell conditionals, but the job author should be deliberate about the meaning. A nonzero result can mean proceed with work, not fail the job, when the command is being used as a change detector.
Sources: apps/docs/content/docs/guides/skipping-tasks.mdx
CI and Remote Cache Integration
Skipping does not replace the normal Turborepo CI pattern; it sits in front of it. The GitHub Actions guide shows a root package script shape where build and test commands invoke the task runner, a root configuration that defines outputs and dependencies, and a workflow that checks out code, sets up the package manager, installs dependencies, then runs build and test. Add the affected query before expensive steps for jobs that target a specific workspace. Keep the regular build and test commands for the paths where the query says the workspace is affected.
Sources: apps/docs/content/docs/guides/ci-vendors/github-actions.mdx, apps/docs/content/docs/crafting-your-repository/running-tasks.mdx
jobs:
web:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Check whether web is affected
run: |
affected=$(turbo query affected --packages web)
count=$(echo "$affected" | jq '.data.affectedPackages.length')
if [ "$count" -eq 0 ]; then exit 0; fi
- name: Install dependencies and run tasks
run: pnpm install && pnpm build && pnpm testRemote Caching remains valuable for every affected job that continues past the gate. The free Vercel Remote Cache announcement describes remote cache as a distributed layer that keeps developers and CI from doing the same work twice, and it explains that Vercel builds are automatically configured while other CI providers use token and team environment variables. In practical terms, use affected querying to avoid jobs for unaffected workspaces, and use remote cache credentials so the jobs that remain can restore previous outputs whenever their inputs already match a known artifact.
Sources: apps/docs/content/blog/free-vercel-remote-cache.mdx, apps/docs/content/blog/joining-vercel.mdx, apps/docs/content/docs/guides/ci-vendors/github-actions.mdx
Legacy turbo-ignore and Migration Guidance
The skipping guide marks the older ignore package as deprecated and directs readers to use the affected query command instead. The migration reason is not merely naming. The affected query produces structured results, supports package and task selections, exposes comparison customization, and has an exit-code shorthand for simple gates. If a repository still has deployment scripts built around the legacy package, migrate one target at a time: reproduce the existing skip condition with an affected package query, verify checkout depth, then replace ad hoc parsing with JSON or documented exit codes.
Sources: apps/docs/content/docs/guides/skipping-tasks.mdx
A good migration test is to choose one application workspace and run the query on three branches: a branch with only unrelated changes, a branch with direct application changes, and a branch with changes in a shared package consumed by the application. The first should skip, while the other two should continue. This validates that the package graph, task configuration, and source-control comparison agree. Once the behavior is trusted, apply the same pattern to preview deployments, package-specific test jobs, and expensive verification tasks that do not need to run for every pull request.
Sources: apps/docs/content/docs/guides/skipping-tasks.mdx, apps/docs/content/docs/crafting-your-repository/configuring-tasks.mdx
Next Steps
Start by adding a single affected query gate to the most expensive workspace-specific CI job. Make checkout history explicit, decide whether you need JSON details or the exit-code shorthand, and keep Remote Caching configured for the work that still runs. Then review the task configuration for correct dependencies and outputs so the affected result reflects the repository graph rather than only direct file paths. For broader context, read the task configuration, running tasks, CI vendor, remote caching, and query reference pages before standardizing the pattern across all applications and deploy targets.
Sources: apps/docs/content/docs/guides/skipping-tasks.mdx, apps/docs/content/docs/crafting-your-repository/configuring-tasks.mdx, apps/docs/content/docs/crafting-your-repository/running-tasks.mdx, apps/docs/content/docs/guides/ci-vendors/github-actions.mdx