Claude Code for Turborepo Monorepo (2026)

Why Claude Code for Turborepo

Turborepo makes JavaScript/TypeScript monorepos fast through intelligent task scheduling and content-aware caching. But configuring it correctly requires understanding the task dependency graph, setting up remote cache for team-wide sharing, configuring package boundaries to prevent import violations, and structuring workspace packages for optimal cache hit rates. Misconfigured pipelines lead to stale caches, unnecessary rebuilds, and CI times worse than without Turborepo.

Claude Code generates turbo.json configurations with correct task dependencies, sets up Vercel Remote Cache or custom S3 backends, and structures workspace packages to maximize cache hit rates across development and CI.

The Workflow

Step 1: Initialize Turborepo Workspace

# Create new monorepo
npx create-turbo@latest my-monorepo
# Or add to existing workspace
cd existing-project
npm install turbo --save-dev

Step 2: Configure Task Pipeline

// turbo.json
{
  "$schema": "https://turbo.build/schema.json",
  "ui": "tui",
  "globalDependencies": [
    "**/.env.*local",
    "tsconfig.base.json"
  ],
  "tasks": {
    "build": {
      "dependsOn": ["^build"],
      "inputs": ["src/**", "tsconfig.json", "package.json"],
      "outputs": ["dist/**", ".next/**"],
      "outputLogs": "new-only"
    },
    "test": {
      "dependsOn": ["build"],
      "inputs": ["src/**", "tests/**", "vitest.config.*"],
      "outputs": ["coverage/**"],
      "outputLogs": "new-only"
    },
    "lint": {
      "dependsOn": ["^build"],
      "inputs": ["src/**", "biome.json", ".eslintrc.*"],
      "outputs": []
    },
    "typecheck": {
      "dependsOn": ["^build"],
      "inputs": ["src/**", "tsconfig.json"],
      "outputs": []
    },
    "dev": {
      "cache": false,
      "persistent": true
    },
    "db:migrate": {
      "cache": false,
      "dependsOn": []
    }
  }
}
// packages/shared-ui/package.json
{
  "name": "@myorg/shared-ui",
  "version": "0.1.0",
  "private": true,
  "main": "./dist/index.js",
  "types": "./dist/index.d.ts",
  "scripts": {
    "build": "tsup src/index.ts --format esm,cjs --dts",
    "test": "vitest run",
    "lint": "biome check src/",
    "typecheck": "tsc --noEmit",
    "dev": "tsup src/index.ts --watch"
  }
}

Step 3: Configure Remote Cache

# Vercel Remote Cache (simplest)
npx turbo login
npx turbo link
# Or custom S3 backend
cat > .turbo/config.json << 'EOF'
{
  "teamId": "myteam",
  "apiUrl": "https://turbo-cache.internal.myorg.com"
}
EOF
# .github/workflows/ci.yml
name: CI
on: [push, pull_request]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 2  # For turbo change detection
      - uses: pnpm/action-setup@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: 'pnpm'
      - run: pnpm install --frozen-lockfile
      # Run only affected packages on PRs
      - name: Build (affected only)
        if: github.event_name == 'pull_request'
        run: turbo build --filter='...[HEAD^1]'
        env:
          TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
          TURBO_TEAM: ${{ secrets.TURBO_TEAM }}
      # Run everything on main
      - name: Build (all)
        if: github.ref == 'refs/heads/main'
        run: turbo build
        env:
          TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
          TURBO_TEAM: ${{ secrets.TURBO_TEAM }}
      - run: turbo test lint typecheck --concurrency=4

Step 4: Verify

# Run full pipeline
turbo build test lint typecheck
# Check what would run (dry run)
turbo build --dry=json | jq '.tasks[] | {package: .package, task: .task, cache: .cache.status}'
# Run only affected packages
turbo build --filter='...[main]'
# Show task dependency graph
turbo build --graph=graph.html

CLAUDE.md for Turborepo Monorepo

# Turborepo Monorepo Standards
## Domain Rules
- Every package must have build, test, lint, typecheck scripts
- Build output must be in dist/ or .next/ (defined in turbo.json outputs)
- Shared packages use tsup for building (ESM + CJS + DTS)
- Internal packages: prefix with @myorg/ namespace
- Never import from another package's src/ - always from dist/
- Remote cache enabled for all team members and CI
- Use --filter for PR builds to reduce CI time
## File Patterns
- turbo.json (root pipeline configuration)
- packages/*/package.json (workspace packages)
- apps/*/package.json (applications)
- pnpm-workspace.yaml (workspace definition)
- .turbo/config.json (remote cache configuration)
## Common Commands
- turbo build (build all packages in dependency order)
- turbo build --filter=@myorg/api (build specific package)
- turbo build --filter='...[main]' (build affected since main)
- turbo build --dry=json (show what would run)
- turbo build --graph=graph.html (visualize task graph)
- turbo prune --scope=@myorg/api --docker (create minimal Docker context)

Common Pitfalls in Turborepo Management

  • Missing inputs causing stale cache: If turbo.json inputs do not include all files that affect the build (e.g., missing .env or config files), Turborepo serves stale cached results. Claude Code audits inputs against actual build dependencies.

  • Circular dependencies between packages: Package A imports from B and B imports from A. Turborepo cannot resolve the build order. Claude Code detects cycles in package.json dependencies and restructures with a shared-types package.

  • Docker builds ignoring cache: turbo prune --docker creates a minimal context, but multi-stage Dockerfiles must install dependencies before copying source for caching to work. Claude Code generates proper multi-stage Dockerfiles.

Frequently Asked Questions

Do I need a paid Anthropic plan to use this?

Claude Code works with any Anthropic API plan, including the free tier. However, the free tier has lower rate limits (requests per minute and tokens per minute) that may slow down multi-step workflows. For professional use, the Build or Scale plan provides higher limits and priority access during peak hours.

How does this affect token usage and cost?

The token cost depends on the size of your prompts and Claude’s responses. Typical development tasks consume 10K-50K tokens per interaction. Using a CLAUDE.md file and skills reduces exploration tokens by 50-80%, which directly lowers costs. Monitor your usage at console.anthropic.com/settings/billing.

Can I customize this for my specific project?

Yes. All Claude Code behavior can be customized through CLAUDE.md (project rules), .claude/settings.json (permissions), and .claude/skills/ (domain knowledge). The most impactful customization is adding your project’s specific patterns, conventions, and common commands to CLAUDE.md so Claude Code follows your standards from the start.

What happens when Claude Code makes a mistake?

Claude Code creates files and edits through standard filesystem operations, so all changes are visible in git diff. If a change is wrong, revert it with git checkout -- <file> for a single file or git stash for all changes. Claude Code does not make irreversible changes unless you explicitly allow destructive commands in settings.json.

Practical Details

When working with Claude Code on this topic, keep these implementation details in mind:

Project Configuration. Your CLAUDE.md should include specific references to how your project handles this area. Include file paths, naming conventions, and any project-specific patterns that differ from defaults. Claude Code reads this file at session start and uses it to guide all operations.

Integration with Existing Tools. Claude Code works alongside your existing development tools rather than replacing them. It respects .gitignore for file visibility, uses your project’s installed dependencies, and follows the build/test scripts defined in package.json (or equivalent). Ensure your toolchain is working correctly before involving Claude Code.

Performance Considerations. For large codebases (10,000+ files), Claude Code’s file scanning can be slow if not properly scoped. Use .claudeignore to exclude generated directories (dist, build, .next, coverage) and dependency directories (node_modules, vendor). This typically reduces scan time by 80-90%.

Version Control Integration. All changes Claude Code makes are regular filesystem operations visible to git. Use git diff after each significant change to review what was modified. For experimental changes, create a branch first with git checkout -b experiment/topic so you can easily discard or keep the results.

Get started → Generate your project setup with our Project Starter.

Estimate tokens → Calculate your usage with our Token Estimator.

Try it: Estimate your monthly spend with our Cost Calculator.

Implementation Details

When working with this in Claude Code, pay attention to these practical details:

Project configuration. Add specific instructions to your CLAUDE.md file describing how your project handles this area. Include file paths, naming conventions, and any patterns that differ from common defaults. Claude Code reads CLAUDE.md at the start of every session and uses it to guide all operations.

Testing the setup. After configuration, verify everything works by running a simple test task. Ask Claude Code to perform a read-only operation first (like listing files or reading a config) before moving to write operations. This confirms that permissions, paths, and tools are all correctly configured.

Monitoring and iteration. Track your results over several sessions. If Claude Code consistently makes the same mistake, the fix is usually a more specific CLAUDE.md instruction. If it makes different mistakes each time, the issue is likely in the project setup or toolchain configuration.

Troubleshooting Checklist

When something does not work as expected, check these items in order:

  1. CLAUDE.md exists at the project root — run ls -la CLAUDE.md to verify
  2. Node.js version is 18+ — run node --version to check
  3. API key is set — run echo $ANTHROPIC_API_KEY | head -c 10 to verify (shows first 10 characters only)
  4. Disk space is available — run df -h . to check
  5. Network can reach the API — run curl -s -o /dev/null -w "%{http_code}" https://api.anthropic.com (should return 401 without auth, meaning the server is reachable)
  6. No conflicting processes — run ps aux | grep claude | grep -v grep to check for stale sessions