# Monorepo Cache Audit > Audit one Turborepo monorepo's task and cache configuration - does turbo accept it, and is every cache hit a correct one - then fix it. The free check runs in the browser and uploads nothing: it reads the pasted turbo.json files, the root and workspace package.json files, pnpm-workspace.yaml, the CI workflow that runs turbo and a committed .turbo/config.json, parses the JSON with comments allowed keeping the line of every key, reads every task definition, every package with its scripts and framework, every turbo command in scripts and CI with its flags and every CI env entry, and runs 21 deterministic checks drawn from Turborepo practice. The paid audit rates the configuration, the task graph, the outputs and the hash inputs, confirms or dismisses every flag and gives exact before/after edits per finding; the paid fix lane writes the whole fixed file(s) and a changes list tied to the flags. The page checks every quote and line against the paste, applies every edit and file back into the paste, re-parses it and re-runs its checks - including that every task, package and script is still there and that no file was added - and calls out a reply that repeats a credential from the paste. App: https://monorepo-cache-audit.skillsafe.ai/ API tutorial: https://monorepo-cache-audit.skillsafe.ai/api.html ## Input - The configuration files pasted into one box, each introduced by a `# file: ` line (`# file: turbo.json`, `# file: apps/web/package.json`, `# file: .github/workflows/ci.yml`); dropped files or a dropped repository folder are joined that way automatically (node_modules, build output and other files are skipped). A paste with no `# file:` line is read as one file, named by what it looks like (turbo.json, package.json, pnpm-workspace.yaml or a CI workflow). - A file's directory is its package: `apps/web/turbo.json` is the package configuration of the package whose package.json is `apps/web/package.json`. The root files are the ones with no directory. - JSON is parsed with `//` and block comments and trailing commas allowed; a file that does not parse is named with its line and left out of the checks. CI files are read line by line (not as full YAML): `env:` and `variables:` blocks, and every line that runs turbo. - turbo commands are found in package scripts and CI lines (`turbo run build test`, `pnpm turbo build`, `npx turbo@2 run lint`), with their tasks and flags (`--filter`, `--force`, `--env-mode`, `--token`, `--api`). - Nothing is installed, hashed or run: every flag is a reading of the text, with the file and line it points at. The remote cache, the machines, .env and tsconfig files and unpasted packages are not visible: TR-22 says so, and the note is where you give facts ("the web build reads DATABASE_URL", "we install with pnpm 9.12.0"). ## Flags the free check raises - TR-01 (medium): a root package.json without turbo in its dependencies, or turbo at latest, *, x or a >= range. - TR-02 (high): a root package.json with no packageManager field (low when turbo is pinned to 1.x). - TR-03 (high): Turborepo 1 syntax - "pipeline", "outputMode", or "$VAR" entries in dependsOn (low when turbo is pinned to 1.x). - TR-04 (high): a package turbo.json without "extends": ["//"], or one that sets root-only keys (globalDependencies, globalEnv, globalPassThroughEnv, remoteCache, ui, envMode ...). - TR-05 (high): a turbo command in a script or CI runs a task that is not a key of tasks in any pasted turbo.json. - TR-06 (high): a credential written into the configuration - a secret-named CI variable (TURBO_TOKEN, *_SECRET, *_PASSWORD ...) with a literal value instead of a secret reference, a password in a URL, a token in .turbo/config.json, or --token=. The value is masked as *** everywhere the page shows it. - TR-07 (medium): remoteCache.apiUrl, TURBO_API or --api over http:// (localhost exempt). - TR-08 (high): the root build task has no "^build" while a pasted package with a build script depends on another pasted workspace package that has one. - TR-09 (high): a dependsOn entry that names a task marked "persistent": true. - TR-10 (medium): a long-running task (named dev, start, serve, watch, storybook, preview, or whose scripts run next dev, vite, tsx watch, nodemon or --watch) that is not "persistent": true, or not "cache": false. - TR-11 (high): a task with side effects (deploy, publish, release, migrate, db:push, seed, or scripts running vercel deploy, wrangler deploy, npm publish, changeset publish, prisma migrate deploy, docker push, kubectl apply, terraform apply ...) without "cache": false. - TR-12 (medium): a dependsOn entry naming a task that no pasted turbo.json defines. - TR-13 (high): a build task (named build, compile, bundle, dist or build:*, or whose scripts run next build, vite build, tsup, tsc, rollup, webpack, esbuild ...) that is cached and lists no outputs. - TR-14 (high): a package's build resolves to outputs that miss its framework's build directory (.next for Next.js, .output for Nuxt, dist for Vite, Astro and tsup). - TR-15 (low): .next/** in outputs without !.next/cache/** (medium: node_modules or .turbo in outputs). - TR-16 (medium): "cache": false on a repeatable task (build, test, lint, typecheck ...), or --force / --no-cache on a turbo command. - TR-17 (medium): inputs that do not include "$TURBO_DEFAULT$". - TR-18 (low): a Next.js, Vite, Nuxt, Astro, SvelteKit, Create React App or Expo package whose build inputs and globalDependencies do not name .env files. - TR-19 (medium): a variable a CI file that runs turbo sets in an env or variables block, not declared in any env, passThroughEnv, globalEnv or globalPassThroughEnv (wildcards honoured; TURBO_*, CI, NODE_OPTIONS and a few install-time variables and the framework prefixes Turborepo infers, such as NEXT_PUBLIC_* and VITE_*, are exempt). Not raised in loose mode, which TR-20 covers. - TR-20 (medium): "envMode": "loose" in the root turbo.json, or --env-mode=loose on a turbo command. - TR-21 (medium): globalDependencies of "**/*", "**" or "*"; GITHUB_SHA, a build number or another per-commit or per-run variable in globalEnv or a task's env. - TR-22 (info): context - counts, the turbo version and package manager, files that did not parse, what is outside the check. ## Free extras - Every task definition with its dependsOn, outputs, inputs and cache settings; every package with its framework, scripts and workspace dependencies; every turbo command with its flags; every file. - Put any audit finding (or all of them, or the fixed files) back into the paste and re-run the check; undo puts the original back. - Exports: the check as Markdown, the flags as CSV, the edited or fixed files, the changes as a unified .patch for git apply, the findings or changes as CSV, the whole result as JSON. A rerun of the same files says what moved since the last run of that lane. - Large pastes: the analysis sent to the model is bounded (about 60,000 characters; the 150 most severe flags first) and every cut is stated in facts.notes and on the page. ## Paid lanes (the `task` field) - `audit`: `{task, verdict: blocked|needs_work|ready, headline, repo, areas: [{area: config|graph|outputs|hashing, status: sound|fragile|broken, note}], findings: [{id, flags, file, line, severity, area, title, evidence, why, edits: [{before, after}]}], flag_answers: [{flag, status: confirmed|dismissed, reason}], plan, questions, summary}`. `before` is an exact slice of the file, applied in order; every edited file must still parse. - `fix`: `{task, verdict: fixed|partial, headline, files: [{path, content}], changes: [{file, task, flags, change, why}], verify, open: [{item, flags, reason}], questions, summary}`. `content` is the whole file; `task` is a task key or `(file)`; every task key, package and script stays, and no file is added. - Run input: `{task, code, facts, note?, audit_handoff?, retry_note?}` - all strings; `facts` is the page's analysis as a JSON string. The audit hands its findings to the fix lane with every edit applied to `code`. - The model never invents a version, a packageManager value, an endpoint, a team or a variable name: without one from the note or the paste the item is a question (audit) or left open (fix). - Model: gpt-terra, 10% publisher markup. A run needs a signed-in account; the reservation shown before a run is a hold, and only what the run uses is charged. ## Sources - turborepo-caching by Seth Hobson, wshobson/agents (github.com/wshobson/agents, plugins/developer-essentials/skills/turborepo-caching), MIT - https://skillsafe.ai/skill/@wshobson/turborepo-caching - The checks and the reconciliation are original to this app. Turborepo is a trademark of Vercel, Inc.; Monorepo Cache Audit is not affiliated with or endorsed by Vercel or the Turborepo project.