Why Claude Code Is a Perfect Fit for Monorepo Development
Modern software teams increasingly manage multiple packages and applications within a single repository — the monorepo pattern. Tools like Turborepo, pnpm Workspaces, and Nx provide the foundation, but they come with real challenges: managing cross-package dependencies, sharing type definitions, and maintaining consistent coding standards across dozens of packages.
Claude Code excels in monorepo environments because it can reason about an entire repository's context while making changes. Instead of manually tracking which packages are affected by a shared library update, you can let Claude Code handle the ripple effects. This article walks through practical techniques for using Claude Code with Turborepo and pnpm Workspaces.
Prerequisites and Environment Setup
Before diving in, make sure you have the following ready:
- Node.js 20+ installed
- pnpm installed globally (
npm install -g pnpm) - Claude Code updated to the latest version (
npm update -g @anthropic-ai/claude-code) - Basic familiarity with Git operations
If you don't have a monorepo project yet, Turborepo's official starter gets you up and running quickly.
# Create a new Turborepo + pnpm monorepo
pnpm dlx create-turbo@latest my-monorepo
cd my-monorepo
# Check the structure
ls -la packages/ apps/
# Expected output:
# packages/ui — Shared UI component library
# packages/config — Shared ESLint / TypeScript config
# apps/web — Next.js frontend
# apps/docs — Documentation siteDesigning CLAUDE.md for Monorepos
When using Claude Code in a monorepo, your CLAUDE.md placement strategy is the single most important factor for success. Claude Code automatically reads CLAUDE.md files from the current directory and all parent directories, so you can leverage the hierarchy to layer context intelligently.
Root CLAUDE.md — Project-Wide Rules
# My Monorepo — CLAUDE.md
## Project Structure
- Monorepo managed with Turborepo + pnpm Workspaces
- apps/ contains applications, packages/ contains shared libraries
## Universal Rules
- TypeScript strict mode required
- Formatting with ESLint + Prettier
- Testing with Vitest
- Commit messages follow Conventional Commits
## Package Dependencies
- Shared UI imports from @repo/ui
- Configurations reference @repo/config
- Circular dependencies are strictly prohibited
## Common Commands
- pnpm dev — Start all apps in parallel
- pnpm build — Build in dependency order via Turborepo
- pnpm test — Run tests across all packages
- pnpm lint — Lint all packagesPer-Package CLAUDE.md — Scoped Context
# packages/ui — CLAUDE.md
## Purpose
- Shared UI component library used across all apps
- Built on Radix UI primitives + Tailwind CSS
## Component Guidelines
- One component per file in src/components/
- Always re-export through index.ts
- Include Storybook story files alongside components
- Add JSDoc comments to all Props interfacesThis hierarchical approach means Claude Code automatically picks up the right context based on where you're working. Running Claude Code from apps/web/ loads both the root-level shared rules and any web-app-specific instructions, while working in packages/ui/ surfaces the UI library conventions instead.
Cross-Package Refactoring
The most time-consuming task in monorepo development is propagating shared package changes across all consuming applications. Claude Code's subagent capabilities and worktree support make this dramatically more efficient.
Example: Updating a Shared Component API Across the Entire Repo
Imagine you need to add a variant prop to the Button component in @repo/ui and update every usage across all apps.
# Give Claude Code a monorepo-aware instruction
claude "Add a variant prop ('primary' | 'secondary' | 'danger')
to the Button component in packages/ui.
Then find all Button usages under apps/ and set the
appropriate variant for each one based on context.
After all changes, verify with pnpm build && pnpm test
that everything passes."Claude Code will automatically work through this in sequence:
- Update the type definitions and implementation in
packages/ui/src/components/Button.tsx - Use
grepandGlobto find everyButtonimport acrossapps/ - Analyze the context of each usage to infer the appropriate
variantvalue - Run
pnpm buildto execute Turborepo's build pipeline and catch any type errors - Run
pnpm testto verify no regressions were introduced
Safe Refactoring with Worktrees
For large-scale changes, worktrees let you work in isolation without disrupting your main branch.
# Use a worktree for isolated refactoring
claude "Create a new branch using /worktree and
refactor the Button component in packages/ui.
Keep the main branch untouched while you work."Worktrees give you a separate file system state, so your main branch stays clean while you experiment. Once you're satisfied with the changes, you can create a PR directly from the worktree branch.
Leveraging Turborepo's Task Dependencies
Turborepo's greatest strength is its ability to run builds and tests in parallel while respecting package dependency order. Teaching Claude Code about this system leads to smarter suggestions and fewer build failures.
Include turbo.json Context in CLAUDE.md
## Turborepo Task Dependencies
Key tasks from turbo.json:
- build: dependsOn ["^build"] — Dependent packages build first
- test: dependsOn ["build"] — Tests run after build completes
- lint: No dependencies — Runs in parallel
- dev: cache: false, persistent: trueWith this context, Claude Code understands that changing packages/ui will trigger rebuilds in apps/web and can plan its work accordingly.
A Practical turbo.json Configuration
{
"$schema": "https://turbo.build/schema.json",
"globalDependencies": ["**/.env.*local"],
"tasks": {
"build": {
"dependsOn": ["^build"],
"outputs": [".next/**", "!.next/cache/**", "dist/**"]
},
"test": {
"dependsOn": ["build"]
},
"lint": {},
"dev": {
"cache": false,
"persistent": true
},
"type-check": {
"dependsOn": ["^build"]
}
}
}
// Expected behavior:
// pnpm build → packages/config → packages/ui → apps/web, apps/docs (in order)
// pnpm lint → All packages run linting in parallelAdding and Managing Dependencies
When adding new dependencies in a monorepo, it's critical to tell Claude Code the correct scope. Installing a package at the root when it should be scoped to a specific app is a common mistake.
# Add a dependency to a specific app
claude "Add react-hook-form to apps/web and implement
a contact form. Make sure the pnpm add command
is scoped to the apps/web package."Claude Code will correctly scope the installation:
# Command Claude Code executes
cd apps/web
pnpm add react-hook-form
# Or using pnpm's filter syntax
pnpm --filter web add react-hook-formSetting Up Internal Package Dependencies
When one package needs to reference another, use pnpm's workspace:* protocol.
# Add an internal dependency
claude "Add @repo/ui as a workspace dependency
in apps/web's package.json.
Use pnpm's workspace:* protocol."{
"name": "web",
"dependencies": {
"@repo/ui": "workspace:*",
"next": "^16.0.0",
"react": "^19.0.0"
}
}Scaffolding New Packages
Adding a new shared package to a monorepo involves creating directories, configuring package.json, TypeScript settings, and build tooling — all while maintaining consistency with existing packages. Claude Code handles this in a single prompt.
claude "Add a new shared utility package called @repo/utils
under packages/. Requirements:
- TypeScript + Vitest for testing
- tsup for bundling (ESM + CJS output)
- Implement at least 3 utility functions for date formatting,
string manipulation, and validation
- Write unit tests for each function
- Configure it so packages/ui and apps/web can import from it
- Verify pnpm build && pnpm test pass"Claude Code generates a complete package structure:
packages/utils/
├── package.json # name: @repo/utils, tsup config
├── tsconfig.json # Extends shared TSConfig
├── tsup.config.ts # ESM + CJS build config
├── src/
│ ├── index.ts # Re-exports
│ ├── date.ts # Date formatting utilities
│ ├── string.ts # String manipulation utilities
│ └── validation.ts # Validation utilities
├── tests/
│ ├── date.test.ts
│ ├── string.test.ts
│ └── validation.test.ts
└── CLAUDE.md # Package-specific context
Common Pitfalls and Solutions
Here are the most frequent issues you'll encounter when using Claude Code with monorepos, along with proven fixes.
pnpm Hoisting Issues
Dependency hoisting is a common source of "module not found" errors in monorepos.
# Control hoisting in .npmrc
shamefully-hoist=true
# Or hoist specific packages only
public-hoist-pattern[]=@prisma/*Documenting your .npmrc settings in CLAUDE.md helps Claude Code suggest the right fix when dependency resolution goes wrong.
TypeScript Path Resolution Errors
Cross-package TypeScript imports can fail if path mappings aren't configured correctly.
{
"compilerOptions": {
"paths": {
"@repo/ui": ["../../packages/ui/src"],
"@repo/utils": ["../../packages/utils/src"]
}
}
}
// Add this to each apps/*/tsconfig.json to enable
// proper type resolution in both your editor and Claude CodeStale Turborepo Cache
When changes don't seem to take effect after a build, the cache might be the culprit.
# Clear the Turborepo cache
pnpm turbo clean
# Or force-rebuild a specific task
pnpm turbo build --forceWrapping Up
Claude Code and monorepo development are a powerful combination. By structuring your CLAUDE.md files hierarchically, documenting task dependencies, and leveraging Claude Code's ability to reason across packages, you can dramatically reduce the overhead of cross-package refactoring, dependency management, and new package scaffolding.
Here's a quick recap of the key strategies:
- Layer your CLAUDE.md files — root for shared rules, per-package for scoped context
- Document Turborepo task dependencies so Claude Code understands build order
- Use holistic prompts for cross-package refactoring — let Claude Code see the full picture
- Leverage worktrees for safe, isolated large-scale changes
- Include pnpm filter syntax in CLAUDE.md for correctly scoped operations
Start by creating a CLAUDE.md at the root of your existing monorepo. Even that single step will noticeably improve the quality of Claude Code's suggestions.
For more on getting started with Claude Code, check out the [Claude Code Setup Guide]((/articles/claude-code/setup-guide). To learn about worktrees in depth, see the [Claude Code Worktree Guide]((/articles/claude-code/worktree). And for parallel subagent execution, take a look at [Claude Code Subagent Parallel Execution]((/articles/claude-code/subagent-parallel).