---
title: "Turborepo: review, setup & limitations · Undominated.ai"
canonical: https://undominated.ai/skills/jetbrains-turborepo/
description: "Monorepo build-system discipline for Turborepo: package tasks instead of root tasks, turbo.json task registration, cache outputs and hashing inputs, environment variables as cache keys, --affected runs, CI setup, and tag-based package boundaries."
---

# Turborepo: review, setup & limitations · Undominated.ai

> Monorepo build-system discipline for Turborepo: package tasks instead of root tasks, turbo.json task registration, cache outputs and hashing inputs, environment variables as cache keys, --affected runs, CI setup, and tag-based package boundaries.

[← Explore all skills](/skills/)

LANGUAGES AND TOOLING / JetBrains

# Turborepo

Monorepo build-system discipline for Turborepo: package tasks instead of root tasks, turbo.json task registration, cache outputs and hashing inputs, environment variables as cache keys, --affected runs, CI setup, and tag-based package boundaries.

 [See setup guidance ↓](#setup)[Original source ↗](https://github.com/JetBrains/skills/tree/e0f258b5cfed145015cb3e48da9a97947f7c4ed7/turborepo)

SOURCE REVIEW

 Reviewed 2026-10-13
 Evidence 10 linked sources
 Publisher JetBrains
 Licence [MIT (skill-local, Vercel copyright) ↗](https://github.com/JetBrains/skills/blob/e0f258b5cfed145015cb3e48da9a97947f7c4ed7/turborepo/LICENSE.md)
 Revision e0f258b5cfed
 [Read what was—and wasn’t—checked ↓](#review)

“Turborepo monorepo build system guidance. Triggers on: turbo.json, task pipelines, dependsOn, caching, remote cache, the "turbo" CLI, --filter, --affected, CI optimization, environment variables, internal packages, monorepo structure/best practices, and boundaries.”

 [JetBrains · upstream description ↗](https://github.com/JetBrains/skills/blob/e0f258b5cfed145015cb3e48da9a97947f7c4ed7/turborepo/SKILL.md) Our analysis follows below.

01 / THE REASONING

## Why this made the selection.

 - Leads with the mistake every Turborepo setup makes — task logic in the root package.json — and shows the correct package-scripts plus turbo.json registration as wrong/right code pairs, including why root tasks defeat parallelization.
- Organised as decision trees for the questions agents actually receive (cache not restoring, environment variables missing from the hash, running only changed packages), each routing to one specific reference file.
- Treats environment variables as a hashing concern — strict-mode filtering, the env key, .env files in inputs — and enforces the turbo run versus bare turbo distinction for anything written into code.

### A good fit for

 - Structuring a new JavaScript/TypeScript monorepo with apps/ and packages/ and correct task registration
- Debugging cache misses, missing outputs and environment-variable-induced rebuilds
- Wiring CI to build only affected packages and enforcing package import boundaries with tags

### Weigh up before choosing

 - Pinned to the vendored snapshot of Turborepo 2.8.18-canary.7 (synced 2026-03-16); Turborepo releases quickly and flag or boundaries behaviour may drift from newer versions.
- Vercel-flavoured in places: remote-cache and CI recipes assume Vercel or GitHub Actions.
- The JetBrains mirror is the distribution; updates arrive only when the mirror re-syncs the vendor source.
- The mirror’s metadata.source link (antfu/skills/tree/main/skills/turborepo) is dead: antfu/skills removed its vendored skills on 2026-09-25 (https://github.com/antfu/skills/commit/e98e476e315f068f72d53bd3afb34fdd4d5851c3). The text originates in vercel/turborepo skills/turborepo.
- The JetBrains/skills README disclaims the catalogue as provided for demonstration and educational purposes only and asks you to test each skill before relying on it.
- Vercel Remote Cache outside Vercel needs npx turbo login and npx turbo link locally, and TURBO_TOKEN and TURBO_TEAM in CI (references/caching/remote-cache.md); that path was not exercised.
- The download is the complete skill directory at e0f258b5cfed145015cb3e48da9a97947f7c4ed7: SKILL.md, SYNC.md, command/turborepo.md and the 23 reference files, with the skill-local LICENSE.md.

02 / THE REVIEW RECORD

## What we actually inspected.

Source review has boundaries. A clear record is more useful than a “safe” badge.

### Material inspected

 - turborepo/SKILL.md (JetBrains mirror, 917 lines, read in full)
- turborepo/LICENSE.md
- turborepo/SYNC.md
- turborepo/command/turborepo.md (bundled in the download)
- turborepo/references/ (23 bundled files scanned for commands, fetches and credentials; they document npx tools and placeholder tokens only)
- JetBrains/skills README mirror policy, security scanning and disclaimer
- vercel/turborepo skills/turborepo/SKILL.md at 77190449c8c2595ab05eff2a43d633d3de651c2b (diffed against the mirror)
- antfu/skills skills/turborepo SKILL.md and LICENSE.md at c35a5588a5158b5b404a14fb10469b2b6dc1952b (compared byte for byte)
- antfu/skills commit e98e476e315f068f72d53bd3afb34fdd4d5851c3 (vendored skills removed)

### Our findings

 - The skill directory carries its own MIT LICENSE.md (Vercel, Inc copyright) and a SYNC.md naming the vendored source revision — provenance is explicit rather than implied.
- Anti-patterns are stated as wrong/right code pairs (root scripts bypassing turbo, turbo shorthand written into package.json or CI), not prose warnings.
- The 917-line SKILL.md routes to 23 reference files in nine topic directories (best-practices, boundaries, caching, ci, cli, configuration, environment, filtering, watch) plus command/turborepo.md; the boundaries reference covers tag-based import restriction and is marked experimental.
- The SKILL.md equals vercel/turborepo skills/turborepo/SKILL.md at 77190449c8c2595ab05eff2a43d633d3de651c2b, the SHA SYNC.md names, plus three metadata lines the mirror adds (short-description, author: Anthony Fu, source). antfu/skills vendored the same file byte for byte at c35a5588a5158b5b404a14fb10469b2b6dc1952b, with the LICENSE.md the mirror carries.
- Upstream health: metadata.source points at antfu/skills/tree/main/skills/turborepo, which antfu/skills deleted on 2026-09-25 in commit e98e476e315f068f72d53bd3afb34fdd4d5851c3 (https://github.com/antfu/skills/commit/e98e476e315f068f72d53bd3afb34fdd4d5851c3) ("chore!: remove vendored skills"); the link is dead at antfu/skills HEAD. The text still exists in vercel/turborepo (checked 2026-10-13).
- The cache decision tree sends missing outputs to the outputs key, hash debugging to --summarize or --dry, and environment-caused misses to references/environment/gotchas.md; a root .env file is listed as an anti-pattern.

### Not established by this review

 - No monorepo was created or built with this skill; the rules were read, not executed.
- Cache behaviour and --affected runs were not exercised against a real repository.

The review applies to the material and revision named here. A newer upstream release can change its behavior.

03 / PUT IT TO WORK

## Add a skill to your workflow.

[Upstream setup instructions ↗](https://github.com/vercel-labs/skills/blob/7407f3893ad4dceab546ac002c3ef806e4000c73/README.md)

DOCUMENTED COMMAND

 npx skills add JetBrains/skills/turborepo --skill turborepo Copy command ↗

Run in your terminal to choose your AI tools, project or global scope, and installation method. This short command follows the current upstream version; the review covers the revision shown above.

 Optional: install the reviewed revision

Keeps the original source and installer version where recorded, while leaving your AI tools and installation scope for you to choose.

 npx skills add https://github.com/JetBrains/skills/tree/e0f258b5cfed145015cb3e48da9a97947f7c4ed7/turborepo --skill turborepo Copy reviewed-revision command ↗ - Install the complete skill directory; the references and command docs are the substance.
- Bring the existing turbo.json and package layout, or start from the structure decision tree.
- For manual installation instead, download the complete bundle from https://undominated.ai/resources/skills/jetbrains-turborepo/bundle.zip and extract it into a new directory. It holds SKILL.md and 26 supporting files unchanged at revision e0f258b5, the upstream licence and an attribution file.
- Place the extracted directory in your host's documented skills directory, named turborepo. Keep SKILL.md and the licence together.

### Before you start

 - Node.js/npm for the installer
- An agent that supports the Agent Skills format
- A JavaScript/TypeScript monorepo (existing or planned)

### Compatibility

Agent Skills-compatible coding agents · Turborepo 2.x monorepos · JavaScript/TypeScript package.json and turbo.json files

### Reads turbo.json, package.json and CI files; writes task configuration

 - Read turbo.json, package manifests and CI workflow files
- Write task registrations, package scripts and CI pipeline edits
- Write turbo run into package.json and CI; the SKILL.md reserves the turbo shorthand for one-off terminal commands

### Cost model

MIT-licensed instruction package; builds and any remote-cache usage cost separate infrastructure.

THE COMPLETE REVIEWED DEFINITION

## Read it before you reuse it.

Original source bytes, with attribution. Review the host-specific setup notes above.

 Copy definition ↗ [Download complete resource + licence ↗](/resources/skills/jetbrains-turborepo/bundle.zip)[Raw Markdown ↗](/resources/skills/jetbrains-turborepo/definition.md)
 ---
name: turborepo
description: |
 Turborepo monorepo build system guidance. Triggers on: turbo.json, task pipelines,
 dependsOn, caching, remote cache, the "turbo" CLI, --filter, --affected, CI optimization, environment
 variables, internal packages, monorepo structure/best practices, and boundaries.

 Use when user: configures tasks/workflows/pipelines, creates packages, sets up
 monorepo, shares code between apps, runs changed/affected packages, debugs cache,
 or has apps/packages directories.
metadata:
 short-description: "Structure and optimize Turborepo monorepos"
 author: Anthony Fu
 version: 2.8.18-canary.7
 source: https://github.com/antfu/skills/tree/main/skills/turborepo
---

# 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

**DO NOT create Root Tasks. ALWAYS create package tasks.**

When creating tasks/scripts/pipelines, you MUST:

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

**DO NOT** put task logic in root `package.json`. This defeats Turborepo's parallelization.

```json
// 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" } }
```

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

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

```json
// 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 (rare).

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

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

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

```yaml
# 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.

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

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

```yaml
# 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.

```json
// 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.

```json
// 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.

```json
// 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:**

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

2. **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

```json
// 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. Be specific.

```json
// 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/**"]
 }
 }
}
```

### Repetitive Task Configuration

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

```json
// 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.

```bash
# 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.

```json
// 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.

```json
// 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:**

1. Read the package's script (e.g., `"build": "tsc"`, `"test": "vitest"`)
2. Determine if it writes files to disk or only outputs to stdout
3. Only flag if the task produces files that should be cached

```json
// 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/**"]`
- 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:

```json
// 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:

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

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

```json
{
 "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

```json
// 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:

```json
// 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:

```json
// 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

```typescript
// 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

```json
// 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

```json
{
 "$schema": "https://v2-8-18-canary-7.turborepo.dev/schema.json",
 "tasks": {
 "build": {
 "dependsOn": ["^build"],
 "outputs": ["dist/**", ".next/**", "!.next/cache/**"]
 },
 "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**:

```json
// 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:

```json
{
 "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:**

```json
{
 "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

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

## Reference Index

### Configuration

| File | Purpose |
| ------------------------------------------------------------------------------- | -------------------------------------------------------- |
| [configuration/RULE.md](./references/configuration/RULE.md) | turbo.json overview, Package Configurations |
| [configuration/tasks.md](./references/configuration/tasks.md) | dependsOn, outputs, inputs, env, cache, persistent |
| [configuration/global-options.md](./references/configuration/global-options.md) | globalEnv, globalDependencies, cacheDir, daemon, envMode |
| [configuration/gotchas.md](./references/configuration/gotchas.md) | Common configuration mistakes |

### Caching

| File | Purpose |
| --------------------------------------------------------------- | -------------------------------------------- |
| [caching/RULE.md](./references/caching/RULE.md) | How caching works, hash inputs |
| [caching/remote-cache.md](./references/caching/remote-cache.md) | Vercel Remote Cache, self-hosted, login/link |
| [caching/gotchas.md](./references/caching/gotchas.md) | Debugging cache misses, --summarize, --dry |

### Environment Variables

| File | Purpose |
| ------------------------------------------------------------- | ----------------------------------------- |
| [environment/RULE.md](./references/environment/RULE.md) | env, globalEnv, passThroughEnv |
| [environment/modes.md](./references/environment/modes.md) | Strict vs Loose mode, framework inference |
| [environment/gotchas.md](./references/environment/gotchas.md) | .env files, CI issues |

### Filtering

| File | Purpose |
| ----------------------------------------------------------- | ------------------------ |
| [filtering/RULE.md](./references/filtering/RULE.md) | --filter syntax overview |
| [filtering/patterns.md](./references/filtering/patterns.md) | Common filter patterns |

### CI/CD

| File | Purpose |
| --------------------------------------------------------- | ------------------------------- |
| [ci/RULE.md](./references/ci/RULE.md) | General CI principles |
| [ci/github-actions.md](./references/ci/github-actions.md) | Complete GitHub Actions setup |
| [ci/vercel.md](./references/ci/vercel.md) | Vercel deployment, turbo-ignore |
| [ci/patterns.md](./references/ci/patterns.md) | --affected, caching strategies |

### CLI

| File | Purpose |
| ----------------------------------------------- | --------------------------------------------- |
| [cli/RULE.md](./references/cli/RULE.md) | turbo run basics |
| [cli/commands.md](./references/cli/commands.md) | turbo run flags, turbo-ignore, other commands |

### Best Practices

| File | Purpose |
| ----------------------------------------------------------------------------- | --------------------------------------------------------------- |
| [best-practices/RULE.md](./references/best-practices/RULE.md) | Monorepo best practices overview |
| [best-practices/structure.md](./references/best-practices/structure.md) | Repository structure, workspace config, TypeScript/ESLint setup |
| [best-practices/packages.md](./references/best-practices/packages.md) | Creating internal packages, JIT vs Compiled, exports |
| [best-practices/dependencies.md](./references/best-practices/dependencies.md) | Dependency management, installing, version sync |

### Watch Mode

| File | Purpose |
| ------------------------------------------- | ----------------------------------------------- |
| [watch/RULE.md](./references/watch/RULE.md) | turbo watch, interruptible tasks, dev workflows |

### Boundaries (Experimental)

| File | Purpose |
| ----------------------------------------------------- | ----------------------------------------------------- |
| [boundaries/RULE.md](./references/boundaries/RULE.md) | Enforce 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

The download contains SKILL.md . Extract the whole bundle; the supporting files are required. Inspect the included MANIFEST.json for file hashes.

By **JetBrains**. [Exact upstream source ↗](https://github.com/JetBrains/skills/blob/e0f258b5cfed145015cb3e48da9a97947f7c4ed7/turborepo/SKILL.md) · [Licence](/resources/skills/jetbrains-turborepo/LICENSE.txt) · [Attribution](/resources/skills/jetbrains-turborepo/ATTRIBUTION.txt)

SHA-256 39fcf2d3c9a640a1f23b9a2cc3d72383f0a89e768528fd884294ddf247004595

 Read the applicable licence Copyright (c) 2026 Vercel, Inc

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

04 / FOLLOW THE EVIDENCE

## The source trail.

Our notes are separate from the original resource. Check upstream before adopting a new version.

 - [Skill definition at reviewed revision ↗](https://github.com/JetBrains/skills/blob/e0f258b5cfed145015cb3e48da9a97947f7c4ed7/turborepo/SKILL.md) Checked 2026-10-13 https://github.com/JetBrains/skills/blob/e0f258b5cfed145015cb3e48da9a97947f7c4ed7/turborepo/SKILL.md Supports: summary, upstreamDescription, whySelected, bestFor, limitations, review, access
- [Skill-local license (MIT, Vercel copyright) ↗](https://github.com/JetBrains/skills/blob/e0f258b5cfed145015cb3e48da9a97947f7c4ed7/turborepo/LICENSE.md) Checked 2026-10-13 https://github.com/JetBrains/skills/blob/e0f258b5cfed145015cb3e48da9a97947f7c4ed7/turborepo/LICENSE.md Supports: license
- [Vendor sync record naming the source revision ↗](https://github.com/JetBrains/skills/blob/e0f258b5cfed145015cb3e48da9a97947f7c4ed7/turborepo/SYNC.md) Checked 2026-10-13 https://github.com/JetBrains/skills/blob/e0f258b5cfed145015cb3e48da9a97947f7c4ed7/turborepo/SYNC.md Supports: review, limitations
- [Reference directory listing at reviewed revision (23 documents in nine topic directories) ↗](https://github.com/JetBrains/skills/tree/e0f258b5cfed145015cb3e48da9a97947f7c4ed7/turborepo/references) Checked 2026-10-13 https://github.com/JetBrains/skills/tree/e0f258b5cfed145015cb3e48da9a97947f7c4ed7/turborepo/references Supports: review, whySelected
- [Remote cache reference ↗](https://github.com/JetBrains/skills/blob/e0f258b5cfed145015cb3e48da9a97947f7c4ed7/turborepo/references/caching/remote-cache.md) Checked 2026-10-13 https://github.com/JetBrains/skills/blob/e0f258b5cfed145015cb3e48da9a97947f7c4ed7/turborepo/references/caching/remote-cache.md Supports: limitations, access
- [Mirror policy: JetBrains-filtered, JetBrains-verified snapshot with source links and CI skill scanning ↗](https://github.com/JetBrains/skills/blob/e0f258b5cfed145015cb3e48da9a97947f7c4ed7/README.md) Checked 2026-10-13 https://github.com/JetBrains/skills/blob/e0f258b5cfed145015cb3e48da9a97947f7c4ed7/README.md Supports: review, install, limitations
- [Origin of the text: vercel/turborepo skills/turborepo/SKILL.md at the SYNC.md revision ↗](https://github.com/vercel/turborepo/blob/77190449c8c2595ab05eff2a43d633d3de651c2b/skills/turborepo/SKILL.md) Checked 2026-10-13 https://github.com/vercel/turborepo/blob/77190449c8c2595ab05eff2a43d633d3de651c2b/skills/turborepo/SKILL.md Supports: review, limitations
- [Vendored copy in antfu/skills (SKILL.md and LICENSE.md the mirror carries) ↗](https://github.com/antfu/skills/tree/c35a5588a5158b5b404a14fb10469b2b6dc1952b/skills/turborepo) Checked 2026-10-13 https://github.com/antfu/skills/tree/c35a5588a5158b5b404a14fb10469b2b6dc1952b/skills/turborepo Supports: review, license
- [antfu/skills commit removing its vendored skills, including turborepo ↗](https://github.com/antfu/skills/commit/e98e476e315f068f72d53bd3afb34fdd4d5851c3) Checked 2026-10-13 https://github.com/antfu/skills/commit/e98e476e315f068f72d53bd3afb34fdd4d5851c3 Supports: review, limitations
- [Skills installer source formats and selective installation ↗](https://github.com/vercel-labs/skills/blob/7407f3893ad4dceab546ac002c3ef806e4000c73/README.md) Checked 2026-10-13 https://github.com/vercel-labs/skills/blob/7407f3893ad4dceab546ac002c3ef806e4000c73/README.md Supports: install

KEEP COMPARING

## Other approaches to consider.

Related by category or shared topics. These are alternatives to inspect, not a measured quality order.

 [### .NET Timezone ↗ Resolves .NET timezone work through the right library first — TimeZoneConverter for cross-platform, NodaTime for recurring schedules and strict DST arithmetic — and ships both Windows and IANA identifiers on every answer, seven copy-paste code patterns, and the pitfall list from DateTimeKind.Unspecified to DST transitions that skip or repeat local times.](/skills/github-dotnet-timezone/)[### Ruff Recursive Fix ↗ Enforces Python code quality with scoped Ruff runs: safe fixes first, unsafe fixes second with diff review each pass, then targeted manual remediation under explicit stop criteria.](/skills/github-ruff-recursive-fix/)[### Trail of Bits Modern C++ ↗ Pushes new C++ toward C++20, 23, and 26 idioms and a hardened libc++, and stops when the user requires an older standard or the file is C.](/skills/trailofbits-modern-cpp/)

 [AI Tools ↗](/tools/)[Skills ↗](/skills/)[Agents ↗](/agents/)[MCP Servers ↗](/mcp-servers/)[Workflows ↗](/workflows/)

## Continue your investigation

 - [Choose a toolkit](/tools/)
- [Inspect execution hosts](/agents/)
- [Check tool access](/mcp-servers/)
- [Check project dependencies](/check-repo/)
