Skip to content

Monorepo work with AI coding agents depends on the project graph, which Claude Code, Codex and Cursor lack by default. The Nx MCP server, Nx skills or turbo ls output supply it; a rules file adds the layering policy; and affected-only build, lint and boundary checks verify each change instead of a human reading every diff.

This page is for developers and tech leads who own a pnpm, Nx or Turborepo workspace with more than a handful of packages. You rename a type in @company/core, the agent updates the three call sites it found with grep, and CI fails in two packages you never opened because they import it through @company/ui. Or a security fix lands in the shared auth package and you cannot say which 23 services must rebuild, in what order, or which teams to tell. Both are graph questions, and an agent without the graph answers them by guessing.

If your repository is large but not split into packages, start with working with large codebases; this page assumes you already have a context strategy.

  • A verified way to hand the project graph to Claude Code, Codex and Cursor, for Nx and for Turborepo workspaces
  • A rules file that states build order and forbidden imports, so the agent does not “fix” a cycle by adding an edge you would reject
  • Copy-paste prompts for impact analysis, a graph-driven rename, a rename without a graph server, a graph-diff review, and a drift audit
  • A gate sequence that proves a cross-package change without anyone reading every line: affected builds, module-boundary lint, and a before/after graph diff
  • Recovery steps for the failures you will hit: a stale graph, hidden MCP tools, a server that will not start, and dependents that were never rebuilt

How do you give an AI agent your monorepo’s project graph?

Section titled “How do you give an AI agent your monorepo’s project graph?”

An agent reads files. It does not know that apps/web depends on @company/ui, which depends on @company/core, until something tells it. In an Nx workspace, Nx ships that something. In Turborepo and plain pnpm workspaces, you supply it from the command line.

Nx workspaces: let Nx write the agent configuration

Section titled “Nx workspaces: let Nx write the agent configuration”

Nx 23 has a command that configures the MCP server, skills and instruction files for each agent at once. Run it from the workspace root:

  1. Run the configurator for the agents your team uses:

    Terminal window
    npx nx configure-ai-agents --agents claude codex cursor

    If npx nx configure-ai-agents --help fails, your Nx predates the command. Migrate first, and review the migration as its own pull request before you add agent configuration on top of it; a major-version Nx migration rewrites configuration across the workspace:

    Terminal window
    npx nx migrate latest
    npm install # or pnpm install / yarn
    npx nx migrate --run-migrations
  2. Read the diff before you commit it. In a test run against Nx 23.2.1, the command wrote a managed block into CLAUDE.md and AGENTS.md, seven skills under .agents/skills/ (among them nx-workspace, nx-run-tasks and nx-generate), a ci-monitor-subagent for Codex under .codex/agents/, an nx-mcp entry in .codex/config.toml that launches npx nx mcp, and a .claude/settings.json that enables the nx plugin from the nrwl/nx-ai-agents-config marketplace. It also set multi_agent = true for Codex and added sandbox allowances for ~/.nx and /tmp/.nx. Keep what you want; remove what your security policy does not allow.

  3. Check the result later, after upgrades:

    Terminal window
    npx nx configure-ai-agents --check=all

The Cursor step needs the cursor command on your PATH; without it, the configurator skips Cursor and points you to the Nx Console extension. The manual entries in the next section work in every case.

Use this when you do not run the configurator, or when you want a pinned version. Pin it: in August 2025, malicious nx versions were published to npm that scanned the file system for credentials (Nx security advisory GHSA-cxm3-wv7p-598c, 2025-08-27), and npx -y with no version runs whatever is newest.

Add the server at project scope so the entry lands in a shared .mcp.json that you commit, instead of the default local scope in your own ~/.claude.json:

Terminal window
claude mcp add nx --scope project -- npx -y nx-mcp@0.25.0 --no-minimal
claude mcp list

The options (--scope, -e, --transport) go before the server name; everything after -- is the launch command.

For the wider MCP picture (security, token cost, other servers) see the MCP ecosystem guides.

Turborepo and pnpm workspaces: feed the graph from the CLI

Section titled “Turborepo and pnpm workspaces: feed the graph from the CLI”

Turborepo 2.11 has no MCP server of its own, but its CLI answers the same questions, and every agent can run it:

Terminal window
npx turbo ls --output json # every package, as JSON (--output is experimental)
npx turbo ls --filter=...@company/core # a package plus everything that depends on it
npx turbo ls --affected # packages changed since `main`, plus their dependents
npx turbo run build --affected --dry-run # the task graph turbo would run, without running it

--affected compares against main, so it only has something to report once files have changed. To plan a change before any edit, use the --filter=...<package> form. Put these commands in the rules file (next section) so the agent runs them before it plans, instead of inferring the graph from import statements.

What must the rules file say that the graph cannot?

Section titled “What must the rules file say that the graph cannot?”

The graph records what depends on what. It does not record what is allowed: that apps never import from other apps, that core has no external dependencies, that exported types change only through a deprecation. Without that policy, an agent resolves a circular import by adding the edge that creates it.

Put the policy in the root CLAUDE.md and package-specific rules in each package’s own CLAUDE.md, which Claude Code loads when it works in that directory:

# CLAUDE.md (root)
pnpm + Turborepo monorepo. Layers, lowest first:
packages/core -> packages/ui, packages/api-client -> apps/web, apps/api, apps/admin
Hard rules:
- packages/* MUST NOT import from apps/*. apps/* MUST NOT import from each other.
- packages/core MUST NOT gain external runtime dependencies.
- Exported types change only by adding a deprecated alias first.
Before planning a cross-package change: run `npx turbo ls --filter=...<changed package> --output json` to list the package and its dependents.
After changing a package: `npx turbo run build test --filter=...@company/core`
(the leading `...` selects the package and everything that depends on it).

Phrase layering rules as prohibitions (“MUST NOT import”), not descriptions (“apps usually use packages”). Then enforce the same rule in lint (see how to prove a cross-package change), because a rules file is advice and a lint rule is a gate.

Run impact analysis before the agent edits anything

Section titled “Run impact analysis before the agent edits anything”

The most valuable monorepo prompt asks what breaks before any file changes. With the graph available, the agent returns packages in rebuild order, not a list of grep hits.

Check the answer cheaply. Before any edit, in a Turborepo or pnpm workspace, the package list must match npx turbo ls --filter=...@company/core. After the change, it must match npx nx show projects --affected or npx turbo ls --affected. If the agent lists a package the tool does not, or misses one, its graph read was wrong. Stop and fix the context before it goes further.

Refactor across packages from the bottom of the graph up

Section titled “Refactor across packages from the bottom of the graph up”

A cross-package change stays small only if each layer compiles before the next one changes. The sequence is the same in all three tools; what differs is how you run the layers in parallel.

  1. Get the plan. Run the impact prompt and compare its package list with the tool’s own list of dependents (npx turbo ls --filter=...<package>, or the Nx project graph).

  2. Change the lowest package and build it alone — for example npx nx build @company/core or npx turbo run build --filter=@company/core — before any dependent sees the change.

  3. Add a compatibility shim. Keep the old name as a deprecated alias so every layer above still compiles while you migrate it.

  4. Migrate one layer at a time. Build and test each layer before the agent moves up. A failure then points at one package, not five.

  5. Run the affected gate (next section), then remove the shim in a separate, small change.

Without a graph server, you give the agent the order yourself. The hard stop after the listing step replaces the check the graph would have done:

Parallel layers. Once the lowest layer has landed, the packages in the next layer that do not depend on each other can each run in their own worktree. Check first: npx turbo ls <package> lists a package’s dependencies, and the Nx graph shows the same. In the layer order from the rules file above, if ui imports types from api-client, the two run in sequence, not in parallel. Start one worktree per independent package: claude --worktree ui-migration in Claude Code, codex --worktree in Codex, or Cursor’s Worktrees. Never parallelize across layers; a dependent built against an unmerged dependency proves nothing. The parallel agents guide covers the orchestration side.

How do you prove a cross-package change without reading every diff?

Section titled “How do you prove a cross-package change without reading every diff?”

A 40-package rename produces a diff nobody reads line by line, and nobody should have to. Four checks carry the evidence; the package owners sign off on the parts that need a human.

CheckCommand or mechanismWhat it provesWho acts on a failure
Affected build, test, lintnpx nx affected -t build test lint --base=origin/main or npx turbo run build test lint --affectedEvery dependent compiles and passes its tests against the new codeThe agent fixes; you rerun
Module boundariesNx: the @nx/enforce-module-boundaries rule from @nx/eslint-plugin with project tags. Other workspaces: a dependency-rule check such as dependency-cruiser (npm install --save-dev dependency-cruiser, then npx depcruise --init), run as a fitness functionNo forbidden import was added to make something compileThe agent fixes; a new exception needs the tech lead
Graph diffNx: npx nx graph --file=before.json on the base branch and --file=after.json on the change. Turborepo: the turbo query command below, redirected to before.json and after.jsonWhich dependency edges were added or removedThe owner of each package that gained an edge approves it (CODEOWNERS)
Full pipelineYour normal CI run on the merge requestNothing outside the affected set brokeNormal CI ownership

In a Turborepo workspace, turbo ls --output json without package names lists only names and paths, not edges. Ask turbo query for the edges instead (checked with turbo 2.11.5, 2026-09-30):

Terminal window
npx turbo query '{ packages { items { name directDependencies { items { name } } } } }' > before.json

The graph diff is the check that replaces reading. A rename should add no edges. If apps/admin now depends on apps/web, the diff shows it in one line, however large the code change. Turn boundary rules into CI gates with architecture fitness functions, and attach the four results to the pull request as an evidence bundle.

Audit configuration drift and the task graph on a schedule

Section titled “Audit configuration drift and the task graph on a schedule”

Monorepos drift quietly: one package on another TypeScript version, one tsconfig.json that stopped extending the base, one test target whose inputs include Markdown, so every doc edit invalidates the cache. Run the audit monthly, or in a scheduled agent job, rather than after an incident.

Measure any task-graph fix before you accept it: compare the run time of the same affected build before and after, on the same CI runner. An agent’s estimate of time saved is a guess.

Publishing @company/payments before the @company/core version it needs ships a broken package. Let Changesets own the versioning mechanics and use the agent to draft the changesets and check the order.

Then a human runs npx changeset version and npx changeset publish from CI. Keep publishing out of the agent’s hands; it is the one step you cannot roll back with git revert.

What breaks when agents work in a monorepo?

Section titled “What breaks when agents work in a monorepo?”
  • The MCP server does not start. Run claude mcp list or codex mcp list. A failed server usually means npx is missing from the PATH the agent inherits, or it timed out while computing the graph. Fix the PATH, or raise startup_timeout_sec in Codex above its 30-second default, for example to 60.
  • The agent says it has no graph tools. The server is running in its default minimal mode. Install the Nx skills with nx configure-ai-agents, or add --no-minimal.
  • The agent reports “no Nx workspace”. The server started outside the workspace root. Launch the agent from the directory that holds nx.json, or pass the workspace path as the first argument: npx nx-mcp@0.25.0 /path/to/workspace.
  • Impact analysis lists packages that no longer exist. The graph is cached. Run npx nx reset, which clears the cache and shuts down the Nx daemon (it restarts on the next command), then ask the agent to read the graph again.
  • A shared package changed and its dependents did not. Nothing told the agent that the change cascades. Add the build-order rule and the ...@company/core filter to the rules file, and make the affected gate a required CI check.
  • Tests pass locally and fail in CI downstream. The dependents were tested against stale builds of their dependencies. Rebuild the whole affected set (nx affected or turbo run --affected), not only the package you edited.
  • The agent introduced a circular dependency to make something compile. The rule was a description, not a prohibition, and lint did not enforce it. Rewrite the rule as “MUST NOT”, add the boundary lint rule, and reject the change.
  • Codex ignores AGENTS.md. Since Codex CLI 0.150.0, untrusted projects no longer supply project-level AGENTS.md instructions. Mark the workspace as trusted when Codex asks, then start a new session.
  • The agent invents exports on a very large change. The graph plus the task overflowed its context. Split the work to one layer per turn and use --base to narrow nx affected.
  • nx configure-ai-agents changed more than you expected. It can enable a Claude Code plugin marketplace, Codex multi-agent mode and sandbox allowances. Review .claude/settings.json and .codex/config.toml in the diff like any other dependency change.