pnpm + Turborepo Monorepo Instructions
CLAUDE.md for a pnpm/Turborepo monorepo: package boundary rules, the task pipeline, affected-only builds, and how agents should add dependencies without breaking workspaces.
Use when: Use at the root of a pnpm workspace with Turborepo so agents scope commands to the right package, respect import boundaries, and avoid running the entire pipeline for one-package changes.
The skill file
Claude Code · CLAUDE.mdCLAUDE.md3114 chars
# Project Instructions — Monorepo (pnpm + Turborepo)
## Layout
```
apps/web/ # customer-facing app
apps/admin/ # internal admin app
packages/ui/ # shared React components — no app-specific code
packages/core/ # domain logic, framework-free TypeScript
packages/config/ # shared eslint/ts/tailwind config presets
```
Workspace names follow `@<your-scope>/<dir>`, e.g. `@acme/ui`. Use the workspace name, not relative paths, when importing across packages.
## Commands
Always scope to the package you changed; full-repo runs are for pre-commit verification only.
```bash
pnpm turbo run build --filter=@acme/web # build one app + its deps
pnpm turbo run test --filter=@acme/core # test one package
pnpm turbo run test --filter='...[origin/main]' # affected-only: everything changed vs main
pnpm turbo run lint typecheck test build # full pipeline — before committing
pnpm --filter @acme/web dev # dev server for one app
```
`--filter='...[origin/main]'` (changed packages plus their dependents) is the default verification for any change. Run the unfiltered pipeline only when you touched root config, `turbo.json`, or `packages/config/`.
## Dependency rules
- Add dependencies with `pnpm add <pkg> --filter @acme/<target>` — never edit a `package.json` dependencies block by hand, and never `pnpm add` at the root unless it is a repo-wide dev tool.
- Internal dependencies use `"workspace:*"`. If you import from a sibling package, you must add it to that package's `package.json`; pnpm's strict node linker will fail otherwise — that failure is correct, do not work around it with root installs.
- Allowed import directions: `apps/* → packages/*`, `packages/ui → packages/core`. Never `packages/* → apps/*`, and never between the two apps. If two apps need the same code, move it into a package.
## Pipeline (turbo.json)
- `build` depends on `^build` (upstream packages build first). `test` and `typecheck` depend on `^build`.
- Outputs are cached. If a task seems stale, run with `--force` once to confirm before suspecting the cache; do not delete `.turbo/` as a first resort.
- When you add a task to a package, register it in `turbo.json` with correct `dependsOn` and `outputs`, otherwise caching will silently misbehave.
## Conventions
- Each package owns its `tsconfig.json`, extending `@acme/config/tsconfig.base.json`. Do not duplicate compiler options that the base already sets.
- Shared packages export through an explicit `exports` map in `package.json` — no deep imports like `@acme/core/src/internal/foo`.
- Changes that touch a shared package require running tests for its dependents: `pnpm turbo run test --filter='...@acme/core'` (note the leading `...` selects dependents).
- Generated files (`dist/`, `.turbo/`, `*.tsbuildinfo`) are never edited or committed.
## Gotchas
- Node version is pinned in `.nvmrc` and `engines`; pnpm version in `packageManager`. Do not bump either casually.
- `pnpm-lock.yaml` conflicts: take main's version, then re-run `pnpm install` — never hand-merge the lockfile.
Install
drop into your repoSave this to your project or home directory so Claude Code can load it.
path./CLAUDE.md
Discussion
What people are saying
Forks
0 forks of this skillLoading forks…