Skip to content

Multi-Repo Workflows

Your team has an API gateway, three backend services, a shared library, and two frontend apps — each in its own repository. You need to add a new field to the user profile. That means updating the shared types library, the user service API, the gateway’s schema, and both frontend apps. You open Cursor in the user service repo, and the agent has no visibility into the shared library or the gateway. Every prompt requires you to manually explain what exists in the other repos.

Multi-repo development with AI tools requires specific strategies to bridge the gap between repositories that the agent cannot see simultaneously.

  • Techniques for giving Cursor context about code that lives in other repositories
  • A rules-based approach for encoding cross-repo dependencies and contracts
  • Workflow patterns for coordinating changes across multiple services
  • Strategies for monorepo versus polyrepo AI-assisted development

Cursor indexes and searches the repository that is currently open. It does not have native awareness of sibling repositories. When your API contract is defined in one repo and consumed in another, the agent working in the consumer repo cannot see the contract definition.

There are several practical approaches to solve this.

VS Code (and Cursor) supports multi-root workspaces where you open multiple folders as a single workspace. This gives the agent visibility into all included repositories:

{
"folders": [
{ "path": "./api-gateway" },
{ "path": "./user-service" },
{ "path": "./shared-types" },
{ "path": "./frontend-app" }
],
"settings": {
"search.exclude": {
"**/node_modules": true,
"**/dist": true
}
}
}

Save this as project.code-workspace at the root of your project directory. Open it with File > Open Workspace from File.

Strategy 2: Rules That Document Cross-Repo Contracts

Section titled “Strategy 2: Rules That Document Cross-Repo Contracts”

When multi-root workspaces are not practical (too many repos, too much noise), encode the contract information in rules:

---
description: Cross-repo API contracts
alwaysApply: true
---
This service consumes the User API from the user-service repo.
User API contract (source of truth: user-service/src/routes/users.ts):
- GET /api/users/:id returns { id, email, firstName, lastName, role, createdAt }
- PATCH /api/users/:id accepts { firstName?, lastName?, email? }
- POST /api/users accepts { email, firstName, lastName, password }
Shared types (source of truth: shared-types/src/user.ts):
- UserResponse: { id: string, email: string, firstName: string, lastName: string, role: 'admin' | 'user', createdAt: string }
- CreateUserRequest: { email: string, firstName: string, lastName: string, password: string }
- UpdateUserRequest: Partial<Omit<CreateUserRequest, 'password'>>
When making changes that affect these contracts, flag it -- the corresponding services will need updates too.

For critical shared types, maintain a local copy or symlink in each consuming repo:

Terminal window
# In your consuming repo
mkdir -p .cursor/contracts
cp ../shared-types/src/user.ts .cursor/contracts/user-types.ts
cp ../api-gateway/schema.graphql .cursor/contracts/gateway-schema.graphql

Reference these in your prompts with @.cursor/contracts/user-types.ts to give the agent exact type information from the source repo.

When a change spans multiple repos, start with the shared contract:

  1. Update the shared types / API contract definition in the source repo
  2. Commit and (if applicable) publish the updated types package
  3. In each consuming repo, update the dependency and adapt code to the new contract
  4. Run tests in each repo to verify compatibility

For large cross-repo features, use separate Cursor windows for each repository. Plan the change in one window, then execute in each:

  1. Planning window (any repo): Use Ask mode to design the cross-cutting change
  2. Service A window: Implement the service-side changes
  3. Service B window: Implement the consuming-side changes
  4. Integration testing: Run end-to-end tests across services

If you use a monorepo (Turborepo, Nx, pnpm workspaces), Cursor has native visibility into all packages. This simplifies multi-service work but introduces noise. Use folder-scoped rules to keep the agent focused:

---
globs: "packages/api/**/*.ts"
---
This is the API package. It depends on:
- packages/shared-types for TypeScript interfaces
- packages/db for database queries via Drizzle ORM
API routes are in packages/api/src/routes/. Follow the pattern in users.ts for new routes.
Do not modify packages outside of packages/api/ unless explicitly asked.

Agent suggests changes to the wrong repo in a multi-root workspace. Add rules that constrain each service’s boundaries. Tell the agent explicitly which directories it should modify.

Contract documentation in rules becomes stale. Automate contract file copying as part of your CI or pre-commit hook. Or use OpenAPI/GraphQL schema files as the source of truth and reference them directly.

Agent does not understand service boundaries. Your rules need to explain the architecture. A brief description of which service owns which domain and how they communicate goes a long way.