Skills · Coding

Turborepo Caching

Unverified24/40

Configure Turborepo for efficient monorepo builds with local and remote caching. Use when setting up Turborepo, optimizing build pipelines, or implementing distributed caching.

Originally by wshobson · MIT

Claude CodePartialHas SKILL.md but declares no allowed-tools — Claude Code will ask for permission each time
Cursor·UnknownWe have not crawled the repo tree, so we will not guess
Codex·UnknownWe have not crawled the repo tree, so we will not guess
Gemini CLI·UnknownThe spec defines no detection rule for Gemini
Copilot·UnknownWe have not crawled the repo tree, so we will not guess
npx agentalley add turborepo-caching

This command does not work yet — the CLI is still being built. Until then, use Raw in the reader below to take the file.

Who is stuck, and on what

Configure Turborepo for efficient monorepo builds with local and remote caching. Use when setting up Turborepo, optimizing build pipelines, or implementing distributed caching.

The whole source

No sign-in, no blur, nothing truncated
turborepo-caching/SKILL.md371 lines7.9 KBRawView on GitHub
Frontmatter — 2 properties
nameturborepo-caching
descriptionConfigure Turborepo for efficient monorepo builds with local and remote caching. Use when setting up Turborepo, optimizing build pipelines, or implementing distributed caching.
1---
2name: turborepo-caching
3description: Configure Turborepo for efficient monorepo builds with local and remote caching. Use when setting up Turborepo, optimizing build pipelines, or implementing distributed caching.
4---A5No allowed-tools declared — no way to tell what this skill may touch
5 
6# Turborepo Caching
7 
8Production patterns for Turborepo build optimization.
9 
10## When to Use This Skill
11 
12- Setting up new Turborepo projects
13- Configuring build pipelines
14- Implementing remote caching
15- Optimizing CI/CD performance
16- Migrating from other monorepo tools
17- Debugging cache misses
18 
19## Core Concepts
20 
21### 1. Turborepo Architecture
22 
23```
24Workspace Root/
25├── apps/
26│ ├── web/
27│ │ └── package.json
28│ └── docs/
29│ └── package.json
30├── packages/
31│ ├── ui/
32│ │ └── package.json
33│ └── config/
34│ └── package.json
35├── turbo.json
36└── package.json
37```
38 
39### 2. Pipeline Concepts
40 
41| Concept | Description |
42| -------------- | -------------------------------- |
43| **dependsOn** | Tasks that must complete first |
44| **cache** | Whether to cache outputs |
45| **outputs** | Files to cache |
46| **inputs** | Files that affect cache key |
47| **persistent** | Long-running tasks (dev servers) |
48 
49## Templates
50 
51### Template 1: turbo.json Configuration
52 
53```json
54{
55 "$schema": "https://turbo.build/schema.json",A2Sends to turbo.build — outside the allowlist, and this file also reads environment variables or keys
56 "globalDependencies": [".env", ".env.local"],
57 "globalEnv": ["NODE_ENV", "VERCEL_URL"],
58 "pipeline": {
59 "build": {
60 "dependsOn": ["^build"],
61 "outputs": ["dist/**", ".next/**", "!.next/cache/**"],
62 "env": ["API_URL", "NEXT_PUBLIC_*"]
63 },
64 "test": {
65 "dependsOn": ["build"],
66 "outputs": ["coverage/**"],
67 "inputs": ["src/**/*.tsx", "src/**/*.ts", "test/**/*.ts"]
68 },
69 "lint": {
70 "outputs": [],
71 "cache": true
72 },
73 "typecheck": {
74 "dependsOn": ["^build"],
75 "outputs": []
76 },
77 "dev": {
78 "cache": false,
79 "persistent": true
80 },
81 "clean": {
82 "cache": false
83 }
84 }
85}
86```
87 
88### Template 2: Package-Specific Pipeline
89 
90```json
91// apps/web/turbo.json
92{
93 "$schema": "https://turbo.build/schema.json",
94 "extends": ["//"],
95 "pipeline": {
96 "build": {
97 "outputs": [".next/**", "!.next/cache/**"],
98 "env": ["NEXT_PUBLIC_API_URL", "NEXT_PUBLIC_ANALYTICS_ID"]
99 },
100 "test": {
101 "outputs": ["coverage/**"],
102 "inputs": ["src/**", "tests/**", "jest.config.js"]
103 }
104 }
105}
106```
107 
108### Template 3: Remote Caching with Vercel
109 
110```bash
111# Login to Vercel
112npx turbo login
113 
114# Link to Vercel project
115npx turbo link
116 
117# Run with remote cache
118turbo build --remote-only
119 
120# CI environment variables
121TURBO_TOKEN=your-token
122TURBO_TEAM=your-team
123```
124 
125```yaml
126# .github/workflows/ci.yml
127name: CI
128 
129on:
130 push:
131 branches: [main]
132 pull_request:
133 
134env:
135 TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
136 TURBO_TEAM: ${{ vars.TURBO_TEAM }}
137 
138jobs:
139 build:
140 runs-on: ubuntu-latest
141 steps:
142 - uses: actions/checkout@v4
143 
144 - uses: actions/setup-node@v4
145 with:
146 node-version: 20
147 cache: "npm"
148 
149 - name: Install dependencies
150 run: npm ci
151 
152 - name: Build
153 run: npx turbo build --filter='...[origin/main]'
154 
155 - name: Test
156 run: npx turbo test --filter='...[origin/main]'
157```
158 
159### Template 4: Self-Hosted Remote Cache
160 
161```typescript
162// Custom remote cache server (Express)
163import express from "express";
164import { createReadStream, createWriteStream } from "fs";
165import { mkdir } from "fs/promises";
166import { join } from "path";
167 
168const app = express();
169const CACHE_DIR = "./cache";
170 
171// Get artifact
172app.get("/v8/artifacts/:hash", async (req, res) => {
173 const { hash } = req.params;
174 const team = req.query.teamId || "default";
175 const filePath = join(CACHE_DIR, team, hash);
176 
177 try {
178 const stream = createReadStream(filePath);
179 stream.pipe(res);
180 } catch {
181 res.status(404).send("Not found");
182 }
183});
184 
185// Put artifact
186app.put("/v8/artifacts/:hash", async (req, res) => {
187 const { hash } = req.params;
188 const team = req.query.teamId || "default";
189 const dir = join(CACHE_DIR, team);
190 const filePath = join(dir, hash);
191 
192 await mkdir(dir, { recursive: true });
193 
194 const stream = createWriteStream(filePath);
195 req.pipe(stream);
196 
197 stream.on("finish", () => {
198 res.json({
199 urls: [`${req.protocol}://${req.get("host")}/v8/artifacts/${hash}`],
200 });
201 });
202});
203 
204// Check artifact exists
205app.head("/v8/artifacts/:hash", async (req, res) => {
206 const { hash } = req.params;
207 const team = req.query.teamId || "default";
208 const filePath = join(CACHE_DIR, team, hash);
209 
210 try {
211 await fs.access(filePath);
212 res.status(200).end();
213 } catch {
214 res.status(404).end();
215 }
216});
217 
218app.listen(3000);
219```
220 
221```json
222// turbo.json for self-hosted cache
223{
224 "remoteCache": {
225 "signature": false
226 }
227}
228```
229 
230```bash
231# Use self-hosted cache
232turbo build --api="http://localhost:3000" --token="my-token" --team="my-team"
233```
234 
235### Template 5: Filtering and Scoping
236 
237```bash
238# Build specific package
239turbo build --filter=@myorg/web
240 
241# Build package and its dependencies
242turbo build --filter=@myorg/web...
243 
244# Build package and its dependents
245turbo build --filter=...@myorg/ui
246 
247# Build changed packages since main
248turbo build --filter='...[origin/main]'
249 
250# Build packages in directory
251turbo build --filter='./apps/*'
252 
253# Combine filters
254turbo build --filter=@myorg/web --filter=@myorg/docs
255 
256# Exclude package
257turbo build --filter='!@myorg/docs'
258 
259# Include dependencies of changed
260turbo build --filter='...[HEAD^1]...'
261```
262 
263### Template 6: Advanced Pipeline Configuration
264 
265```json
266{
267 "$schema": "https://turbo.build/schema.json",
268 "pipeline": {
269 "build": {
270 "dependsOn": ["^build"],
271 "outputs": ["dist/**"],
272 "inputs": ["$TURBO_DEFAULT$", "!**/*.md", "!**/*.test.*"]
273 },
274 "test": {
275 "dependsOn": ["^build"],
276 "outputs": ["coverage/**"],
277 "inputs": ["src/**", "tests/**", "*.config.*"],
278 "env": ["CI", "NODE_ENV"]
279 },
280 "test:e2e": {
281 "dependsOn": ["build"],
282 "outputs": [],
283 "cache": false
284 },
285 "deploy": {
286 "dependsOn": ["build", "test", "lint"],
287 "outputs": [],
288 "cache": false
289 },
290 "db:generate": {
291 "cache": false
292 },
293 "db:push": {
294 "cache": false,
295 "dependsOn": ["db:generate"]
296 },
297 "@myorg/web#build": {
298 "dependsOn": ["^build", "@myorg/db#db:generate"],
299 "outputs": [".next/**"],
300 "env": ["NEXT_PUBLIC_*"]
301 }
302 }
303}
304```
305 
306### Template 7: Root package.json Setup
307 
308```json
309{
310 "name": "my-turborepo",
311 "private": true,
312 "workspaces": ["apps/*", "packages/*"],
313 "scripts": {
314 "build": "turbo build",
315 "dev": "turbo dev",
316 "lint": "turbo lint",
317 "test": "turbo test",
318 "clean": "turbo clean && rm -rf node_modules",
319 "format": "prettier --write \"**/*.{ts,tsx,md}\"",
320 "changeset": "changeset",
321 "version-packages": "changeset version",
322 "release": "turbo build --filter=./packages/* && changeset publish"
323 },
324 "devDependencies": {
325 "turbo": "^1.10.0",
326 "prettier": "^3.0.0",
327 "@changesets/cli": "^2.26.0"
328 },
329 "packageManager": "[email protected]"
330}
331```
332 
333## Debugging Cache
334 
335```bash
336# Dry run to see what would run
337turbo build --dry-run
338 
339# Verbose output with hashes
340turbo build --verbosity=2
341 
342# Show task graph
343turbo build --graph
344 
345# Force no cache
346turbo build --force
347 
348# Show cache status
349turbo build --summarize
350 
351# Debug specific task
352TURBO_LOG_VERBOSITY=debug turbo build --filter=@myorg/web
353```
354 
355## Best Practices
356 
357### Do's
358 
359- **Define explicit inputs** - Avoid cache invalidation
360- **Use workspace protocol** - `"@myorg/ui": "workspace:*"`
361- **Enable remote caching** - Share across CI and local
362- **Filter in CI** - Build only affected packages
363- **Cache build outputs** - Not source files
364 
365### Don'ts
366 
367- **Don't cache dev servers** - Use `persistent: true`
368- **Don't include secrets in env** - Use runtime env vars
369- **Don't ignore dependsOn** - Causes race conditions
370- **Don't over-filter** - May miss dependencies
371 

Reviews

Installed this one?Write the first review and take the Trailblazer badge.

Reviews only open after a real install, so this is empty — and we leave it empty rather than invent one.

Alternatives

Also in Coding