Now liveThe Skillselion MCP - thousands of ranked skills, loaded into your agent mid-task. No install.Get it →
acedergren avatar

Turborepo

  • 25 installs
  • 22 repo stars
  • Updated May 28, 2026
  • acedergren/agentic-tools

turborepo is a Claude Code skill for Turborepo monorepo architecture decisions such as monorepo vs polyrepo, package boundaries, and cache-miss debugging.

About

This skill guides Turborepo monorepo architecture decisions: choosing monorepo versus polyrepo, when to split packages, setting package boundaries, avoiding circular dependencies, and debugging cache misses. A developer uses it when structuring or scaling a monorepo, not for basic CLI syntax. It stresses defining tasks per package rather than in the root to enable parallelization.

  • Turborepo monorepo architecture decisions: monorepo vs polyrepo, when to split packages
  • Fixes cache misses and enforces package tasks over root tasks
  • Break-even guidance and package-boundary decision trees

Turborepo by the numbers

  • 25 all-time installs (skills.sh)
  • Ranked #889 of 1,435 DevOps & CI/CD skills by installs in the Skillselion catalog
  • Data as of Jul 28, 2026 (Skillselion catalog sync)
At a glance

turborepo capabilities & compatibility

Capabilities
monorepo architecture · build caching · package boundaries
Use cases
devops · ci cd · refactoring
Pricing
Free
From the docs

What turborepo says it does

**The #1 Turborepo mistake**: Putting task logic in root `package.json`.
SKILL.md
**Break-even**: Monorepo worth it when 3+ apps share 30%+ code AND frequent coordination is required.
SKILL.md
npx skills add https://github.com/acedergren/agentic-tools --skill turborepo

Add your badge

Show developers this skill is listed on Skillselion. Paste this into your README.

Listed on Skillselion
Installs25
repo stars22
Last updatedMay 28, 2026
Repositoryacedergren/agentic-tools

What it does

Decide Turborepo monorepo structure, package boundaries, and fix cache misses.

Who is it for?

Deciding monorepo vs polyrepo, when to split packages, and debugging Turborepo cache misses.

Skip if: Basic Turborepo CLI syntax like turbo run build.

When should I use this skill?

When making Turborepo monorepo architecture decisions or debugging cache misses.

What you get

Package boundaries, task placement, and caching are set so the monorepo parallelizes and caches correctly.

By the numbers

  • 7-row strategic assessment table
  • Break-even rule: 3+ apps sharing 30%+ code

Files

SKILL.mdMarkdownGitHub ↗

Turborepo - Monorepo Architecture Expert

Assumption: You know turbo run build. This covers architectural decisions.

Arguments

  • $ARGUMENTS: Monorepo decision, package boundary, or cache issue to analyze
  • Example: /turborepo why is turbo cache missing in CI
  • Example: /turborepo should packages/ui be split from packages/web-core
  • If empty: ask which Turborepo architecture problem is in scope

---

Before Adopting Turborepo: Strategic Assessment

SignalRecommendation
1-3 engineersPolyrepo — monorepo overhead not worth it
<20% shared codePolyrepo
>50% shared code + frequent coordinationMonorepo compelling
Mixed languages (Go/Python/JS)Nx or polyrepo — Turborepo is JS/TS focused
All builds <5min totalOverhead not justified yet
Breaking changes require 3+ reposMonorepo wins
Services deploy independentlyPolyrepo

Break-even: Monorepo worth it when 3+ apps share 30%+ code AND frequent coordination is required.

---

Critical Rule: Package Tasks, Not Root Tasks

The #1 Turborepo mistake: Putting task logic in root package.json.

// WRONG - defeats parallelization
// Root package.json
{ "scripts": { "build": "cd apps/web && next build && cd ../api && tsc" } }

// CORRECT - each package owns its task
// apps/web/package.json
{ "scripts": { "build": "next build" } }

// Root package.json - ONLY delegates
{ "scripts": { "build": "turbo run build" } }

Why: Turborepo can't parallelize sequential shell commands. Package tasks enable task graph parallelization.

---

Decision: When to Split a Package

Considering splitting code into a package?
│
├─ Used by 1 app only → DON'T split yet
│   └─ Keep in app; wait for second consumer
│      WHY: Premature abstraction, overhead > benefit
│
├─ Used by 2+ apps → MAYBE split
│   ├─ Stable API (rarely changes) → Split
│   ├─ Unstable (changes every sprint) → DON'T split yet
│   └─ Mixed team ownership → DON'T split (use import path)
│      WHY: Shared packages need stable APIs + clear owners
│
├─ Publishing to npm → MUST split
│
└─ CI builds > 10min → Split by stability, not domain
    └─ Stable packages cache; unstable packages always rebuild

Anti-pattern: Creating packages for "clean architecture" with no consumers. Every package adds build, test, and version overhead.

---

Anti-Patterns

❌ #1: Circular Dependencies

Symptom: turbo run build fails with "Could not resolve dependency graph"

packages/ui → packages/utils
packages/utils → packages/ui  // circular

Fix: Extract shared code to a third package (packages/shared).

For indirect cycles (A → B → C → A), use: npx madge --circular --extensions ts,tsx packages/

❌ #2: Overly Granular Packages

Symptom: Every feature touches 5+ packages; 10+ version bumps per sprint; pnpm workspace:* version hell.

Fix: Group by change frequency, not by domain:

packages/ui/            # All components (changes often)
packages/ui-primitives/ # Headless components (stable)
packages/icons/         # Generated SVGs (rarely changes)

Rule: Package boundary = different change frequency. Packages that always change together should be one package.

❌ #3: Missing Task Dependencies

Symptom: Tests pass locally, fail in CI with "Cannot find module './dist/index.js'"

Cause: Tests run before build completes — race condition.

// WRONG - no dependsOn for test
{ "tasks": { "build": { "outputs": ["dist/**"] }, "test": {} } }

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

`^build` = build this package's dependencies first. `build` = build this package first.

❌ #4: Cache Miss Hell

Symptom: Cache never hits; every run rebuilds everything.

Cause: inputs glob too broad — comment changes trigger rebuild.

// WRONG
{ "build": { "inputs": ["src/**"] } }

// CORRECT
{ "build": { "inputs": ["src/**/*.{ts,tsx}", "!src/**/*.test.ts"] } }

Debug:

turbo run build --dry --graph          # Visualize task graph
turbo run build --dry=json | jq '.tasks[] | select(.cache.status == "MISS")'

---

Decision: Monorepo vs Polyrepo

Starting new project?
│
├─ Single team, single product → Polyrepo (simpler)
│
├─ Shared UI library → Monorepo
│   └─ Develop library + test in consumers simultaneously
│
├─ Microservices in different languages → Polyrepo
│   └─ Turborepo is JS/TS focused
│
└─ Multiple teams, shared code, atomic changes needed → Monorepo

Practical advice: Start polyrepo, migrate to monorepo when the cross-repo coordination pain exceeds the tooling cost.

---

Package Boundary Patterns

By stability (recommended):

packages/core/      # Changes quarterly (semantic versioning)
packages/features/  # Changes weekly (workspace protocol)
packages/utils/     # Changes monthly

By consumer:

packages/public-api/  # External consumers — strict versioning
packages/internal/    # Internal apps — workspace protocol OK

By team: Only works if teams rarely share code. Otherwise creates silos.

---

Turborepo vs Alternatives

Prefer TurborepoPrefer NxPrefer Rush
JS/TS monorepoProject graph visualization needed100+ packages
Vercel remote cachingPolyglot (JS + Python + Go)Publishing to npm is primary goal
pnpm/npm workspacesWant opinionated project structurePhantom dependency detection needed

---

Error Recovery

Cache never hits

1. turbo run build --dry=json | jq '.tasks[0].hash' — see current hash 2. Narrow inputs glob to exclude non-code files 3. Fallback: "cache": false in turbo.json temporarily to debug without cache pressure

Circular dependency error

1. turbo run build --dry --graph=graph.html — visualize in browser 2. npx madge --circular --extensions ts,tsx packages/ — for indirect cycles 3. Extract common code to packages/shared

Tests fail in CI but pass locally

1. turbo run test --dry --graph — verify build runs before test 2. Add "dependsOn": ["build"] to test task 3. turbo run test --force — bypass cache to confirm ordering

Overly granular packages causing version hell

1. git log --oneline --since="1 month ago" -- packages/ — count version bumps per package 2. Packages that change together 5+ times → merge them 3. Fallback: use workspace:* to auto-link versions while planning merge

---

When to Load Full Reference

READ `references/cli-options.md` when: encountering 3+ unknown CLI flags, need advanced --filter patterns across 10+ packages, or setting up complex pipeline options.

READ `references/remote-cache-setup.md` when: setting up remote cache for teams, debugging cache auth errors, or configuring self-hosted cache with custom storage.

Do NOT load references for: basic architecture decisions, single cache miss debugging, or monorepo adoption decisions — all covered above.

---

Resources

  • Official Docs: https://turbo.build/repo/docs

Related skills

FAQ

When is a monorepo worth it?

When 3+ apps share 30%+ code and frequent coordination is required; small teams or low shared code favor polyrepo.

What is the #1 Turborepo mistake?

Putting task logic in the root package.json, which defeats parallelization; each package should own its task.

DevOps & CI/CDdeployinfra

This week in AI coding

Five minutes, every Monday - the tools, releases and tactics for developers.

unsubscribe anytime.