Agentbrisk

AI Coding Agents in Monorepos: Strategies That Actually Work

April 20, 2026 · Editorial Team · 7 min read · monorepoai-codingnx

Monorepos and AI coding agents are awkward together, but not incompatible. The main problem is context: a monorepo might have 50 packages, 300,000 lines of code, and configs for a dozen different runtimes. An AI agent that tries to understand all of that at once will either lose context on what matters or spend all its context window on things irrelevant to the current task.

The fix isn't to avoid AI tools in monorepos. It's to scope them correctly.


Why monorepos create specific problems for AI agents

Most AI coding tools were designed for the single-project model. You open a folder, the agent has access to your code, and context is naturally scoped to what's in that folder.

In a monorepo, you might have:

packages/
  api/            (Node.js, TypeScript)
  web/            (React, TypeScript)
  mobile/         (React Native)
  shared/         (TypeScript utilities)
  admin/          (Next.js)
apps/
  worker/         (Python)
  data-pipeline/  (Python)
infra/
  terraform/
  docker/
tooling/
  eslint-config/
  tsconfig/

If you open this entire repository in Cursor and ask "add user authentication to the API," the model might look at the web app, the mobile app, and the worker trying to figure out which "API" you mean. It might suggest patterns from the wrong package. It might try to make changes in files that have nothing to do with your task.

The context problem gets worse as the monorepo grows. A 200k-line codebase consumes significant context before the model gets to the actual task.


Strategy 1: Package-level workspace scoping

The most reliable approach is to scope your agent session to the package you're working in.

In Claude Code, you can open a subdirectory directly:

cd packages/api
claude

Claude Code's context is now rooted at packages/api/. It sees that package's CLAUDE.md, its files, its dependencies in the local node_modules. It doesn't try to process the rest of the monorepo.

In Cursor, use the "Add Folder" feature to add only the specific package directory to your workspace, rather than opening the entire monorepo root. Alternatively, open the monorepo root but configure your rules to be explicit about which packages are in scope.

When you need cross-package work, you can open multiple folders in the same Cursor window. Add packages/api and packages/shared together when you're working on a shared utility used by the API.


Strategy 2: Package-level CLAUDE.md files

Claude Code supports CLAUDE.md files at any level of the directory tree. It reads the nearest CLAUDE.md from the working directory upward. This means you can have:

monorepo-root/
  CLAUDE.md          (monorepo-wide conventions)
  packages/
    api/
      CLAUDE.md      (API-specific context)
    web/
      CLAUDE.md      (web app context)

The root CLAUDE.md covers things that span the whole repo:

## Monorepo structure
This is an Nx monorepo. Packages are in /packages/.

## Shared tooling
- ESLint config: @company/eslint-config (do not modify directly)
- TypeScript base: packages/tsconfig/
- Common types: packages/shared/src/types/

## Cross-package rules
- Never import across package boundaries directly, use published package names
- Changes to packages/shared affect all packages; be careful
- New packages: copy from packages/template/

Each package CLAUDE.md focuses on that package's specifics:

## Package: API (packages/api)

### Stack
- Node.js 22, Express 5, TypeScript 5.4
- PostgreSQL 16, Drizzle ORM
- Redis for caching and sessions

### Entry points
- HTTP server: src/server.ts
- Route definitions: src/routes/
- Services: src/services/

### Do not modify
- src/generated/ (auto-generated from schema)
- package.json scripts (managed by Nx)

When you work in packages/api, Claude Code reads both files and combines them. The model gets the monorepo context plus the package specifics, without needing to process the other packages.


Strategy 3: Nx and Turborepo task scoping

Both Nx and Turborepo have task graphs that let you run commands scoped to affected packages. You can combine this with AI workflows.

Finding affected packages after a change:

# Nx
npx nx affected --target=test

# Turborepo
npx turbo run test --filter=...[HEAD^1]

When you ask an agent to make a change to a shared utility, you can prompt it:

After making changes to packages/shared, run `npx nx affected --target=build` 
to find what packages are affected, then check each one for breaking changes.

This turns a potentially sprawling task into a scoped, verifiable workflow.

Package dependency graphs. Nx's dependency graph is useful context for an agent working across packages:

npx nx graph --file=project-graph.json

You can point the agent at this file to help it understand which packages depend on which others before making changes.


Configuring .ignore patterns for monorepos

AI tools respect .gitignore but you can add more specific exclusions for the agent through tool-specific ignore files.

For Claude Code, you can add a .claudeignore file that works like .gitignore:

# Don't index generated files
**/dist/
**/.nx/
**/node_modules/
**/*.generated.ts
**/coverage/

# Don't index other packages when working in a subpackage
# (Add this to package-level .claudeignore)
../../packages/mobile/
../../packages/data-pipeline/
../../infra/

For Cursor, use .cursorignore:

# Large generated artifacts
**/dist/
**/build/
**/.next/
**/.nx/cache/
**/node_modules/

# Generated code
**/*.generated.ts
**/prisma/migrations/

# Unrelated packages (customize per workspace)
infra/
packages/data-pipeline/
packages/mobile/

Keep these files in version control. The whole team benefits from consistent context scoping.


Dealing with shared types and utilities

The trickiest part of AI coding in a monorepo is cross-package type usage. When the agent doesn't know what types are available in packages/shared, it'll either make assumptions or create duplicate types.

A few approaches that work:

Index your shared exports explicitly in CLAUDE.md. Not all of them, but the most commonly used ones:

## Shared utilities (from packages/shared)
Available types:
- `UserId`, `OrgId`, `ProjectId` (branded strings, in @company/shared/types)
- `Pagination`, `PaginatedResult<T>` (for list endpoints)
- `Result<T, E>`, `Ok<T>`, `Err<E>` (Result pattern)

Available utilities:
- `formatDate(date: Date, format: string): string`
- `slugify(text: string): string`
- `hashPassword(password: string): Promise<string>`

Import from '@company/shared', not by relative path.

Show the agent shared types at the start of relevant sessions:

Before we start, here are the key types from packages/shared that 
we'll be using: [paste relevant type definitions]

This is faster than pointing the agent at the shared package and hoping it reads all the right files.


Real workflow: adding a feature across multiple packages

Here's how a cross-package feature workflow looks in practice. Suppose you're adding a "projects" concept that requires changes to:

  • packages/shared: new Project type
  • packages/api: new project endpoints
  • packages/web: new project UI

Session 1 (shared types): Open Claude Code in packages/shared. Prompt: "Add a Project type and related types to src/types/project.ts. Here's the schema: [paste]." Commit this change first.

Session 2 (API): Open Claude Code in packages/api. Add to your session context: "The Project type was just added to @company/shared. Here's the relevant type definition: [paste]. Now add CRUD endpoints for projects following the same pattern as users in src/routes/users.ts."

Session 3 (web): Open Claude Code in packages/web. Context: "The project API endpoints are now live at /api/projects. The Project type from @company/shared is [paste]. Add a projects list page following the same pattern as the users page at src/pages/users."

Each session is scoped. Each one starts with the relevant shared context pasted explicitly rather than relying on the agent to find it. This takes an extra minute of setup per session but eliminates most of the confusion from cross-package unknowns.


Monorepo-specific prompt patterns

A few prompt patterns that work specifically well in monorepo contexts:

"Working in X, not touching Y": Being explicit about scope prevents accidental cross-package changes.

We're working in packages/api only. Do not modify any files outside 
packages/api. If you need something from packages/shared, tell me 
and I'll check if it exists or if we need to add it.

"Run the Nx target to verify": Asking the agent to verify with the monorepo tool catches build issues early.

After implementing this, run `npx nx build api` to make sure it 
builds without errors.

"Check affected packages before committing": For changes to shared code.

You just modified packages/shared. Run `npx nx affected --target=test` 
and check if any other packages fail.

Turborepo-specific considerations

Turborepo's pipeline configuration (turbo.json) is worth including in your root CLAUDE.md context:

## Build pipeline (Turborepo)
Key tasks and their dependencies:
- `build`: builds in dependency order
- `test`: runs unit tests (runs after build)
- `lint`: runs eslint
- `dev`: starts dev servers

Run a single package: `npx turbo run build --filter=api`
Run affected: `npx turbo run test --filter=...[HEAD^1]`

Agents working in a Turborepo context often try to run npm test or tsc directly. If you tell them the correct Turborepo commands, they'll use those instead, which respects the dependency graph and gives you correct output.


What to avoid

A few anti-patterns that cause more problems in monorepos than in single-project setups:

Opening the entire monorepo root in an agent session for single-package work. The context overhead is real. Scope to the package.

Letting the agent modify package.json scripts. In Nx and Turborepo setups, the pipeline configuration is delicate. Add "do not modify package.json scripts" to your CLAUDE.md.

Ignoring the dependency graph. If you change a shared utility without checking what depends on it, you'll get broken builds in packages you didn't touch. Use nx affected or turbo run --filter to catch this.

Multiple agent sessions modifying the same shared package concurrently. This creates conflicts that are painful to untangle. Make shared package changes first, commit them, then start the downstream package sessions.


The scoping strategies here will dramatically reduce the amount of irrelevant context your agent sessions carry. Less irrelevant context means more accurate suggestions, fewer hallucinated file paths, and faster iteration.

Search