Claude Code for Monorepos: A Complete Guide to Managing Large Codebases
Learn how to use Claude Code in monorepos and large codebases. Covers nested CLAUDE.md setup, context management, parallel agents, and workflow automation. 2026 guide.
Claude Code for Monorepos: Managing Large Codebases Without Losing Your Mind
You've got a monorepo with 500,000 lines of code split across 12 packages. Your frontend team uses React, the backend is Node.js with some Go services, and the shared types live in a third package that nobody really owns. You open Claude Code and type your first message — and watch it hallucinate about a package structure that doesn't exist.
This is the monorepo problem. Claude Code is remarkable at single-project development, but large codebases introduce context challenges, cross-package dependency confusion, and workflow complexity that require deliberate setup to solve. This guide covers exactly that setup.
By the end, you'll know how to configure Claude Code to navigate your monorepo reliably, scope context to avoid noise, run parallel agents across packages, and automate the repetitive workflows that eat your day.
Why Monorepos Break Default Claude Code Behavior
Before the solutions, it helps to understand the failure modes.
Context window exhaustion. A fresh Claude Code session in a monorepo consumes 15–25K tokens of baseline context just loading the project structure before you type a single character. In a large codebase, that baseline can hit 40–60K. You burn through your available context before the real work begins. Cross-package confusion. When you ask Claude to add a feature to yourauth package, it might reach into your ui package for patterns — and import the wrong version of a shared component. Without package-level context, Claude treats everything as one flat codebase.
Missing conventions. Every monorepo has conventions that aren't in the code: which packages are internal-only, which are public-facing, how cross-package imports work, which test framework each package uses. If these conventions aren't documented where Claude can see them, it guesses — and gets them wrong.
Slow iteration loops. Making a cross-package change (update the API response type, update the frontend type, update the tests) takes three separate Claude sessions with no shared context. You spend more time explaining context than writing code.
The good news: all of these are solvable. The solution is a combination of CLAUDE.md architecture, context scoping, and parallel agent patterns.
Setting Up a Two-Tier CLAUDE.md Architecture
The single most important configuration change you can make in a monorepo is a nested CLAUDE.md structure. Anthropic's official recommendation is one root-level file plus one file per package — and it makes a significant difference in practice.
Root CLAUDE.md: Global Conventions
Your root CLAUDE.md should cover everything that's always true across the entire repo:
markdown# Monorepo Root
## Repository Structure
- `/packages/api` — Node.js REST API (Express + TypeScript)
- `/packages/ui` — React frontend (Next.js 15)
- `/packages/shared` — Shared types, utilities, constants
- `/packages/worker` — Background job processor (BullMQ)
- `/services/infra` — Terraform configurations (read-only to devs)
## Cross-Package Import Rules
- `ui` can import from `shared` only — never from `api` or `worker`
- `api` can import from `shared` only
- `worker` can import from `shared` and `api/src/models` only
- Circular imports are forbidden and will fail CI
## Shared Conventions
- All packages use TypeScript strict mode
- Testing: Vitest for unit tests, Playwright for E2E (ui only)
- Linting: ESLint + Prettier with shared config in `/config/`
- No `any` types in `shared` package (zero tolerance)
## Working on Cross-Package Changes
When a change affects multiple packages:
1. Update `shared` types first
2. Update API package to match new types
3. Update UI package last
4. Run `pnpm -r build` to verify all packages compilePer-Package CLAUDE.md: Package-Specific Rules
Each package gets its own CLAUDE.md that covers that package's specific stack, patterns, and constraints. Claude automatically walks the directory tree upward and loads every CLAUDE.md it finds — so when you're working in /packages/ui, it loads both the root file and the UI-specific file.
Here's an example for /packages/api/CLAUDE.md:
markdown# API Package
## Stack
- Express 4 on Node.js 20+
- TypeScript 5.4
- Prisma ORM (PostgreSQL via Neon)
- Zod for request validation
- JWT auth via `src/middleware/auth.ts`
## Route Structure
- Routes live in `src/routes/<resource>/`
- Each route file exports a router
- All routes mounted in `src/app.ts`
- Always add Zod schemas before adding routes
## Error Handling
- Use `AppError` class from `src/errors.ts`
- Never throw raw `new Error()` in route handlers
- All async route handlers must be wrapped with `asyncHandler()`
## Database Rules
- Never write raw SQL — always use Prisma client
- Migrations in `prisma/migrations/` — don't edit manually
- Use `prisma.$transaction()` for multi-table writes
## What's Out of Scope Here
- Authentication implementation lives in `src/middleware/auth.ts` — don't refactor
- Email sending via `src/services/email.ts` — uses Resend SDKThis two-tier structure means Claude has precise context when it matters and global context when it needs cross-package awareness.
Context Management: Scoping Claude to the Right Part of Your Codebase
Even with good CLAUDE.md files, context management requires active attention in a large monorepo. These three techniques cut noise significantly.
Open Claude Code From the Package Directory
The simplest technique: instead of opening Claude Code from the repo root, cd into the specific package you're working on first.
bash# Instead of this:
cd /my-monorepo
claude
# Do this:
cd /my-monorepo/packages/api
claudeClaude will still find the root CLAUDE.md by walking up the directory tree, but it won't automatically scan the entire /packages/ui and /packages/worker directories into context. You get global conventions with local focus.
Use /clear Between Package Switches
When you switch from working on api to working on ui, run /clear in Claude Code to reset the context. This prevents API-specific patterns from bleeding into UI-specific suggestions.
The discipline: one session per package. Context is cheaper than confusion.
Write a .claudeignore File
Claude Code respects .claudeignore files (same syntax as .gitignore). Use it to exclude directories that Claude doesn't need:
gitignore# .claudeignore at repo root
node_modules/
dist/
.next/
coverage/
*.log
*.lock
services/infra/
docs/Excluding services/infra/ is particularly useful if that directory contains thousands of Terraform files that are irrelevant to application development. One engineering team reported a 40% reduction in context usage after adding a .claudeignore.
Running Parallel Agents Across Packages
This is where Claude Code's --parallel flag (and Claude Code Ultracode mode) becomes genuinely powerful in monorepos. Instead of working through packages sequentially, you can run agents on multiple packages simultaneously.
The use case: you're updating the User type in your shared package and need to propagate that change to both api and ui.
Sequential Approach (Slow)
Session 1: Update shared/src/types/user.ts
Session 2: Update api/src/models/user.ts and api/src/routes/users/
Session 3: Update ui/src/components/UserProfile.tsx and ui/src/hooks/Wall clock time: sum of all three sessions.
Parallel Approach (Fast)
With Claude Code's parallel agents feature:
bashclaude --parallel \
"In /packages/api: Update all references to User type to include the new `displayName` field added in shared/src/types/user.ts" \
"In /packages/ui: Update UserProfile.tsx and useUser hook to show the new displayName field from the User type"Both agents run simultaneously. Wall clock time equals the slower of the two agents, not their sum. For a three-package change, you save approximately 60% of the time.
The critical requirement: write agent prompts that are self-contained. Don't reference "the change we just made" — each agent starts with its own context. Tell each agent exactly what changed and what it needs to do.
Parallel Testing Across Packages
Running tests is another high-value parallel workload:
bash# Run in separate terminals after a cross-package change
claude "Run all tests in /packages/api and fix any failures caused by the User type change"
claude "Run all tests in /packages/ui and fix any failures caused by the User type change"Each agent independently identifies and fixes failures in its package. This is particularly useful before opening a pull request on a cross-package change.
Automating Monorepo Workflows With Claude Code Skills
CLAUDE.md handles conventions. Skills handle workflows. The distinction matters for maintainability.
A Skill is a repeatable process documented in a markdown file that Claude can execute on command. In a monorepo, skills are most useful for:
- Adding a new API endpoint (schema → route → tests → docs)
- Creating a new package from a template
- Running the full cross-package release checklist
- Adding a new shared utility
Here's an example skill at /packages/api/.claude/skills/add-endpoint.md:
markdown# Add API Endpoint
When asked to add a new endpoint, follow this sequence exactly:
1. **Create Zod schema** in `src/routes/<resource>/schema.ts`
- Request body schema (if POST/PUT)
- Response schema
- Export both
2. **Create route file** in `src/routes/<resource>/index.ts`
- Import schema
- Import asyncHandler from `src/utils/`
- All handlers wrapped with asyncHandler()
- Validate request with schema.parse()
3. **Mount in app.ts**
- Add import at top with other routes
- Add app.use() with correct prefix
4. **Write tests** in `src/routes/<resource>/index.test.ts`
- Happy path test
- Validation error test (400)
- Auth error test (401)
- Use the test helpers from `src/test/helpers.ts`
5. **Verify compilation**: Run `tsc --noEmit` before finishingWith this skill in place, you type Add a POST /users/:id/preferences endpoint and Claude executes the full five-step process without you needing to specify each step. The skill ensures consistency regardless of which developer (or agent) is adding the endpoint.
Advanced: Using LSP for Navigation-Heavy Tasks
For very large codebases — multiple millions of lines — grep-based navigation becomes unreliable. The Language Server Protocol (LSP) integration in Claude Code is the solution.
LSP gives Claude the same "go to definition" and "find all references" capabilities that your editor has. It understands TypeScript types, Go interfaces, and cross-file symbol references in a way that file search can't match.
Enable LSP in your Claude Code configuration:
json// .claude/config.json
{
"lsp": {
"enabled": true,
"servers": {
"typescript": "typescript-language-server --stdio",
"go": "gopls serve"
}
}
}With LSP enabled, when you ask Claude to "find everywhere the UserService is called," it uses actual symbol resolution rather than text search. This eliminates the false positives and missed references that make large-codebase navigation frustrating.
One enterprise engineering team with a 2M+ line TypeScript monorepo reported that enabling LSP was "the single biggest quality improvement" in their Claude Code rollout — primarily because grep was returning hundreds of false positives that Claude was wasting context processing.
Common Mistakes and How to Avoid Them
Mistake: One CLAUDE.md to rule them all. Putting everything in a single root CLAUDE.md creates a bloated file that Claude loads for every session, even when most of it is irrelevant. Use the nested structure. Mistake: Vague cross-package instructions. "Update the UI to match the API change" is not enough for a parallel agent. "In /packages/ui/src/hooks/useUser.ts, update the response type to include the newdisplayName: string field returned from the API" is what actually works.
Mistake: Letting Claude read all packages simultaneously. If you ask Claude to "make this change across the whole repo" from the root directory, it will try to read everything and run out of useful context before it starts writing. Scope your sessions.
Mistake: No .claudeignore. Build artifacts, log files, and infrastructure configs create context noise. Ignoring them is free performance.
Mistake: Not versioning CLAUDE.md. Your CLAUDE.md files are project documentation. They should be in version control, reviewed in PRs, and updated when conventions change. Treat them like your README.md.
Key Takeaways
- Use a two-tier CLAUDE.md structure: root file for global conventions, per-package files for package-specific rules
- Scope Claude Code sessions to the package you're working on — open Claude from the package directory
- Write
.claudeignoreto exclude build artifacts, infrastructure configs, and unrelated directories - Use parallel agents for cross-package changes to cut wall-clock time by 60%+
- Document repeatable workflows as Skills, not in CLAUDE.md
- Enable LSP for codebases where grep-based navigation creates false positives
Next Steps
If you're preparing for the Claude Certified Architect (CCA) exam, monorepo patterns and multi-agent orchestration are covered in the agentic workflows section of the exam. AI for Anything has a complete CCA practice test bank with 200+ questions covering Claude Code, MCP, and agent architecture — the exact topics enterprise teams are hiring for in 2026.
Start with the free sample questions to see where you stand before diving into exam prep.
Ready to Start Practicing?
300+ scenario-based practice questions covering all 5 CCA domains. Detailed explanations for every answer.
Free CCA Study Kit
Get domain cheat sheets, anti-pattern flashcards, and weekly exam tips. No spam, unsubscribe anytime.