You point Cursor at a 12-package monorepo and ask it to add a feature in apps/web. It opens 47 files across 6 packages, refactors packages/utils for no reason, and leaves an unrelated package in a broken state. This is the default failure mode of AI agents in monorepos. This tutorial gives engineers in turborepo, Nx, pnpm-workspace, or Yarn-workspace setups a reliable per-package workflow that keeps agents inside their lane while still letting them do cross-package work safely.
What this tutorial solves
Monorepos are AI-hostile: too much context, unclear ownership, hidden coupling. Without structure, agents either ignore the wrong package or refactor across boundaries. This workflow uses three tools — a root and per-package CLAUDE.md (or AGENTS.md, equivalents), explicit scoping in every prompt, and a two-phase commit pattern for cross-package work — to make agents productive without producing review chaos.
Who this is for
Developers in turborepo, Nx, pnpm-workspace, or Yarn-workspace setups; also large single repos with clear package boundaries. Engineering leads writing AI guidelines for the team also benefit — these conventions are what make AI-generated PRs reviewable at scale.
When to reach for it
Any non-trivial change in a monorepo with three or more packages. Especially when the change might cross package boundaries (a new API endpoint consumed by web, a new shared component, an update to a generated client). Single-package edits in a monorepo still work fine with default tools; structure matters when the agent needs to know not to touch sibling packages.
When this is NOT the right tool
Tiny monorepos (2-3 packages, shared everything) — the overhead is not worth it. Pre-monorepo conversions where structure is still being decided — let the structure stabilize first. For a single-app codebase, see using AI to audit a React Native project instead.
Before you start
- Inventory packages and document boundaries. Which package owns the API contract? Which owns shared types? Which is internal-only?
- Pin the tool. Cursor, Claude Code, Continue, Aider all work; switching mid-task is how agents lose context.
- Decide your test strategy. Per-package tests are not enough for cross-package work; you need at least one cross-package integration test and a working full-build command.
- Confirm your build tool can run a single-package build (turbo run build —filter=…). The agent will use this to validate work without running the world.
Step by step
- Maintain a root CLAUDE.md (or AGENTS.md, depending on tool) listing each package: name, one-line purpose, public API surface, ownership, and what the package must NOT depend on. The “must not depend on” rule is often more important than the “depends on” rule.
- For each task, scope explicitly in the prompt: “Work in packages/api only. Do NOT touch packages/ui, apps/web, or any tests outside packages/api.” Be specific about both the target and the exclusions.
- Use the agent’s file glob or search tools to limit retrieval to the target package. In Cursor, use folder scope. In Claude Code, set the working directory. In Aider, pass only the target files.
- For cross-package changes, do them in two passes. First pass: write the consuming package’s call site against the new contract that doesn’t yet exist. Commit. Second pass: implement the providing package. Commit. This makes review trivial — each commit is a single concern.
- After every cross-package edit, ask the agent explicitly: “Did this change a public API surface? If yes, list every package that consumes this API and tell me what needs to change in each.” Models forget downstream consumers by default.
- Run the full monorepo build and test before committing. Individual package tests are not enough — turbo run build && turbo run test from the root, or your equivalent. Cross-package contract breaks only surface in the integrated build.
First-run exercise
- Pick a single-package change in your highest-traffic package — a small bug fix or one utility addition. Real work, contained blast radius.
- Run the agent with explicit scope. Measure: did it stay in the package? Did it touch anything you did not ask for?
- If the agent strayed, the prompt is too loose or the root CLAUDE.md is missing boundary rules. Fix one and retry.
- For the second exercise, attempt a deliberate cross-package change using the two-phase commit pattern. Check that each commit reviews cleanly on its own.
Quality check
- Each commit in the PR touches one package (or two if you intentionally did the two-phase pattern). Multi-package commits are reviewing hell.
- The full monorepo build passes. Not just the package the agent worked in.
- The agent’s PR description names every package touched. If it does not, your prompt missed asking for it.
- Generated code (graphql types, protobuf, prisma client) is regenerated and committed. The agent’s documentation should remind it to do this; if it forgot, your CLAUDE.md is missing the regeneration command.
How to reuse this workflow
- Save the scoping prompt template as part of your team handbook. New engineers paste it; the agent stays in line.
- For each cross-package pattern that recurs (new API endpoint plus web consumer, new shared component plus app integration), document a two-phase recipe.
- Re-audit the root CLAUDE.md every quarter. Packages get added or split; outdated boundary docs are worse than none.
Recommended workflow
Adding a new API endpoint used by the web app: scope to apps/web → write the call site against the new contract → commit (build fails intentionally) → scope to packages/api → implement the endpoint → commit → full monorepo build + e2e tests → open PR with two clean commits.
Common mistakes
- Running the agent at the repo root with no scope. It will retrieve random files from the wrong package.
- Editing across package boundaries in one prompt — review becomes painful and the diff is impossible to bisect.
- Forgetting per-package conventions (test framework, linter rules) when the root CLAUDE.md doesn’t mention them.
- Skipping the full monorepo test — package tests pass while the integrated system breaks.
- Letting the agent regenerate generated code into the wrong package. Always specify which package owns generated artifacts.
- Treating CLAUDE.md as a one-time write. Boundaries drift; outdated docs mislead the agent into the same trap as no docs.
Advanced tips
- For each package, a short CLAUDE.md describing its boundaries beats one big repo-root file. The agent’s context loader picks up the nearest package’s doc.
- Use Cursor’s @-mention or Claude Code’s file references to lock attention to specific files when the package is large.
- For shared types or generated code, document the regeneration command in CLAUDE.md so the agent knows to run it (“after changing the schema, run pnpm gen:types from repo root”).
- For very large monorepos, maintain a “module map” — a one-line entry per package describing inputs, outputs, and the one file the agent should read first.
- Pre-load the agent with the changelog of recent cross-package changes. New work tends to follow recent patterns.
Output checklist
- Repo-root and per-package CLAUDE.md files exist and describe boundaries.
- Task scoped to specific packages in the prompt.
- Cross-package changes done in two phases with separate commits.
- Full monorepo build and tests pass.
- Generated code regenerated and committed.
- PR description lists every package touched.
FAQ
- Cursor vs Claude Code in monorepos?: Both work. Cursor lets you scope to a folder; Claude Code respects CWD. Pick the one whose UX matches your habits.
- How big is too big?: When agents start retrieving the wrong package consistently, it is time for per-package CLAUDE.md and explicit scoping.
- Should I use one CLAUDE.md or many?: Many. One per package plus a small root index. Agents are better at finding the nearest doc than reading one giant file.
- What about Bazel monorepos?: Same pattern, but document the build target naming convention. Agents will guess wrong otherwise.
- How do I prevent the agent from “improving” unrelated code?: Explicit exclusion in the prompt: “Do not modify files outside packages/api. Do not run linters that auto-format other packages.”
- What if my packages don’t have clear boundaries?: Fix that first. Without boundaries, AI cannot help in a monorepo — and neither can human engineers.
Related
Tags: #AI coding #Tutorial #Workflow