DEV Community

Cover image for How to Understand a Codebase You Didn't Write
John Nickell
John Nickell

Posted on

How to Understand a Codebase You Didn't Write

Think about how you find one word in a dictionary. You don't start at A and read every page. You open to the middle, decide which half your word's in, and throw the other half away. Then again, and again, until you're standing on top of it.

Now apply that to an unfamiliar codebase. That's the whole idea, and it turns "I have no clue where to start" into about four good questions.

The Advice Everyone Gives, and Why It's Wrong

"Read the whole codebase before you touch anything." I've given that advice and I've taken it, and I think it's wrong.

The intent behind it is fine. Nobody wants a new hire blundering into a critical path with zero context. But "read everything" isn't a method. It's a gesture. There are codebases I've worked in north of 200,000 lines. If I tried to read them front to back before touching anything, I'd still be reading.

What the advice produces instead is a specific kind of shallow familiarity. You've seen most of the files. You couldn't explain what any single module does. That's not understanding. That's having scrolled.

The Dictionary Trick

The method is the same bisection you'd use to find a word: ask what behavior you need to understand, then find where it enters the system. That's your first split. Everything off that path doesn't exist for now, not forever, just for now.

Most of the time the entry point takes minutes to find. HTTP endpoints have routes. Queue consumers have message types. Scheduled jobs have names. Once you have it, follow the behavior. Stop when you hit something you can't trace. Ask why that thing exists. Stop again. You're narrowing the codebase one bisection at a time until you land on the module that owns the thing you need.

The Seam

What you're narrowing toward is the seam: the boundary where one module's responsibility ends and another's begins. A well-built system has these. You can follow a behavior all the way through one module, come out the other side, and know exactly what that module's job is and where it stops.

This is not an argument for understanding less. Ignoring the parts of the system outside your seam isn't the same as shipping code you don't understand. It's how you get to the point where you can explain something. You own one thing completely and work outward from there. Every senior developer I've worked with does this instinctively. Nobody reads the whole repo on day one.

You can hold one thing deeply or ten things shallowly. The ten things feel like coverage. The one thing is what actually makes you useful.

The Scar

Here's the specific version, because none of this is theoretical. I got dropped into a project once with no documentation worth reading, and a git history where every commit message was "fix" or "update" or "final," then "final2." Ticket due Friday.

For the first few hours I did what most people do: opened the file tree, started reading. By hour three I had a dozen tabs open and understood nothing I hadn't understood when I started. I'd seen files. I hadn't learned anything.

The question that turned it around was almost embarrassingly obvious: what does this ticket actually touch? I found the entry point, an HTTP endpoint, and followed it. I stopped when I hit something I couldn't trace. I asked why it existed. I stopped again. Forty minutes later I had a solid model of one module and one clear flow through it. That was enough to start, and it was enough to finish. The rest of the codebase never revealed itself in those forty minutes. The part I needed did.

Four Questions, Portable

Write these on an index card:

  1. Name the actual behavior, not the feature name or the ticket title. "A user cancels an order before it ships" is a behavior. "The cancellation flow" is a category.
  2. Find where it enters the system: a handler, a consumer, a job. Almost always fast.
  3. Follow what it changes. The state change tells you what the code actually owns.
  4. Name what it depends on to run, for this behavior specifically. That's your context boundary. Everything outside it is outside for a reason, even if the reason is "not today."

The Tool That Shortens the Scar

Remember the forty minutes I spent finding one HTTP endpoint in a codebase whose git history read like a confession? There's a tool that would have cut that closer to five.

It's a Claude Code skill called Understand Anything. Install it once through the plugin marketplace, then from inside the project run /understand scoped to the folder you care about. Underneath, a multi-agent pipeline splits the work: tree-sitter handles the structural layer, Claude handles the semantic layer, and together they build a knowledge graph of every file, function, class, and dependency in that scope.

What you get is a dashboard. Click a node, see what it connects to. Read a plain-English summary of what a file is for. Ask a direct question, "what calls into this aggregate?", and it answers from the graph instead of re-reading the source. There's a guided tour too, ordered by dependency, so you learn a module in the order that makes sense instead of whatever order the file tree lists it in.

The piece I keep coming back to is the diff tool. Before you push, /understand-diff shows you what the graph says your change actually touches. That's a different question than what you think you're touching, and it's the kind of thing worth knowing before the PR goes out, not after.

It's free and MIT licensed. Find it here:

https://github.com/Egonex-AI/Understand-Anything

The Line to Protect

One thing I don't want to get lost in all of this: finding the right chunk and ignoring the rest is not the same as saying it's fine to ship code you don't understand. It's the opposite. The four questions are how you get to real understanding of one thing instead of a vague impression of everything.

You don't have to understand everything. You have to understand the right thing, and you have to understand it cold.

Watch the full episode for the visuals and the full walk-through of the method, plus the question I'm asking in the comments:

The Thinking Engineer — one channel, one bet: AI can write the code now, but somebody still has to understand it. That somebody is the job that isn't going away.

Top comments (0)