Writing

Structure Your Repo So AI Can Find Its Way Around

Structure Your Repo So AI Can Find Its Way Around - abstract illustration

An AI doesn't have a map of your repo. It works the way a new engineer would on their first day: it reads the code to figure out where things are. The difference is that it does this with a much narrower view at any one moment, seeing a handful of files instead of the whole tree in its head. Everything I do to make a repo navigable for the model turns out to be the same thing that makes it navigable for a person who just cloned it.

The model reads your repo the way a new hire would

Drop a competent engineer into an unfamiliar codebase and watch what they do. They look for a README. They scan the top-level folders to infer the shape of the system. They open a file, follow an import, open the file it points to. They build a mental model incrementally, one file at a time, until they know enough to make the change safely.

A coding agent does exactly this, except its working memory is smaller and it resets often. It can't hold the whole tree at once, so at any given moment it's reasoning over a narrow slice and inferring the rest from names, structure, and whatever documentation it can find. I've written before that the model sees far less than you think it does. Repo structure is the other half of that problem: not what you paste into the window, but how easily the model can find the right things to pull in on its own.

The throughline for everything below is that you're optimizing for navigability under a flashlight beam. A repo that's discoverable to a human is discoverable to a model. A repo full of implicit knowledge, one-off conventions, and code that no longer runs forces the model to guess, and it guesses with total confidence.

Consistent, predictable layout beats clever layout

The single biggest lever is convention. If your project puts things where the framework and the ecosystem expect them, the model can find them by convention instead of by search. It already knows, from training on thousands of similar projects, that controllers tend to live in one place, migrations in another, tests mirroring the source tree. Lean into that. A boring, predictable layout is a feature.

The failure mode is inconsistency, not any particular style. If half your services are named EmailSyncService and the other half are svc_email_2, the model can't generalize from one to the next. It finds the first, infers a pattern, and the pattern breaks. Pick a naming convention and a folder structure and hold the line on it. When the model can correctly predict the path of a file it hasn't seen yet, you've done this right.

This is worth being concrete about:

  • Name by what it is, consistently. If a thing is a repository, call it SomethingRepository everywhere, not SomethingRepo in one module and SomethingDao in another.
  • Mirror your structure. Tests that shadow the source tree, config that lives where config lives in your stack, assets grouped the way the framework expects them.
  • Don't invent private taxonomies that only make sense if you were in the room when they were decided. The model was not in the room, and neither was the engineer you hire next year.

A top-level instruction file that orients the model

Every repo I work in has a CLAUDE.md at its root. It's the first thing the model reads, and it exists to answer the questions a new engineer would ask before touching anything: what's this project, how is it built and run, how is it organized, and where are the deeper references. It's the README written for the reader who has to act, not just understand.

Mine are not long. They cover how to build and run the thing, the non-obvious conventions of the project, the commands that matter, and a short list of pointers to the fuller documentation. That last part matters more than it looks: the instruction file doesn't have to contain everything, it has to route. It tells the model that the stack-specific patterns live in one place and that the domain rules live in another, so the model knows where to look instead of reconstructing it from scratch. This is where a CLAUDE.md and an authoritative reference library the AI follows in every project reinforce each other: the instruction file is the index, the library is the shelf.

The rule I hold myself to is that the instruction file has to stay true. A stale CLAUDE.md that describes a build step you removed is worse than none, because the model trusts it and acts on the lie. When I change how a project is built, updating that file is part of the change, not a follow-up I get to later.

Colocate documentation and index files with what they describe

Documentation that lives far from the code it describes goes stale and gets missed. I keep short index and documentation files next to the folders they describe, so that when the model is working in a folder, the explanation of that folder is right there in the same neighborhood it's already reading.

In my Obsidian vault, which is backed by git and organized as a filing system, most folders carry an index.md that lists what the folder contains. That's not decoration. When an agent lands in a folder, the index tells it what's there and what each thing is for, without the agent having to open every file to find out. The cost of keeping those indexes current is real, so I automate it: an agent audits the tree and regenerates indexes that have drifted. The payoff is that navigation becomes a read instead of a search.

The general principle: put the description of a thing next to the thing. A folder that explains itself is a folder the model can enter cold and understand, under the beam, without loading the rest of the tree to make sense of it.

Clear module boundaries so the relevant context is localized

The worst repos to work in with AI are the ones where doing anything requires touching everything. The logic for one feature is smeared across a dozen files in unrelated corners, and to change it safely the model would have to load all of them at once, which is exactly the thing its context window won't let it do well.

Clean module boundaries fix this by localizing context. When the code for a concern lives together and talks to the rest of the system through a narrow, explicit interface, the relevant context for a task fits in the window at the same time. The model can pull in the module, its boundary, and its tests, and have everything it needs without dragging in half the codebase. This is the structural version of scoping a task to what the model can hold. A well-bounded module is a task-sized unit of code.

You feel the difference immediately. In a well-bounded repo the model makes a change with three files open and gets it right. In a tangled one it makes a plausible change that quietly breaks something two directories away, because the thing it broke was never in view.

Remove dead and duplicated code

Dead code is a trap you set for the model. It can't tell, from reading alone, that a function is never called or that a module was replaced two years ago and left in place. It sees code that looks live, and it follows it. I've watched a model faithfully extend an abandoned code path because nothing in the repo said it was abandoned; every signal it had said this is how the project does it.

Duplication is the same failure with two heads. When the same logic exists in three slightly different copies, the model has no way to know which one is canonical. It may edit the wrong one, or worse, edit one and leave the other two to disagree with it. Every stale copy is a wrong path the model can wander down with full confidence.

Deleting dead code and collapsing duplicates is good hygiene regardless of AI. But working with a model raises the stakes, because the model takes the repo at face value in a way a skeptical human doesn't. It has no memory of the meeting where you decided that folder was deprecated. If it's in the tree and it looks real, it's real as far as the model is concerned. Keep the tree honest.

None of this is exotic and none of it is AI-specific. It's the same discipline that makes a codebase pleasant for the humans who inherit it: predictable structure, an honest front door, docs that sit where the work is, boundaries you can reason about, and no corpses in the tree. The model just happens to be the most literal new hire you will ever onboard, and it rewards a well-kept repo more consistently than any of us do.

Building something like this?

This is the kind of work I do for clients. Tell me what you're building and I'll give you a straight read on the approach.

Book a 30-minute call