Back to blog
Quality
Claude Code

When AI Agents Split Your Codebase Into Too Many Files

Thang Doan
Thang Doan

You ask an agent to add a small feature to a single component. The PR arrives with six new files. There is a utils/ file for one helper function. There is a types/ file for two interfaces. There is an index.ts that re-exports everything. The original component file is now 40 lines shorter and split across the new files.

The agent did exactly what it has seen in a thousand open-source repos. None of those splits help you read the feature.

Why agents split by default

Most public code is split. Models trained on it absorb the pattern: feature work means new files in new folders. When the agent sees "add a settings panel", it reaches for the structure it has seen most often.

The agent does not ask whether the split earns its keep. It does not count how many callers a helper has. It does not check whether two interfaces are used together everywhere. It applies the median pattern, and the median pattern is over-split.

The actual cost of over-splitting

Six files for one feature means six files to read to understand one feature. The reviewer opens them all. The next developer who touches the code opens them all. The agent itself, next session, opens them all again because none of them is self-contained.

Navigation overhead is the visible cost. The hidden cost is coupling disguised as separation. Files that change together end up scattered, so every change touches multiple files in multiple folders. The git diff looks bigger. The review takes longer. The blast radius of a refactor expands.

When splitting is correct

Split when one of these is actually true.

The file exceeds roughly 300 lines and has more than one clear responsibility. Line count alone is not enough. The file must contain two things that change for different reasons.

A piece of logic has at least three real callers. Not exported. Not "could be reused". Actually imported from three places today.

A specific collaborator needs to own a part independently. You and another developer are stepping on each other because the file is shared.

The file has unrelated concerns that change at different rates. Auth logic mixed with formatting logic mixed with network calls.

If none of these are true, keep the code together.

The index.ts trap

The worst pattern is the barrel file. You create index.ts to re-export from five other files so the import path looks clean at the call site. You have added a file whose only job is to hide the structure you created.

If the import path needs an index.ts to be readable, the problem is not the path. It is that you split too early. Collapse the files. The barrel disappears.

What to do with agent PRs

Apply the same test you would apply to a junior's PR, but with less patience.

Does this new utils/ file have a function used by at least three callers? If not, fold it back into the file that uses it.

Does this types/ file contain interfaces that always travel together? If yes, they belong in the same file as the code that uses them.

Does this services/ folder have one service? It is not a services folder. It is a service. Drop the folder.

Reject the PR with one comment: "Collapse files unless one of the four conditions is met." Most agents will produce a simpler version on the second pass. The ones that do not are signalling they cannot review their own structure, which is a different conversation.

What the simpler version looks like

One file for the feature. Everything the feature needs in that file. The reviewer reads top to bottom and understands what the feature does.

If a future change makes the file genuinely too big, split then. You will know because one of the four conditions will be true. Splitting before that point is gambling on requirements you do not have.

Recommended for you

Enjoyed this article?

Subscribe for new articles. No spam. Unsubscribe anytime.

By subscribing you agree to receive the newsletter. See the Privacy page.