crates/turborepo-lib/src/turbo_json/ARCHITECTURE.md
This document explains the process of loading turbo.json files and creating task definitions in Turborepo.
The process involves several phases that transform raw configuration files into an executable task graph.
The loading and resolving of task definitions is driven during task graph construction.
The configuration and task loading process follows this high-level flow:
turbo.json files into raw structuresConfiguration is collected from multiple sources with the following priority (highest to lowest):
.turbo/config.json)~/.turbo/auth.json)~/.turbo/config.json)TurborepoConfigBuilder (crates/turborepo-lib/src/config/mod.rs): Orchestrates the configuration loading processTurboJsonReader (crates/turborepo-lib/src/config/turbo_json.rs): Extracts configuration options from the root turbo.json fileConfigurationOptions: The final merged configuration structureTurborepo uses two different schemas for turbo.json files depending on their location:
Root turbo.json (RawRootTurboJson): Located at the repository root
globalEnv, globalDependencies, globalPassThroughEnv)remoteCache, ui, daemon (deprecated), envMode, etc.)futureFlags.globalConfiguration is enabled, these move under a global key (RawGlobalConfig) with renamed fields (e.g. globalDependencies → inputs)extends fieldPackage turbo.json (RawPackageTurboJson): Located in workspace packages
extends: ["//", ...] to inherit from root configuration (root must be first)["//", "shared-config"])tags and boundariesTurboJsonLoader (crates/turborepo-lib/src/turbo_json/loader.rs): Loads and resolves turbo.json filesRawRootTurboJson (crates/turborepo-lib/src/turbo_json/raw.rs): Root turbo.json schemaRawPackageTurboJson (crates/turborepo-lib/src/turbo_json/raw.rs): Package turbo.json schemaRawTurboJson (crates/turborepo-lib/src/turbo_json/raw.rs): Unified raw structure that can represent either typeTurboJson: Validated structure containing raw task definitionsturbo.json or turbo.jsonc filesRawRootTurboJson or RawPackageTurboJson)RawTurboJson structure via TryFrom<RawRootTurboJson> (validates globalConfiguration flag constraints — either the global key or the old top-level keys must be used, not both)TurboJson with structural validation (calls resolve_global_config() to normalize global fields into top-level fields for downstream consumers)RawGlobalConfig and the global keyWhen futureFlags.globalConfiguration is enabled, RawRootTurboJson accepts a
global: Option<Spanned<RawGlobalConfig>> field. During the TryFrom
conversion to RawTurboJson:
global field is copied to RawTurboJson.global, top-level global keys are rejected with an errorglobal key is rejectedThe resolve_global_config() method on RawTurboJson moves fields from
global into the top-level slots (e.g. global.inputs → global_dependencies,
global.env → global_env). It is called on reading paths
(TurboJson::try_from, turbo_json_to_config_options) but NOT before
serialization, so serde_json::to_string_pretty preserves the original format
(important for turbo prune).
ProcessedTaskDefinition (crates/turborepo-lib/src/turbo_json/processed.rs): Intermediate representation with DSL token processingProcessedGlob: Parsed glob patterns with separated components (base pattern, negation flag, turbo_root flag)ProcessedInputs/ProcessedOutputs: Collections of processed globs with resolution methods$TURBO_ROOT$ and ! prefixes from glob patterns$TURBO_ROOT$ usage$ not allowed)$ not allowed in dependsOn)^ not allowed in with)RawTaskDefinition: Raw task configuration from JSONProcessedTaskDefinition: Intermediate representation with parsed DSL tokensTaskDefinition: Final validated and resolved task configurationTaskId and TaskName (from turborepo-task-id crate): Task identification typesThe resolution now follows a three-stage pipeline:
Raw → Processed (ProcessedTaskDefinition::from_raw):
ProcessedGlob::from_spanned_*)ProcessedEnv::new, ProcessedPassThroughEnv::new)ProcessedDependsOn::new)ProcessedWith::new)Processed → Resolved (TaskDefinition::from_processed):
$TURBO_ROOT$ token replacement using resolve() methodsdependsOn into topological and task dependenciescache and interactive fields)interruptible and persistent fields)Inheritance: The extend module handles merging multiple ProcessedTaskDefinitions before final resolution