Home / Articles

Why the Modular Monorepo Suits Coding Agents: See Everything, Touch Little

Polyrepos blind agents and unstructured monorepos flood them. Open context, encapsulation and a real dependency graph make the modular monorepo work for agents.

Publisher: REACTAPP.TOP7 min read1695 words

This article is published in English.

Sources: The Shine of the Modular Monorepo in the Agentic Era

An old argument with new stakes

For years, engineers have sorted themselves into two groups. One keeps all code in a single repository, and the other gives every piece a home of its own, with plenty of compromises in the middle. Nobody is right across the board, and anyone claiming so is usually extrapolating from one project. Ask whether a monorepo or polyrepo is better and the truthful reply is "it depends": on how big the system is, how closely its parts are coupled, who's on the team and how often things ship. A few loosely related services belong in separate repos. A product woven tightly around shared contracts points the opposite direction.

Coding agents made the argument hotter. Hand one a task that crosses a frontend, a shared library and a backend contract, and the repo layout stops being a matter of taste. Its consequences show up in code quality, in how frequently the agent has to guess, and in how disoriented it becomes. This case is made from inside a TypeScript NX setup covering six platforms. That's a declared vantage point, and it won't match everyone's, so read it as a strongly held opinion that's meant to start a conversation. Four words sum up the claim: see everything, touch little.

Cliff one: walls the agent can't see past

Picture the split world most teams inhabit: one frontend repo, a pair of backend service repos, a shared-types package in a private registry, and an infra repo. The boundaries make sense and every piece has an owner.

Suppose an agent in the frontend repo is asked to alter how it calls an endpoint that belongs to a service repo it can't open. Without the handler to read, it guesses what the response looks like. A stale type stub or a lone test example becomes its evidence. The result compiles on the local machine and is likely wrong once integrated. Every repo boundary is a wall the agent can't look past, and it plugs each one with a believable assumption. What shields the humans leaves the agents hungry for information.

Teams cover the gap in three main ways, and a few of the fixes are good:

  • Git submodules place the dependency repos inside the main repo so the file tree looks unified. The agent gains the ability to read all of it, at the usual price: pinned commits drift, keeping things fresh turns into a chore, and the workflow pleases nobody.
  • Multi-root IDE workspaces let Cursor or VS Code index several repos together, which helps when the goal is just reading across them. The arrangement belongs to one machine and not to the project, though, and the agent gets a heap of files with no dependency graph. It knows code exists but not what relies on what.
  • Synthetic monorepos are the serious choice. NX's Polygraph, for one, joins separate repos into a single dependency graph while leaving the code where it is. A coordinating agent consults that graph to figure out which repos a change reaches, launches an agent in each, and opens matching pull requests while tracking CI everywhere. It comes closest to monorepo behavior on top of a polyrepo layout.

Respect is due to the synthetic approach, but look at what it actually does: it tunnels through walls that stay standing. Engineers spend real effort at the tooling layer to recreate the visibility that a monorepo provides structurally at no cost. And when none of these tools exist, the human is the tunnel, reading service B, carrying the lessons to the agent on service A, pasting type definitions into chat, and acting as a courier between sealed sessions.

Cliff two: the structureless pile

So everything moves into one repo, and the matter is closed? Not quite. A monorepo with no internal structure fails worse, because it tempts. All of it is visible, which feels like enough. In reality there's one enormous app directory, libraries that import each other from every angle, no enforced boundaries, and no sense of which slice belongs to whom.

Here, open context hurts. An agent that sees everything gets no hint about what to skip. The window fills with code that's close by on disk and irrelevant to the job, one edit ripples across imports nobody tracked, and the question that counts, what does this change affect, gets the reply "possibly everything." Visibility minus structure is loud noise and not context, which is why dumping all code in one repo isn't the takeaway.

Three pillars of a modular monorepo

A modular monorepo wins by doing three things at once. Dropping any one sends you off the ridge.

Open context. One tree holds it all and the agent can walk through it: frontend, backend, shared libraries, tests and the type contracts that tie them together, in a single session. No walls, no guessing, no courier. NX's roadmap is loudest about this pillar, and fairly so, since an agent reading a contract's producer and all its consumers in one pass will make better edits.

Encapsulation. Libraries are bounded and expose explicit public surfaces, so the agent needn't hold the whole system in mind. It works on a slice. That edge is what allows seeing everything and touching little to coexist, and without it open context collapses into cliff two.

A real dependency graph, with tools to explore it. This is the pillar people underrate. NX treats the graph as a first-class artifact that can be queried. Rather than grepping and hoping to infer structure, the agent can run nx show projects, open nx graph, ask what a change touches, and receive a precise answer a machine can parse. The map lives in the repo and not in a wiki or a senior engineer's memory, and it's executable.

Together these resolve the four-word thesis. Seeing everything is pillar one, touching little is pillar two, and knowing which little to touch is pillar three, the bridge that makes the first two safe to combine.

Acquire and verify

Agents run in a loop of pulling context, changing code, checking the change, and going around again. All monorepo hygiene serves one of two jobs: getting context cheaply, or checking an action cheaply.

  • Strong types (acquire). A shared types library gives the agent a contract it can read and the compiler can enforce. That answers the blind-agent problem from cliff one, because no response shape needs guessing when it's written down and checked. Types double as documentation that never goes stale.
  • Lint and module-boundary rules (verify). With NX's @nx/enforce-module-boundaries, a forbidden import throws rather than sneaking by, and the error lands inside the agent's own loop as feedback. If the agent wires a UI library into the data layer, the rule refuses it, and the architecture is learned from the failure without anyone writing it out.
  • TDD and affected tests (verify). nx affected makes cheap checking concrete. After editing a slice, the agent runs just the tests downstream of it and sees red or green fast, without a full-suite wait or doubt about whether the change held. Short loops are what make agent work feel like building and not babysitting.
  • Skills and AGENTS.md or CLAUDE.md (acquire). Running npx nx configure-ai-agents in a workspace installs an MCP server, agent skills and the convention files. Skills arrive on demand and not all at once in the prompt, so how to scaffold a library is learned exactly when one is being scaffolded. They also steer the agent toward querying the graph over grepping, tying back to pillar three.
  • Atomic per-module guides (acquire). Each library can hold a brief README or AGENTS.md, giving local context right where the agent has just arrived. Entering that library brings in its contract and conventions without pulling the remainder of the tree along.

Tally the list and it reads acquire, verify, verify, acquire, acquire, though the ordering is incidental. Every affordance fits one of the two jobs. A modular monorepo isn't one feature for agents but many small ones that keep the loop quick and grounded.

The case against

Nobody benefits from a sales pitch, so consider the counterargument. Context windows keep expanding, and multi-root workspaces and synthetic-monorepo tools keep closing the distance. A skeptic might call the monorepo's advantage a passing artifact of present limits, erased by a large enough window and decent cross-repo tooling. The sharper form doesn't concern windows. Polygraph shows a dependency graph can be rebuilt over a polyrepo, so the structure often credited to monorepos can't be theirs alone.

Each version mistakes where the benefit comes from. It was never about reading more raw text. It's structure. A larger window lets a lost agent be lost in finer detail without naming the right door. A synthetic graph is also structure, which explains why it works, but that structure is rebuilt and upkept on top of the split and isn't given by the layout. Raw context grows with the model, structure grows with discipline, and structure turns seeing everything from a hazard into an asset. As windows grow, a monorepo lacking modules gets riskier, because the floodgate opens wider. The adjective carries the load.

What the agentic era revealed

Project graphs, module boundaries and shared types once looked like conveniences for a human team. The agentic era exposed what they had been the whole time: an interface for non-human collaborators. Architecture drawn up for human thinking turned out to be repo-level context engineering, years before the term existed. That makes the point something other than monorepos coming back into fashion. The modular monorepo quietly answered a question nobody had asked yet. See everything, touch little, and agents merely made it plain.