About turborepo
A skill that sets conventions for using Turborepo with pnpm workspaces in monorepos. It guides agents through package layout, dependency management, task configuration, and caching, including projects with non-JavaScript components.
Key features
- 01pnpm workspace conventions
- 02Monorepo package layout
- 03Turborepo task configuration
- 04Cache inputs and outputs
- 05Non-JavaScript project guidance
Use cases
- 01Creating a Turborepo monorepo
- 02Adding internal workspace dependencies
- 03Configuring task pipelines and caching
- 04Running Rust or Python tasks in the workspace
Install
Copy the command and run it in a terminal.
npx skills add https:/ / github.com/ philtzjp/ skills --skill turborepoAfter installing, type/turborepoin Claude Code to confirm it loaded.
Details
From the project READMEturborepo
方針
Turborepo と pnpm ワークスペースの組み合わせに従う。パッケージマネージャーは pnpm に統一し、ロックファイルは pnpm-lock.yaml だけをコミットする。
Turborepo は更新が速く、turbo.json のキー名も変わってきている。設定の形に迷ったら記憶に頼らず下を引く。
- ドキュメント https://turborepo.dev/docs
- turbo.json のリファレンス https://turborepo.dev/docs/reference/configuration
- タスクの構成 https://turborepo.dev/docs/crafting-your-repository/configuring-tasks
- キャッシュ https://turborepo.dev/docs/crafting-your-repository/caching
- 複数言語の扱い https://turborepo.dev/docs/guides/multi-language
- 更新情報 https://turborepo.dev/blog
- リリースと破壊的変更 https://github.com/vercel/turborepo/releases
turbo.json のタスク定義キーは v2 以降 tasks。pipeline は旧名。古い記事を写さない。
Turborepo をグローバルにインストールしない。pnpm exec turbo を使うか、ルートの devDependency として入れる。
構成
my-monorepo/
pnpm-workspace.yaml
turbo.json
package.json
apps/ デプロイ可能なアプリケーション
packages/ 共有ライブラリと設定
- ワークスペース構成は pnpm-workspace.yaml で定義する。
- apps と packages の分離を維持する。デプロイ可能なアプリを packages に置かない。共有ライブラリを apps に置かない。
- ネストしたパッケージを作らない。
パッケージ
- 名前は
@<org>/プレフィックスを持つスコープ付きにする。 - 内部パッケージにはすべて
"private": trueを設定する。 - 各 package.json に exports を定義する。main より exports を優先する。
- 共有 TypeScript 設定を packages/tsconfig/ に置き、各パッケージがそれを継承する。
- 内部依存は
workspace:*プロトコルで参照する。
責務パッケージ
次を packages 配下に必ず置く。
- log ログ集約
- error エラー集約
- prompt AI プロンプト集約
- env 環境変数集約
- db データベース集約
利用側は @<org>/log などを workspace:* で依存に追加する。該当する責務を呼び出し側で再実装しない。
package.json の生成と更新
package.json をゼロから手書きしない。ルート、apps/、packages/ のいずれでも同じ。
pnpm init # package.json を生成する
pnpm create <template> # フレームワークの scaffolder を使う
依存関係の追加、更新、削除はコマンドで行う。
pnpm add -D -w turbo typescript # ルートの devDependency
pnpm add --filter @<org>/dashboard zod # 特定パッケージの外部依存
pnpm add --filter @<org>/dashboard --workspace @<org>/log # 内部依存を workspace:* で解決
pnpm update --filter @<org>/dashboard
pnpm remove --filter @<org>/dashboard zod
- ルート以外を対象にするときは
--filterでパッケージを指定する。 - ワークスペース内部依存には
--workspaceを併用する。 - dependencies、devDependencies、peerDependencies を直接編集しない。
- コマンドで設定できないフィールド(name のスコープ化、private、exports、scripts)だけ、生成済みの package.json に最小限の編集を加える。
手順例
# ルートワークスペース
mkdir my-monorepo && cd my-monorepo
pnpm init
# pnpm-workspace.yaml に apps/* と packages/* を定義する
pnpm add -D -w turbo typescript
# 責務パッケージ
mkdir -p packages/log
(cd packages/log && pnpm init)
# name を @<org>/log にし、private と exports を設定する
# アプリ
pnpm create next-app@latest apps/dashboard
pnpm add --filter @<org>/dashboard --workspace @<org>/log
turbo.json
依存関係を考慮したタスクパイプラインを定義する。
{
"$schema": "https://turborepo.dev/schema.json",
"tasks": {
"build": {
"dependsOn": ["^build"],
"outputs": ["dist/**", ".next/**", "!.next/cache/**"]
},
"lint": {},
"test": { "dependsOn": ["^build"] },
"dev": { "cache": false, "persistent": true }
}
}
^buildは依存パッケージのタスクを先に走らせる指定。- outputs を正確に書く。書き漏らすとキャッシュから復元されない。
- dev のような常駐タスクは
cache: falseとpersistent: trueにする。 - 環境変数がビルド結果に影響するなら env に列挙する。列挙しないと環境が違ってもキャッシュが当たる。
コンパイル方針
デフォルトは JIT(Just-in-Time)コンパイルパターンを採る。tsc で dist に出すコンパイル済みパターンへの切り替えは、明示的に要求されたときだけ行う。
非 JavaScript プロジェクト
Turborepo は JavaScript 専用ではない。Cargo、Go、Python などのプロジェクトも同じタスクグラフに載せられる。
Rust(Cargo)と Python は、独立してキャッシュしたい単位ごとに package.json を置き、その scripts から各言語のツールチェーンを呼ぶ。Turborepo はネイティブの依存グラフを解析せず、パッケージマネージャー上の関係を使う。
{
"name": "@<org>/engine",
"private": true,
"scripts": {
"build": "cargo build --release",
"test": "cargo test",
"lint": "cargo clippy -- -D warnings"
}
}
turbo.json 側で inputs と outputs を書き、キャッシュを効かせる。
{
"tasks": {
"build": {
"inputs": ["src/**", "Cargo.toml", "Cargo.lock"],
"outputs": ["target/release/**"]
}
}
}
- inputs を絞らないと、無関係なファイルの変更でキャッシュが外れる。
- outputs に target 全体を指定すると成果物が巨大になる。必要なパスだけ指定する。
- Cargo 自身のインクリメンタルキャッシュと二重になる。どちらで効かせるかを決めてから設定する。
Go は experimental なネイティブ対応がある。turbo.json で futureFlags を有効にし、go.work にモジュールを列挙する。この場合 Go パッケージ側に package.json は不要で、モジュールパスがパッケージの識別子になる。
{
"futureFlags": { "experimentalGoWorkspaces": true }
}
experimental なので挙動が変わり得る。採用前に上のドキュメントで現状を確認する。
確定前に確認する
- pnpm 以外のロックファイル(package-lock.json、yarn.lock)が混ざっていないか。
- デプロイ可能なアプリが packages に、共有ライブラリが apps に入っていないか。
- 内部依存が
workspace:*になっているか。 - 各パッケージが private と exports を持ち、共有 tsconfig を継承しているか。
- 責務パッケージを呼び出し側で再実装していないか。
- turbo.json のキーが tasks になっているか。pipeline のまま残っていないか。
- outputs と inputs と env が正確か。キャッシュが誤って当たる、または常に外れる状態になっていないか。
- 依存の追加を手書きの package.json 編集で済ませていないか。
- turbo をグローバルインストールしていないか。