Introduction
Monorepos consolidate multiple packages, applications, and shared libraries into a single repository. Companies like Google, Meta, and Microsoft use monorepos to manage codebases with thousands of developers working across hundreds of interconnected projects. The benefits are substantial: atomic commits across packages, simplified dependency management, and consistent tooling.
Claude Code works exceptionally well with monorepos because it can understand relationships between packages and maintain consistency across the entire codebase. When you refactor a shared utility, Claude sees all the consumers. When you update a type definition, Claude knows which packages need corresponding changes.
However, the scale of monorepos requires thoughtful configuration. Without it, Claude might make changes in the wrong package, apply patterns from one package where they don't belong, or overwhelm its context window with irrelevant code. This guide shows you how to configure Claude Code for effective monorepo development.
Benefits of Claude Code in Monorepos
Monorepos and Claude Code are a powerful combination. Here's why they work so well together.
Shared Context Across Packages
Claude can see your entire codebase in one session. When working on a feature that spans your API, web app, and mobile app, Claude understands how they connect. It can trace data from your backend types through your API layer to your frontend components without switching repositories or losing context.
Cross-Package Awareness for Refactoring
Refactoring in a monorepo is dramatically safer with Claude. Rename a function in a shared library, and Claude identifies every call site across all packages. Change a data model, and Claude updates the consumers. This cross-package awareness prevents the silent breakages that plague multi-repo setups.
Consistent Naming and Patterns
A single CLAUDE.md file can enforce conventions across your entire monorepo. Field naming, error handling patterns, test structure, component architecture, all defined once and applied everywhere. No more drift between packages developed by different team members.
Better Understanding of Dependencies
Claude can read your package manifests and workspace configuration to understand dependency relationships. It knows that @acme/utils is consumed by @acme/web and @acme/api. It can warn you when a change to a shared package might have unintended effects downstream.
The Monorepo Advantage: In a multi-repo setup, Claude would need to be told about cross-repository dependencies. In a monorepo, it discovers them automatically by reading the code and configuration files.
Challenges to Overcome
Monorepos introduce unique challenges for AI-assisted development. Understanding them helps you configure Claude effectively.
Large Context from Many Files
Monorepos can contain thousands of files across dozens of packages. Claude's context window is large but not infinite. Without guidance, Claude might load files from irrelevant packages, wasting context on code that doesn't matter for the current task.
Mixed Concerns
Your monorepo likely contains frontend code, backend code, shared libraries, infrastructure configs, and build tooling. Each domain has different patterns, conventions, and best practices. Claude needs to know which apply where.
Different Conventions per Package
Legacy packages might use older patterns while newer packages follow updated conventions. Your React app uses hooks while an older package still has class components. Your API uses REST while a newer service uses GraphQL. Claude needs to respect these differences rather than homogenizing everything.
Risk of Unintended Cross-Package Changes
When Claude has access to everything, it might "helpfully" modify packages outside your intended scope. You ask for a bug fix in the web app, and Claude also "improves" the shared utilities. This can create unexpected merge conflicts and break other team members' work.
The Scope Problem: Without clear boundaries, Claude treats the entire monorepo as fair game. A simple task in one package can cascade into changes across many packages, each needing review and potentially introducing bugs.
CLAUDE.md for Monorepos
Your root-level CLAUDE.md is the most important configuration file for monorepo development. It gives Claude the map it needs to navigate your workspace effectively.
Document the Workspace Structure
Start your CLAUDE.md with a clear description of your monorepo's organization. List every package with its purpose, ownership, and key characteristics.
# Acme Monorepo
This is a monorepo containing all Acme applications and shared packages.
## Workspace Structure
```
acme/
apps/
web/ # Next.js web application (React, TypeScript)
mobile/ # React Native mobile app (Expo)
api/ # Node.js API server (Express, TypeScript)
admin/ # Internal admin dashboard (React)
packages/
ui/ # Shared React component library
utils/ # Shared utility functions
types/ # Shared TypeScript type definitions
config/ # Shared configuration (ESLint, TypeScript, etc.)
infrastructure/
terraform/ # AWS infrastructure as code
docker/ # Docker configurations
```
## Package Dependencies
- `apps/*` depend on `packages/*`
- `packages/ui` depends on `packages/utils` and `packages/types`
- `packages/utils` has no internal dependencies
- `packages/types` has no internal dependencies (source of truth)
## Conventions
- All packages use TypeScript with strict mode
- Shared code goes in `packages/`, never copied between apps
- Types are defined in `packages/types` and imported everywhere
Define Shared Conventions
Document the patterns and conventions that apply across all packages. These are the rules Claude should follow regardless of which package it's working in.
## Naming Conventions
- File names: kebab-case (user-service.ts, not UserService.ts)
- React components: PascalCase (UserProfile.tsx)
- Functions: camelCase (getUserById)
- Constants: SCREAMING_SNAKE_CASE (MAX_RETRY_COUNT)
- Database fields: snake_case (created_at)
- API fields: camelCase (createdAt)
## Error Handling
All packages use the shared Result type from @acme/types:
```typescript
type Result<T, E = Error> = { ok: true; value: T } | { ok: false; error: E };
```
Never throw exceptions for expected errors. Use Result types.
## Testing
- Unit tests: Jest, colocated with source (*.test.ts)
- Integration tests: In __tests__/ directory
- E2E tests: In apps/*/e2e/ directories
Specify Package Interactions
Help Claude understand how packages communicate and depend on each other. This prevents changes that would break the dependency graph.
## Package Interaction Rules
1. Apps never import directly from other apps
2. Packages never import from apps
3. Changes to `packages/types` require updating all consumers
4. `packages/ui` exports are re-exported through `packages/ui/index.ts`
5. Internal package code uses relative imports; cross-package uses aliases
## API Contracts
The API at `apps/api` serves both web and mobile apps.
Contract changes require coordinated updates:
1. Update types in `packages/types`
2. Update API in `apps/api`
3. Update web in `apps/web`
4. Update mobile in `apps/mobile`
Never change API contracts without updating all consumers.
Tip: Include a "How to Add a New Package" section in your CLAUDE.md. This helps Claude assist with creating new packages that follow your established patterns.
Package-Level Configurations
Sometimes a package needs rules that differ from or extend the root CLAUDE.md. Package-level configuration files handle this.
When to Use Package-Level CLAUDE.md
Add a CLAUDE.md to a package when it has unique requirements that don't apply to other packages. Common scenarios include legacy packages with different conventions, packages with specific security requirements, or experimental packages trying new patterns.
Package-Level Configuration Example
Here's an example for an API package with specific requirements.
# API Package Configuration
This package contains the Acme REST API server.
## Package-Specific Rules
- All routes must validate input using Zod schemas
- Database queries go through repository classes, never direct calls
- Authentication middleware required on all routes except /health
- Response format: { data: T } for success, { error: string } for failure
## Directory Structure
```
apps/api/
src/
routes/ # Express route handlers
services/ # Business logic
repositories/ # Database access
middleware/ # Express middleware
validators/ # Zod schemas
types/ # API-specific types (extends @acme/types)
```
## Testing Requirements
- Every route needs integration tests
- Mock external services, never call them in tests
- Use the test database, not production
## Do Not
- Import from other apps (web, mobile, admin)
- Add new dependencies without checking bundle size
- Expose internal error messages to clients
Inheritance and Override Rules
Root-level CLAUDE.md applies everywhere. Package-level CLAUDE.md adds specificity but shouldn't contradict root conventions. Think of it as CSS specificity: more specific rules win, but base rules still apply.
Keep Package Configs Minimal: If you find yourself writing extensive package-level configurations, consider whether those conventions should be elevated to the root CLAUDE.md. Package configs work best when they document exceptions, not entire systems.
Selective Package Focus
Most tasks don't require the entire monorepo. Focusing Claude on specific packages improves performance and prevents unintended changes.
Explicit Path References
When starting a task, tell Claude exactly which packages are in scope. Be specific about paths.
# Good: Specific scope
"Add a date picker component to apps/web. Use the DateInput
from packages/ui. Don't modify packages/ui itself."
# Good: Clear boundaries
"Fix the authentication bug in apps/api/src/middleware/auth.ts.
This change should only affect the API package."
# Bad: Vague scope
"Add date picking functionality"
# Claude might add it to multiple packages
# Bad: No boundaries
"Improve the authentication"
# Claude might modify shared types, API, web, and mobile
Session Start Protocol
Begin sessions by establishing context. Tell Claude which packages you're working in and which are off-limits.
User: "Today I'm working on the mobile app. Focus on apps/mobile
and packages/ui. Don't modify apps/web or apps/api unless I
explicitly ask."
Claude: "Understood. I'll focus on:
- apps/mobile (primary)
- packages/ui (for shared components)
I'll avoid modifying apps/web, apps/api, and other packages
unless you explicitly expand the scope."
Workspace-Aware Commands
Most monorepo tools support workspace-scoped commands. Use these in your instructions to Claude.
# Run tests for a specific package
pnpm --filter @acme/web test
# Build only affected packages
turbo build --filter=@acme/api...
# Lint a specific workspace
yarn workspace @acme/mobile lint
# Add dependency to specific package
npm install lodash -w packages/utils
Pro Tip: Create package-scoped aliases in your root CLAUDE.md. Instead of typing full paths, define shortcuts like "web = apps/web" that Claude recognizes.
Cross-Package Changes
Some features genuinely span multiple packages. Coordinating these changes requires careful planning.
Plan the Order
When changes span packages, sequence matters. Generally, update packages in dependency order: shared packages first, then consumers.
Feature: Add user preferences to all apps
Sequence:
1. packages/types - Add UserPreferences type
2. packages/utils - Add preference validation helpers
3. apps/api - Add preferences endpoints
4. packages/ui - Add PreferencesForm component
5. apps/web - Integrate preferences page
6. apps/mobile - Integrate preferences screen
7. apps/admin - Add preferences management
Each step should be complete and tested before proceeding.
Don't parallelize steps with dependencies between them.
Validate at Each Step
After changing a shared package, verify that consumers still build and their tests pass. Catch integration issues early.
After modifying packages/types:
1. Build packages/types
pnpm --filter @acme/types build
2. Type-check all consumers
pnpm --filter "@acme/*" typecheck
3. Run affected tests
turbo test --filter=@acme/types...
4. If anything fails, fix before proceeding
Don't stack changes across multiple packages without validation.
Document Dependencies in ECOSYSTEM.md
For complex cross-package features, document the relationships in your ECOSYSTEM.md file. This gives Claude and your team a reference for coordination.
## Feature: User Preferences
### Affected Packages
| Package | Changes | Status |
|---------|---------|--------|
| @acme/types | UserPreferences interface | Complete |
| @acme/api | /preferences endpoints | In Progress |
| @acme/web | PreferencesPage component | Pending |
| @acme/mobile | PreferencesScreen | Pending |
### Data Flow
```
Mobile/Web -> API -> Database
^ |
| v
+--- packages/types (shared types)
```
### Breaking Changes
None. New fields are optional with defaults.
Warning: Cross-package changes are the riskiest work in a monorepo. Always create a new branch, make incremental commits, and get code review on each package before merging. Claude can help coordinate, but humans should review cross-package changes carefully.
Tools and Patterns
Different monorepo tools have different conventions. Claude can read their configuration files to understand your workspace structure automatically.
Nx
Nx workspaces use project.json files and nx.json for configuration. Claude can read these to understand build targets, dependencies, and affected projects.
# Claude can read nx.json to understand:
- Project graph and dependencies
- Cacheable operations
- Default task configurations
# Useful Nx commands for Claude:
nx affected:build # Build only changed packages
nx graph # Visualize dependencies
nx run web:serve # Run specific target
Turborepo
Turborepo uses turbo.json for pipeline configuration. Claude can understand task dependencies and caching from this file.
# Claude can read turbo.json to understand:
- Build pipelines and dependencies
- Which tasks are cacheable
- Output directories
# Useful Turborepo commands for Claude:
turbo build --filter=@acme/web... # Build web and deps
turbo test --affected # Test changed packages
pnpm Workspaces
pnpm uses pnpm-workspace.yaml to define workspace packages. Claude reads this to understand package locations.
# pnpm-workspace.yaml
packages:
- 'apps/*'
- 'packages/*'
# Claude can use pnpm workspace commands:
pnpm --filter @acme/web add lodash # Add to specific package
pnpm -r build # Build all packages
pnpm --filter "...@acme/types" test # Test types and dependents
Yarn Workspaces and Lerna
Yarn workspaces are defined in the root package.json. Lerna adds versioning and publishing capabilities with lerna.json.
# Claude reads package.json workspaces field:
{
"workspaces": ["apps/*", "packages/*"]
}
# And lerna.json for versioning:
{
"version": "independent",
"packages": ["apps/*", "packages/*"]
}
# Useful commands:
yarn workspace @acme/web add lodash
lerna changed # See changed packages
lerna run build # Build all packages
Tip: Add a "Monorepo Tools" section to your CLAUDE.md listing which tools you use and their key commands. Claude will reference this when suggesting operations.
Conclusion
Claude Code and monorepos are a powerful combination when configured properly. The key is giving Claude the map it needs to navigate your workspace while setting clear boundaries to prevent unintended changes.
Start with a comprehensive root CLAUDE.md that documents your workspace structure, lists all packages with their purposes, defines shared conventions, and explains how packages interact. Add package-level configuration files only when a package has genuine exceptions to the root conventions.
When working, be explicit about scope. Tell Claude which packages are in play for the current task and which are off-limits. For cross-package changes, plan the sequence carefully, validate at each step, and document the coordination in your ECOSYSTEM.md.
Your monorepo tools are your friends. Nx, Turborepo, pnpm workspaces, and Lerna all have conventions that Claude can understand. Point Claude at your configuration files and it will respect your workspace boundaries automatically.
With the right configuration, Claude becomes a productivity multiplier in monorepos. It sees the connections between packages that humans might miss, maintains consistency across the codebase, and coordinates complex changes that span multiple applications. That's the promise of AI-assisted monorepo development, and it's within reach with thoughtful configuration.
Ready for Monorepo-Scale Development?
Claude Architect includes monorepo-optimized templates, workspace configuration generators, and validation tools that keep your packages consistent.
Join the Waitlist