The first time you run Claude Code on a real monorepo, the context usage chart looks like a Black Friday traffic graph. A single "explain how this feature works" question pulls in 40 files, and you're staring at a 150k-token conversation before Claude has typed a word. Here's how to keep Claude Code useful on a huge codebase without eating through your token budget, or your patience.
Why this matters
Claude Code is a great collaborator on small projects and a great collaborator on big projects if you configure it correctly. Out of the box, it defaults to reading liberally: the file you referenced, its imports, related test files, CLAUDE.md, and whatever else it thinks relevant. That's the right default on a 50-file project and the wrong default on a 50,000-file monorepo.
With the right configuration, scoped attention, targeted rules, aggressive context management, Claude Code stays precise on a monorepo. You get the speed you want without the token bill you don't.
Before you start
You need:
- Claude Code 1.5+ installed and working on a large repo.
- A monorepo you actually work in. The guide makes more sense with a concrete codebase to configure against.
- 30 minutes. Mostly in config files.
Step 1: Understand what Claude reads by default
Run /context in an active session. Claude shows you exactly what's in its current window:
- CLAUDE.md files (root + any parent/subpath).
- Files you've mentioned or Claude has opened.
- Tool definitions.
- The conversation so far.
Look at the line counts. On a monorepo, you'll often see dozens of files loaded from "looking around," many irrelevant to the task. That's the problem to fix.
Step 2: Scope with a monorepo-aware CLAUDE.md
At the repo root, your CLAUDE.md should be small, only truly repo-wide rules. Monorepo context belongs in sub-path CLAUDE.md files:
/CLAUDE.md # Repo-wide conventions, very short
/apps/web/CLAUDE.md # Next.js app conventions
/apps/api/CLAUDE.md # API server conventions
/packages/ui/CLAUDE.md # Shared UI package conventionsClaude walks the directory tree from the file it's editing, reading every CLAUDE.md along the way. So when you're editing in apps/web/, Claude reads apps/web/CLAUDE.md + CLAUDE.md, not apps/api/CLAUDE.md.
This alone cuts CLAUDE.md overhead by 60-70% in a typical monorepo.
Step 3: Configure an ignore list
Claude Code respects a .claudeignore (or equivalent, check your version's name). Use it like .gitignore:
# .claudeignore
node_modules/
dist/
.next/
coverage/
*.lock
*.min.js
pnpm-lock.yaml
# Monorepo apps you're not touching right now
apps/legacy-dashboard/Anything in .claudeignore is invisible to Claude, no reads, no greps, nothing. Scoping to the app you're actually working in is the biggest single token win.
For per-session scoping, some versions let you pass --project-dir apps/web to launch Claude Code already scoped to that sub-app. If available, use it for narrow-scope sessions.
Step 4: Avoid open-ended exploration prompts
Prompts like "give me an overview of this codebase" are monorepo budget-killers. Claude will try to read dozens of files to answer, costing you tokens and rarely producing insight you didn't already have.
Replace with scoped questions:
- "How does
apps/web/src/app/api/checkout/route.tshandle the webhook signature?" - "Find all uses of
useAuth()inapps/web/and list them." - "Summarize the changes in the last 3 commits that touched
packages/ui/."
Specific location + specific question = a small, focused read. Claude answers in a few file reads instead of forty.
Step 5: Use /compact or /clear aggressively
Claude Code has commands to reduce the live context:
/clear, wipes the conversation history, keeping only CLAUDE.md and current task. Use between distinct tasks./compact, asks Claude to summarize the current conversation into a shorter form, replacing the verbose history. Use mid-task when context is getting heavy.
Rule of thumb: if a conversation has 30+ turns of tool use, /compact. If you're starting a new task (different feature, different app), /clear.
Step 6: Scope tool use with rule files
For very large repos, limit what Claude can read via permission rules. In .claude/settings.json (or your version's config path), restrict Read and Glob to paths you're working in:
{
"permissions": {
"allow": {
"Read": ["apps/web/**", "packages/ui/**", "CLAUDE.md"],
"Glob": ["apps/web/**", "packages/ui/**"]
},
"deny": {
"Read": ["apps/legacy-*/**"]
}
}
}Now Claude physically cannot read the parts of the monorepo you're not working in. Safer and cheaper.
Check your Claude Code version's docs for the exact permissions format, it's stabilized but the key names can shift.
Step 7: Cache what's stable
For long sessions in a big repo, the initial context (CLAUDE.md + tool definitions) is stable while the conversation grows. That's a prompt caching opportunity, see How Do I Keep My Claude Prompt Cache Hit Rate High?, though Claude Code handles caching under the hood on supported models. Verify in your session logs that cached reads are happening; if not, update to the latest Claude Code.
Step 8: Build a "starting prompt" that skips orientation
Instead of letting Claude figure out where to start on every task, give it a preamble:
/clear
We're working in apps/web/, a Next.js 16 app. The feature I'm building is the
Stripe webhook handler at apps/web/src/app/api/webhooks/stripe/route.ts. It
currently handles checkout.session.completed; we're adding invoice.paid.
Related files: apps/web/src/lib/stripe.ts (client), apps/web/prisma/schema.prisma
(Subscription model). Start by reading those three files.You've done the orientation Claude would have paid 20 file reads to do. The task proceeds from a small, correct initial context.
Verify it worked
1. Cold-start context is small. Open a fresh Claude Code session, type /context. Line count should be under a few thousand, mostly CLAUDE.md and tool definitions, not app code.
2. Tasks finish with fewer file reads. A medium task that used to take 40 Read tool calls should now take 10-15. Watch the tool-use indicators.
3. Cost per session drops. If you're on API billing, compare a typical session's cost before and after configuration. Target: 50%+ reduction.
Where this breaks
- Ignoring files you actually need. A
.claudeignorethat excludespackages/shared/means Claude can't see your shared utilities, which are probably relevant. Start permissive, tighten as you notice over-reads. - Stale sub-path CLAUDE.md files. Conventions evolve; sub-path CLAUDE.md files get stale fast because nobody looks at them unless they're actively working there. Add a reminder in root CLAUDE.md: "Sub-path CLAUDE.md files exist at X, Y, Z, keep them current."
- Claude hallucinating about code it can't see. When you restrict reads aggressively, Claude sometimes confidently describes code it didn't actually read. Ask "show me the line you're referring to", if Claude can't cite, it was guessing. Widen the scope if this happens often.
- Per-app permissions drift from actual app structure. Adding a new sub-app that isn't in the allowlist means Claude can't see it on day one. Update
.claude/settings.jsonwhen you add apps, same time you update other repo-level configs. - Compact losing important context.
/compactis a summary, not a lossless compression. Details in the compacted portion can disappear. Don't compact right before a precision task; compact after.
What to try next
- How Do I Write a CLAUDE.md That Actually Changes Claude's Behavior?, the foundation of per-sub-path scoping.
- How Do I Keep My Claude Prompt Cache Hit Rate High?, the cost lever that matters most on long Claude Code sessions in big repos.
- How Do I Set Up Claude Code Hooks for Auto-Quality?, quality gates matter more in a big repo where a small mistake can cascade. Hooks run the gates automatically.
Let's talk about your AI + SEO stack
If you'd rather skip the how-to and have it shipped for you, that's what I do. Start a conversation and we'll figure out the fastest path to results.
Let's Talk