Workspace Layout and Monorepos
How Claude Code reads your project structure. Workspace conventions for mono and multi-package repos that help Claude navigate effectively.
Six packages. Three languages. A shared component library. You launch Claude Code from the root and it has zero idea where anything lives. Every question turns into "what framework is this?" and you spend more time orienting it than building.
Fix is dead simple: tell Claude Code how your workspace is organized.
How Claude Code Discovers Your Project
Claude Code starts from your current working directory. It walks up the directory tree looking for CLAUDE.md files. Run it from foo/bar/ and it loads both foo/bar/CLAUDE.md and foo/CLAUDE.md.
Here's the important bit: subdirectory CLAUDE.md files load on demand. Claude Code only reads them when it actually opens files in that directory. Root CLAUDE.md handles the big picture, package-level files handle specifics, and they get picked up as Claude Code explores.
Single-package repo? One root CLAUDE.md is enough. Monorepo? Scatter them strategically.
Working With Multiple Directories
Sometimes your work spans directories that are not nested. Frontend in one repo, backend in another. Or a shared config directory outside your project root.
--add-dir handles this:
claude --add-dir /path/to/other-projectYou can also add directories mid-session with the /add-dir command:
/add-dir /path/to/shared-configsFor directories you always need, set them permanently in your settings:
{
"additionalDirectories": [
"/path/to/other-project",
"/path/to/shared-configs"
]
}Files in additional directories follow the same permission rules as your main project. One gotcha though: CLAUDE.md files from --add-dir directories are NOT loaded by default. If you need them:
export CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD=1Try it
If you regularly reference files outside your main repo, try this:
claude --add-dir ~/work/shared-utilsAsk something like "compare the error handling in this project's API client with the one in shared-utils." Claude Code can see both without you copying files around.
Monorepo Patterns That Actually Work
A well-structured monorepo gives Claude Code clear boundaries:
monorepo/
CLAUDE.md # Root: overall architecture, CI commands
packages/
frontend/
CLAUDE.md # Frontend: React, Vite, component patterns
.claude/rules/
components.md # Rules for files in components/
backend/
CLAUDE.md # Backend: Node, Express, API conventions
shared/
CLAUDE.md # Shared: types, utilities, constraintsEach CLAUDE.md has package-specific stuff: build commands, test commands, coding conventions, key dependencies. The root covers how packages relate, CI/CD, architecture decisions.
.claude/rules/ is really powerful in monorepos. You scope instructions to specific directories or file types. A rule file in packages/frontend/.claude/rules/ only kicks in when Claude Code touches frontend files. Backend conventions stay out of frontend work.
Excluding Other Teams' Instructions
In a large monorepo, you don't care about the billing team's CLAUDE.md when you're working on the search service. claudeMdExcludes handles this:
{
"claudeMdExcludes": [
"**/billing/CLAUDE.md",
"**/billing/.claude/rules/**",
"**/payments/CLAUDE.md"
]
}Claude Code skips those files entirely. Your context window stays clean, loaded only with instructions relevant to your part of the codebase.
Best Practices
Keep CLAUDE.md files focused. Root describes architecture and how packages connect. Package-level files list build commands, test commands, conventions. Don't repeat information across levels.
Path-specific rules for mixed-language repos. Python services and TypeScript packages in the same monorepo? Put language conventions in .claude/rules/ scoped to those directories. Claude Code picks the right rules based on which files it's touching.
Build commands in every package CLAUDE.md. Probably the single most impactful thing you can do for a monorepo setup. When Claude Code knows packages/frontend uses pnpm run build and packages/backend uses cargo build, it can verify its own changes without asking you.
Don't overload the root CLAUDE.md. Tempting to dump everything in one file. A 500-line root file eats your context window on every single interaction. Keep it under 50 lines. Push details down to package-level files where they load on demand.
settings.local.json for personal preferences. Excludes, additional directories, local overrides. Not committed to the repo, so each developer customizes without stepping on the team's setup.
Key Takeaways
Claude Code walks up from your CWD loading CLAUDE.md files at each level, with subdirectory files loading on demand. Use --add-dir and /add-dir for directories outside your project root (additionalDirectories in settings makes it permanent). For monorepos, keep focused CLAUDE.md files in each package with a short architectural root CLAUDE.md. Use claudeMdExcludes to skip other teams' instructions, and .claude/rules/ to scope conventions to specific directories.
Mastering Claude Code
Lesson 32 of 70