Monorepo Navigation
Working effectively in monorepo codebases with package boundaries, workspace tools, shared dependencies, and scoped changes.
You are an AI agent working within monorepo codebases. Your role is to understand package boundaries, navigate workspace structures, manage cross-package dependencies, and ensure changes are scoped correctly — all while respecting the monorepo's tooling and conventions. ## Key Points - Start by identifying the workspace configuration: `package.json` workspaces field, `pnpm-workspace.yaml`, `turbo.json`, `nx.json`, `lerna.json`, or `Cargo.toml` with workspace members. - Map the top-level directory structure. Common layouts: `packages/`, `apps/`, `libs/`, `services/`, or `modules/` directories. - Read the root configuration to understand how packages relate: shared dependencies, build ordering, and naming conventions. - Each package typically has its own `package.json` (Node), `Cargo.toml` (Rust), `go.mod` (Go), or equivalent manifest. - Look for a root-level README or CONTRIBUTING file that explains the monorepo's conventions. - Each package should have a clear public API — exported functions, types, and components. Internal implementation is private. - When importing from another package, import from the package's entry point (e.g., `@org/utils`), not from internal paths (`@org/utils/src/internal/helper`). - If you need something from another package's internals, that is a signal the package's public API needs extending, not that you should reach in. - Check for explicit dependency declarations. A package must declare its dependencies in its own manifest, not rely on hoisting. - **npm/yarn/pnpm workspaces**: Handle dependency installation and linking between packages. Understand hoisting behavior — pnpm isolates by default, npm/yarn hoist to root. - **Turborepo**: Orchestrates build tasks with caching and parallelism. Reads `turbo.json` for pipeline definitions. Respects dependency graph for task ordering. - **Nx**: Provides dependency graph visualization, affected package detection, and computation caching. Uses `nx.json` and `project.json` per package.
skilldb get autonomous-agent-skills/monorepo-navigationFull skill: 79 linesMonorepo Navigation
You are an AI agent working within monorepo codebases. Your role is to understand package boundaries, navigate workspace structures, manage cross-package dependencies, and ensure changes are scoped correctly — all while respecting the monorepo's tooling and conventions.
Philosophy
A monorepo is not a single project — it is a collection of projects that share a repository for coordination benefits. The key discipline is respecting package boundaries. Code changes should be scoped to the smallest set of packages necessary. Shared code should be explicitly shared through defined interfaces, not through implicit imports across boundaries. The monorepo's tooling exists to manage complexity; learn the tools before fighting the structure.
Techniques
Understanding Monorepo Structure
- Start by identifying the workspace configuration:
package.jsonworkspaces field,pnpm-workspace.yaml,turbo.json,nx.json,lerna.json, orCargo.tomlwith workspace members. - Map the top-level directory structure. Common layouts:
packages/,apps/,libs/,services/, ormodules/directories. - Read the root configuration to understand how packages relate: shared dependencies, build ordering, and naming conventions.
- Each package typically has its own
package.json(Node),Cargo.toml(Rust),go.mod(Go), or equivalent manifest. - Look for a root-level README or CONTRIBUTING file that explains the monorepo's conventions.
Package Boundaries
- Each package should have a clear public API — exported functions, types, and components. Internal implementation is private.
- When importing from another package, import from the package's entry point (e.g.,
@org/utils), not from internal paths (@org/utils/src/internal/helper). - If you need something from another package's internals, that is a signal the package's public API needs extending, not that you should reach in.
- Check for explicit dependency declarations. A package must declare its dependencies in its own manifest, not rely on hoisting.
Workspace Tools
- npm/yarn/pnpm workspaces: Handle dependency installation and linking between packages. Understand hoisting behavior — pnpm isolates by default, npm/yarn hoist to root.
- Turborepo: Orchestrates build tasks with caching and parallelism. Reads
turbo.jsonfor pipeline definitions. Respects dependency graph for task ordering. - Nx: Provides dependency graph visualization, affected package detection, and computation caching. Uses
nx.jsonandproject.jsonper package. - Lerna: Manages versioning and publishing for multi-package repositories. Often used alongside workspace tools.
- Run tasks through the monorepo tool (
turbo run build,nx build my-app), not directly in each package, to leverage caching and correct ordering.
Shared Dependencies
- Keep shared dependencies at the root level to ensure consistent versions across packages.
- Use the monorepo tool's deduplication features to prevent version conflicts.
- When adding a dependency, determine if it belongs to a specific package or is shared across many.
- Pin versions of critical shared dependencies to prevent one package's update from breaking others.
- Watch for phantom dependencies — packages using dependencies they did not explicitly declare, relying on hoisting.
Cross-Package Changes
- When a change in one package affects its public API, identify all consuming packages and update them in the same PR.
- Use the monorepo tool's affected detection (
turbo run test --filter=...[HEAD],nx affected:test) to find packages impacted by a change. - When modifying a shared package, run tests for all dependent packages, not just the changed package.
- If a shared package change is large, consider a phased approach: add the new API first, migrate consumers, then remove the old API.
Build Ordering
- Understand that packages must be built in dependency order. If
appdepends onutils,utilsmust build first. - The monorepo tool handles this automatically when the dependency graph is correctly declared.
- If builds fail with "module not found" for a workspace package, the build order is likely wrong or the dependency is not declared.
- Use
turbo.jsonpipeline ornx.jsontargetDependencies to define task dependencies (e.g.,builddepends on upstreambuild).
Keeping Changes Scoped
- When making a change, identify the minimum set of packages that need modification.
- Do not make unrelated changes to other packages in the same PR — it makes review harder and increases risk.
- If a change requires touching many packages, consider whether the change should be in a shared package instead.
- Use path-based filtering in CI to run only the tests relevant to changed packages.
Best Practices
- Learn the specific monorepo tooling before making changes. Each tool has its own conventions and commands.
- Use the dependency graph to understand impact. Change a leaf package with confidence; change a core shared package with caution.
- Run the monorepo's lint, type-check, and test commands from the root to validate the full dependency chain.
- When creating a new package, follow existing conventions: naming, directory structure, configuration patterns.
- Keep package interfaces narrow. The more a package exposes, the harder it is to change.
- Use workspace-level scripts for common operations so all developers use the same commands.
Anti-Patterns
- Importing across package boundaries via relative paths: Bypasses the package's public API and creates invisible coupling. Always import via the package name.
- Not declaring dependencies: Relying on hoisting to make undeclared dependencies available. Works until someone changes the install configuration.
- Building packages individually without the orchestrator: Misses dependency ordering and caching. Always use the monorepo tool.
- Putting everything in a shared package: A "commons" package that every other package depends on becomes a bottleneck. Share intentionally.
- Ignoring affected detection: Running all tests for every change wastes time. Use the tools designed to identify what is affected.
- Cross-package circular dependencies: Package A depends on B, B depends on A. This blocks builds and indicates a design problem. Extract shared code into a third package.
- Modifying multiple unrelated packages in one PR: Makes review difficult and increases the chance of merge conflicts with other developers.
Install this skill directly: skilldb add autonomous-agent-skills
Related Skills
Multi File Editing
Coordinating changes across multiple files safely with consistency guarantees, dependency tracking, and partial-update prevention
Next.js Patterns
Next.js application development patterns — App Router, server components, server actions, data fetching, middleware, route handlers, static generation, and metadata management.
NoSQL Patterns
Working with NoSQL databases effectively — MongoDB document design, Redis data structures, DynamoDB access patterns, denormalization strategies, eventual consistency, secondary indexes, TTL expiration, and atomic operations.
Observability Instrumentation
Adding telemetry to code systematically with traces, metrics, and structured logs
ORM Patterns
Working with Object-Relational Mappers effectively — Prisma, Sequelize, SQLAlchemy, TypeORM patterns for relation handling, migrations, query optimization, and transaction management.
Output Verification
Systematic verification of your own work through testing, diff review, regression checking, and scope validation before presenting results