Claude Code is most effective when it behaves like a senior engineer joining a focused task, not like a crawler reading your entire repository. Large codebases can contain millions of tokens across source files, tests, generated code, lockfiles, docs, snapshots, and build artifacts. If you let the model inspect everything, you pay in latency, cost, and worse answers.
The key is context control. Give Claude Code a narrow problem, a small set of relevant files, and a repeatable workflow for discovering more only when needed.
Start with a Repository Map, Not the Repository
Before asking Claude Code to modify code, generate a compact map of the project. This gives the model architecture-level awareness without loading full files.
# Show top-level structure, excluding noisy directories.
tree -L 3 \
-I 'node_modules|dist|build|coverage|.git|vendor|target|__pycache__'
# Find important entry points.
rg "main\(|createServer|app\.listen|FastAPI|SpringApplication|NextResponse" \
--glob '!node_modules' \
--glob '!dist' \
--glob '!build'
# List recently changed files if the task relates to current work.
git diff --name-only main...HEADThen paste or reference only the output. Ask Claude to infer the likely files to inspect next. This is far cheaper than sending whole directories.
Use a Strong CLAUDE.md File
A project instruction file prevents you from repeatedly explaining conventions. Keep it short, specific, and stable. Do not paste your entire architecture document into it.
# CLAUDE.md
## Project overview
- TypeScript monorepo using pnpm workspaces.
- API lives in apps/api.
- React admin UI lives in apps/admin.
- Shared validation schemas live in packages/schemas.
## Rules
- Prefer small, surgical changes.
- Do not edit generated files.
- Do not run broad formatting across the repo.
- Before modifying code, explain the files you need to inspect.
## Commands
- pnpm test --filter api
- pnpm lint --filter admin
- pnpm typecheckThis file acts like a compact operating manual. It saves tokens across sessions and reduces accidental exploration.
Ask for a Plan Before Reading Files
Do not start with “fix this bug” and let the agent roam. Start with a planning prompt that limits exploration.
claude
# Prompt:
# We need to fix a bug where admin users cannot export invoices.
# Do not edit files yet.
# First, identify the 3-6 files most likely involved.
# Use search commands before opening files.
# Explain why each file is relevant.This forces Claude Code to build a hypothesis. You can approve or correct the target area before it spends tokens on unrelated modules.
Prefer Search Results Over Full Files
Most questions can be answered with symbol searches, call sites, and small snippets. Use ripgrep aggressively.
# Find the export feature by route, label, or permission name.
rg "export.*invoice|invoice.*export|EXPORT_INVOICES|canExport" apps packages
# Show nearby lines only.
rg "EXPORT_INVOICES" apps packages -n -C 3
# Find callers of a function without opening every file.
rg "exportInvoices\(" apps packagesWhen you paste search output, include file paths and line numbers. Claude can then request exact files or ranges. This turns a broad scan into a targeted investigation.
Open File Ranges, Not Whole Files
Large files are token traps. If a file has 1,500 lines, Claude rarely needs all of it. Provide the relevant region plus nearby imports and types.
# Print a focused range from a large file.
sed -n '120,240p' apps/api/src/routes/invoices.ts
# Include imports separately if needed.
sed -n '1,40p' apps/api/src/routes/invoices.tsAsk Claude to state if it needs more context. A disciplined model should request the next smallest useful slice.
Exclude Noise at the Tooling Level
Generated files, dependency folders, lockfiles, and snapshots are expensive distractions. Configure your tools so searches and file listings avoid them by default.
# .rgignore
node_modules/
dist/
build/
coverage/
.next/
target/
vendor/
*.lock
*.snap
*.generated.*
openapi.generated.tsFor monorepos, also exclude unrelated applications. If you are fixing billing in the API, there is usually no reason to search mobile, marketing, or infrastructure folders.
Work in Small Task Loops
Large sessions accumulate stale context. Use short loops: inspect, plan, patch, test, summarize, clear. This keeps the model focused and makes failures easier to debug.
# A token-efficient loop:
# 1. Ask Claude to inspect only named files.
# 2. Ask for a minimal patch.
# 3. Run the narrowest test.
# 4. Paste only failing output.
# 5. Ask for a fix.
pnpm test --filter api -- invoices.export.test.tsIf the conversation becomes long, ask Claude to summarize the current state, then clear the session and restart with the summary.
# Prompt before clearing:
# Summarize the bug, files inspected, decisions made, current diff,
# and the next command to run. Keep it under 200 words.Use Git Diffs as the Source of Truth
When reviewing changes, do not ask Claude to reread modified files from scratch. Give it the diff. Diffs are compact and naturally emphasize what changed.
# Review only your current patch.
git diff -- apps/api/src/routes/invoices.ts packages/schemas/invoice.ts
# Review staged changes before commit.
git diff --cachedA good review prompt is specific: “Check this diff for authorization bypasses and broken type assumptions.” Avoid vague prompts like “Does this look good?”
Create Lightweight Architecture Notes
If Claude repeatedly needs the same context, write a short note instead of re-sending files. Keep these notes close to the code.
# docs/ai/billing-context.md
Billing flow summary:
1. Admin UI calls POST /api/invoices/export.
2. API checks EXPORT_INVOICES permission.
3. API enqueues invoice-export job.
4. Worker writes CSV to object storage.
5. UI polls export status by job id.
Relevant files:
- apps/admin/src/features/invoices/ExportButton.tsx
- apps/api/src/routes/invoices.ts
- apps/api/src/permissions.ts
- apps/worker/src/jobs/invoiceExport.tsThis is not a replacement for code. It is a routing table that helps Claude choose the right code faster.
Patch with Constraints
When it is time to edit, constrain the blast radius. Claude Code should know exactly what it may and may not change.
# Prompt:
# Implement the smallest fix.
# You may edit only:
# - apps/api/src/routes/invoices.ts
# - apps/api/src/permissions.ts
# Add or update one focused test.
# Do not refactor unrelated code.
# Do not rename public APIs.These limits reduce token use and protect the codebase from opportunistic rewrites.
Automate Context Bundles for Repeated Tasks
For common areas, create scripts that print exactly the files and snippets Claude needs. This is useful for teams that often touch the same subsystem.
#!/usr/bin/env python3
"""Print a compact billing context bundle for Claude Code."""
from pathlib import Path
FILES = [
"apps/api/src/routes/invoices.ts",
"apps/api/src/permissions.ts",
"apps/worker/src/jobs/invoiceExport.ts",
]
for name in FILES:
path = Path(name)
print(f"\n--- {name} ---")
# Limit output to keep the bundle small.
lines = path.read_text().splitlines()
for i, line in enumerate(lines[:220], start=1):
print(f"{i:04d}: {line}")Review these scripts periodically. A stale context bundle is worse than no bundle because it gives confident but outdated guidance.
Know When to Stop the Agent
Token burn often starts when the model gets uncertain. If Claude begins opening unrelated files, stop it. Restate the task, provide the latest evidence, and narrow the next step. Human steering is cheaper than autonomous wandering.
Use Claude Code like a precise collaborator: map first, search before reading, read ranges before files, patch narrowly, and reset often. Large codebases become manageable when context is treated as an engineering resource, not an unlimited input stream.