NEW Browse AI tools across categories — updated daily. See what's new →

Turborepo

Monorepo build system with intelligent task caching, parallel execution, and dependency graph orchestration. Caches task outputs and runs tasks in parallel based on declared dependencies; supports ...

Authorvercel
Version1.0.0
LicenseMIT
Token count~6,394
UpdatedJun 5, 2026

Monorepo build system with intelligent task caching, parallel execution, and dependency graph orchestration. Caches task outputs and runs tasks in parallel based on declared dependencies; supports remote caching for CI/CD workflows Filters and runs only changed packages with --affected , or use --filter for custom package selection Configures tasks in turbo.json with dependsOn , outputs , inputs , and env keys; supports package-specific overrides via Package Configurations Enforces monorepo...

Install

Quick install

via npx skills · works with 57+ agents
npx skills add https://github.com/vercel/turborepo/tree/HEAD/skills/turborepo
Or pick agent:
npx skills add vercel/turborepo --skill turborepo --agent claude-code
npx skills add vercel/turborepo --skill turborepo --agent cursor
npx skills add vercel/turborepo --skill turborepo --agent codex
npx skills add vercel/turborepo --skill turborepo --agent opencode
npx skills add vercel/turborepo --skill turborepo --agent github-copilot
npx skills add vercel/turborepo --skill turborepo --agent windsurf
More install options

Shorthand — useful for multi-skill repos:

npx skills add vercel/turborepo --skill turborepo

Manual — clone the repo and drop the folder into your agent's skills directory:

git clone https://github.com/vercel/turborepo.git
cp -r turborepo/skills/turborepo ~/.claude/skills/
How to use: Once installed, ask your agent to "use the turborepo skill" or describe what you want (e.g. "Monorepo build system with intelligent task caching, parallel execution, and dep"). Requires Node.js 18+.

turborepo

Monorepo build system with intelligent task caching, parallel execution, and dependency graph orchestration. Caches task outputs and runs tasks in parallel based on declared dependencies; supports remote caching for CI/CD workflows Filters and runs only changed packages with --affected , or use --filter for custom package selection Configures tasks in turbo.json with dependsOn , outputs , inputs , and env keys; supports package-specific overrides via Package Configurations Enforces monorepo...

turborepoby vercel

Monorepo build system with intelligent task caching, parallel execution, and dependency graph orchestration. Caches task outputs and runs tasks in parallel based on declared dependencies; supports remote caching for CI/CD workflows Filters and runs only changed packages with --affected , or use --filter for custom package selection Configures tasks in turbo.json with dependsOn , outputs , inputs , and env keys; supports package-specific overrides via Package Configurations Enforces monorepo...

npx skills add https://github.com/vercel/turborepo --skill turborepoDownload ZIPGitHub

Turborepo Skill

Build system for JavaScript/TypeScript monorepos. Turborepo caches task outputs and runs tasks in parallel based on dependency graph.

IMPORTANT: Package Tasks, Not Root Tasks

Prefer package tasks over Root Tasks.

When creating tasks/scripts/pipelines, you MUST default to package tasks:

  • Add the script to each relevant package's package.json
  • Register the task in root turbo.json
  • Root package.json only delegates via turbo run <task>

DO NOT put task logic in root package.json when it can live in packages. This defeats Turborepo's parallelization.

`// DO THIS: Scripts in each package
// apps/web/package.json
{ "scripts": { "build": "next build", "lint": "eslint .", "test": "vitest" } }

// apps/api/package.json
{ "scripts": { "build": "tsc", "lint": "eslint .", "test": "vitest" } }

// packages/ui/package.json
{ "scripts": { "build": "tsc", "lint": "eslint .", "test": "vitest" } }
`
`// turbo.json - register tasks
{
"tasks": {
"build": { "dependsOn": ["^build"], "outputs": ["dist/**"] },
"lint": {},
"test": { "dependsOn": ["build"] }
}
}
`
`// Root package.json - ONLY delegates, no task logic
{
"scripts": {
"build": "turbo run build",
"lint": "turbo run lint",
"test": "turbo run test"
}
}
`
`// DO NOT DO THIS - defeats parallelization
// Root package.json
{
"scripts": {
"build": "cd apps/web && next build && cd ../api && tsc",
"lint": "eslint apps/ packages/",
"test": "vitest"
}
}
`

Root Tasks (//#taskname) are ONLY for tasks that truly cannot exist in packages, such as Vitest Projects' //#test, repo-wide release scripts, or tooling that does not invoke turbo itself.

Secondary Rule: turbo run vs turbo

Always use turbo run when the command is written into code:

`// package.json - ALWAYS "turbo run"
{
"scripts": {
"build": "turbo run build"
}
}
`
`# CI workflows - ALWAYS "turbo run"
- run: turbo run build --affected
`

The shorthand turbo <tasks> is ONLY for one-off terminal commands typed directly by humans or agents. Never write turbo build into package.json, CI, or scripts.

Quick Decision Trees

"I need to configure a task"

`Configure a task?
├─ Define task dependencies → references/configuration/tasks.md
├─ Lint/check-types (parallel + caching) → Use Transit Nodes pattern (see below)
├─ Specify build outputs → references/configuration/tasks.md#outputs
├─ Handle environment variables → references/environment/RULE.md
├─ Set up dev/watch tasks → references/configuration/tasks.md#persistent
├─ Package-specific config → references/configuration/RULE.md#package-configurations
└─ Global settings (cacheDir, daemon) → references/configuration/global-options.md
`

"My cache isn't working"

`Cache problems?
├─ Tasks run but outputs not restored → Missing `outputs` key
├─ Cache misses unexpectedly → references/caching/gotchas.md
├─ Need to debug hash inputs → Use --summarize or --dry
├─ Want to skip cache entirely → Use --force or cache: false
├─ Remote cache not working → references/caching/remote-cache.md
└─ Environment causing misses → references/environment/gotchas.md
`

"I want to run only changed packages"

`Run only what changed?
├─ Changed packages + dependents (RECOMMENDED) → turbo run build --affected
├─ Custom base branch → --affected --affected-base=origin/develop
├─ Manual git comparison → --filter=...[origin/main]
└─ See all filter options → references/filtering/RULE.md
`

--affected is the primary way to run only changed packages. It automatically compares against the default branch and includes dependents.

"I want to filter packages"

`Filter packages?
├─ Only changed packages → --affected (see above)
├─ By package name → --filter=web
├─ By directory → --filter=./apps/*
├─ Package + dependencies → --filter=web...
├─ Package + dependents → --filter=...web
└─ Complex combinations → references/filtering/patterns.md
`

"Environment variables aren't working"

`Environment issues?
├─ Vars not available at runtime → Strict mode filtering (default)
├─ Cache hits with wrong env → Var not in `env` key
├─ .env changes not causing rebuilds → .env not in `inputs`
├─ CI variables missing → references/environment/gotchas.md
└─ Framework vars (NEXT_PUBLIC_*) → Auto-included via inference
`

"I need to set up CI"

`CI setup?
├─ GitHub Actions → references/ci/github-actions.md
├─ Vercel deployment → references/ci/vercel.md
├─ Remote cache in CI → references/caching/remote-cache.md
├─ Only build changed packages → --affected flag
├─ Skip unnecessary builds → turbo-ignore (references/cli/commands.md)
└─ Skip container setup when no changes → turbo-ignore
`

"I want to watch for changes during development"

`Watch mode?
├─ Re-run tasks on change → turbo watch (references/watch/RULE.md)
├─ Dev servers with dependencies → Use `with` key (references/configuration/tasks.md#with)
├─ Restart dev server on dep change → Use `interruptible: true`
└─ Persistent dev tasks → Use `persistent: true`
`

"I need to create/structure a package"

`Package creation/structure?
├─ Create an internal package → references/best-practices/packages.md
├─ Repository structure → references/best-practices/structure.md
├─ Dependency management → references/best-practices/dependencies.md
├─ Best practices overview → references/best-practices/RULE.md
├─ JIT vs Compiled packages → references/best-practices/packages.md#compilation-strategies
└─ Sharing code between apps → references/best-practices/RULE.md#package-types
`

"How should I structure my monorepo?"

`Monorepo structure?
├─ Standard layout (apps/, packages/) → references/best-practices/RULE.md
├─ Package types (apps vs libraries) → references/best-practices/RULE.md#package-types
├─ Creating internal packages → references/best-practices/packages.md
├─ TypeScript configuration → references/best-practices/structure.md#typescript-configuration
├─ ESLint configuration → references/best-practices/structure.md#eslint-configuration
├─ Dependency management → references/best-practices/dependencies.md
└─ Enforce package boundaries → references/boundaries/RULE.md
`

"I want to enforce architectural boundaries"

`Enforce boundaries?
├─ Check for violations → turbo boundaries
├─ Tag packages → references/boundaries/RULE.md#tags
├─ Restrict which packages can import others → references/boundaries/RULE.md#rule-types
└─ Prevent cross-package file imports → references/boundaries/RULE.md
`

Critical Anti-Patterns

Using turbo Shorthand in Code

turbo run is recommended in package.json scripts and CI pipelines. The shorthand turbo <task> is intended for interactive terminal use.

`// WRONG - using shorthand in package.json
{
"scripts": {
"build": "turbo build",
"dev": "turbo dev"
}
}

// CORRECT
{
"scripts": {
"build": "turbo run build",
"dev": "turbo run dev"
}
}
`
`# WRONG - using shorthand in CI
- run: turbo build --affected

# CORRECT
- run: turbo run build --affected
`

Root Scripts Bypassing Turbo

Root package.json scripts MUST delegate to turbo run, not run tasks directly.

`// WRONG - bypasses turbo entirely
{
"scripts": {
"build": "bun build",
"dev": "bun dev"
}
}

// CORRECT - delegates to turbo
{
"scripts": {
"build": "turbo run build",
"dev": "turbo run dev"
}
}
`

Using && to Chain Turbo Tasks

Don't chain turbo tasks with &&. Let turbo orchestrate.

`// WRONG - turbo task not using turbo run
{
"scripts": {
"changeset:publish": "bun build && changeset publish"
}
}

// CORRECT
{
"scripts": {
"changeset:publish": "turbo run build && changeset publish"
}
}
`

prebuild Scripts That Manually Build Dependencies

Scripts like prebuild that manually build other packages bypass Turborepo's dependency graph.

`// WRONG - manually building dependencies
{
"scripts": {
"prebuild": "cd ../../packages/types && bun run build && cd ../utils && bun run build",
"build": "next build"
}
}
`

However, the fix depends on whether workspace dependencies are declared:

*
If dependencies ARE declared (e.g., "@repo/types": "workspace:*" in package.json), remove the prebuild script. Turbo's dependsOn: ["^build"] handles this automatically.

*
If dependencies are NOT declared, the prebuild exists because ^build won't trigger without a dependency relationship. The fix is to:

Add the dependency to package.json: "@repo/types": "workspace:"

  • Then remove the prebuild script
`// CORRECT - declare dependency, let turbo handle build order
// package.json
{
"dependencies": {
"@repo/types": "workspace:*",
"@repo/utils": "workspace:*"
},
"scripts": {
"build": "next build"
}
}

// turbo.json
{
"tasks": {
"build": {
"dependsOn": ["^build"]
}
}
}
`

Key insight: ^build only runs build in packages listed as dependencies. No dependency declaration = no automatic build ordering.

Overly Broad globalDependencies

globalDependencies affects ALL tasks in ALL packages via the global hash — tasks cannot opt out of specific files, even with negation globs in inputs. Be specific.

`// WRONG - heavy hammer, affects all hashes
{
"globalDependencies": ["**/.env.*local"]
}

// BETTER - move to task-level inputs
{
"globalDependencies": [".env"],
"tasks": {
"build": {
"inputs": ["$TURBO_DEFAULT$", ".env*"],
"outputs": ["dist/**"]
}
}
}
`

With futureFlags.globalConfiguration, this problem is reduced because global.inputs files are folded into each task's inputs (not the global hash). Tasks can exclude specific files:

`// BEST - global.inputs with per-task exclusion
{
"futureFlags": { "globalConfiguration": true },
"global": {
"inputs": [".env"]
},
"tasks": {
"build": { "outputs": ["dist/**"] },
"lint": {
"inputs": ["$TURBO_DEFAULT$", "!$TURBO_ROOT$/.env"]
}
}
}
`

Repetitive Task Configuration

Look for repeated configuration across tasks that can be collapsed. Turborepo supports shared configuration patterns.

`// WRONG - repetitive env and inputs across tasks
{
"tasks": {
"build": {
"env": ["API_URL", "DATABASE_URL"],
"inputs": ["$TURBO_DEFAULT$", ".env*"]
},
"test": {
"env": ["API_URL", "DATABASE_URL"],
"inputs": ["$TURBO_DEFAULT$", ".env*"]
},
"dev": {
"env": ["API_URL", "DATABASE_URL"],
"inputs": ["$TURBO_DEFAULT$", ".env*"],
"cache": false,
"persistent": true
}
}
}

// BETTER - use globalEnv and globalDependencies for shared config
{
"globalEnv": ["API_URL", "DATABASE_URL"],
"globalDependencies": [".env*"],
"tasks": {
"build": {},
"test": {},
"dev": {
"cache": false,
"persistent": true
}
}
}
`

When to use global vs task-level:

  • globalEnv / globalDependencies - affects ALL tasks, use for truly shared config
  • Task-level env / inputs - use when only specific tasks need it

NOT an Anti-Pattern: Large env Arrays

A large env array (even 50+ variables) is not a problem. It usually means the user was thorough about declaring their build's environment dependencies. Do not flag this as an issue.

Using --parallel Flag

The --parallel flag bypasses Turborepo's dependency graph. If tasks need parallel execution, configure dependsOn correctly instead.

`# WRONG - bypasses dependency graph
turbo run lint --parallel

# CORRECT - configure tasks to allow parallel execution
# In turbo.json, set dependsOn appropriately (or use transit nodes)
turbo run lint
`

Package-Specific Task Overrides in Root turbo.json

When multiple packages need different task configurations, use Package Configurations (turbo.json in each package) instead of cluttering root turbo.json with package#task overrides.

`// WRONG - root turbo.json with many package-specific overrides
{
"tasks": {
"test": { "dependsOn": ["build"] },
"@repo/web#test": { "outputs": ["coverage/**"] },
"@repo/api#test": { "outputs": ["coverage/**"] },
"@repo/utils#test": { "outputs": [] },
"@repo/cli#test": { "outputs": [] },
"@repo/core#test": { "outputs": [] }
}
}

// CORRECT - use Package Configurations
// Root turbo.json - base config only
{
"tasks": {
"test": { "dependsOn": ["build"] }
}
}

// packages/web/turbo.json - package-specific override
{
"extends": ["//"],
"tasks": {
"test": { "outputs": ["coverage/**"] }
}
}

// packages/api/turbo.json
{
"extends": ["//"],
"tasks": {
"test": { "outputs": ["coverage/**"] }
}
}
`

Benefits of Package Configurations:

  • Keeps configuration close to the code it affects
  • Root turbo.json stays clean and focused on base patterns
  • Easier to understand what's special about each package
  • Works with $TURBO_EXTENDS$ to inherit + extend arrays

When to use package#task in root:

  • Single package needs a unique dependency (e.g., "deploy": { "dependsOn": ["web#build"] })
  • Temporary override while migrating

See references/configuration/RULE.md#package-configurations for full details.

Using ../ to Traverse Out of Package in inputs

Don't use relative paths like ../ to reference files outside the package. Use $TURBO_ROOT$ instead.

`// WRONG - traversing out of package
{
"tasks": {
"build": {
"inputs": ["$TURBO_DEFAULT$", "../shared-config.json"]
}
}
}

// CORRECT - use $TURBO_ROOT$ for repo root
{
"tasks": {
"build": {
"inputs": ["$TURBO_DEFAULT$", "$TURBO_ROOT$/shared-config.json"]
}
}
}
`

Missing outputs for File-Producing Tasks

Before flagging missing outputs, check what the task actually produces:

  • Read the package's script (e.g., "build": "tsc", "test": "vitest")
  • Determine if it writes files to disk or only outputs to stdout
  • Only flag if the task produces files that should be cached
`// WRONG: build produces files but they're not cached
{
"tasks": {
"build": {
"dependsOn": ["^build"]
}
}
}

// CORRECT: build outputs are cached
{
"tasks": {
"build": {
"dependsOn": ["^build"],
"outputs": ["dist/**"]
}
}
}
`

Common outputs by framework:

Next.js: [".next/", "!.next/cache/", "!.next/dev/*"]

Vite/Rollup: ["dist/*"]

tsc: ["dist/*"] or custom outDir

TypeScript --noEmit can still produce cache files:

When incremental: true in tsconfig.json, tsc --noEmit writes .tsbuildinfo files even without emitting JS. Check the tsconfig before assuming no outputs:

`// If tsconfig has incremental: true, tsc --noEmit produces cache files
{
"tasks": {
"typecheck": {
"outputs": ["node_modules/.cache/tsbuildinfo.json"] // or wherever tsBuildInfoFile points
}
}
}
`

To determine correct outputs for TypeScript tasks:

  • Check if incremental or composite is enabled in tsconfig
  • Check tsBuildInfoFile for custom cache location (default: alongside outDir or in project root)
  • If no incremental mode, tsc --noEmit produces no files

^build vs build Confusion

`{
"tasks": {
// ^build = run build in DEPENDENCIES first (other packages this one imports)
"build": {
"dependsOn": ["^build"]
},
// build (no ^) = run build in SAME PACKAGE first
"test": {
"dependsOn": ["build"]
},
// pkg#task = specific package's task
"deploy": {
"dependsOn": ["web#build"]
}
}
}
`

Environment Variables Not Hashed

`// WRONG: API_URL changes won't cause rebuilds
{
"tasks": {
"build": {
"outputs": ["dist/**"]
}
}
}

// CORRECT: API_URL changes invalidate cache
{
"tasks": {
"build": {
"outputs": ["dist/**"],
"env": ["API_URL", "API_KEY"]
}
}
}
`

.env Files Not in Inputs

Turbo does NOT load .env files - your framework does. But Turbo needs to know about changes:

`// WRONG: .env changes don't invalidate cache
{
"tasks": {
"build": {
"env": ["API_URL"]
}
}
}

// CORRECT: .env file changes invalidate cache
{
"tasks": {
"build": {
"env": ["API_URL"],
"inputs": ["$TURBO_DEFAULT$", ".env", ".env.*"]
}
}
}
`

Root .env File in Monorepo

A .env file at the repo root is an anti-pattern — even for small monorepos or starter templates. It creates implicit coupling between packages and makes it unclear which packages depend on which variables.

`// WRONG - root .env affects all packages implicitly
my-monorepo/
├── .env # Which packages use this?
├── apps/
│ ├── web/
│ └── api/
└── packages/

// CORRECT - .env files in packages that need them
my-monorepo/
├── apps/
│ ├── web/
│ │ └── .env # Clear: web needs DATABASE_URL
│ └── api/
│ └── .env # Clear: api needs API_KEY
└── packages/
`

Problems with root .env:

  • Unclear which packages consume which variables
  • All packages get all variables (even ones they don't need)
  • Cache invalidation is coarse-grained (root .env change invalidates everything)
  • Security risk: packages may accidentally access sensitive vars meant for others
  • Bad habits start small — starter templates should model correct patterns

If you must share variables, use globalEnv to be explicit about what's shared, and document why.

Strict Mode Filtering CI Variables

By default, Turborepo filters environment variables to only those in env/globalEnv. CI variables may be missing:

`// If CI scripts need GITHUB_TOKEN but it's not in env:
{
"globalPassThroughEnv": ["GITHUB_TOKEN", "CI"],
"tasks": { ... }
}
`

Or use --env-mode=loose (not recommended for production).

Shared Code in Apps (Should Be a Package)

`// WRONG: Shared code inside an app
apps/
web/
shared/ # This breaks monorepo principles!
utils.ts

// CORRECT: Extract to a package
packages/
utils/
src/utils.ts
`

Accessing Files Across Package Boundaries

`// WRONG: Reaching into another package's internals
import { Button } from "../../packages/ui/src/button";

// CORRECT: Install and import properly
import { Button } from "@repo/ui/button";
`

Too Many Root Dependencies

`// WRONG: App dependencies in root
{
"dependencies": {
"react": "^18",
"next": "^14"
}
}

// CORRECT: Only repo tools in root
{
"devDependencies": {
"turbo": "latest"
}
}
`

Common Task Configurations

Standard Build Pipeline

`{
"$schema": "https://v2-9-17-canary-3.turborepo.dev/schema.json",
"tasks": {
"build": {
"dependsOn": ["^build"],
"outputs": ["dist/**", ".next/**", "!.next/cache/**", "!.next/dev/**"]
},
"dev": {
"cache": false,
"persistent": true
}
}
}
`

Add a transit task if you have tasks that need parallel execution with cache invalidation (see below).

Dev Task with ^dev Pattern (for turbo watch)

A dev task with dependsOn: ["^dev"] and persistent: false in root turbo.json may look unusual but is correct for turbo watch workflows:

`// Root turbo.json
{
"tasks": {
"dev": {
"dependsOn": ["^dev"],
"cache": false,
"persistent": false // Packages have one-shot dev scripts
}
}
}

// Package turbo.json (apps/web/turbo.json)
{
"extends": ["//"],
"tasks": {
"dev": {
"persistent": true // Apps run long-running dev servers
}
}
}
`

Why this works:

  • Packages (e.g., @acme/db, @acme/validators) have "dev": "tsc" — one-shot type generation that completes quickly
  • Apps override with persistent: true for actual dev servers (Next.js, etc.)
  • turbo watch re-runs the one-shot package dev scripts when source files change, keeping types in sync

Intended usage: Run turbo watch dev (not turbo run dev). Watch mode re-executes one-shot tasks on file changes while keeping persistent tasks running.

Alternative pattern: Use a separate task name like prepare or generate for one-shot dependency builds to make the intent clearer:

`{
"tasks": {
"prepare": {
"dependsOn": ["^prepare"],
"outputs": ["dist/**"]
},
"dev": {
"dependsOn": ["prepare"],
"cache": false,
"persistent": true
}
}
}
`

Transit Nodes for Parallel Tasks with Cache Invalidation

Some tasks can run in parallel (don't need built output from dependencies) but must invalidate cache when dependency source code changes.

The problem with dependsOn: ["^taskname"]:

  • Forces sequential execution (slow)

The problem with dependsOn: [] (no dependencies):

  • Allows parallel execution (fast)
  • But cache is INCORRECT - changing dependency source won't invalidate cache

Transit Nodes solve both:

`{
"tasks": {
"transit": { "dependsOn": ["^transit"] },
"my-task": { "dependsOn": ["transit"] }
}
}
`

The transit task creates dependency relationships without matching any actual script, so tasks run in parallel with correct cache invalidation.

How to identify tasks that need this pattern: Look for tasks that read source files from dependencies but don't need their build outputs.

With Environment Variables

`{
"globalEnv": ["NODE_ENV"],
"globalDependencies": [".env"],
"tasks": {
"build": {
"dependsOn": ["^build"],
"outputs": ["dist/**"],
"env": ["API_URL", "DATABASE_URL"]
}
}
}
`

With futureFlags.globalConfiguration, the same config moves global settings under global — and .env becomes a per-task input instead of a global hash input:

`{
"futureFlags": { "globalConfiguration": true },
"global": {
"env": ["NODE_ENV"],
"inputs": [".env"]
},
"tasks": {
"build": {
"dependsOn": ["^build"],
"outputs": ["dist/**"],
"env": ["API_URL", "DATABASE_URL"]
}
}
}
`

Reference Index

Configuration

FilePurposeconfiguration/RULE.mdturbo.json overview, Package Configurationsconfiguration/tasks.mddependsOn, outputs, inputs, env, cache, persistentconfiguration/global-options.mdglobalEnv, globalDependencies, global key, futureFlags, cacheDir, envModeconfiguration/gotchas.mdCommon configuration mistakes

Caching

FilePurposecaching/RULE.mdHow caching works, hash inputscaching/remote-cache.mdVercel Remote Cache, self-hosted, login/linkcaching/gotchas.mdDebugging cache misses, --summarize, --dry

Environment Variables

FilePurposeenvironment/RULE.mdenv, globalEnv, passThroughEnvenvironment/modes.mdStrict vs Loose mode, framework inferenceenvironment/gotchas.md.env files, CI issues

Filtering

FilePurposefiltering/RULE.md--filter syntax overviewfiltering/patterns.mdCommon filter patterns

CI/CD

FilePurposeci/RULE.mdGeneral CI principlesci/github-actions.mdComplete GitHub Actions setupci/vercel.mdVercel deployment, turbo-ignoreci/patterns.md--affected, caching strategies

CLI

FilePurposecli/RULE.mdturbo run basicscli/commands.mdturbo run flags, turbo-ignore, other commands

Best Practices

FilePurposebest-practices/RULE.mdMonorepo best practices overviewbest-practices/structure.mdRepository structure, workspace config, TypeScript/ESLint setupbest-practices/packages.mdCreating internal packages, JIT vs Compiled, exportsbest-practices/dependencies.mdDependency management, installing, version sync

Watch Mode

FilePurposewatch/RULE.mdturbo watch, interruptible tasks, dev workflows

Boundaries (Experimental)

FilePurposeboundaries/RULE.mdEnforce package isolation, tag-based dependency rules

Source Documentation

This skill is based on the official Turborepo documentation at:

  • Source: apps/docs/content/docs/ in the Turborepo repository
  • Live: https://turborepo.dev/docs

More skills from vercel

agent-friendly-apisby vercelCompanion skill for the Agent-Friendly APIs course on Vercel Academy. Build a feedback API, make it agent-friendly with structured documentation, then create a Claude Code skill that generates the docs automatically.filesystem-agentsby vercelYou are a knowledgeable teaching assistant for the Building Filesystem Agents course on Vercel Academy. You help students build agents that navigate filesystems with bash to answer questions about structured data.add-provider-packageby vercelGuide for adding new AI provider packages to the AI SDK. Use when creating a new @ai-sdk/<provider> package to integrate an AI service into the SDK.csvby vercelAnalyze and transform CSV data using bash toolsaiby vercelPython ai module — models, agents, hooks, middleware, MCP, structured outputcron-jobsby vercelVercel Cron Jobs configuration and best practices. Use when adding, editing, or debugging scheduled tasks in vercel.json.frontend-designby vercelCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, artifacts,…vercel-react-best-practicesby vercelReact and Next.js performance optimization guidelines from Vercel Engineering. This skill should be used when writing, reviewing, or refactoring React/Next.js…

---

Source: https://github.com/vercel/turborepo/tree/HEAD/skills/turborepo
Author: vercel
Discovered via: mcpservers.org

SKILL.md source

---
name: turborepo
description: Monorepo build system with intelligent task caching, parallel execution, and dependency graph orchestration. Caches task outputs and runs tasks in parallel based on declared dependencies; supports ...
---

# turborepo

Monorepo build system with intelligent task caching, parallel execution, and dependency graph orchestration. Caches task outputs and runs tasks in parallel based on declared dependencies; supports remote caching for CI/CD workflows Filters and runs only changed packages with --affected , or use --filter for custom package selection Configures tasks in turbo.json with dependsOn , outputs , inputs , and env keys; supports package-specific overrides via Package Configurations Enforces monorepo...

# turborepoby vercel
Monorepo build system with intelligent task caching, parallel execution, and dependency graph orchestration. Caches task outputs and runs tasks in parallel based on declared dependencies; supports remote caching for CI/CD workflows Filters and runs only changed packages with --affected , or use --filter for custom package selection Configures tasks in turbo.json with dependsOn , outputs , inputs , and env keys; supports package-specific overrides via Package Configurations Enforces monorepo...

`npx skills add https://github.com/vercel/turborepo --skill turborepo`Download ZIPGitHub

## Turborepo Skill

Build system for JavaScript/TypeScript monorepos. Turborepo caches task outputs and runs tasks in parallel based on dependency graph.

## IMPORTANT: Package Tasks, Not Root Tasks

Prefer package tasks over Root Tasks.

When creating tasks/scripts/pipelines, you MUST default to package tasks:

* Add the script to each relevant package's `package.json`

* Register the task in root `turbo.json`

* Root `package.json` only delegates via `turbo run <task>`

DO NOT put task logic in root `package.json` when it can live in packages. This defeats Turborepo's parallelization.

```
`// DO THIS: Scripts in each package
// apps/web/package.json
{ "scripts": { "build": "next build", "lint": "eslint .", "test": "vitest" } }

// apps/api/package.json
{ "scripts": { "build": "tsc", "lint": "eslint .", "test": "vitest" } }

// packages/ui/package.json
{ "scripts": { "build": "tsc", "lint": "eslint .", "test": "vitest" } }
`
```

```
`// turbo.json - register tasks
{
"tasks": {
"build": { "dependsOn": ["^build"], "outputs": ["dist/**"] },
"lint": {},
"test": { "dependsOn": ["build"] }
}
}
`
```

```
`// Root package.json - ONLY delegates, no task logic
{
"scripts": {
"build": "turbo run build",
"lint": "turbo run lint",
"test": "turbo run test"
}
}
`
```

```
`// DO NOT DO THIS - defeats parallelization
// Root package.json
{
"scripts": {
"build": "cd apps/web && next build && cd ../api && tsc",
"lint": "eslint apps/ packages/",
"test": "vitest"
}
}
`
```

Root Tasks (`//#taskname`) are ONLY for tasks that truly cannot exist in packages, such as Vitest Projects' `//#test`, repo-wide release scripts, or tooling that does not invoke `turbo` itself.

## Secondary Rule: `turbo run` vs `turbo`

Always use `turbo run` when the command is written into code:

```
`// package.json - ALWAYS "turbo run"
{
"scripts": {
"build": "turbo run build"
}
}
`
```

```
`# CI workflows - ALWAYS "turbo run"
- run: turbo run build --affected
`
```

The shorthand `turbo <tasks>` is ONLY for one-off terminal commands typed directly by humans or agents. Never write `turbo build` into package.json, CI, or scripts.

## Quick Decision Trees

### "I need to configure a task"

```
`Configure a task?
├─ Define task dependencies → references/configuration/tasks.md
├─ Lint/check-types (parallel + caching) → Use Transit Nodes pattern (see below)
├─ Specify build outputs → references/configuration/tasks.md#outputs
├─ Handle environment variables → references/environment/RULE.md
├─ Set up dev/watch tasks → references/configuration/tasks.md#persistent
├─ Package-specific config → references/configuration/RULE.md#package-configurations
└─ Global settings (cacheDir, daemon) → references/configuration/global-options.md
`
```

### "My cache isn't working"

```
`Cache problems?
├─ Tasks run but outputs not restored → Missing `outputs` key
├─ Cache misses unexpectedly → references/caching/gotchas.md
├─ Need to debug hash inputs → Use --summarize or --dry
├─ Want to skip cache entirely → Use --force or cache: false
├─ Remote cache not working → references/caching/remote-cache.md
└─ Environment causing misses → references/environment/gotchas.md
`
```

### "I want to run only changed packages"

```
`Run only what changed?
├─ Changed packages + dependents (RECOMMENDED) → turbo run build --affected
├─ Custom base branch → --affected --affected-base=origin/develop
├─ Manual git comparison → --filter=...[origin/main]
└─ See all filter options → references/filtering/RULE.md
`
```

`--affected` is the primary way to run only changed packages. It automatically compares against the default branch and includes dependents.

### "I want to filter packages"

```
`Filter packages?
├─ Only changed packages → --affected (see above)
├─ By package name → --filter=web
├─ By directory → --filter=./apps/*
├─ Package + dependencies → --filter=web...
├─ Package + dependents → --filter=...web
└─ Complex combinations → references/filtering/patterns.md
`
```

### "Environment variables aren't working"

```
`Environment issues?
├─ Vars not available at runtime → Strict mode filtering (default)
├─ Cache hits with wrong env → Var not in `env` key
├─ .env changes not causing rebuilds → .env not in `inputs`
├─ CI variables missing → references/environment/gotchas.md
└─ Framework vars (NEXT_PUBLIC_*) → Auto-included via inference
`
```

### "I need to set up CI"

```
`CI setup?
├─ GitHub Actions → references/ci/github-actions.md
├─ Vercel deployment → references/ci/vercel.md
├─ Remote cache in CI → references/caching/remote-cache.md
├─ Only build changed packages → --affected flag
├─ Skip unnecessary builds → turbo-ignore (references/cli/commands.md)
└─ Skip container setup when no changes → turbo-ignore
`
```

### "I want to watch for changes during development"

```
`Watch mode?
├─ Re-run tasks on change → turbo watch (references/watch/RULE.md)
├─ Dev servers with dependencies → Use `with` key (references/configuration/tasks.md#with)
├─ Restart dev server on dep change → Use `interruptible: true`
└─ Persistent dev tasks → Use `persistent: true`
`
```

### "I need to create/structure a package"

```
`Package creation/structure?
├─ Create an internal package → references/best-practices/packages.md
├─ Repository structure → references/best-practices/structure.md
├─ Dependency management → references/best-practices/dependencies.md
├─ Best practices overview → references/best-practices/RULE.md
├─ JIT vs Compiled packages → references/best-practices/packages.md#compilation-strategies
└─ Sharing code between apps → references/best-practices/RULE.md#package-types
`
```

### "How should I structure my monorepo?"

```
`Monorepo structure?
├─ Standard layout (apps/, packages/) → references/best-practices/RULE.md
├─ Package types (apps vs libraries) → references/best-practices/RULE.md#package-types
├─ Creating internal packages → references/best-practices/packages.md
├─ TypeScript configuration → references/best-practices/structure.md#typescript-configuration
├─ ESLint configuration → references/best-practices/structure.md#eslint-configuration
├─ Dependency management → references/best-practices/dependencies.md
└─ Enforce package boundaries → references/boundaries/RULE.md
`
```

### "I want to enforce architectural boundaries"

```
`Enforce boundaries?
├─ Check for violations → turbo boundaries
├─ Tag packages → references/boundaries/RULE.md#tags
├─ Restrict which packages can import others → references/boundaries/RULE.md#rule-types
└─ Prevent cross-package file imports → references/boundaries/RULE.md
`
```

## Critical Anti-Patterns

### Using `turbo` Shorthand in Code

`turbo run` is recommended in package.json scripts and CI pipelines. The shorthand `turbo <task>` is intended for interactive terminal use.

```
`// WRONG - using shorthand in package.json
{
"scripts": {
"build": "turbo build",
"dev": "turbo dev"
}
}

// CORRECT
{
"scripts": {
"build": "turbo run build",
"dev": "turbo run dev"
}
}
`
```

```
`# WRONG - using shorthand in CI
- run: turbo build --affected

# CORRECT
- run: turbo run build --affected
`
```

### Root Scripts Bypassing Turbo

Root `package.json` scripts MUST delegate to `turbo run`, not run tasks directly.

```
`// WRONG - bypasses turbo entirely
{
"scripts": {
"build": "bun build",
"dev": "bun dev"
}
}

// CORRECT - delegates to turbo
{
"scripts": {
"build": "turbo run build",
"dev": "turbo run dev"
}
}
`
```

### Using `&&` to Chain Turbo Tasks

Don't chain turbo tasks with `&&`. Let turbo orchestrate.

```
`// WRONG - turbo task not using turbo run
{
"scripts": {
"changeset:publish": "bun build && changeset publish"
}
}

// CORRECT
{
"scripts": {
"changeset:publish": "turbo run build && changeset publish"
}
}
`
```

### `prebuild` Scripts That Manually Build Dependencies

Scripts like `prebuild` that manually build other packages bypass Turborepo's dependency graph.

```
`// WRONG - manually building dependencies
{
"scripts": {
"prebuild": "cd ../../packages/types && bun run build && cd ../utils && bun run build",
"build": "next build"
}
}
`
```

However, the fix depends on whether workspace dependencies are declared:

*
If dependencies ARE declared (e.g., `"@repo/types": "workspace:*"` in package.json), remove the `prebuild` script. Turbo's `dependsOn: ["^build"]` handles this automatically.

*
If dependencies are NOT declared, the `prebuild` exists because `^build` won't trigger without a dependency relationship. The fix is to:

* Add the dependency to package.json: `"@repo/types": "workspace:*"`

* Then remove the `prebuild` script

```
`// CORRECT - declare dependency, let turbo handle build order
// package.json
{
"dependencies": {
"@repo/types": "workspace:*",
"@repo/utils": "workspace:*"
},
"scripts": {
"build": "next build"
}
}

// turbo.json
{
"tasks": {
"build": {
"dependsOn": ["^build"]
}
}
}
`
```

Key insight: `^build` only runs build in packages listed as dependencies. No dependency declaration = no automatic build ordering.

### Overly Broad `globalDependencies`

`globalDependencies` affects ALL tasks in ALL packages via the global hash — tasks cannot opt out of specific files, even with negation globs in `inputs`. Be specific.

```
`// WRONG - heavy hammer, affects all hashes
{
"globalDependencies": ["**/.env.*local"]
}

// BETTER - move to task-level inputs
{
"globalDependencies": [".env"],
"tasks": {
"build": {
"inputs": ["$TURBO_DEFAULT$", ".env*"],
"outputs": ["dist/**"]
}
}
}
`
```

With `futureFlags.globalConfiguration`, this problem is reduced because `global.inputs` files are folded into each task's inputs (not the global hash). Tasks can exclude specific files:

```
`// BEST - global.inputs with per-task exclusion
{
"futureFlags": { "globalConfiguration": true },
"global": {
"inputs": [".env"]
},
"tasks": {
"build": { "outputs": ["dist/**"] },
"lint": {
"inputs": ["$TURBO_DEFAULT$", "!$TURBO_ROOT$/.env"]
}
}
}
`
```

### Repetitive Task Configuration

Look for repeated configuration across tasks that can be collapsed. Turborepo supports shared configuration patterns.

```
`// WRONG - repetitive env and inputs across tasks
{
"tasks": {
"build": {
"env": ["API_URL", "DATABASE_URL"],
"inputs": ["$TURBO_DEFAULT$", ".env*"]
},
"test": {
"env": ["API_URL", "DATABASE_URL"],
"inputs": ["$TURBO_DEFAULT$", ".env*"]
},
"dev": {
"env": ["API_URL", "DATABASE_URL"],
"inputs": ["$TURBO_DEFAULT$", ".env*"],
"cache": false,
"persistent": true
}
}
}

// BETTER - use globalEnv and globalDependencies for shared config
{
"globalEnv": ["API_URL", "DATABASE_URL"],
"globalDependencies": [".env*"],
"tasks": {
"build": {},
"test": {},
"dev": {
"cache": false,
"persistent": true
}
}
}
`
```

When to use global vs task-level:

* `globalEnv` / `globalDependencies` - affects ALL tasks, use for truly shared config

* Task-level `env` / `inputs` - use when only specific tasks need it

### NOT an Anti-Pattern: Large `env` Arrays

A large `env` array (even 50+ variables) is not a problem. It usually means the user was thorough about declaring their build's environment dependencies. Do not flag this as an issue.

### Using `--parallel` Flag

The `--parallel` flag bypasses Turborepo's dependency graph. If tasks need parallel execution, configure `dependsOn` correctly instead.

```
`# WRONG - bypasses dependency graph
turbo run lint --parallel

# CORRECT - configure tasks to allow parallel execution
# In turbo.json, set dependsOn appropriately (or use transit nodes)
turbo run lint
`
```

### Package-Specific Task Overrides in Root turbo.json

When multiple packages need different task configurations, use Package Configurations (`turbo.json` in each package) instead of cluttering root `turbo.json` with `package#task` overrides.

```
`// WRONG - root turbo.json with many package-specific overrides
{
"tasks": {
"test": { "dependsOn": ["build"] },
"@repo/web#test": { "outputs": ["coverage/**"] },
"@repo/api#test": { "outputs": ["coverage/**"] },
"@repo/utils#test": { "outputs": [] },
"@repo/cli#test": { "outputs": [] },
"@repo/core#test": { "outputs": [] }
}
}

// CORRECT - use Package Configurations
// Root turbo.json - base config only
{
"tasks": {
"test": { "dependsOn": ["build"] }
}
}

// packages/web/turbo.json - package-specific override
{
"extends": ["//"],
"tasks": {
"test": { "outputs": ["coverage/**"] }
}
}

// packages/api/turbo.json
{
"extends": ["//"],
"tasks": {
"test": { "outputs": ["coverage/**"] }
}
}
`
```

Benefits of Package Configurations:

* Keeps configuration close to the code it affects

* Root turbo.json stays clean and focused on base patterns

* Easier to understand what's special about each package

* Works with `$TURBO_EXTENDS$` to inherit + extend arrays

When to use `package#task` in root:

* Single package needs a unique dependency (e.g., `"deploy": { "dependsOn": ["web#build"] }`)

* Temporary override while migrating

See `references/configuration/RULE.md#package-configurations` for full details.

### Using `../` to Traverse Out of Package in `inputs`

Don't use relative paths like `../` to reference files outside the package. Use `$TURBO_ROOT$` instead.

```
`// WRONG - traversing out of package
{
"tasks": {
"build": {
"inputs": ["$TURBO_DEFAULT$", "../shared-config.json"]
}
}
}

// CORRECT - use $TURBO_ROOT$ for repo root
{
"tasks": {
"build": {
"inputs": ["$TURBO_DEFAULT$", "$TURBO_ROOT$/shared-config.json"]
}
}
}
`
```

### Missing `outputs` for File-Producing Tasks

Before flagging missing `outputs`, check what the task actually produces:

* Read the package's script (e.g., `"build": "tsc"`, `"test": "vitest"`)

* Determine if it writes files to disk or only outputs to stdout

* Only flag if the task produces files that should be cached

```
`// WRONG: build produces files but they're not cached
{
"tasks": {
"build": {
"dependsOn": ["^build"]
}
}
}

// CORRECT: build outputs are cached
{
"tasks": {
"build": {
"dependsOn": ["^build"],
"outputs": ["dist/**"]
}
}
}
`
```

Common outputs by framework:

* Next.js: `[".next/**", "!.next/cache/**", "!.next/dev/**"]`

* Vite/Rollup: `["dist/**"]`

* tsc: `["dist/**"]` or custom `outDir`

TypeScript `--noEmit` can still produce cache files:

When `incremental: true` in tsconfig.json, `tsc --noEmit` writes `.tsbuildinfo` files even without emitting JS. Check the tsconfig before assuming no outputs:

```
`// If tsconfig has incremental: true, tsc --noEmit produces cache files
{
"tasks": {
"typecheck": {
"outputs": ["node_modules/.cache/tsbuildinfo.json"] // or wherever tsBuildInfoFile points
}
}
}
`
```

To determine correct outputs for TypeScript tasks:

* Check if `incremental` or `composite` is enabled in tsconfig

* Check `tsBuildInfoFile` for custom cache location (default: alongside `outDir` or in project root)

* If no incremental mode, `tsc --noEmit` produces no files

### `^build` vs `build` Confusion

```
`{
"tasks": {
// ^build = run build in DEPENDENCIES first (other packages this one imports)
"build": {
"dependsOn": ["^build"]
},
// build (no ^) = run build in SAME PACKAGE first
"test": {
"dependsOn": ["build"]
},
// pkg#task = specific package's task
"deploy": {
"dependsOn": ["web#build"]
}
}
}
`
```

### Environment Variables Not Hashed

```
`// WRONG: API_URL changes won't cause rebuilds
{
"tasks": {
"build": {
"outputs": ["dist/**"]
}
}
}

// CORRECT: API_URL changes invalidate cache
{
"tasks": {
"build": {
"outputs": ["dist/**"],
"env": ["API_URL", "API_KEY"]
}
}
}
`
```

### `.env` Files Not in Inputs

Turbo does NOT load `.env` files - your framework does. But Turbo needs to know about changes:

```
`// WRONG: .env changes don't invalidate cache
{
"tasks": {
"build": {
"env": ["API_URL"]
}
}
}

// CORRECT: .env file changes invalidate cache
{
"tasks": {
"build": {
"env": ["API_URL"],
"inputs": ["$TURBO_DEFAULT$", ".env", ".env.*"]
}
}
}
`
```

### Root `.env` File in Monorepo

A `.env` file at the repo root is an anti-pattern — even for small monorepos or starter templates. It creates implicit coupling between packages and makes it unclear which packages depend on which variables.

```
`// WRONG - root .env affects all packages implicitly
my-monorepo/
├── .env # Which packages use this?
├── apps/
│ ├── web/
│ └── api/
└── packages/

// CORRECT - .env files in packages that need them
my-monorepo/
├── apps/
│ ├── web/
│ │ └── .env # Clear: web needs DATABASE_URL
│ └── api/
│ └── .env # Clear: api needs API_KEY
└── packages/
`
```

Problems with root `.env`:

* Unclear which packages consume which variables

* All packages get all variables (even ones they don't need)

* Cache invalidation is coarse-grained (root .env change invalidates everything)

* Security risk: packages may accidentally access sensitive vars meant for others

* Bad habits start small — starter templates should model correct patterns

If you must share variables, use `globalEnv` to be explicit about what's shared, and document why.

### Strict Mode Filtering CI Variables

By default, Turborepo filters environment variables to only those in `env`/`globalEnv`. CI variables may be missing:

```
`// If CI scripts need GITHUB_TOKEN but it's not in env:
{
"globalPassThroughEnv": ["GITHUB_TOKEN", "CI"],
"tasks": { ... }
}
`
```

Or use `--env-mode=loose` (not recommended for production).

### Shared Code in Apps (Should Be a Package)

```
`// WRONG: Shared code inside an app
apps/
web/
shared/ # This breaks monorepo principles!
utils.ts

// CORRECT: Extract to a package
packages/
utils/
src/utils.ts
`
```

### Accessing Files Across Package Boundaries

```
`// WRONG: Reaching into another package's internals
import { Button } from "../../packages/ui/src/button";

// CORRECT: Install and import properly
import { Button } from "@repo/ui/button";
`
```

### Too Many Root Dependencies

```
`// WRONG: App dependencies in root
{
"dependencies": {
"react": "^18",
"next": "^14"
}
}

// CORRECT: Only repo tools in root
{
"devDependencies": {
"turbo": "latest"
}
}
`
```

## Common Task Configurations

### Standard Build Pipeline

```
`{
"$schema": "https://v2-9-17-canary-3.turborepo.dev/schema.json",
"tasks": {
"build": {
"dependsOn": ["^build"],
"outputs": ["dist/**", ".next/**", "!.next/cache/**", "!.next/dev/**"]
},
"dev": {
"cache": false,
"persistent": true
}
}
}
`
```

Add a `transit` task if you have tasks that need parallel execution with cache invalidation (see below).

### Dev Task with `^dev` Pattern (for `turbo watch`)

A `dev` task with `dependsOn: ["^dev"]` and `persistent: false` in root turbo.json may look unusual but is correct for `turbo watch` workflows:

```
`// Root turbo.json
{
"tasks": {
"dev": {
"dependsOn": ["^dev"],
"cache": false,
"persistent": false // Packages have one-shot dev scripts
}
}
}

// Package turbo.json (apps/web/turbo.json)
{
"extends": ["//"],
"tasks": {
"dev": {
"persistent": true // Apps run long-running dev servers
}
}
}
`
```

Why this works:

* Packages (e.g., `@acme/db`, `@acme/validators`) have `"dev": "tsc"` — one-shot type generation that completes quickly

* Apps override with `persistent: true` for actual dev servers (Next.js, etc.)

* `turbo watch` re-runs the one-shot package `dev` scripts when source files change, keeping types in sync

Intended usage: Run `turbo watch dev` (not `turbo run dev`). Watch mode re-executes one-shot tasks on file changes while keeping persistent tasks running.

Alternative pattern: Use a separate task name like `prepare` or `generate` for one-shot dependency builds to make the intent clearer:

```
`{
"tasks": {
"prepare": {
"dependsOn": ["^prepare"],
"outputs": ["dist/**"]
},
"dev": {
"dependsOn": ["prepare"],
"cache": false,
"persistent": true
}
}
}
`
```

### Transit Nodes for Parallel Tasks with Cache Invalidation

Some tasks can run in parallel (don't need built output from dependencies) but must invalidate cache when dependency source code changes.

The problem with `dependsOn: ["^taskname"]`:

* Forces sequential execution (slow)

The problem with `dependsOn: []` (no dependencies):

* Allows parallel execution (fast)

* But cache is INCORRECT - changing dependency source won't invalidate cache

Transit Nodes solve both:

```
`{
"tasks": {
"transit": { "dependsOn": ["^transit"] },
"my-task": { "dependsOn": ["transit"] }
}
}
`
```

The `transit` task creates dependency relationships without matching any actual script, so tasks run in parallel with correct cache invalidation.

How to identify tasks that need this pattern: Look for tasks that read source files from dependencies but don't need their build outputs.

### With Environment Variables

```
`{
"globalEnv": ["NODE_ENV"],
"globalDependencies": [".env"],
"tasks": {
"build": {
"dependsOn": ["^build"],
"outputs": ["dist/**"],
"env": ["API_URL", "DATABASE_URL"]
}
}
}
`
```

With `futureFlags.globalConfiguration`, the same config moves global settings under `global` — and `.env` becomes a per-task input instead of a global hash input:

```
`{
"futureFlags": { "globalConfiguration": true },
"global": {
"env": ["NODE_ENV"],
"inputs": [".env"]
},
"tasks": {
"build": {
"dependsOn": ["^build"],
"outputs": ["dist/**"],
"env": ["API_URL", "DATABASE_URL"]
}
}
}
`
```

## Reference Index

### Configuration

FilePurposeconfiguration/RULE.mdturbo.json overview, Package Configurationsconfiguration/tasks.mddependsOn, outputs, inputs, env, cache, persistentconfiguration/global-options.mdglobalEnv, globalDependencies, global key, futureFlags, cacheDir, envModeconfiguration/gotchas.mdCommon configuration mistakes

### Caching

FilePurposecaching/RULE.mdHow caching works, hash inputscaching/remote-cache.mdVercel Remote Cache, self-hosted, login/linkcaching/gotchas.mdDebugging cache misses, --summarize, --dry

### Environment Variables

FilePurposeenvironment/RULE.mdenv, globalEnv, passThroughEnvenvironment/modes.mdStrict vs Loose mode, framework inferenceenvironment/gotchas.md.env files, CI issues

### Filtering

FilePurposefiltering/RULE.md--filter syntax overviewfiltering/patterns.mdCommon filter patterns

### CI/CD

FilePurposeci/RULE.mdGeneral CI principlesci/github-actions.mdComplete GitHub Actions setupci/vercel.mdVercel deployment, turbo-ignoreci/patterns.md--affected, caching strategies

### CLI

FilePurposecli/RULE.mdturbo run basicscli/commands.mdturbo run flags, turbo-ignore, other commands

### Best Practices

FilePurposebest-practices/RULE.mdMonorepo best practices overviewbest-practices/structure.mdRepository structure, workspace config, TypeScript/ESLint setupbest-practices/packages.mdCreating internal packages, JIT vs Compiled, exportsbest-practices/dependencies.mdDependency management, installing, version sync

### Watch Mode

FilePurposewatch/RULE.mdturbo watch, interruptible tasks, dev workflows

### Boundaries (Experimental)

FilePurposeboundaries/RULE.mdEnforce package isolation, tag-based dependency rules

## Source Documentation

This skill is based on the official Turborepo documentation at:

* Source: `apps/docs/content/docs/` in the Turborepo repository

* Live: https://turborepo.dev/docs

## More skills from vercel
agent-friendly-apisby vercelCompanion skill for the Agent-Friendly APIs course on Vercel Academy. Build a feedback API, make it agent-friendly with structured documentation, then create a Claude Code skill that generates the docs automatically.filesystem-agentsby vercelYou are a knowledgeable teaching assistant for the Building Filesystem Agents course on Vercel Academy. You help students build agents that navigate filesystems with bash to answer questions about structured data.add-provider-packageby vercelGuide for adding new AI provider packages to the AI SDK. Use when creating a new @ai-sdk/<provider> package to integrate an AI service into the SDK.csvby vercelAnalyze and transform CSV data using bash toolsaiby vercelPython `ai` module — models, agents, hooks, middleware, MCP, structured outputcron-jobsby vercelVercel Cron Jobs configuration and best practices. Use when adding, editing, or debugging scheduled tasks in vercel.json.frontend-designby vercelCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, artifacts,…vercel-react-best-practicesby vercelReact and Next.js performance optimization guidelines from Vercel Engineering. This skill should be used when writing, reviewing, or refactoring React/Next.js…

---

**Source**: https://github.com/vercel/turborepo/tree/HEAD/skills/turborepo
**Author**: vercel
**Discovered via**: mcpservers.org

Related skills 6

caveman

★ Featured

Ultra-compressed communication mode. Cuts token usage ~75% by speaking like caveman while keeping full technical accuracy. Supports intensity levels: lite, full (default), ultra, wenyan-lite, wenyan-full, wenyan-ultra. Use when user says "caveman mode", "talk like caveman", "use caveman", "less tokens", "be brief", or invokes /caveman. Also auto-triggers when token efficiency is requested.

juliusbrussee 167k
Development

secure-linux-web-hosting

★ Featured

Use when setting up, hardening, or reviewing a cloud server for self-hosting, including DNS, SSH, firewalls, Nginx, static-site hosting, reverse-proxying an app, HTTPS with Let's Encrypt or ACME clients, safe HTTP-to-HTTPS redirects, or optional post-launch network tuning such as BBR.

xixu-me 155k
Development

readme-i18n

★ Featured

Use when the user wants to translate a repository README, make a repo multilingual, localize docs, add a language switcher, internationalize the README, or update localized README variants in a GitHub-style repository.

xixu-me 155k
Development

lark-shared

★ Featured

Use when first setting up lark-cli, running auth login, switching user/bot identity (--as), handling permission denied or scope errors, needing to update lark-cli, or seeing _notice in JSON output.

larksuite 155k
Development

improve-codebase-architecture

★ Featured

Find deepening opportunities in a codebase, informed by the domain language in CONTEXT.md and the decisions in docs/adr/. Use when the user wants to improve architecture, find refactoring opportunities, consolidate tightly-coupled modules, or make a codebase more testable and AI-navigable.

mattpocock 151k
Development

paper-context-resolver

★ Featured

Optional RigorPilot helper for README-first deep learning repo reproduction. Use only when the README and repository files leave a narrow reproduction-critical gap and the task is to resolve a specific paper detail such as dataset split, preprocessing, evaluation protocol, checkpoint mapping, or runtime assumption from primary paper sources while recording conflicts. Do not use for general paper summary, repo scanning, environment setup, command execution, title-only paper lookup, or replacin...

lllllllama 127k
Development