Environment Variables

Purpose and Scope

Environment variables affect two different parts of a Turborepo workflow, and confusing those parts is the main source of environment-related cache bugs. Application environment variables are inputs to your package scripts: an API URL, public framework prefix, feature flag, package version, or deployment target can change what a build emits. System environment variables configure the turbo process itself: cache sources, Remote Cache endpoints, authentication, logging, package-manager checks, and CI behavior. This page explains both categories, but it focuses first on making task hashes and task runtime environments match the real behavior of your apps.

Sources: apps/docs/content/docs/crafting-your-repository/using-environment-variables.mdx, apps/docs/content/docs/reference/system-environment-variables.mdx

Turborepo’s environment guidance is organized around three practical questions: whether variables are included in the task hash, which Environment Mode controls variables at runtime, and how .env files are handled. These questions matter because a cache hit reuses previous outputs. If a variable changes but was not part of the hash, Turborepo can restore artifacts produced under the wrong configuration. The official guide calls out the serious version of this problem: shipping a preview deployment with production-like configuration, or the reverse, because the build output did not reflect the environment used to produce it.

Sources: apps/docs/content/docs/crafting-your-repository/using-environment-variables.mdx

Relevant Source Files

  • apps/docs/content/docs/crafting-your-repository/using-environment-variables.mdx - Task-oriented guide for adding variables to hashes, choosing Environment Modes, framework inference, and handling .env files.
  • apps/docs/content/docs/reference/configuration.mdx - Reference for turbo.json fields such as globalEnv, globalPassThroughEnv, and task configuration behavior.
  • apps/docs/content/docs/reference/options-overview.mdx - Reference overview that defines the precedence model across turbo.json, system environment variables, and CLI flags.
  • apps/docs/content/docs/reference/system-environment-variables.mdx - Catalog of variables that change Turborepo behavior, including cache, Remote Cache, binary, color, and CI-related settings.
  • apps/docs/content/blog/free-vercel-remote-cache.mdx - Product documentation for Vercel Remote Cache setup, including TURBO_TOKEN and TURBO_TEAM in non-Vercel CI.
  • apps/docs/content/blog/joining-vercel.mdx - Historical product context for Vercel-backed zero-configuration Remote Caching and the open-source CLI.

Task Hashing Model

A task hash is Turborepo’s description of everything that should make a task’s outputs different. For environment variables, the two primary turbo.json keys are globalEnv and env. globalEnv declares variables whose value changes should invalidate every task in the workspace. It is appropriate for values that genuinely shape the whole repository, such as a package version, release channel, or shared token used by several build systems. Task-level env is more granular: it attaches variables to the task that actually consumes them, so a build task can miss cache when MY_API_URL changes without forcing an unrelated lint task to rerun.

Sources: apps/docs/content/docs/crafting-your-repository/using-environment-variables.mdx, apps/docs/content/docs/reference/configuration.mdx

{
  "globalEnv": ["IMPORTANT_GLOBAL_VARIABLE"],
  "tasks": {
    "build": {
      "env": ["MY_API_URL", "MY_API_KEY"]
    }
  }
}

The reference configuration page reinforces the difference between global and task-scoped environment declarations. globalEnv impacts the hash of all tasks, so it is powerful but intentionally broad. globalPassThroughEnv has a different job: it makes variables available to tasks without making their values part of cache keys. That distinction is important for secrets and machine-level values. If a variable can change task outputs, include it in env or globalEnv; if it is needed only at runtime and should not invalidate cache, pass it through. Turborepo also includes a built-in global passthrough set for common operating system variables such as HOME, PATH, APPDATA, SHELL, and PWD.

Sources: apps/docs/content/docs/reference/configuration.mdx

Environment Modes

Environment Modes control which variables are visible to package scripts when turbo runs them. Strict Mode is the default and filters the runtime environment down to the variables declared in env, globalEnv, and passthrough configuration, plus Turborepo’s built-in passthrough variables. Strict Mode is the safest choice for reproducible builds because it forces the repository configuration to document what tasks actually depend on. If a script fails because a variable is missing, the fix is usually to declare that variable in the right place rather than to bypass the model.

Sources: apps/docs/content/docs/crafting-your-repository/using-environment-variables.mdx, apps/docs/content/docs/reference/configuration.mdx

Loose Mode is useful when adopting Turborepo incrementally or when a package relies on a larger ambient environment. In Loose Mode, more variables from the surrounding shell are available to the task at runtime, but availability is not the same as hashing. A variable that is visible in Loose Mode still needs to be listed in env or globalEnv if changes to its value should cause cache misses. Treat Loose Mode as a compatibility tool, not a substitute for explicit cache inputs, because it can hide undeclared dependencies until a different machine, CI job, or deployment target runs the same task.

Sources: apps/docs/content/docs/crafting-your-repository/using-environment-variables.mdx

Framework Inference and Wildcards

Many frontend frameworks expose client-safe variables through well-known prefixes, and Turborepo can infer those prefixes per package. The guide lists framework inference for Next.js with NEXT_PUBLIC_*, Vite and SolidStart with VITE_*, Create React App with REACT_APP_*, Gatsby with GATSBY_*, Nuxt with NUXT_* and NUXT_ENV_*, Expo with EXPO_PUBLIC_*, Astro and SvelteKit with PUBLIC_*, Remix with REMIX_*, RedwoodJS with REDWOOD_ENV_*, and Sanity with SANITY_STUDIO_*. This reduces boilerplate for common app builds while preserving the core rule: values that shape outputs belong in the hash.

Sources: apps/docs/content/docs/crafting-your-repository/using-environment-variables.mdx

Framework inference is per package, so it follows the framework detected in the package where the task runs rather than becoming a repository-wide blanket. You can opt out globally for an invocation with --framework-inference=false, or you can use a negative wildcard in env, such as !NEXT_PUBLIC_*, when a task should not include an inferred prefix. Wildcards also help with custom conventions. For example, a platform team might standardize on APP_PUBLIC_* for browser-safe values or SERVICE_* for backend builds, then use a wildcard instead of naming every variable one by one.

Sources: apps/docs/content/docs/crafting-your-repository/using-environment-variables.mdx, apps/docs/content/docs/reference/configuration.mdx

System Environment Variables and Precedence

System environment variables configure Turborepo itself, not the application code running inside tasks. The options overview defines three ways to manage a turbo invocation: turbo.json, system environment variables, and CLI flags. Use turbo.json for committed defaults, system variables for machine-specific or CI-specific overrides, and flags for one-off invocations. When more than one layer controls the same behavior, flags win over system environment variables and system environment variables override configuration defaults. This precedence model keeps repository defaults stable while allowing CI and local shells to adapt behavior without editing source files.

Sources: apps/docs/content/docs/reference/options-overview.mdx, apps/docs/content/docs/reference/system-environment-variables.mdx

Common system variables include FORCE_COLOR for terminal color, TURBO_BINARY_PATH for rare manual binary discovery cases, TURBO_CACHE for selecting cache sources, TURBO_CACHE_DIR for the local cache directory, TURBO_CACHE_MAX_AGE and TURBO_CACHE_MAX_SIZE for local filesystem cache eviction, and TURBO_DANGEROUSLY_DISABLE_PACKAGE_MANAGER_CHECK for disabling root package-manager declaration checks. Remote Cache settings include TURBO_API, which sets the base URL, plus timeout and preflight variables described in the reference table. These variables change how turbo behaves; they are separate from application variables like MY_API_URL that task scripts consume.

Sources: apps/docs/content/docs/reference/system-environment-variables.mdx, apps/docs/content/docs/reference/options-overview.mdx

Remote Cache and CI Authentication

Remote Caching adds another environment-variable category: credentials and connection details for sharing artifacts across developers and CI. The Vercel Remote Cache announcement states that commands using turbo on Vercel are automatically configured for Remote Cache, but other CI providers should set TURBO_TOKEN and TURBO_TEAM with their respective values. Locally, the documented flow is npx turbo login followed by npx turbo link. These variables authenticate cache access; they should generally be treated as system or secret runtime inputs rather than task-output inputs unless a task directly changes its outputs based on them.

Sources: apps/docs/content/blog/free-vercel-remote-cache.mdx, apps/docs/content/blog/joining-vercel.mdx

npx turbo login
npx turbo link

Compact Reference

NameScopeMain behaviorHash impact
globalEnvRoot turbo.jsonDeclares variables that affect every taskValue changes cause all tasks to miss cache
task envTask config in turbo.jsonDeclares variables consumed by a specific taskValue changes affect that task hash
globalPassThroughEnvRoot turbo.jsonMakes variables available to tasks in Strict ModeDoes not affect hashes unless also in env or globalEnv
Framework inferencePer packageAdds known public-prefix wildcards for supported frameworksIncluded like inferred task env inputs
TURBO_CACHESystem variableControls cache source reading and writingConfigures turbo, not application output by itself
TURBO_CACHE_DIRSystem variableSets local cache directoryConfigures turbo, not application output by itself
TURBO_APISystem variableSets Remote Cache base URLConfigures Remote Cache connection
TURBO_TOKEN / TURBO_TEAMCI or local shellAuthenticates to Vercel Remote Cache outside automatic Vercel setupCredentials for cache access, not task hash inputs by default

A practical review loop is to inspect each task script, list every environment variable that can change its outputs, and place those names in task env unless they truly affect all tasks. Then decide which secrets or machine variables must be available without hashing and put those in passthrough configuration. Finally, make CI explicit: provide Remote Cache credentials as system variables, keep command-specific overrides in flags, and include .env files in the repository’s task inputs when file contents are part of the build behavior. Read the configuration and system-environment reference pages next when you need exact option names for a production setup.

Sources: apps/docs/content/docs/crafting-your-repository/using-environment-variables.mdx, apps/docs/content/docs/reference/configuration.mdx, apps/docs/content/docs/reference/system-environment-variables.mdx