Claude Code in a Monorepo: Setup and Best Practices
Monorepos bring their own set of challenges for AI-assisted development. When you have a frontend, backend, worker, and shared libraries all living under one roof, Claude Code needs clear guidance about which package it is working in, what rules apply, and where to run commands. Here is how to set that up properly.
Subdirectory CLAUDE.md files
The root CLAUDE.md covers repo-wide conventions — formatting standards, commit message style, general architecture. But each package in a monorepo often has its own language, framework, test runner, and coding patterns.
Claude Code reads CLAUDE.md files from the directory you are working in and all parent directories. Use this to layer rules:
repo/
CLAUDE.md # repo-wide: git conventions, PR format, shared types
packages/
api/
CLAUDE.md # Python, FastAPI, use pytest, venv in .venv
web/
CLAUDE.md # TypeScript, Next.js, use pnpm, no default exports
worker/
CLAUDE.md # TypeScript, Cloudflare Workers, use wrangler for dev
shared/
CLAUDE.md # Pure TypeScript, no side effects, no runtime deps
Keep each subdirectory CLAUDE.md short and specific. A good package-level file covers: the language and framework, the test command, the build command, which dependency manager to use, and any package-specific rules that differ from the root. Do not repeat what the root file already says.
Scoping Claude's attention to one package
When you start Claude Code from the repo root, it sees everything. That is fine for cross-cutting changes, but most of the time you are working in one package. There are a few ways to keep Claude focused.
Start from the package directory. The simplest approach. Run claude from packages/web/ and Claude naturally scopes its file reads and searches to that subtree. The root CLAUDE.md is still inherited.
Use explicit instructions. If you are in the root, tell Claude up front: "We are working in the packages/api directory. Do not modify files outside of it." This is surprisingly effective. You can also put this in a session-scoped instruction.
Lean on .claudeignore. If certain packages are large and irrelevant to your current task, a .claudeignore file at the root can exclude them from searches and file reads, reducing noise and token usage.
Worktrees for parallel work across packages
Git worktrees let you check out the same repo at multiple paths simultaneously, each on a different branch. This pairs well with Claude Code when you need to work on multiple packages in parallel — say, an API change and the corresponding frontend update — without context bleeding between tasks. You can also use subagents to explore multiple packages simultaneously within a single session.
# From your main checkout
git worktree add ../sitebuilder-api feature/new-endpoint
git worktree add ../sitebuilder-web feature/new-endpoint-ui
Now you can run a Claude Code session in each worktree. Each session gets its own working directory, its own branch, and its own file context. Changes in one do not confuse the other.
This is especially useful when the API contract needs to be finalized before the frontend work begins. You can complete the API changes in one session, push the branch, then start the frontend session with the updated types available.
Clean up worktrees when done:
git worktree remove ../sitebuilder-api
git worktree remove ../sitebuilder-web
Common pitfalls
Claude reads the wrong package's files. This is the most frequent issue. You ask Claude to fix a test in packages/api and it finds a similarly named file in packages/web instead. The fix is scoping — either start Claude from the right directory, or be explicit in your prompt about which package you mean. Include the full relative path when referencing files.
Installing dependencies in the wrong location. In a monorepo with multiple package.json files or mixed languages, Claude might run npm install at the root when it should run pnpm install inside packages/web. Your package-level CLAUDE.md should specify the exact install command and working directory. Something like: "Always run dependency commands from this directory. Use pnpm not npm."
Applying the wrong linting or formatting rules. A Python package and a TypeScript package have different formatters. If Claude runs prettier on a Python file or black on TypeScript, things break. Hooks scoped to file extensions or directories solve this — but the first line of defense is a clear CLAUDE.md that states which tools apply to which files.
Running tests for the wrong package. Similar to the dependency issue. Claude sees npm test in its context and runs it at the root, which might run all tests or none. Each package CLAUDE.md should specify its test command with the correct working directory.
Tips for large monorepos
Keep package-level CLAUDE.md files under 30 lines. Claude reads all applicable CLAUDE.md files on every interaction. In a monorepo with many packages, bloated instruction files eat into your context window fast.
Use .claudeignore aggressively. Build artifacts, generated code, vendored dependencies, and packages you never touch should be ignored. This speeds up file searches and keeps Claude from indexing irrelevant code.
Prefer starting Claude in a subdirectory. The smaller the initial scope, the less likely Claude is to get confused. You can always ask it to look at files outside the current directory when needed.
Pin dependency commands in CLAUDE.md. Do not assume Claude will infer the right package manager. If your web package uses pnpm and your API uses pip, say so explicitly in each package's instructions.
Test in CI, not just locally. Monorepo changes often have cross-package effects. Claude can help you write the code, but make sure your CI pipeline runs affected package tests on every PR. Do not rely on Claude catching every cross-package dependency.
The core principle is straightforward: reduce ambiguity. A monorepo multiplies the number of places where Claude could take a wrong turn. Subdirectory CLAUDE.md files, proper scoping, and explicit instructions eliminate most of that confusion before it starts.