Originally published at claudeguide.io/claude-code-monorepo-setup
Claude Code works with monorepos out of the box, but a few configuration choices dramatically improve its effectiveness in Turborepo and Nx workspaces. The core pattern: one root CLAUDE.md defines workspace-wide conventions, each package has its own CLAUDE.md for package-specific context, and parallel Claude Code agents handle cross-package tasks concurrently. Teams using this setup report 50% faster cross-package refactors compared to single-package sequential edits. This guide covers the exact setup for both Turborepo and Nx.
The Core Challenge with Monorepos
Monorepos present three problems for AI assistants:
- Scale: 50+ packages means the full file tree exceeds any context window
-
Context isolation: An agent editing
packages/apishould not accidentally modifypackages/web -
Build awareness: Claude must understand
turbo.jsonorproject.jsonpipelines to suggest valid commands
Claude Code solves these with per-package CLAUDE.md files, worktree isolation, and explicit workspace navigation commands.
Root CLAUDE.md Configuration
Create /CLAUDE.md at the repo root:
# Monorepo Configuration
## Workspace Structure
- `apps/` — deployable applications (web, api, mobile)
- `packages/` — shared libraries (ui, utils, config, types)
- `tooling/` — build config (eslint, tsconfig, jest presets)
## Package Manager
Use `pnpm` (not npm or yarn). Always run commands from the repo root.
## Build System
This repo uses Turborepo. Key commands:
- `pnpm turbo build` — build all packages
- `pnpm turbo build --filter=web` — build only `web` and its deps
- `pnpm turbo test --filter=...api` — test packages that depend on `api`
- `pnpm turbo lint` — lint all packages
## Adding Dependencies
- Workspace package: `pnpm add @repo/ui --filter=web`
- External package: `pnpm add zod --filter=api`
- Never run `npm install` or `yarn add`
## TypeScript
All packages extend `@repo/tsconfig`. Do not modify tsconfig directly in packages.
## Conventions
- New packages: copy `packages/_template/` and update `package.json`
- Shared types go in `packages/types/`, not in individual packages
- Never import across app boundaries (apps/ → apps/ is forbidden)
Per-Package CLAUDE.md Files
Each package gets its own CLAUDE.md that narrows Claude's focus:
packages/ui/CLAUDE.md:
# UI Package
React component library. Components must:
- Be accessible (WCAG 2.1 AA)
- Export TypeScript types
- Have Storybook stories in `src/__stories__/`
- Use Tailwind CSS only — no inline styles
Do not import from other workspace packages except `@repo/types`.
apps/api/CLAUDE.md:
# API Application
Express + Prisma REST API. Rules:
- All routes in `src/routes/`, one file per resource
- Use Zod for request validation
- Database access only through `src/db/` — never direct Prisma calls in routes
- Environment variables must be declared in `src/config.ts`
Build: `pnpm turbo build --filter=api`
Dev: `pnpm turbo dev --filter=api`
Test: `pnpm turbo test --filter=api`
This pattern means when Claude Code runs in apps/api/, it reads both the root CLAUDE.md and apps/api/CLAUDE.md, giving it exactly the right context for that package without noise from unrelated packages.
Turborepo-Specific Setup
For Turborepo monorepos, add these workspace commands to root CLAUDE.md:
## Turborepo Pipeline
Pipeline tasks defined in `turbo.json`:
- `build` — depends on upstream `^build`
- `test` — can run in parallel (no dependencies)
- `lint` — can run in parallel
- `dev` — persistent, run per-package
Filter syntax:
- `--filter=web` — only `web`
- `--filter=...web` — `web` and everything it depends on
- `--filter=web...` — `web` and everything that depends on it
- `--filter=[HEAD^1]` — only packages changed since last commit
Tell Claude to use filters when making targeted changes:
claude "Add a Button component to packages/ui. After implementing, run pnpm turbo build --filter=ui to verify it builds."
Nx-Specific Setup
For Nx monorepos, the equivalent CLAUDE.md section:
## Nx Configuration
Project graph: `nx graph`
Key commands:
- `nx build api` — build the api project
- `nx test ui` — test the ui project
- `nx affected --target=build` — build only affected projects
- `nx run-many --target=lint --all` — lint all projects
Project types defined in `project.json` per package.
Generators: `nx g @nx/react:component Button --project=ui`
Navigating Packages with Claude Code
When asking Claude to work on a specific package, be explicit:
# Work in a specific package context
cd apps/web && claude "Add a new /dashboard route using the existing layout component"
# Cross-package work from root
claude "The Button component in packages/ui has a broken onClick type. Fix it and update all usages in apps/web and apps/mobile."
For large cross-package refactors, use the --add flag to give Claude explicit file scope:
claude --add packages/ui/src/Button.tsx --add apps/web/src/pages/Dashboard.tsx \
"Update Button to accept a loading prop and use it in Dashboard"
Parallel Agents for Cross-Package Tasks
The most powerful monorepo pattern: run parallel Claude Code agents across packages using worktrees. This is covered in depth in the Claude Code Complete Guide.
# Create isolated worktrees for parallel work
git worktree add ../repo-api-work main
git worktree add ../repo-web-work main
# Run agents in parallel (in separate terminals)
cd ../repo-api-work && claude "Add /users/preferences endpoint to apps/api"
cd ../repo-web-work && claude "Add user preferences page to apps/web"
Each worktree has its own working tree but shares git history, preventing conflicts between parallel agents.
Build and Test Automation
Configure Claude Code to verify builds after changes using hooks:
json
// .claude/settings.json
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit",
"hooks": [{
"type": "command",
"command": "pnpm turbo build --filter=$(git diff --name-only HEAD | head -1 | cut -d/ -f1-2) 2
---
## Frequently Asked Questions
### Does Claude Code understand Turborepo's `turbo.json` pipeline?
Not automatically. Add the key pipeline tasks and filter syntax to your root CLAUDE.md. Once documented, Claude uses the correct `--filter` flags and understands build dependencies when you ask it to make changes.
### How do I prevent Claude from modifying the wrong package?
Use per-package CLAUDE.md files with explicit scope boundaries ("Do not import from other workspace packages except X"). Additionally, run `claude` from within the target package directory, not the root, for package-specific tasks.
### Should I use one CLAUDE.md or many?
Both. Root CLAUDE.md defines workspace-wide rules (package manager, build system, conventions). Per-package CLAUDE.md files add package-specific context. Claude Code reads both when working in a subdirectory.
### How do parallel Claude Code agents work in a monorepo?
Use `git worktree add` to create isolated working trees from the same repo. Each worktree can have an independent Claude Code session editing different packages simultaneously without file conflicts.
### Can Claude Code run Turborepo commands automatically?
Yes, via hooks. Configure a `PostToolUse` hook in `.claude/settings.json` to run `pnpm turbo build --filter=<package>` after file edits. Claude sees the build output and can fix errors in the same session.
### What is the biggest mistake teams make with Claude Code in monorepos?
Using a single root-level CLAUDE.md without per-package files. This forces Claude to hold the entire workspace context in mind for every task, leading to cross-package mistakes. Per-package CLAUDE.md files dramatically improve accuracy.
### How do I handle private packages and internal tooling?
Add a `tooling/CLAUDE.md` that describes build config packages. Mark internal-only packages explicitly: "This package is a dev tooling preset — never import it in `apps/` or `packages/`."
## Related Guides
- [Claude Code Complete Guide](/claude-code-complete-guide) — Worktrees, hooks, CLAUDE.md, and parallel agents
- [Claude Agent SDK Guide](/claude-agent-sdk-guide) — Building automated agents for monorepo CI
- [Claude Code for Teams](/claude-code-team-setup) — Team-wide Claude Code configuration







