BoilerplateHub

Turborepo Monorepo AGENTS.md Template

For a pnpm workspace driven by Turborepo, with several deployable apps and shared internal packages. It assumes TypeScript project references, a shared UI package, and per-package scripts that Turbo orchestrates. Use it when the main risk is an agent editing the wrong package or breaking the dependency graph.

TurborepopnpmTypeScriptReactESLint
AGENTS.md
Download
# AGENTS.md

This is a pnpm workspace managed by Turborepo containing several deployable apps and shared internal packages.

## Project

Stack: pnpm workspaces, Turborepo, TypeScript, React, ESLint, Vitest.

```
apps/
  web/          public marketing site and app shell
  admin/        internal admin dashboard
  api/          HTTP service, deployed separately
packages/
  ui/           shared React components, no app imports
  core/         domain types and pure business logic
  db/           schema, client, and query helpers
  config/       shared eslint, tsconfig, and tailwind presets
```

Every package is private except where `publishConfig` says otherwise. Package names use the `@repo/` prefix.

Entry points: `turbo.json` (task graph), `pnpm-workspace.yaml` (package discovery), `packages/config/` (every shared preset).

## Architecture

Dependency direction is one way and enforced in review:

```
apps/*  ->  packages/ui, packages/core, packages/db
packages/ui   ->  packages/core
packages/db   ->  packages/core
packages/core ->  nothing internal
```

Rules that follow from this:

- A package in `packages/` never imports from `apps/`.
- `packages/core` has no React, no database driver, and no runtime environment assumptions.
- Cross app imports are forbidden. If `admin` needs something from `web`, it moves to a package.
- Shared code is added to an existing package before a new package is created. Ask before adding a package.
- Internal packages are consumed from TypeScript source, not from a build artifact.

## Commands

Use pnpm at the workspace root.

```bash
pnpm install                        # install the whole workspace
pnpm dev                            # turbo run dev across apps
pnpm build                          # turbo run build, respects the task graph
pnpm lint
pnpm typecheck
pnpm test

pnpm --filter @repo/ui build        # one package
pnpm --filter web dev               # one app
pnpm --filter @repo/core test       # one package's tests
pnpm --filter web add zod           # add a dependency to one package only
turbo run build --filter=web...     # a package and everything it depends on
```

Turbo caches task output. If a task reports success instantly it may be cached, use `--force` when verifying a fix.

Never run `pnpm add` at the root for a dependency that belongs to one package.

## Code style

- Each package exports through its `src/index.ts`. Deep imports into another package's internals are not allowed.
- `packages/ui` components take props only. No data fetching, no environment variables, no router imports.
- Shared packages have no top level side effects, importing them must be free.
- Types shared across packages live in `packages/core`, not duplicated per app.
- Extend the presets in `packages/config` rather than adding a local eslint or tsconfig rule.
- Keep one version of React, TypeScript, and every shared runtime dependency across the workspace.
- No default exports in shared packages, named exports keep refactors mechanical.

## Boundaries

Do not touch without explicit instruction:

- `turbo.json`, root `package.json`, `pnpm-workspace.yaml`.
- `pnpm-lock.yaml`. Use `pnpm --filter <pkg> add` and let it update.
- `packages/config/` presets, they change behavior for every package at once.
- `.github/workflows/` and any deploy configuration.
- Package `name`, `version`, or `exports` fields.

Needs human review: adding a new package, adding a dependency between packages, upgrading a shared runtime dependency, and anything that changes the public surface of `packages/core`.

## Testing

- `pnpm test` runs everything, `pnpm --filter @repo/core test` runs one package.
- `packages/core` and `packages/db` require tests for every exported function.
- `packages/ui` requires tests only for components with logic, not for layout wrappers.
- Apps require tests for route handlers and any code that is not a thin composition of packages.
- When changing a shared package, run the tests of every consumer: `turbo run test --filter=...@repo/core`.

## Git workflow

- Branch from `main`: `feat/short-description`, `fix/short-description`.
- Conventional commits with the package as scope: `fix(ui): correct focus ring on icon button`.
- A commit that touches several packages is fine when it is one logical change, otherwise split it.
- Any change to a package that is published requires a changeset: `pnpm changeset`.
- PR description lists which packages changed and whether consumers need updating.
- Never push to `main`.

What each section does

Project

In a monorepo the first question an agent gets wrong is which package a file belongs to. Listing apps and packages with a one-line purpose each turns that into a lookup. It also makes it obvious when a change is being made in the wrong layer.

Architecture

The dependency direction between packages is the rule that keeps a monorepo from collapsing into a tangle, and it is invisible from any single file. Writing it down stops an agent from adding an import that creates a cycle or pulls app code into a shared package. This is the section that pays for itself fastest.

Commands

Turbo commands run across the graph, so the difference between a root command and a filtered one is significant for both speed and blast radius. Showing the filter syntax means the agent works on one package instead of rebuilding everything. Include the cache behavior so it does not misread a cached success as a real one.

Code style

Shared packages have stricter rules than apps because their mistakes multiply across every consumer. Rules about exports, side effects, and public surface are the ones that actually matter here. Formatting is handled by tooling and does not need to be described.

Boundaries

Workspace plumbing, the root package.json, turbo.json, and tsconfig bases, breaks everything at once when it is wrong. Version drift between packages is another silent failure an agent can introduce with a single install. Mark these as human territory.

Testing

Tests live per package, so the agent needs to know how to run just the affected ones rather than the whole repo. Shared packages need higher coverage than apps because their consumers depend on stable behavior. State which packages are non-negotiable.

Git workflow

Monorepo commits benefit from a scope that names the package, since a reviewer scanning history needs to know what was touched. Changesets or a similar versioning step is easy to forget and blocks release when missed. Say when a version bump is required.

Which agents read this file?

Claude Code looks for CLAUDE.md. Most other agents and editors read AGENTS.md. Rather than maintaining both and letting them drift, keep one real file and symlink the other:

ln -s AGENTS.md CLAUDE.md
git add AGENTS.md CLAUDE.md

Git stores the symlink, so it survives cloning on macOS and Linux. On Windows it needs developer mode or a stub file that references the real one. The full comparison is in CLAUDE.md vs AGENTS.md.

Other templates

Reviews

Leave a comment

Your rating (optional)

0/2000