Ever used Claude on a giant legacy codebase?
You point Claude at the monorepo, ask it to "find everywhere we handle refunds," and it either burns its whole context window flailing through directories or confidently edits the wrong processPayment (the one in the legacy service nobody's touched since 2021).
The instinct is to blame the model. Wait for the next one. That's the wrong lesson.
Truth is, the bleeding-edge devs are already moving away from conversing at length with Claude Code. You need to be doing this, too.
The thing that actually decides whether Claude is useful in a big codebase isn't the model it's the harness around it. And the harness is something you build.
Claude Code doesn't index your repo. There's no embedding pipeline, no vector store, no "build step" that uploads your code to a server. It explores the way you do: list files, grep, read, follow the reference, repeat. This is agentic search. It’s alright.
Compare that to RAG-based tools that embed your whole codebase and retrieve chunks at query time. At scale, those go stale. The pipeline can't keep up with an active team, so you query the index and get back a function you renamed two weeks ago or a module that was deleted last sprint with zero signal that it's wrong. Agentic search reads the live code every time, so it can't lie to you about what's there.
The catch: agentic search is only as good as its starting context. Ask for a vague pattern across a billion lines and you'll hit the context limit before any work happens. Claude needs to know where to look. That's your job, and it's mostly a setup problem.
The five layers of the harness
Think of these as the scaffolding that turns a raw model into something that knows your codebase:
CLAUDE.mdfiles: context Claude reads automatically every session. Root file for the big picture, subdirectory files for local conventions. Because they load every time, keep them lean. Pointers and gotchas, not an encyclopaedia.Hooks: scripts that fire on events. Everyone uses them as guardrails ("don't do X"), but the real win is self-improvement: a stop hook can reflect on the session and propose
CLAUDE.mdupdates while context is fresh. Lint and format here too. Deterministic beats "please remember to."Skills: packaged expertise that loads only when relevant. A security-review skill activates when Claude assesses vulnerabilities; it doesn't clog every other session. You can even scope a skill to a path, so your payments deploy skill never fires when you're working elsewhere.
MCP servers: connections to the tools Claude can't otherwise reach: internal docs, ticketing, your analytics platform, a custom structured-search endpoint. You can set these up pretty easily and cheaply using AWS Bedrock (I’m not being paid to promote, don’t worry).
Plugins : bundles of the above into one installable package, so a good setup stops being tribal knowledge.
Two more worth knowing: LSP integration gives Claude the same "go to definition / find all references" your IDE has symbol-level precision instead of text pattern-matching. (If you live in a multi-language or C/C++ codebase, this is the single highest-value thing you can wire up.) And subagents (isolated Claude instances with their own context) let you split exploring from editing: one maps the subsystem and writes notes to a file, the main agent edits with the full picture.
Making a big repo legible
Three moves do most of the work:
Keep
CLAUDE.mdlean and layered. Claude walks up the tree and loads everyCLAUDE.mdon the way, so root context is never lost which means you can put detail where it belongs and leave the root as a map.Initialise in subdirectories, not the repo root. Counterintuitive in a monorepo, but scoping Claude to the relevant service is what keeps it fast and on-target. Put per-directory test and lint commands in the local
CLAUDE.mdso it never runs the whole suite to check one change.Cut the noise. Use
.ignorefiles and version-controlledpermissions.denyrules in.claude/settings.jsonto exclude generated files, build artefacts, and vendored code so the whole team gets the same clean view for free.
Why this matters even after the next model ships
Here's the twist: your CLAUDE.md rules have a shelf life. A rule like "break every refactor into single-file changes" might have saved an older model from itself (and actively handicap a newer one that handles coordinated cross-file edits fine). Workarounds for yesterday's limitations become tomorrow's overhead. Plan a config review every few months, and especially whenever performance feels like it plateaued after a model release.
One note if you're not a team of one
If you're rolling this out across an org, the pattern that works is boring but real: someone owns it. The fastest adoptions had one person (or a tiny team) wire up the plugins and conventions before anyone else got access, so day-one felt productive instead of frustrating. Without a designated owner, good setups stay tribal and adoption stalls. A standardised CLAUDE.md hierarchy and a curated plugin marketplace beat a hundred devs each reinventing the same skill.
Try this: Pick the gnarliest service in your repo. Write one lean CLAUDE.md for it: three bullets of "what this is," the test command, and the two gotchas that bite newcomers. Then ask Claude to make a change scoped to that directory and watch how much sharper it lands.

