Pulled ALL skills from 15 source repositories: - anthropics/skills: 16 (docs, design, MCP, testing) - obra/superpowers: 14 (TDD, debugging, agents, planning) - coreyhaines31/marketingskills: 25 (marketing, CRO, SEO, growth) - better-auth/skills: 5 (auth patterns) - vercel-labs/agent-skills: 5 (React, design, Vercel) - antfu/skills: 16 (Vue, Vite, Vitest, pnpm, Turborepo) - Plus 13 individual skills from various repos Mosaic Stack is not limited to coding — the Orchestrator and subagents serve coding, business, design, marketing, writing, logistics, analysis, and more. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
7.9 KiB
Configuration Gotchas
Common mistakes and how to fix them.
#1 Root Scripts Not Using turbo run
Root package.json scripts for turbo tasks MUST use turbo run, not direct commands.
// WRONG - bypasses turbo, no parallelization or caching
{
"scripts": {
"build": "bun build",
"dev": "bun dev"
}
}
// CORRECT - delegates to turbo
{
"scripts": {
"build": "turbo run build",
"dev": "turbo run dev"
}
}
Why this matters: Running bun build or npm run build at root bypasses Turborepo entirely - no parallelization, no caching, no dependency graph awareness.
#2 Using && to Chain Turbo Tasks
Don't use && to chain tasks that turbo should orchestrate.
// WRONG - changeset:publish chains turbo task with non-turbo command
{
"scripts": {
"changeset:publish": "bun build && changeset publish"
}
}
// CORRECT - use turbo run, let turbo handle dependencies
{
"scripts": {
"changeset:publish": "turbo run build && changeset publish"
}
}
If the second command (changeset publish) depends on build outputs, the turbo task should run through turbo to get caching and parallelization benefits.
#3 Overly Broad globalDependencies
globalDependencies affects hash for ALL tasks in ALL packages. Be specific.
// WRONG - affects all hashes
{
"globalDependencies": ["**/.env.*local"]
}
// CORRECT - move to specific tasks that need it
{
"globalDependencies": [".env"],
"tasks": {
"build": {
"inputs": ["$TURBO_DEFAULT$", ".env*"],
"outputs": ["dist/**"]
}
}
}
Why this matters: **/.env.*local matches .env files in ALL packages, causing unnecessary cache invalidation. Instead:
- Use
globalDependenciesonly for truly global files (root.env) - Use task-level
inputsfor package-specific .env files with$TURBO_DEFAULT$to preserve default behavior
#4 Repetitive Task Configuration
Look for repeated configuration across tasks that can be collapsed.
// WRONG - repetitive env and inputs across tasks
{
"tasks": {
"build": {
"env": ["API_URL", "DATABASE_URL"],
"inputs": ["$TURBO_DEFAULT$", ".env*"]
},
"test": {
"env": ["API_URL", "DATABASE_URL"],
"inputs": ["$TURBO_DEFAULT$", ".env*"]
}
}
}
// BETTER - use globalEnv and globalDependencies
{
"globalEnv": ["API_URL", "DATABASE_URL"],
"globalDependencies": [".env*"],
"tasks": {
"build": {},
"test": {}
}
}
When to use global vs task-level:
globalEnv/globalDependencies- affects ALL tasks, use for truly shared config- Task-level
env/inputs- use when only specific tasks need it
#5 Using ../ to Traverse Out of Package in inputs
Don't use relative paths like ../ to reference files outside the package. Use $TURBO_ROOT$ instead.
// WRONG - traversing out of package
{
"tasks": {
"build": {
"inputs": ["$TURBO_DEFAULT$", "../shared-config.json"]
}
}
}
// CORRECT - use $TURBO_ROOT$ for repo root
{
"tasks": {
"build": {
"inputs": ["$TURBO_DEFAULT$", "$TURBO_ROOT$/shared-config.json"]
}
}
}
#6 MOST COMMON MISTAKE: Creating Root Tasks
DO NOT create Root Tasks. ALWAYS create package tasks.
When you need to create a task (build, lint, test, typecheck, etc.):
- Add the script to each relevant package's
package.json - Register the task in root
turbo.json - Root
package.jsononly containsturbo run <task>
// WRONG - DO NOT DO THIS
// Root package.json with task logic
{
"scripts": {
"build": "cd apps/web && next build && cd ../api && tsc",
"lint": "eslint apps/ packages/",
"test": "vitest"
}
}
// CORRECT - DO THIS
// apps/web/package.json
{ "scripts": { "build": "next build", "lint": "eslint .", "test": "vitest" } }
// apps/api/package.json
{ "scripts": { "build": "tsc", "lint": "eslint .", "test": "vitest" } }
// packages/ui/package.json
{ "scripts": { "build": "tsc", "lint": "eslint .", "test": "vitest" } }
// Root package.json - ONLY delegates
{ "scripts": { "build": "turbo run build", "lint": "turbo run lint", "test": "turbo run test" } }
// turbo.json - register tasks
{
"tasks": {
"build": { "dependsOn": ["^build"], "outputs": ["dist/**"] },
"lint": {},
"test": {}
}
}
Why this matters:
- Package tasks run in parallel across all packages
- Each package's output is cached individually
- You can filter to specific packages:
turbo run test --filter=web
Root Tasks (//#taskname) defeat all these benefits. Only use them for tasks that truly cannot exist in any package (extremely rare).
#7 Tasks That Need Parallel Execution + Cache Invalidation
Some tasks can run in parallel (don't need built output from dependencies) but must still invalidate cache when dependency source code changes. Using dependsOn: ["^taskname"] forces sequential execution. Using no dependencies breaks cache invalidation.
Use Transit Nodes for these tasks:
// WRONG - forces sequential execution (SLOW)
"my-task": {
"dependsOn": ["^my-task"]
}
// ALSO WRONG - no dependency awareness (INCORRECT CACHING)
"my-task": {}
// CORRECT - use Transit Nodes for parallel + correct caching
{
"tasks": {
"transit": { "dependsOn": ["^transit"] },
"my-task": { "dependsOn": ["transit"] }
}
}
Why Transit Nodes work:
transitcreates dependency relationships without matching any actual script- Tasks that depend on
transitgain dependency awareness - Since
transitcompletes instantly (no script), tasks run in parallel - Cache correctly invalidates when dependency source code changes
How to identify tasks that need this pattern: Look for tasks that read source files from dependencies but don't need their build outputs.
Missing outputs for File-Producing Tasks
Before flagging missing outputs, check what the task actually produces:
- Read the package's script (e.g.,
"build": "tsc","test": "vitest") - Determine if it writes files to disk or only outputs to stdout
- Only flag if the task produces files that should be cached
// WRONG - build produces files but they're not cached
"build": {
"dependsOn": ["^build"]
}
// CORRECT - outputs are cached
"build": {
"dependsOn": ["^build"],
"outputs": ["dist/**"]
}
No outputs key is fine for stdout-only tasks. For file-producing tasks, missing outputs means Turbo has nothing to cache.
Forgetting ^ in dependsOn
// WRONG - looks for "build" in SAME package (infinite loop or missing)
"build": {
"dependsOn": ["build"]
}
// CORRECT - runs dependencies' build first
"build": {
"dependsOn": ["^build"]
}
The ^ means "in dependency packages", not "in this package".
Missing persistent on Dev Tasks
// WRONG - dependent tasks hang waiting for dev to "finish"
"dev": {
"cache": false
}
// CORRECT
"dev": {
"cache": false,
"persistent": true
}
Package Config Missing extends
// WRONG - packages/web/turbo.json
{
"tasks": {
"build": { "outputs": [".next/**"] }
}
}
// CORRECT
{
"extends": ["//"],
"tasks": {
"build": { "outputs": [".next/**"] }
}
}
Without "extends": ["//"], Package Configurations are invalid.
Root Tasks Need Special Syntax
To run a task defined only in root package.json:
# WRONG
turbo run format
# CORRECT
turbo run //#format
And in dependsOn:
"build": {
"dependsOn": ["//#codegen"] // Root package's codegen
}
Overwriting Default Inputs
// WRONG - only watches test files, ignores source changes
"test": {
"inputs": ["tests/**"]
}
// CORRECT - extends defaults, adds test files
"test": {
"inputs": ["$TURBO_DEFAULT$", "tests/**"]
}
Without $TURBO_DEFAULT$, you replace all default file watching.
Caching Tasks with Side Effects
// WRONG - deploy might be skipped on cache hit
"deploy": {
"dependsOn": ["build"]
}
// CORRECT
"deploy": {
"dependsOn": ["build"],
"cache": false
}
Always disable cache for deploy, publish, or mutation tasks.