Terragrunt Updates & Release Notes
104 updates curated from 1 source by the Releasebot Team. Last updated: Jun 16, 2026
- Jul 1, 2026
- Date parsed from source:Jul 1, 2026
- First seen by Releasebot:Jun 16, 2026
- Modified by Releasebot:Jul 1, 2026
v1.1.0
Terragrunt ships a major release that makes stack dependencies, CAS, catalog redesign, and change-based runs available by default, with faster source handling, richer stack generation, improved discovery, new filtering behavior, and release attestation verification for safer installs.
New Features
Stack dependencies
A stack generates a tree of units from a single terragrunt.stack.hcl file. Wiring one of those units to another used to mean defining dependency blocks in your catalog and threading dependency paths through values. Stack dependencies let you declare those relationships up front instead.
Add an autoinclude block inside a unit or stack block, and Terragrunt generates a partial configuration (a terragrunt.autoinclude.hcl file) next to the generated terragrunt.hcl or terragrunt.stack.hcl that's automatically merged into the unit or stack definition. The new unit.<name>.path and stack.<name>.path references resolve to generated paths, so you don't have to hardcode them:
# terragrunt.stack.hcl unit "vpc" { source = "github.com/acme/catalog//units/vpc" path = "vpc" } unit "app" { source = "github.com/acme/catalog//units/app" path = "app" autoinclude { dependency "vpc" { config_path = unit.vpc.path } inputs = { vpc_id = dependency.vpc.outputs.vpc_id } } }Anything that's valid in a unit configuration is valid in its autoinclude block, so you can also patch catalog units with configuration they don't ship with, like retry rules:
# terragrunt.stack.hcl unit "app" { source = "github.com/acme/catalog//units/app" path = "app" autoinclude { errors { retry "transient_errors" { retryable_errors = [".*Error: transient network issue.*"] max_attempts = 3 sleep_interval_sec = 5 } } } }The same works for nested stacks: an autoinclude block inside a stack block patches the generated terragrunt.stack.hcl, so you can, for example, add an extra unit to one environment without forking the stack in your catalog.
Stack configurations also gained two capabilities along the way:
include blocks now work in terragrunt.stack.hcl files, so shared stack configuration can live in a parent folder.
dependency blocks can target stack directories, and the run queue expands them to the units inside. Note that this relationship only goes one way: units can depend on stacks, but stacks cannot depend on stacks or units.
See the stacks documentation for the full reference. Previously gated behind the stack-dependencies experiment, all of this is now enabled by default.
Content Addressable Store (CAS)
The Content Addressable Store (CAS) deduplicates source downloads across configurations. It addresses repositories and modules by their content, stores them locally, and serves later requests from that local store instead of repeating the fetch. This speeds up catalog cloning, OpenTofu/Terraform source fetching, and stack generation, and identical files occupy disk space once regardless of how many configurations use them.
The CAS is no longer limited to Git. It also deduplicates HTTP, Amazon S3, Google Cloud Storage, Mercurial, and SMB sources, along with OpenTofu/Terraform registry sources fetched via tfr://. See supported sources for how each one resolves and deduplicates content.
CAS is enabled by default. Use the --no-cas flag (or TG_NO_CAS=true) to opt out of it for a run:
terragrunt run --all --no-cas -- planTwo new attributes give you finer control, and both default to off:
update_source_with_cas makes a generated stack self-contained. Set it on a unit, stack, or terraform block with a relative source, and terragrunt stack generate rewrites that source into a content-addressed cas:: reference, so the generated tree no longer depends on the surrounding repository layout. Catalog authors can keep relative paths in their sources and still ship a portable, reproducible stack:
# stacks/networking/terragrunt.stack.hcl unit "vpc" { source = "../..//units/vpc" path = "vpc" update_source_with_cas = true }After terragrunt stack generate, the relative path is replaced by a reference to the exact tree the CAS stored:
# Generated output unit "vpc" { source = "cas::sha1:f39ea0ebf891c9954c89d07b73b487ff938ef08b" path = "vpc" update_source_with_cas = true }mutable controls how the CAS places fetched content on disk. By default, the CAS hard links files from its shared store into .terragrunt-cache and marks them read-only, which is fast and uses no extra space, but means the files can't be edited in place. Set mutable = true on a terraform block to copy the content instead, making the working tree safe to edit at the cost of extra I/O and disk space:
# units/vpc/terragrunt.hcl terraform { source = "github.com/acme/catalog//modules/vpc" mutable = true }Previously gated behind the cas experiment, the CAS no longer requires --experiment cas.
Redesigned terragrunt catalog
The catalog command has been redesigned. It now starts without any configuration, discovers components across your catalog repositories in the background, and streams them into the TUI as they're found.
Discovery is no longer limited to a modules/ directory; components can live anywhere in a catalog repository. To control what gets discovered, add a .terragrunt-catalog-ignore file with .gitignore-style globs for the paths you want filtered out.
Components in the TUI now carry metadata to help you navigate a large catalog: each one shows a kind label (template, stack, unit, or module) and optional tags defined in the front-matter of its README.md. From the component list, press s to open a new screen that interactively collects the values used to scaffold the component into your repository.
Previously gated behind the catalog-redesign experiment, the redesigned catalog is now the default terragrunt catalog experience.
Reading detection for local module sources
Terragrunt can select units by the files they read, which is the basis of change-based runs in CI. Previously, pointing a unit's terraform block at a local directory didn't mark the files inside that directory as read, so a change to the module wouldn't select the unit.
When a unit's source is a local module, Terragrunt now records the module's *.tf, *.tf.json, *.hcl, *.tofu, and *.tofu.json files as read by that unit, so --filter 'reading=<path>' and --queue-include-units-reading select the unit when a module file changes:
terragrunt run --all --filter 'reading=./modules/vpc/main.tf' -- planFor files that reading detection doesn't track on its own, the new mark_glob_as_read() HCL function expands a glob and marks every matching file as read in one call:
locals { configs = mark_glob_as_read("${get_terragrunt_dir()}/config/{*.yaml,**/*.yaml}") }Existing pipelines built on --queue-include-units-reading or reading= filters may select more units than before, because changes to local module files now count as reads. Previously gated behind the mark-many-as-read experiment, these behaviors no longer require --experiment mark-many-as-read.
Skip auth during discovery with --no-discovery-auth-provider-cmd
By default, Terragrunt runs your --auth-provider-cmd once for every unit it discovers, so HCL functions that need credentials resolve correctly during parsing. In a large repository, that can mean hundreds of invocations before any unit runs, which can dominate wall-clock time on change-based runs.
The --no-discovery-auth-provider-cmd flag (env: TG_NO_DISCOVERY_AUTH_PROVIDER_CMD) skips those invocations during the discovery phase, leaving auth to run only for the units that actually execute:
terragrunt run --all \ --no-discovery-auth-provider-cmd \ --queue-include-units-reading=./changed-file.txt \ -- planWarning
Use this only when you know parsing resolves without credentials. Units whose configuration depends on values from --auth-provider-cmd during discovery (for example, via get_aws_account_id()) will fail to parse when the flag is set.
Previously gated behind the opt-out-auth experiment, the flag now works without --experiment opt-out-auth.
Run queue displayed as a dependency tree
Before a run --all, Terragrunt lists the units it's about to run. That list now renders as a dependency tree by default instead of a flat list, with units nested under their dependencies, so the run order and the relationships between units are visible before anything executes:
The following units will be run, starting with dependencies and then their dependents:
. ├── monitoring ╰── vpc ╰── database ╰── backend-appThe header adapts to direction: dependencies come before dependents on apply, and the order reverses on destroy.
Previously gated behind the dag-queue-display experiment, the tree display no longer requires --experiment dag-queue-display.
💡 Tips Added
Tip when filtering a stack leaves nested stacks ungenerated
terragrunt stack generate --filter './my-stack | type=stack' generates only the selected
stack, not the nested stacks it contains, which can be surprising for a stack of stacks.
When a non-glob | type=stack filter leaves a stack's nested stacks ungenerated, Terragrunt
now prints a tip showing how to generate them too, for example
--filter './my-stack | type=stack' --filter './my-stack/** | type=stack'.🐛 Bug Fixes
Fix permission denied when generated files overwrite CAS-materialized files
With the CAS enabled, Terragrunt fetches sources as read-only files. Writing a generated file over one of them no longer fails with permission denied:
Files from generate blocks with if_exists = "overwrite", when the module ships the target file (for example, its own versions.tf).
terragrunt.values.hcl, when the unit or stack source already contains one.
terragrunt.autoinclude.hcl, when the unit or stack source already contains one.
.terraform.lock.hcl, when the provider cache server updates a committed lock file during init -upgrade.
In each case, the read-only file is replaced with a writable one, and the shared CAS store is never modified.
Fix permission denied when CAS fetches a git source across filesystems
With the CAS enabled, fetching a git:: source could fail with permission denied on .git/HEAD or .git/config, sending Terragrunt back to the standard getter. It happened when the CAS store and the module's working directory sit on different filesystems, so the files are copied rather than hard-linked, and a read-only leftover from an interrupted run was in the way. Terragrunt now recovers from the leftover and completes the fetch.
Reject update_source_with_cas on a terraform block when CAS is disabled
terragrunt stack generate --no-cas now fails when a generated unit's terraform block sets update_source_with_cas = true, instead of silently emitting the unit with its relative source unchanged. The relative source has no meaning once CAS is disabled, so the generated unit could not resolve its module. This matches the existing behavior for the same attribute on unit and stack blocks, and for a run invoked with --no-cas.
Apply extra_arguments env vars when resolving dependency outputs
Resolving a dependency block's outputs now applies the env_vars from the unit's terraform extra_arguments blocks whose commands include output.
Resolve dependency outputs for units whose before_hook references a dependency
Resolving a unit's dependency outputs no longer evaluates that unit's terraform hooks, so a before_hook (or after_hook) that interpolates ${dependency.<name>.outputs.<key>} no longer fails downstream units with There is no variable named "dependency". Dependency output resolution still applies the unit's extra_arguments env_vars and source.
Select units reading added or deleted glob files in Git-based filters
Git-based filters (for example terragrunt run --all --filter '[HEAD^1...HEAD]' -- plan) now select units
that read an added or deleted file through mark_glob_as_read, even when that file lives outside the unit's
own directory. Previously only modified files outside a unit reached those units; adding or deleting a file
the glob matched left the reading unit out of the run, so its real config change was skipped. Added files are
matched against the newer reference, and deleted files against the older one where the file still exists.mark_glob_as_read constrains its walk to a boundary
mark_glob_as_read now confines glob expansion to a boundary directory. By default the boundary is the enclosing Git repository root; outside a Git repository it is unset. A pattern whose walk would begin outside the boundary returns an error instead of expanding.
This bounds patterns that resolve higher than intended. For example, "${local.dir}/{.yaml}" becomes /{.yaml} when local.dir is empty, which previously walked the entire filesystem. A ? : conditional does not prevent this, because HCL evaluates both branches of a conditional before selecting one. Wrapping the call in try lets the error fall back to a default:
locals { files = sort(try(mark_glob_as_read("${local.dir}/{*.yaml,*.yml,*.json}"), [])) }Pass a leading --terragrunt-boundary argument to set the boundary explicitly, for example to scope the walk to a subdirectory or to widen it to the filesystem root:
locals { scoped = mark_glob_as_read("--terragrunt-boundary=/etc/terragrunt", "/etc/terragrunt/{*.yaml}") all = mark_glob_as_read("--terragrunt-boundary=/", "/{*.yaml}") }Scaffold only detects variables in the module directory
terragrunt scaffold now reads input variables from the module directory itself, matching what OpenTofu and Terraform load for a root module. Previously it scanned subdirectories too, so variable blocks defined in nested modules or examples leaked into the scaffolded inputs even though the module never exposes them.
Resolve interpolated object keys in autoinclude blocks
terragrunt stack generate now resolves interpolated object keys in autoinclude blocks (for example
{ "${local.prefix}_key" = ... }), even when the value references dependency.*. Previously the generated
unit kept the key verbatim, leaking a stack-only reference that is not valid in the unit scope.Fix panic on non-string literal interpolation in autoinclude templates
terragrunt stack generate no longer panics when an autoinclude template interpolates a non-string literal (for example "${0}" or "${true}") alongside a dependency.* reference. The interpolated literal is now rendered to its string form (${0} becomes 0) and the dependency reference is preserved for the unit.
Resolve transitive autoinclude dependencies on a stack directory
run --all no longer fails with "does not contain a terragrunt.hcl file" when an autoinclude dependency points at a stack directory (one holding terragrunt.stack.hcl) and the unit is reached transitively through another unit. The dependency cycle check now skips a target with no unit config, matching the direct dependency case.
🧪 Experiments Updated
Six experiments completed
The following experiments graduated to general availability in this release, and the features they gated are now enabled by default:
- stack-dependencies
- cas
- catalog-redesign
- mark-many-as-read
- opt-out-auth
- dag-queue-display
Each feature is described in the New Features section above.
The corresponding --experiment flags (and TG_EXPERIMENT values) are no longer needed. Passing one still works, but emits a warning about the completed experiment, so you can drop it at your convenience.
Thank you to everyone who ran these experiments early and filed the feedback that got them here.
⚙️ Process Updates
Immutable releases
Starting with this release, Terragrunt releases are published as immutable releases on GitHub. Once a release is published, its tag and assets can no longer be modified or deleted, so the binary you download is guaranteed to be the same binary that was uploaded when the release was published.
See the releases process documentation for details, and Verifying releases with the GitHub CLI for how to check a download against the release attestation.
Install script verifies release attestations
The install script now checks downloaded release assets against the release attestation that ships with immutable releases. For releases starting with v1.1.0, when an authenticated GitHub CLI (v2.81.0 or later) is available, the script verifies the checksums file and the binary against the attestation before installing, and aborts if either does not match the published release. The check is skipped with a warning when gh is unavailable, too old, or unauthenticated. Use --no-verify-attestation to opt out.
Pull Requests
✨ Features
feat: Tip how to run a stack's units when a stack filter matches no units by @denis256 in #6387
🐛 Bug Fixes
fix: autoincludes variables interpolation by @denis256 in #6318
fix: generate overwrite of read-only CAS-materialized files by @denis256 in #6329
fix: CAS integration with committed module lockfiles by @yhakbar in #6330
fix: improved resolving of complex objects in keys by @denis256 in #6317
fix: Fixing update_source_with_cas integration with --no-cas by @yhakbar in #6363
fix: Adding support for adding/deleting files in Git diffs by @yhakbar in #6352
fix: Adding --terragrunt-boundary to mark_glob_as_read by @yhakbar in #6351
fix: Only detect variables in root directory of module by @yhakbar in #6381
fix: resolve transitive autoinclude dependency on a stack directory by @denis256 in #6389
fix: apply extra_arguments env_vars when resolving dependency outputs by @denis256 in #6396
fix: Fixing indenter style by @yhakbar in #6402
fix: Fixing legacy Windows per-drive key for environment variables by @yhakbar in #6412
fix: Fixing Git materialization race HEAD update by @yhakbar in #6411
fix: fixed reference of dependency outputs in terraform hooks by @denis256 in #6423
fix: Fixing deleted changed files by @yhakbar in #6424
📖 Documentation
docs: Documenting --parallelism tweaking considerations better by @yhakbar in #6313
docs: Adding TGS 'Terragrunt at scale' page by @yhakbar in #6307
docs: v1.1.0 changelog polish by @yhakbar in #6333
docs: Improving performance docs by @yhakbar in #6332
docs: Adding immutable releases docs by @yhakbar in #6337
docs: Cleaning up 1.1.0 docs by @yhakbar in #6339
docs: Updating provider size claims for provider cache server docs by @yhakbar in #6341
docs: Documenting Discovery as a term by @yhakbar in #6359
docs: Cleaning up catalog tabs docs by @yhakbar in #6369
🧹 Chores
chore: marking as completed stack dependencies experiment by @denis256 in #6249
chore: Completing mark-many-as-read experiment by @yhakbar in #6310
chore: Completing cas experiment by @yhakbar in #6254
chore: Addressing feedback from #6254 by @yhakbar in #6324
chore: Completing dag-queue-display experiment by @yhakbar in #6320
chore: Completing opt-out-auth experiment by @yhakbar in #6321
chore: Dropping go-git by @yhakbar in #6325
chore: Addressing PR #6325 feedback by @yhakbar in #6335
chore: bump cicd to use opentofu 1.12.2 by @denis256 in #6343
chore: Signing GHA update by @denis256 in #6340
chore: multiple dependencies update by @denis256 in #6356
chore: Updating CI w/ Terragrunt guide to have more accurate screenshots by @yhakbar in #6357
chore: drop usage of github.com/NYTimes/gziphandler by @denis256 in #6364
chore(deps): bump astro from 6.3.2 to 6.4.6 in /docs by @dependabot[bot] in #6366
chore: Completing catalog-redesign experiment by @yhakbar in #6271
chore: Bumping JS dependencies by @yhakbar in #6368
chore: Adding release attestation verification to install script by @yhakbar in #6344
chore: Addressing weekly test stats by @yhakbar in #6354
chore: Addressing #6351 feedback by @yhakbar in #6373
chore: Adding mise.toml lockfile by @yhakbar in #6372
chore: Making progress on lll by @yhakbar in #6377
chore: autoinclude fuzzing tests improvements by @denis256 in #6342
chore: Expand pure testing through venv by @yhakbar in #6090
chore: Dropping TestWindowsTflintIsInvoked by @yhakbar in #6382
chore: Continuing with progress on lll #2 by @yhakbar in #6385
chore: added CICD guard for detecting not run tests by @denis256 in #6383
chore: Addressing weekly tests stats (2026-06-22) by @yhakbar in #6390
chore: Addressing #6390 feedback by @yhakbar in #6391
chore: go deps update by @denis256 in #6392
chore: Running go fix ./... by @yhakbar in #6398
chore(deps): bump actions/checkout from 6.0.2 to 7.0.0 by @dependabot[bot] in #6394
chore: Update cfg locking for units by @yhakbar in #6401
chore: Move log flags off writers by @yhakbar in #6403
chore: Adding env and writers to venv by @yhakbar in #6404
chore: aws-sdk-go-v2/service/s3 upgrade by @denis256 in #6413
chore: Downgrading render log to a debug by @yhakbar in #6429
chore: Engine per unit shutdown by @yhakbar in #6426
📝 Other Changes
Adding Terragrunt Patterns section by @karlcarstensen in #6379
Add FAQ section for docs.terragrunt.com by @karlcarstensen in #6378
Fixing codespell lint error and adding codespell lint commands by @karlcarstensen in #6386
Original source - Jun 12, 2026
- Date parsed from source:Jun 12, 2026
- First seen by Releasebot:Jul 1, 2026
v1.1.0-rc1
Terragrunt releases v1.1.0 release candidate with graduated stack dependencies, content addressable store, redesigned catalog, improved change detection, an opt-out for discovery auth, and a dependency-tree run queue, plus bug fixes and docs updates.
v1.1.0 Release Candidate
This is the first release candidate for Terragrunt v1.1.
This release completes the following experiments:
- stack-dependencies
- cas
- catalog-redesign
- mark-many-as-read
- opt-out-auth
- dag-queue-display
Future release candidates for v1.1.0 will include bug fixes related to these experiments or other urgent bug fixes as necessary, and documentation improvements.
Please try out this release candidate in lower environments and share your feedback in the Associated GitHub discussion.
✨ New Features
Stack dependencies
A stack generates a tree of units from a single terragrunt.stack.hcl file. Wiring one of those units to another used to mean defining dependency blocks in your catalog and threading dependency paths through values. Stack dependencies let you declare those relationships up front instead.
Add an autoinclude block inside a unit or stack block, and Terragrunt generates a partial configuration (a terragrunt.autoinclude.hcl file) next to the generated terragrunt.hcl or terragrunt.stack.hcl that's automatically merged into the unit or stack definition. The new unit.<name>.path and stack.<name>.path references resolve to generated paths, so you don't have to hardcode them:
# terragrunt.stack.hcl unit "vpc" { source = "github.com/acme/catalog//units/vpc" path = "vpc" } unit "app" { source = "github.com/acme/catalog//units/app" path = "app" autoinclude { dependency "vpc" { config_path = unit.vpc.path } inputs = { vpc_id = dependency.vpc.outputs.vpc_id } } }Anything that's valid in a unit configuration is valid in its autoinclude block, so you can also patch catalog units with configuration they don't ship with, like retry rules:
# terragrunt.stack.hcl unit "app" { source = "github.com/acme/catalog//units/app" path = "app" autoinclude { errors { retry "transient_errors" { retryable_errors = [".*Error: transient network issue.*"] max_attempts = 3 sleep_interval_sec = 5 } } } }The same works for nested stacks: an autoinclude block inside a stack block patches the generated terragrunt.stack.hcl, so you can, for example, add an extra unit to one environment without forking the stack in your catalog.
Stack configurations also gained two capabilities along the way:
include blocks now work in terragrunt.stack.hcl files, so shared stack configuration can live in a parent folder.
dependency blocks can target stack directories, and the run queue expands them to the units inside. Note that this relationship only goes one way: units can depend on stacks, but stacks cannot depend on stacks or units.
See the stacks documentation for the full reference. Previously gated behind the stack-dependencies experiment, all of this is now enabled by default.
Content Addressable Store (CAS)
The Content Addressable Store (CAS) deduplicates source downloads across configurations. It addresses repositories and modules by their content, stores them locally, and serves later requests from that local store instead of repeating the fetch. This speeds up catalog cloning, OpenTofu/Terraform source fetching, and stack generation, and identical files occupy disk space once regardless of how many configurations use them.
The CAS is no longer limited to Git. It also deduplicates HTTP, Amazon S3, Google Cloud Storage, Mercurial, and SMB sources, along with OpenTofu/Terraform registry sources fetched via tfr://. See supported sources for how each one resolves and deduplicates content.
CAS is enabled by default. Use the --no-cas flag (or TG_NO_CAS=true) to opt out of it for a run:
terragrunt run --all --no-cas -- planTwo new attributes give you finer control, and both default to off:
update_source_with_cas makes a generated stack self-contained. Set it on a unit, stack, or terraform block with a relative source, and terragrunt stack generate rewrites that source into a content-addressed cas:: reference, so the generated tree no longer depends on the surrounding repository layout. Catalog authors can keep relative paths in their sources and still ship a portable, reproducible stack:
# stacks/networking/terragrunt.stack.hcl unit "vpc" { source = "../..//units/vpc" path = "vpc" update_source_with_cas = true }After terragrunt stack generate, the relative path is replaced by a reference to the exact tree the CAS stored:
# Generated output unit "vpc" { source = "cas::sha1:f39ea0ebf891c9954c89d07b73b487ff938ef08b" path = "vpc" update_source_with_cas = true }mutable controls how the CAS places fetched content on disk. By default, the CAS hard links files from its shared store into .terragrunt-cache and marks them read-only, which is fast and uses no extra space, but means the files can't be edited in place. Set mutable = true on a terraform block to copy the content instead, making the working tree safe to edit at the cost of extra I/O and disk space:
# units/vpc/terragrunt.hcl terraform { source = "github.com/acme/catalog//modules/vpc" mutable = true }Previously gated behind the cas experiment, the CAS no longer requires --experiment cas.
Redesigned terragrunt catalog
The catalog command has been redesigned. It now starts without any configuration, discovers components across your catalog repositories in the background, and streams them into the TUI as they're found.
Discovery is no longer limited to a modules/ directory; components can live anywhere in a catalog repository. To control what gets discovered, add a .terragrunt-catalog-ignore file with .gitignore-style globs for the paths you want filtered out.
Components in the TUI now carry metadata to help you navigate a large catalog: each one shows a kind label (template, stack, unit, or module) and optional tags defined in the front-matter of its README.md. From the component list, press s to open a new screen that interactively collects the values used to scaffold the component into your repository.
Previously gated behind the catalog-redesign experiment, the redesigned catalog is now the default terragrunt catalog experience.
Reading detection for local module sources
Terragrunt can select units by the files they read, which is the basis of change-based runs in CI. Previously, pointing a unit's terraform block at a local directory didn't mark the files inside that directory as read, so a change to the module wouldn't select the unit.
When a unit's source is a local module, Terragrunt now records the module's *.tf, *.tf.json, *.hcl, *.tofu, and *.tofu.json files as read by that unit, so --filter 'reading=<path>' and --queue-include-units-reading select the unit when a module file changes:
terragrunt run --all --filter 'reading=./modules/vpc/main.tf' -- planFor files that reading detection doesn't track on its own, the new mark_glob_as_read() HCL function expands a glob and marks every matching file as read in one call:
locals { configs = mark_glob_as_read("${get_terragrunt_dir()}/config/{*.yaml,**/*.yaml}") }Existing pipelines built on --queue-include-units-reading or reading= filters may select more units than before, because changes to local module files now count as reads. Previously gated behind the mark-many-as-read experiment, these behaviors no longer require --experiment mark-many-as-read.
Skip auth during discovery with --no-discovery-auth-provider-cmd
By default, Terragrunt runs your --auth-provider-cmd once for every unit it discovers, so HCL functions that need credentials resolve correctly during parsing. In a large repository, that can mean hundreds of invocations before any unit runs, which can dominate wall-clock time on change-based runs.
The --no-discovery-auth-provider-cmd flag (env: TG_NO_DISCOVERY_AUTH_PROVIDER_CMD) skips those invocations during the discovery phase, leaving auth to run only for the units that actually execute:
terragrunt run --all \ --no-discovery-auth-provider-cmd \ --queue-include-units-reading=./changed-file.txt \ -- planWarning
Use this only when you know parsing resolves without credentials. Units whose configuration depends on values from --auth-provider-cmd during discovery (for example, via get_aws_account_id()) will fail to parse when the flag is set.
Previously gated behind the opt-out-auth experiment, the flag now works without --experiment opt-out-auth.
Run queue displayed as a dependency tree
Before a run --all, Terragrunt lists the units it's about to run. That list now renders as a dependency tree by default instead of a flat list, with units nested under their dependencies, so the run order and the relationships between units are visible before anything executes:
The following units will be run, starting with dependencies and then their dependents:
. ├── monitoring ╰── vpc ╰── database ╰── backend-appThe header adapts to direction: dependencies come before dependents on apply, and the order reverses on destroy.
Previously gated behind the dag-queue-display experiment, the tree display no longer requires --experiment dag-queue-display.
🐛 Bug Fixes
Fix permission denied when generated files overwrite CAS-materialized files
With the CAS enabled, Terragrunt fetches sources as read-only files. Writing a generated file over one of them no longer fails with permission denied:
Files from generate blocks with if_exists = "overwrite", when the module ships the target file (for example, its own versions.tf).
terragrunt.values.hcl, when the unit or stack source already contains one.
terragrunt.autoinclude.hcl, when the unit or stack source already contains one.
.terraform.lock.hcl, when the provider cache server updates a committed lock file during init -upgrade.
In each case, the read-only file is replaced with a writable one, and the shared CAS store is never modified.
Resolve interpolated object keys in autoinclude blocks
terragrunt stack generate now resolves interpolated object keys in autoinclude blocks (for example
{ "${local.prefix}_key" = ... }), even when the value references dependency.*. Previously the generated
unit kept the key verbatim, leaking a stack-only reference that is not valid in the unit scope.
Fix panic on non-string literal interpolation in autoinclude templates
terragrunt stack generate no longer panics when an autoinclude template interpolates a non-string literal (for example "${0}" or "${true}") alongside a dependency.* reference. The interpolated literal is now rendered to its string form (${0} becomes 0) and the dependency reference is preserved for the unit.
🧪 Experiments Updated
Six experiments completed
The following experiments graduated to general availability in this release, and the features they gated are now enabled by default:
- stack-dependencies
- cas
- catalog-redesign
- mark-many-as-read
- opt-out-auth
- dag-queue-display
Each feature is described in the New Features section above.
The corresponding --experiment flags (and TG_EXPERIMENT values) are no longer needed. Passing one still works, but emits a warning about the completed experiment, so you can drop it at your convenience.
Thank you to everyone who ran these experiments early and filed the feedback that got them here.
Pull Requests
🐛 Bug Fixes
- fix: autoincludes variables interpolation by @denis256 in #6318
- fix: generate overwrite of read-only CAS-materialized files by @denis256 in #6329
- fix: CAS integration with committed module lockfiles by @yhakbar in #6330
- fix: improved resolving of complex objects in keys by @denis256 in #6317
📖 Documentation
- docs: Documenting --parallelism tweaking considerations better by @yhakbar in #6313
- docs: Adding TGS 'Terragrunt at scale' page by @yhakbar in #6307
- docs: v1.1.0 changelog polish by @yhakbar in #6333
- docs: Improving performance docs by @yhakbar in #6332
🧹 Chores
- chore: marking as completed stack dependencies experiment by @denis256 in #6249
- chore: Completing mark-many-as-read experiment by @yhakbar in #6310
- chore: Completing cas experiment by @yhakbar in #6254
- chore: Addressing feedback from #6254 by @yhakbar in #6324
- chore: Completing dag-queue-display experiment by @yhakbar in #6320
- chore: Completing opt-out-auth experiment by @yhakbar in #6321
- chore: Dropping go-git by @yhakbar in #6325
- chore: Addressing PR #6325 feedback by @yhakbar in #6335
All of your release notes in one feed
Join Releasebot and get updates from Gruntwork and hundreds of other software products.
- Jun 10, 2026
- Date parsed from source:Jun 10, 2026
- First seen by Releasebot:Jun 11, 2026
v1.0.8
Terragrunt releases a broad update with faster file tracking, sharper error messages, and expanded support across CAS, catalogs, autoinclude, and S3 sources. It also adds new experiments for hooks and telemetry, plus documentation improvements including clean Markdown for every docs page.
🏎️ Performance Improvements
Faster read-file tracking with the mark-many-as-read experiment
With the mark-many-as-read experiment enabled, Terragrunt records every module file it marks as read during parsing. The bookkeeping for that record scaled quadratically: each new path was checked against every path recorded so far, which got expensive for units with large local module sources, and monorepos paid that cost again for every unit and every command.
Recording a path now takes constant time no matter how many paths came before it, and re-marking already-recorded files is cheaper still. The reading lists reported by find and list are unchanged.
🐛 Bug Fixes
assume_role: preserve commas inside list expressions
Terragrunt previously failed to correctly parse assume_role attributes containing list values such as transitive_tag_keys or policy_arns. Commas inside nested list expressions were incorrectly treated as top-level separators, causing generated configurations to fail with parsing errors.
assume_role = { role_arn = "arn:aws:iam::123456789012:role/test-role" transitive_tag_keys = ["Project", "Projects"] }This resulted in errors similar to:
Missing item separator; Expected a comma to mark the beginning of the next item.
Terragrunt now preserves commas inside nested list and object expressions when parsing assume_role blocks, allowing configurations containing array attributes to be processed correctly.
Thanks to @Rahul-Kumar-prog for contributing this fix!
Completed experiments now evaluate as permanently enabled
Features gated behind a completed experiment were treated as disabled instead of permanently enabled, so functionality that graduated out of experiment status could silently stop working.
The one affected code path was hcl validate --inputs with a git filter expression such as --filter '[HEAD~1...HEAD]': after the filter-flag experiment completed, the command stopped preparing git worktrees for the filter. Git filter expressions now work with hcl validate --inputs again, matching find, list, and the other commands that accept filters.
Exposed-include resolution errors now name the include block, file, and failing field
When resolving an include block with expose = true, Terragrunt surfaced low-level parsing or conversion errors with no indication of which include block, file, or field was at fault. This was especially hard to debug for errors that carry no source location, such as:
unsuitable value: a bool is required
The error is now annotated with the include block name, the included (parent) file path, and a single dotted locator for the failing field — the top-level config field (dependency, inputs, locals, or feature) plus the attribute path within it when go-cty can determine one:
exposed include "root" (/path/to/root.hcl): dependency.outputs["enabled"]: unsuitable value: a bool is required
When go-cty cannot resolve a precise attribute path, the locator degrades to just the field name:
exposed include "root" (/path/to/root.hcl): dependency: unsuitable value: a bool is required
Errors that originate in HCL parsing already carry a source range (file:line:column) and are preserved unchanged. This narrows the search from the entire configuration tree to a specific file and field.
Intersecting a graph traversal with another filter no longer drops the traversed components
A graph traversal combined with an intersected filter dropped the components reached in discovery.
e.g., ...a-dependent | type=unit (the dependents of a-dependent, intersected with type of units) returned only a-dependent itself instead of its dependents, and git-change traversals such as ...[HEAD~1...HEAD] | type=unit lost the dependents of the changed units.
A component that matched both a graph expression target and a positive filesystem or git filter was classified as discovered before the graph traversal ran, so the traversal never expanded from it. Terragrunt now checks graph expression targets first, so intersecting a traversal with another filter keeps the dependencies and dependents it reaches.
generate blocks now honor hcl_fmt
Terragrunt now accepts hcl_fmt on generate blocks and preserves the setting when configurations are parsed, written, and parsed again. This lets generated .tf, .hcl, and .tofu files opt out of automatic HCL formatting by setting hcl_fmt = false, matching the existing generate = { ... } attribute-map behavior.
Telemetry resource now honors OTEL_SERVICE_NAME and OTEL_RESOURCE_ATTRIBUTES
Terragrunt previously hardcoded the service.name resource attribute to terragrunt for every emitted trace and metric, ignoring the standard OpenTelemetry environment variables. Multiple Terragrunt invocations could not be distinguished in an OpenTelemetry backend without an intermediate collector to rewrite the attribute.
The resource is now composed via resource.New with WithFromEnv() placed after Terragrunt's defaults, so OTEL_SERVICE_NAME and OTEL_RESOURCE_ATTRIBUTES are honored on every span and metric. Per the OpenTelemetry specification, OTEL_SERVICE_NAME takes precedence over a service.name entry in OTEL_RESOURCE_ATTRIBUTES. The default service.name remains terragrunt when neither variable is set.
s3:: sources: support virtual-hosted-style URLs
s3:: source URLs using the virtual-hosted-style S3 endpoint format were rejected:
terraform { source = "s3::https://my-bucket.s3.us-west-2.amazonaws.com/terraform/modules/myapp.zip" }This resulted in errors like:
ERROR downloading source url s3::https://my-bucket.s3.us-west-2.amazonaws.com/...
- URL is not a valid S3 URL
Terragrunt now accepts every AWS S3 endpoint form, including virtual-hosted-style URLs (<bucket>.s3.<region>.amazonaws.com) and modern path-style URLs (s3.<region>.amazonaws.com).
Windows console mode is restored when Terragrunt exits
On Windows, running a Terragrunt command from Nushell could leave the shell unable to read input afterward, with keystrokes such as the arrow keys appearing as raw escape sequences instead of being interpreted.
While it runs, Terragrunt reconfigures the console it shares with the parent shell so that terminal escape sequences are processed, but it did not put the original mode back when it exited. PowerShell reapplies its own console settings on every prompt and recovers on its own, so the problem surfaces only in shells that keep the inherited mode, such as Nushell. Terragrunt now records the console mode at startup and restores it on exit, returning the shell to the state it was in beforehand.
Reported in #6245.
📖 Documentation Updates
Clean Markdown is available for every docs page at <url>.md
Every docs page is now served as clean Markdown at the same URL with .md appended. For example, /getting-started/install is also available at /getting-started/install.md.
curl https://docs.terragrunt.com/getting-started/install.mdThe .md version contains the page content without the site navigation or other surrounding HTML, which makes it well suited as context for LLMs and AI tooling: it is smaller and carries only the documentation itself. Coverage includes every page, including the CLI command reference and the changelog.
This complements the existing llms.txt and llms-full.txt files by providing a per-page Markdown source.
🧪 Experiments Added
optional-hooks — Add experimental --no-hooks flag support for terragrunt run
The terragrunt run command now supports an experimental --no-hooks flag for disabling hook execution during command runs.
The feature is gated behind the optional-hooks experiment and skips execution of before_hook, after_hook, and error_hook blocks when enabled.
TG_EXPERIMENT=optional-hooks terragrunt run --no-hooks planThis feature is currently experimental because disabling hooks changes Terragrunt execution semantics and may evolve in future releases.
Using --no-hooks without enabling the optional-hooks experiment will return an error.
hook-context-env experiment exposes additional TG_CTX_* env vars to hooks
Enable the new hook-context-env experiment to surface three additional environment variables to every before_hook, after_hook, and error_hook:
TG_CTX_HOOK_TYPE — before_hook, after_hook, or error_hook, identifying which lifecycle phase invoked the hook.
TG_CTX_SOURCE — the resolved terraform source URL (CLI --source override, else evaluated terraform.source with source-map applied, else .).
TG_CTX_TERRAGRUNT_DIR — the directory of the current Terragrunt config.terragrunt run --all --experiment hook-context-env -- applyThese variables make it easier to share a single hook script across lifecycle phases and to access the unit's source and config directory without threading them through hook arguments.
🧪 Experiments Updated
cas: fallbacks now emit telemetry
When the cas experiment is enabled and a CAS operation cannot complete, Terragrunt falls back to a slower path (the standard download client, or a temporary clone when the shared git store is unavailable) and keeps going. Until now the only record of a fallback was a warning in the logs, which made it impractical to measure how often CAS degrades across a fleet.
Each fallback now also emits a cas_fallback telemetry event whose reason attribute identifies the cause: init_error, getter_error, git_store_unavailable, probe_failure, or stack_generation_error. Operators collecting OpenTelemetry traces or metrics from Terragrunt can count and alert on these events to judge CAS health before relying on it by default.
CAS flags for the catalog command
The catalog command now accepts the --no-cas and --cas-clone-depth flags, which were already available on run, stack generate, and stack run. When --no-cas is set, catalog repositories are cloned with plain Git even if the cas experiment is enabled. --cas-clone-depth controls the git clone --depth value the CAS uses when cloning catalog repositories.
terragrunt catalog --experiment cas --cas-clone-depth=-1cas — update_source_with_cas requires a literal source string
When a catalog unit, stack, or terraform block set update_source_with_cas = true with a source that was not a literal string, rewriting silently produced a wrong source. Interpolation such as "../units/${local.name}" had the interpolated portion dropped, leaving a bare prefix; a reference such as local.foo resolved to the directory containing the block itself. In both cases stack generation packaged the wrong directory without any error.
Stack generation now fails with an error explaining that update_source_with_cas requires a literal source string. Non-literal expressions, including interpolation, function calls, and references like local.foo, are rejected.
cas — Malformed cas:: references fail with a clear error
A cas:: source with a malformed hash, such as cas::sha1:a, used to fail with an opaque internal error while looking the hash up in the store.
CAS references are now validated up front: the hash must be lowercase hexadecimal with exactly 40 characters for sha1 or 64 for sha256. References that don't match are rejected with an error identifying the bad reference.
cas — Repositories with submodules now clone correctly
Cloning a repository that contains git submodules through the Content Addressable Store failed while ingesting the repository:
git_cat_file: fatal: Not a valid object name <hash>
A submodule appears in the repository tree as a pointer to a commit in another repository, so the object behind it cannot be read from the repository being cloned.
The CAS now fetches each submodule from the URL registered in .gitmodules at its pinned commit and materializes its contents in place, including nested submodules. Relative submodule URLs (such as ../sibling.git) are resolved against the parent repository URL, matching git's behavior. Submodule contents are stored and deduplicated like any other content, so repeated clones reuse the cache.
catalog-redesign — Failures now exit nonzero and name the sources that failed
The redesigned catalog exited with code 0 even when it failed: a session that ended on an unreachable repository, a failed scaffold, or a failed copy reported success in its exit code. Repositories that failed to load during discovery were dropped too: the warning logged for each one was drawn over by the full-screen interface, so a run where every source failed showed the same "No catalog sources were discovered" screen as a run that genuinely found nothing.
The catalog now exits nonzero when the session ends on a failure: a discovery failure that leaves nothing to browse, a failed scaffold, or a failed copy. Quitting a working session still exits 0. When some sources fail to load while others succeed, the catalog stays usable and a clean quit still exits 0; the component list shows how many sources failed, and the failed repositories are printed with their causes after the catalog closes. When every source fails, the error screen lists each failed repository instead of claiming nothing was found, and dismissing it exits nonzero.
Running terragrunt catalog without an interactive terminal, such as in CI, used to fail with a raw error from the underlying TUI library:
bubbletea: error opening TTY: bubbletea: could not open TTY: open /dev/tty: no such device or addressIt now fails immediately with an error stating that the catalog command requires an interactive terminal.
catalog-redesign — Scaffolding a component no longer fails with a path-traversal error
Scaffolding a component from the catalog (pressing s) could fail on macOS while downloading the source:
subdirectory component contain path traversal out of the repositoryThe catalog caches each repository under the system temporary directory, which macOS reports through a symlink (/var/folders/... pointing at /private/var/folders/...). The source location Terragrunt handed to the downloader was built against the unresolved path, so it pointed outside the cached repository and was rejected.
Terragrunt now resolves the temporary directory before discovering components, so the source stays inside the repository and scaffolding proceeds.
stack-dependencies: HCL tooling now handles autoinclude
Two tooling gaps around the experimental autoinclude block are closed:
hcl validate now validates autoinclude blocks. With the stack-dependencies experiment enabled, validating a terragrunt.stack.hcl that declares autoinclude runs the same strict checks as terragrunt stack generate. A malformed block (for example, a locals block inside autoinclude) is now reported at validation time instead of passing hcl validate and only failing later during generation. Without the experiment, validation behavior is unchanged.
read_terragrunt_config() can read stack-level autoinclude files. Reading a generated terragrunt.autoinclude.stack.hcl previously failed because the file was decoded as a unit configuration, which rejects its unit and stack blocks. With the experiment enabled, the file is now decoded as the stack-file fragment it is, returning its unit and stack blocks the same way reading a terragrunt.stack.hcl does. Unit-level terragrunt.autoinclude.hcl files already read correctly and continue to do so.
stack-dependencies: autoinclude merges like a regular include
A generated unit autoinclude (terragrunt.autoinclude.hcl) now merges into the unit's config using the same default merge as a regular include, which is a shallow merge, applied uniformly across generation, full parse, and discovery. Top-level keys from the unit and the autoinclude combine, and on a conflict the autoinclude wins and replaces the unit's value rather than deep-merging nested maps; locals stay local in scope.
A generated stack autoinclude (terragrunt.autoinclude.stack.hcl) injects unit and stack blocks into the generated terragrunt.stack.hcl. An injected block whose name matches an existing unit or stack now overrides that block wholesale, consistent with unit autoinclude override semantics, and an injected block with a new name is added. This applies uniformly across generation, full parse, and discovery, so a name match no longer produces a duplicate-name error. A stack autoinclude may not declare a top-level dependency block (stacks have no dependencies; declare the dependency inside the target unit's own autoinclude).
A dependency block injected through an autoinclude is now available before a unit's remote_state is evaluated, so referencing dependency.<name>.outputs.<key> there no longer fails. remote_state now behaves the same as generate blocks.
stack-dependencies: autoinclude blocks can reference values.*
An autoinclude block may now reference the stack's values.. Previously a values. reference was rejected at stack generate time, except in a dependency config_path. It now resolves to a literal like local.*, unit.<name>.path, and stack.<name>.path, wherever it appears: inputs, generate, remote_state, mock_outputs, and config_path.
Function calls in an autoinclude now resolve at generate time too, in the terragrunt.stack.hcl context, instead of being kept verbatim and evaluated in the generated unit. Only a dependency.* reference (a dependency's outputs) stays verbatim and resolves inside the unit; in a mixed expression the stack-level parts resolve and only the dependency.* reference is kept.
Because functions now evaluate against the stack file rather than the unit, directory and include functions report the stack file's location: get_terragrunt_dir returns the stack file's directory, and path_relative_to_include returns ".". If you relied on these resolving in the unit, move them to the unit's own configuration, or derive a per-unit value such as a remote_state backend key from unit.<name>.path.
A locals block inside an autoinclude remains rejected; declare stack-level locals in terragrunt.stack.hcl instead.
stack-dependencies: stack dependencies resolve values.* in the target stack's locals
Expanding a dependency that points at a generated stack directory no longer fails when that stack's terragrunt.stack.hcl reads values.* in its locals block. Previously, terragrunt stack generate succeeded but terragrunt run --all then failed with There is no variable named "values" while expanding the dependency into its units.
Dependency expansion now reads the generated terragrunt.values.hcl next to each terragrunt.stack.hcl it visits, including nested stacks, so each nesting level resolves values.* from its own values file, the same way a full stack parse does.
stack-dependencies: component path references in values no longer break next to autoinclude blocks
A unit or stack block's values can reference unit.<name>.path and stack.<name>.path even when another block in the same terragrunt.stack.hcl declares an autoinclude. Previously, the presence of any autoinclude block made stack generate reject those references with Unknown variable; There is no variable named "unit", while the same file without an autoinclude generated fine.
Pull Requests
✨ Features
feat: add hook-context-env experiment by @arnaud-dezandee in #6189
feat: Adding CAS fallback telemetry by @yhakbar in #6298
🐛 Bug Fixes
fix: Fixing filter tests on Windows by @yhakbar in #6247
fix: Fix Windows nushell bug by @yhakbar in #6250
fix(codegen): fix assume_role parsing failure when transitive_tag_keys or policy_arns arrays are present by @Rahul-Kumar-prog in #5975
fix: Fixing scaffold path traversal check by @yhakbar in #6255
fix(telemetry): honor OTEL_SERVICE_NAME and OTEL_RESOURCE_ATTRIBUTES environment variables by @Tensho in #6256
fix: Fixing graph traversal bug with intersected filter by @yhakbar in #6270
fix: resolve locals in autoinclude mock_outputs by @denis256 in #6274
fix: report the offending field in Terragrunt config errors by @denis256 in #6284
fix: Fixing values without autoinclude by @yhakbar in #6290
fix: Fixing values references in locals of terragrunt.stack.hcl files by @yhakbar in #6291
fix: Fixing experiment promotion by @yhakbar in #6293
fix: Adding support for submodules in CAS by @yhakbar in #6294
fix: Validating CAS sources by @yhakbar in #6296
fix: Support autoinclude in hcl validate and fix read_terragrunt_config() for configurations using autoinclude by @yhakbar in #6297
fix: Fixing legacy virtual hosted style S3 URLs by @yhakbar in #6311
fix: Addressing lint findings by @yhakbar in #6312
📖 Documentation
docs: Documenting CAS Getters by @yhakbar in #6251
docs: Support completedSince by @yhakbar in #6252
docs: Since/Before cleanup by @yhakbar in #6277
docs: Since/Before cleanup workflow by @yhakbar in #6276
docs: Support .md changelog files by @yhakbar in #6286
docs: Adding autoinclude documentation by @yhakbar in #6299
🧹 Chores
chore: weekly tests reporting by @denis256 in #6191
chore: Add thanks for #5975 by @yhakbar in #6253
chore: autoinclude merge fixes by @denis256 in #6248
chore: cleaned unused code by @denis256 in #6260
chore: Add CodeRabbit release check by @yhakbar in #6278
chore(deps): bump actions/upload-artifact from 7.0.0 to 7.0.1 by @dependabot[bot] in #6265
chore(deps): bump docker/setup-docker-action from 5.1.0 to 5.2.0 by @dependabot[bot] in #6266
chore(deps): bump aws-actions/configure-aws-credentials by @dependabot[bot] in #6267
chore: Make autoinclude more flexible, supporting values.* by @yhakbar in #6283
chore: Threading venv through CLI by @yhakbar in #6089
chore: Isolate test git servers by @yhakbar in #6233
chore: Add --no-cas flag to the catalog command by @yhakbar in #6292
chore: Clean up from #6290 by @yhakbar in #6295
chore: Adding DAG view tests by @yhakbar in #6300
chore: Speeding up files read by @yhakbar in #6301
📝 Other Changes
Make guides collapsed to start by @karlcarstensen in #6262
Fix for light/dark mode by @karlcarstensen in #6264
Collapse reference section by @karlcarstensen in #6263
serve clean Markdown at .md for every page by @karlcarstensen in #6281
Feature/optional hooks experiment by @Rahul-Kumar-prog in #6227
Update to llms.txt. Added curated llms.txt and configured plugin to also serve full and small by @karlcarstensen in #6280
Changelog by @karlcarstensen in #6285
Fix #5054: support hcl_fmt in generate blocks by @DadaVinqi in #6287
fix Fixing catalog exit codes by @yhakbar in #6302
Original source - Jun 1, 2026
- Date parsed from source:Jun 1, 2026
- First seen by Releasebot:Jun 1, 2026
v1.0.7
Terragrunt adds optional versions for tfr:// module sources and expands CAS to cover more remote sources and registry modules. This release also improves stack dependency path handling, fixes Windows filtering and panic cases, and tightens parallelism validation for safer, smoother runs.
✨ New Features
tfr:// source URLs accept an optional version
The version query parameter on tfr:// source URLs is now optional. When omitted, Terragrunt queries the registry's list-versions endpoint and downloads the latest stable version, matching how OpenTofu and Terraform resolve a module reference that has no version constraint.
terraform { source = "tfr:///terraform-aws-modules/vpc/aws" }Prereleases are excluded from resolution, so a registry that only publishes 4.0.0-rc1 alongside 3.3.0 will pin to 3.3.0. Pin a version explicitly with ?version= when you need reproducible builds or want to opt into a prerelease.
Thanks to @raman1236 for contributing this feature!
🐛 Bug Fixes
update_source_with_cas: preserve //subdir on a unit's terraform.source
When a unit's terraform.source used the // subdir convention (for example, source = "../..//modules/foo") and opted into update_source_with_cas, the rewritten source dropped the //subdir tail and the synthetic tree contained only the leaf module's files. A module that referenced a sibling via a relative path (source = "../bar") could not resolve that reference after materialization.
Rewrites now preserve the original //subdir (for example, cas::sha1:<hash>//modules/foo), and the synthetic tree is rooted at the path before //, so sibling files reachable via relative paths land in the materialized working directory.
Sources without // are unchanged: the tree stays scoped to the leaf module, and the rewritten reference has no //subdir tail.
--filter now detects affected units on Windows
On Windows, terragrunt find --filter '[origin/main...HEAD]' (and its variants) returned no affected units even when git diff reported changed files. The source= and reading= filters were affected by the same problem.
Filter glob patterns are always written with forward slashes, but the affected-unit comparison was being made with Windows backslash separators, so nothing matched. Terragrunt now compares paths consistently with forward slashes on every platform, and the filter detects changed units on Windows as it already did on Linux and macOS.
Reported in #6214.
startswith, endswith, strcontains, and run_cmd no longer panic on malformed calls
Calling startswith, endswith, or strcontains with the wrong number of arguments (for example a single argument instead of two) crashed Terragrunt instead of reporting a configuration error. Calling run_cmd with only option flags and no command (for example run_cmd("--terragrunt-quiet")) crashed the same way.
These calls now return a clear error: a wrong-number-of-parameters error for the string functions, and an empty-command error for run_cmd.
The --parallelism flag no longer accepts non-positive numbers
Previously, terragrunt commands that accept the --parallelism flag (or equivalently the $TG_PARALLELISM environment variable) used to hang indefinitely when invoked with --parallelism=0.
Terragrunt now validates that the value is positive and exits with an error otherwise.
Reported in #6211
🧪 Experiments Updated
cas — content-addressing for non-git sources
CAS now covers module sources beyond git: http(s), Amazon S3, Google Cloud Storage, and Mercurial. Repeat runs against an unchanged remote reuse the cached tree instead of downloading the bytes again.
Before fetching, CAS issues a cheap remote probe (an HTTP HEAD, an S3 object-attributes lookup, a GCS metadata read, or hg identify) to derive a cache key without pulling the source. On a hit, the cached tree is linked directly; on a miss, or when the remote exposes no usable signal, CAS downloads the source, ingests it, and keys the resulting tree by its content hash. A remote that publishes a new version under the same address pins to a new entry, so a stale cache cannot serve outdated bytes.
cas — OpenTofu/Terraform registry sources
Module sources of the form tfr://... are now content-addressed in CAS. Repeat runs against the same pinned registry version reuse the cached module instead of re-downloading the archive from the registry.
CAS resolves a tfr:// source by asking the registry where the underlying archive lives and uses that resolved URL as the cache key. Two runs that pin the same version share one entry; a republish under the same version pins to a new entry, so a stale cache cannot serve outdated bytes.
stack-dependencies: unit.<name>.path and stack.<name>.path resolve in values
The stack-dependencies experiment now exposes unit.<name>.path and stack.<name>.path when evaluating the values attribute of a unit or stack block, not only inside autoinclude blocks. A parent stack can pass the generated path of a sibling component down into a child stack, so a unit nested in that child stack can depend on a unit that lives at a different level of the hierarchy.
unit "vpc" { source = "../catalog/units/vpc" path = "vpc" } stack "app" { source = "../catalog/stacks/app" path = "app" values = { vpc_path = unit.vpc.path } }A unit inside the app stack reads values.vpc_path and uses it as the config_path of an autoinclude dependency, wiring the cross-level relationship at generation time. Paths follow the same layout the generator produces, including no_dot_terragrunt_stack on the referenced block.
stack-dependencies: simplified unit.* / stack.* ref shape
The stack-dependencies experiment no longer resolves stack.<name>.<unit_name>.path or stack.<name>.<nested_stack>.path. Only the top-level stack.<name>.path and unit.<name>.path forms remain. stack.<name>.name and unit.<name>.name are gone too; both only ever echoed the label that the reference already had to spell out.
Nested references required parsing every nested catalog up front and conflicted with the reserved name and path attributes on each ref: a nested unit named name or path could not be addressed.
To depend on a generated unit inside a stack, compute the path as ${stack.<name>.path}/<unit-relative-path> directly. The layout under a stack's generated directory follows no_dot_terragrunt_stack on the parent stack and on each unit, so hand-computed paths must mirror that resolution.
stack-dependencies: .terragrunt-stack-origin no longer written
Terragrunt no longer writes the .terragrunt-stack-origin file when generating nested stacks. Set update_source_with_cas = true on your unit and stack blocks if you would like relative paths in your catalog to resolve correctly instead.
Pull Requests
✨ Features
feat: Make version optional in tfr:// module registry URLs by @yhakbar in #6112
feat: Supporting all getters in CAS by @yhakbar in #6076
🐛 Bug Fixes
fix: Removing use of cas.WithFS by @yhakbar in #6195
fix: panics in startswith / endswith / strcontains / run_cmd by @denis256 in #5984
fix: Allowing all TG HCL fns in terragrunt.stack.hcl, including autoinclude by @yhakbar in #6166
fix: Fixing synthetic trees for terraform.source URLs with // by @yhakbar in #6218
fix: Fixing nested generation for paths with // by @yhakbar in #6234
fix: Fixing stack path variables in values by @yhakbar in #6235
fix: Fixing stack autoinclude by @yhakbar in #6236
fix: Fixing git filters on Windows by @yhakbar in #6242
fix: validate that --parallelism value is positive by @ccmtaylor in #6212
📖 Documentation
docs: Cleaning up experiment docs by @yhakbar in #6228
docs: Fixing unreleased changelog page by @yhakbar in #6237
docs: Cleaning up changelogs for v1.0.7 by @yhakbar in #6246
🧹 Chores
chore: Getting rid of fatih/structs dependency by @yhakbar in #6186
chore: Getting rid of go-homedir direct dependency by @yhakbar in #6184
chore: improved coderabbit rules by @denis256 in #6193
chore: Consolidating on lipgloss for color by @yhakbar in #6188
chore: Removing go-errors as a dependency by @yhakbar in #6182
chore: tests simplification by @denis256 in #6208
chore: Adding separate archive field by @yhakbar in #6196
chore: Addressing UI/UX feedback for interactive scaffold in catalog by @yhakbar in #6175
chore: added unknown-unknowns heuristics for coderabbit by @denis256 in #6220
chore: Make clone tests a bit faster by @yhakbar in #6081
chore: stacks dependencies simplificaitons by @denis256 in #6171
chore(deps): bump actions/stale from 10.2.0 to 10.3.0 by @dependabot[bot] in #6201
chore: Fixing gopls workflow by @yhakbar in #6229
chore: Increasing test coverage for stack dependencies by @yhakbar in #6231
chore: Go and GHA dependencies by @denis256 in #6240
chore: Ensuring full support for tfr in CAS by @yhakbar in #6123
chore: Adding no // path test for source with CAS by @yhakbar in #6239
chore: Modernizing using gopls by @yhakbar in #6232
Original source - May 25, 2026
- Date parsed from source:May 25, 2026
- First seen by Releasebot:May 26, 2026
v1.0.6
Terragrunt ships bug fixes, experiments, and stack improvements, including safer discovery and render handling, an experimental deep_merge HCL function, opt-out auth during discovery, and a more interactive catalog scaffold flow.
🐛 Bug Fixes
terragrunt no longer hangs when download_dir is a non-hidden subdirectory of the unit
Setting download_dir (via the attribute, --download-dir, or TG_DOWNLOAD_DIR) to a subdirectory of the unit's working directory whose name did not start with a dot caused commands that prepare the OpenTofu or Terraform source (apply, plan, run, and similar) to hang.
For example:
# /infra/web/terragrunt.hcl download_dir = "cache" terraform { source = "./mod" }Here terragrunt apply would copy ./mod into cache/, see the new cache/ directory on the next read of the unit, and recurse into it. The default .terragrunt-cache was unaffected because Terragrunt's source-copy step skips any directory whose name starts with a dot.
These configurations now produce an immediate error identifying the source and destination paths.
mark-many-as-read experiment now triggers during discovery
With the mark-many-as-read experiment enabled, a unit whose terraform { source = ... } pointed at a local module did not show up under --filter 'reading=' filters that referenced files inside that module. Discovery would parse the unit, but the module files were never recorded as read, so the reading filter attribute could not match and the queue came back empty.
The module walk now runs on the discovery code path as well, so changes to files in a local module source flow through to the units that depend on them.
terragrunt render no longer crashes on exclude or catalog blocks with certain attributes
Rendering a config crashed with a value has no attribute of that name panic before any output could be produced when:
- the exclude block set no_run, or
- the catalog block set default_template, no_shell, or no_hooks.
These attributes are now carried through the render pipeline alongside the other fields on their respective blocks, so both blocks round-trip cleanly.
terragrunt render no longer crashes on multiple errors.ignore blocks with mismatched signals
Rendering a config that defined more than one errors.ignore block crashed with an inconsistent list element types panic when the signals map was populated on one block and absent (or differently typed) on another. The same crash showed up in dependency-output evaluation, since both paths build the same rendered representation of the config.
Each ignore block is now rendered with a uniform shape. Indexed access (errors.ignore[0]), length, and iteration still work, and the signals map on each block is preserved as written.
Suppress spurious Unknown variable: dependency errors during dependency resolution
terragrunt plan and apply no longer print ERROR Error: Unknown variable "dependency" lines when a unit pulls in a shared include (e.g. via find_in_parent_folders) that references dependency.* outputs. The plans completed correctly, but the error lines cluttered CI logs.
Resolves #6036.
terragrunt stack commands no longer crash on stacks with multiple units
Running terragrunt stack output (or any command that resolves concurrently parsing multiple configuration files) against a stack with several units could intermittently crash while the units were being parsed in parallel due to a race on internal bookkeeping of files read (used in the reading filter attribute).
Parallel unit parsing now coordinates safely when recording which source files were read, preventing crashes.
terraform_binary properly respected when both tofu and terraform are on PATH
A regression in command execution caching resulted in over-caching the STDOUT result of tofu --version when both tofu and terraform were available on PATH and terraform_binary was set. Early on in the execution flow, Terragrunt checks if OpenTofu is installed what its version is to determine if it supports setting of the automatic provider cache directory. This resulted in the value of terraform_binary being ignored for later version checks to assess compliance with terraform_version_constraint.
The version-detection cache used per run is now scoped to the binary that produced each entry, so the version recorded against an early default-binary resolution no longer leaks into the later resolution that honors terraform_binary.
🧪 Experiments Added
deep-merge experiment adds a deep_merge HCL function
Enable the new deep-merge experiment to use the deep_merge(map1, map2, ...) HCL function.
deep_merge recursively merges map and object values. Later arguments override earlier arguments for overlapping keys, nested maps are merged recursively, lists are appended, and null arguments are ignored.
This is useful when composing inputs from multiple decoded JSON, YAML, or HCL-derived maps:
locals { config_json_files = sort(fileset(get_terragrunt_dir(), "*.json")) config = deep_merge([ for file in local.config_json_files : jsondecode(file("${get_terragrunt_dir()}/${file}")) ]...) } inputs = local.configCalling deep_merge without enabling the deep-merge experiment returns an error.
opt-out-auth — Opt out of --auth-provider-cmd during discovery
Enable the new opt-out-auth experiment to use --no-discovery-auth-provider-cmd (env: TG_NO_DISCOVERY_AUTH_PROVIDER_CMD), which disables the auth provider command during the discovery phase.
Without the flag, Terragrunt assumes that --auth-provider-cmd must be run per parsed component during the discovery phase so that it can reliably resolve HCL functions such as get_aws_account_id and run_cmd. On large repositories with run --all --filter='reading=', this dominates wall-clock time because the auth command runs for every discovered unit rather than only the subset that will run.
The --no-discovery-auth-provider-cmd flag turns off auth invocations during discovery. The auth provider command still runs normally when running units.
Units whose discovery-relevant blocks depend on credentials produced by --auth-provider-cmd will fail to parse with the flag set. Use it when you know that parsing will resolve successfully without any authentication done beforehand by Terragrunt.
While this flag is experimental, you must also opt-in to the opt-out-auth experiment by setting the TG_EXPERIMENT environment variable to opt-out-auth or by passing the --experiment=opt-out-auth flag to terragrunt run. This flag might experience breaking changes based on community feedback for the duration of the experiment.
e.g.
terragrunt run --all \ --experiment=opt-out-auth \ --no-discovery-auth-provider-cmd \ --queue-include-units-reading=./changed-file.txt \ plan🧪 Experiments Updated
catalog-redesign — Interactive scaffold form on s
Pressing s from the catalog list or detail view now opens an in-TUI form that prompts for every variable/value the selected component exposes. The form is modal: in navigate mode j and k (or the arrow keys) move between fields and enter interacts with the focused one. Required entries are flagged, and optional entries show their default in a muted style until the user opts in.
enter on a text or HCL field switches the form into edit mode. Typing edits the value in place; esc returns to navigate. Only fields the user actually changes get written to the generated file, and optional defaults stay implicit, so the result is leaner than the placeholder flow.
enter on a boolean field toggles between [x] true and [ ] false directly, without a separate edit mode.
x on an optional field marks it "use default" again, removing any in-progress value and leaving the source's default to apply.
Complex types (lists, maps, objects) accept raw HCL and are validated before the file is written, so a typo surfaces inline rather than producing a broken terragrunt.hcl or terragrunt.values.hcl file.
ctrl+d finishes the form. Required fields the user never set still write as # TODO: fill in value so the rest of the file is usable.
S (capital) keeps the previous placeholder-only flow, generating the same TODO-laden file as before for users who prefer to populate values by editing the generated file.
stack-dependencies: parser tolerates HCL expressions throughout terragrunt.stack.hcl
The stack-dependencies experiment now defers evaluation of source, path, values, and include.path until each unit or stack block is parsed on its own. As a result, autoinclude resolution during stack generation and run --all discovery no longer fall over when other parts of a stack file use Terragrunt functions, local., or values.. A few adjacent behaviors are tightened up at the same time.
Autoinclude resolves even when sibling units use expressions.
Before 1.0.6, if any unit in a stack file used a function call or a local.* / values.* reference in source, path, or values, generating an autoinclude on a different unit in the same file could fail. The parser now leaves those expressions alone until they're needed, so an unrelated unit can carry an autoinclude block without being blocked by its neighbors:
locals { shared_region = "us-east-1" } unit "account" { source = "${get_terragrunt_dir()}/../catalog/units/account" path = "account" values = { account = values.account region = local.shared_region } } unit "roles" { source = "${get_terragrunt_dir()}/../catalog/units/roles" path = "roles" autoinclude { dependency "account" { config_path = unit.account.path } } }include blocks in terragrunt.stack.hcl accept computed paths.
The path attribute on an include block can be an HCL expression, not just a string literal. An autoinclude block in the included file is resolved normally after the include merges in:
include "shared" { path = find_in_parent_folders("shared.stack.hcl") }What's Changed
- chore: Fixing release bug fix notification by @yhakbar in #6143
- fix: Fixing panic in render WriteTo by @yhakbar in #6144
- fix: Fixing files read race by @yhakbar in #6145
- Implement IndexNow by @karlcarstensen in #6150
- docs: added filtering of compatibility table by @denis256 in #6149
- feat: add deep_merge HCL function as experiment by @EvansM4 in #5535
- chore(deps): bump jdx/mise-action from 4.0.0 to 4.0.1 by @dependabot[bot] in #6153
- chore(deps): bump peter-evans/create-pull-request from 8.1.0 to 8.1.1 by @dependabot[bot] in #6154
- chore(deps): bump DavidAnson/markdownlint-cli2-action from 22.0.0 to 23.2.0 by @dependabot[bot] in #6155
- chore(deps): bump the js-dependencies group across 1 directory with 12 updates by @dependabot[bot] in #6156
- chore: Trimming JS deps by @yhakbar in #6159
- feat: Allow opt-out from auth in discovery by @yhakbar in #6119
- chore: Removing setup-go from Windows signing by @yhakbar in #6158
- chore: stacks dependencies variables by @denis256 in #6072
- chore: google dependencies update by @denis256 in #6161
- docs: Cleaning up changelog for stack dependencies permissive parser by @yhakbar in #6163
- fix: Fixing tf binary version over-caching by @yhakbar in #6148
- chore: Addressing feedback from #6148 by @yhakbar in #6168
- fix: Fixing panic in ignore signal by @yhakbar in #6167
- feat: Add TUI interactivity for catalog scaffold by @yhakbar in #6162
- chore: Plumbing in vfs to getter by @yhakbar in #6070
- fix: Reducing spurious unknown variable dependency errors by @yhakbar in #6060
- chore: Upping strict control test coverage by @yhakbar in #6080
- chore: Increasing virtualization further by @yhakbar in #6084
- docs: Enhance documentation for --out-dir usage by @FernandoArteaga-telus in #6176
- fix: Fixing mark-many-as-read for discovery by @yhakbar in #6174
- chore: Bumping golang deps from #6164 by @yhakbar in #6177
- chore: Clean-up of comments from #6174 by @yhakbar in #6179
- chore: Clean up strict control debug message by @yhakbar in #6178
- chore: Removing go-commons dependency by @yhakbar in #6180
- fix: Fixing download_dir copy infinite recursion by @yhakbar in #6169
- chore: Fixing sops tests by @yhakbar in #6187
New Contributors
- @EvansM4 made their first contribution in #5535
- @FernandoArteaga-telus made their first contribution in #6176
Full Changelog: v1.0.5...v1.0.6
Original source - May 18, 2026
- Date parsed from source:May 18, 2026
- First seen by Releasebot:May 19, 2026
v1.0.5
Terragrunt releases faster stack output, full cross-platform provider lock files, and a broad set of fixes for auth, caching, source handling, and run reporting. It also adds new CAS enhancements, an azure-backend experiment, and better filter and stack-target guidance.
✨ New Features
Full .terraform.lock.hcl files from the provider cache server
When the provider cache server is used against the OpenTofu provider registry, Terragrunt now writes .terraform.lock.hcl files containing h1: hashes for every platform the registry supports. A single terragrunt init produces a lock file that works on every platform, removing the need to run tofu providers lock -platform=... separately for each target architecture.
provider "registry.opentofu.org/hashicorp/null" { version = "3.2.2" constraints = "3.2.2" hashes = [ "h1:+1mRmfyz6oA00IhrrSkHK3h/Mdh032x2p0F6OMdMo5s=", "h1:FjLTqvaaYo+vHN8pHZB1cOwEGiNzOj+I9kQyHmr9/7o=", # ... one entry per supported platform ... "zh:00e5877d19fb1c1d8c4b3536334a46a5c86f57146fd115c7b7b4b5d2bf2de86d", # ... one entry per supported platform ... ] }The hashes come from the registry's per-platform download response. When the registry does not supply them (for example, a third-party registry that has not adopted the field), Terragrunt falls back to its previous behavior of writing an h1: hash for the current platform plus zh: hashes for every platform listed in the shasums document.
Tip
Thanks to the OpenTofu team
This feature builds on work done by the OpenTofu team to expose per-platform hashes directly from the OpenTofu provider registry. Starting with OpenTofu 1.12, tofu init populates .terraform.lock.hcl with hashes for every supported platform out of the box, with no tofu providers lock invocation required. Users on older OpenTofu versions still get the same lock files when running through Terragrunt's provider cache server, but upgrading to 1.12 is the easiest way to get the same behavior everywhere, including when using the automatic provider cache dir.
🏎️ Performance Improvements
stack output fetches unit outputs in parallel
terragrunt stack output now fetches outputs from multiple units at the same time, which is noticeably faster on larger stacks. Use the existing --parallelism flag (or TG_PARALLELISM) to lower concurrency if you need to.
terragrunt stack output --parallelism 4💡 Tips Added
Stack-target hint when --filter is missing | type=stack
run and stack generate now emit a tip when a --filter path resolves to a directory containing terragrunt.stack.hcl but the filter is not restricted to stacks. Without | type=stack, stack generate ignores the filter and run does not generate that stack.
The tip prints the offending filter, the suggested rewrite, and a link to the filter docs. Suppress it with --no-tip stack-target-missing-type-stack or --no-tips.
🐛 Bug Fixes
Auth provider command returning null no longer crashes Terragrunt
If the command configured via --auth-provider-cmd wrote the JSON value null to stdout, Terragrunt crashed with a nil pointer dereference before it could obtain credentials.
A null response is now treated as an empty response: no environment variables and no credentials are applied, and the run continues.
Auto-init now re-runs after a source change when modules are already cached
terragrunt plan/apply could fail with Error: Required plugins are not installed after a source-version change in any unit with a module "" block. The .terragrunt-init-required marker written on source change was being ignored because modulesNeedInit short-circuited as soon as .terraform/modules/ existed.
The marker check now lives at the top of needsInitRunCfg and is honored regardless of cached .terraform/modules/ contents.
Thanks to @arnaud-dezandee for contributing this fix!
--download-dir is now respected through dependency blocks and read_terragrunt_config
A custom download directory set via --download-dir (or TG_DOWNLOAD_DIR) was honored for the unit being run, but lost as soon as parsing crossed into another config. dependency blocks and read_terragrunt_config() would fall back to the dependency's local .terragrunt-cache next to its terragrunt.hcl, ignoring the user-set path.
TG_DOWNLOAD_DIR=/tmp/tg-cache terragrunt run --all plan # Root unit: outputs landed in /tmp/tg-cache ✓ # Dependency outputs: written next to each dependency's terragrunt.hcl ✗When the parsing context switches to a new config path, the download directory is now updated only if it still points at the previous module's default location. A user-supplied path never matches any module's default and is carried through every dependency hop unchanged.
Thanks to @maonat for contributing this fix!
remote_state — apply tags during DynamoDB lock table creation
Terragrunt previously applied dynamodb_table_tags to DynamoDB lock tables after table creation rather than during the initial CreateTable API request.
This caused failures in environments enforcing required AWS resource tags through SCPs or tag policies, where tags must be present at resource creation time.
Terragrunt now includes dynamodb_table_tags in the initial DynamoDB table creation request during remote state bootstrap.
remote_state { backend = "s3" config = { bucket = "my-state-bucket" dynamodb_table = "terraform-locks" dynamodb_table_tags = { Environment = "prod" Team = "platform" } } }Thanks to @Rahul-Kumar-prog for contributing this fix!
Engine archive extraction rejects path-traversal entries
When Terragrunt extracted an engine archive while the engine experiment was active, entries whose target path resolved outside the extraction directory were not rejected correctly. Such an entry could overwrite files anywhere the Terragrunt process could write.
These entries are now rejected early with a descriptive error before any bytes are written. Engine archives produced by Gruntwork were never affected; the gap only mattered for a tampered or untrusted archive.
Thanks to @jackiesre721 for reporting this!
--filter combined with a negation no longer parses excluded units
When a positive path filter was combined with a negated one, Terragrunt classified any unit that matched neither expression as requiring defensive parsing before exclusion instead of being excluded early.
e.g.
$ terragrunt run --all --filter './foo' --filter '!./baz' # If `./bar` existed on disk, it would be parsed before being excluded. This is no longer the case.Any positive filepath filter now consistently results in units that cannot be discovered during Terragrunt discovery being excluded from parsing for evaluating candidacy of inclusion. When a sufficiently complex filter is present, like the following:
$ terragrunt run --all --filter './foo' --filter '!./baz' --filter 'reading=root.hcl' # If `./bar` existed on disk, it will still be parsed before being excluded to determine if it reads `root.hcl`.macOS and Windows binaries report the correct release version
The v1.0.4 macOS and Windows release binaries reported terragrunt version main and parsed as 0.0.0, breaking any terragrunt_version_constraint configured against them.
sign-macos.yml and sign-windows.yml included build jobs for standalone workflow_dispatch runs. During the release workflow, those jobs still saw the original workflow_dispatch event from release.yml, so the old condition evaluated to true. The redundant build used BUILD_VERSION=${{ github.ref_name }} and replaced the correctly versioned artifact uploaded by build.yml.
The signing workflows now skip their internal build job when invoked via workflow_call and only build when dispatched directly, so release binaries keep the version stamped by build.yml.
Fixed 403 Forbidden on nested private modules when using the provider cache server
With TG_PROVIDER_CACHE enabled, OpenTofu/Terraform sent nested module-registry lookups to the upstream registry with the cache server's API key as the bearer token, instead of the credentials configured for that host. Private registries rejected those requests:
Error: Error accessing remote module registry Failed to retrieve available versions for module "<name>" from <registry>: error looking up module versions: 403 Forbidden.Terragrunt sets TF_TOKEN_<host> to the cache server's API key so the cache can front provider downloads. Module-registry requests bypassed the cache and went straight to the upstream, so the registry saw the cache key instead of the user's token.
The cache server now also fronts the modules.v1 endpoint for each configured registry. It drops the inbound cache-server bearer, looks up the user's credentials for the upstream host from the loaded CLI config (TF_TOKEN_<host>, ~/.terraform.d/credentials.tfrc.json, etc.), and forwards the request with that token.
Run report file generation no longer stalls or deadlocks with many runs
Generating a run report via --report-file could stall or deadlock when a queue contained many runs and some were still recording their final status as the report was written.
Reports now serialize each run independently, so writing a report no longer blocks status updates from runs that are still finishing.
Thanks to @jackiesre721 for contributing this fix!
Declining a run --all or --graph confirmation no longer skips cleanup
When terragrunt run --all destroy (or --all state, --all apply, or the equivalent --graph variants) prompted for confirmation and the user answered "no", Terragrunt terminated the process directly, skipping cleanup the run had registered.
Cleanup now runs before Terragrunt exits.
s3:: and gcs:: stack sources now download
Stack file source URLs starting with s3::https:// or gcs::https:// previously failed with a credentials error even when valid credentials were available. They now download. Existing stack files need no change.
Plain https://www.googleapis.com/storage/... URLs are now intended to download anonymously without GCP credentials, but Terragrunt continues to use GCS credentials to download them for backward compatibility, emitting a deprecation warning the first time it does so. To opt into the new behavior, enable the legacy-gcs-public-prefix strict control. To pull from a private GCS bucket explicitly, prefix the URL with gcs:: yourself.
Fixed nested key order in terragrunt stack output
When a unit lived inside more than one nested stack, terragrunt stack output rendered its key with the stack names reversed, so a unit inside root_stack_3 > stack_v3 > stack_v2 appeared under stack_v2.stack_v3.root_stack_3 instead of root_stack_3.stack_v3.stack_v2. Deeply nested units also leaked to the top level of the output.
The output now joins stack names from outermost to innermost, matching the declared hierarchy in both the HCL and JSON formats.
Thanks to @anuragrao04 for contributing this fix!
Fixed failed to create directory ...: file exists from the provider cache server
If a previous run had cached a provider by symlinking ~/.terraform.d/plugins/<provider> into Terragrunt's own provider cache, and that user plugin directory was later moved or deleted, the symlink was left dangling. The next run failed with failed to create directory ...: file exists and refused to cache the provider.
Terragrunt now removes a dangling symlink at the cache path on the next run and proceeds to download the provider. A non-symlink at that path is left in place and surfaced as an error.
🧪 Experiments Added
azure-backend — Native Azure Storage (azurerm) remote-state support
The azure-backend experiment has been added as the gate for native Terragrunt support of the Azure Storage (azurerm) remote-state backend. Once it stabilizes, Terragrunt will bootstrap, delete, and migrate Azure storage accounts and blob containers the same way it already does for S3 and GCS, and read state directly from Azure blobs for --dependency-fetch-output-from-state.
In this release the flag is reserved only. Enabling it has no behavioral effect, and remote_state { backend = "azurerm" } continues to pass through to the OpenTofu and Terraform native azurerm backend.
Track progress and share feedback in #4307. For setup steps, see the experiment documentation.
Thanks to @omattsson for driving this experiment forward!
🧪 Experiments Updated
CAS keeps a central Git store for incremental fetches
CAS now keeps one bare Git repository per remote URL inside its store, under ~/.cache/terragrunt/cas/store/git/ on Linux by default. See Storage for where this lives on macOS and Windows. On a cache miss, Terragrunt fetches just the requested ref into that repository instead of running a fresh shallow clone into a temporary directory. Repeated misses against the same remote reuse the existing pack files, so fetching a second ref from the same repository transfers only the new objects.
Concurrent Terragrunt runs against the same remote URL share one fetch instead of cloning in parallel; later runs reuse what the first one transferred. If the shared fetch hangs or fails, Terragrunt logs a warning and falls back to a temporary clone so cloning still succeeds.
You can reclaim space at any time by deleting the git/ subdirectory:
rm -rf ~/.cache/terragrunt/cas/store/gitcas — Commit SHAs accepted in ref=
Source URLs of the form git::<url>?ref=<commit-sha> now resolve through CAS. Previously these clones failed because Terragrunt asked the remote to look up the SHA as a symbolic reference, which Git servers don't support.
Both full SHAs (SHA-1 and SHA-256) and abbreviated SHAs are accepted. Abbreviated SHAs must disambiguate inside the repository, the same rule Git itself applies.
terraform { source = "git::https://github.com/acme/infrastructure-modules.git//vpc?ref=a1b2c3d4e5f67890abcdef1234567890deadbeef" }The first cold clone of a repository pinned to a commit SHA fetches the full history of every branch. Shallow fetches require a ref name, and fetching a commit SHA at limited depth depends on a server option (uploadpack.allowAnySHA1InWant) that is not universally enabled, so CAS fetches all branches at full depth and resolves the SHA locally. Subsequent clones reuse the cached repository and never touch the network for the same commit. Branch and tag refs continue to use the existing shallow path.
cas — mutable attribute on terraform, unit, and stack blocks
A new mutable attribute opts a block out of CAS hardlinking when its source is fetched through CAS. With mutable = true, files materialized into .terragrunt-cache (for terraform) or .terragrunt-stack (for unit and stack) are copied from the CAS store and the working tree is editable.
The default is false. Files are materialized read-only so an accidental edit cannot reach back into the shared CAS store.
terraform { source = "git::https://github.com/acme/infrastructure-modules.git//vpc?ref=v1.0.0" mutable = true }The flag is orthogonal to update_source_with_cas and has no effect when content is fetched through the standard download path, which already produces an independent copy.
cas — update_source_with_cas now idempotent across unit and stack blocks
A terragrunt.stack.hcl with two blocks pointing at the same template directory used to fail stack generate when each block had update_source_with_cas = true. The first block's pass rewrote the shared template's source to a cas::sha256:... reference, then the second block's pass re-read the rewritten file and treated the reference as a relative path.
CAS now skips re-processing a source once it already carries the cas:: prefix, so multiple unit or stack blocks can share a template and resolve to the same synthetic tree.
cas — symlinks in the source repository
Source repositories fetched through CAS used to materialize committed symlinks as regular files whose contents were the link target path. The destination tree no longer matched the upstream layout, and any tooling that followed the link saw plain text instead.
CAS now writes a real symbolic link at the destination. Symlink targets that resolve outside the destination tree are rejected so a hostile or stale source cannot escape the working directory.
catalog-redesign — component tags
The catalog-redesign experiment now reads a tags field from the component's README.md front-matter. Tags appear as colored pills next to the component in the list view and in the detail view above the rendered README.
<!-- Frontmatter name: VPC App description: A VPC for application workloads. tags: [networking, aws, module] -->Either inline-array or dash-list YAML form is accepted. Tags render in gray by default. When a tag matches a known component-type name (module, template, unit, or stack, case-insensitive), the pill takes on that type's color.
A tag matching a component-type name also promotes the component into that type's tab. A template whose tags include module appears under both Templates (by its native kind) and Modules (by tag), without changing how it scaffolds.
To learn more, see Component tags.
What's Changed
feat: read catalog component tags from README front-matter by @yhakbar in #6033
feat: Generate full lock files by @yhakbar in #5992
feat: Adding stack target tip by @yhakbar in #6013
feat: Adding central Git store for CAS by @yhakbar in #6003
feat: adding support for commit refs in CAS by @yhakbar in #6010
feat: Adding mutable attribute for clones to force copy instead of hard links by @yhakbar in #6011
feat: stack outputs parallel fetching by @denis256 in #6104
feat: outputs fetching performance improvements by @denis256 in #6122
feat(experiments): register azure-backend experiment with stub azurerm backend by @omattsson in #6014
fix: Fixing provider cache test flake by @yhakbar in #6056
fix: Fixing panic in --auth-provider-cmd against null by @yhakbar in #6137
fix: Making update_source_with_cas idempotent within a single terragrunt generate call by @yhakbar in #6142
fix: Refactoring some HCL fn parameter logic by @yhakbar in #6043
fix: Fixing weak path classifier by @yhakbar in #6062
fix: Fixing race condition in dependencyBlockToCtyValue by @yhakbar in #6067
fix: Fixing string coercion in tags for catalog by @yhakbar in #6066
fix: Propagate original credential configs for requests to modules by @yhakbar in #5999
fix: Fix missing tags in DynamoDB lock table creation during bootstrap by @Rahul-Kumar-prog in #5974
fix: Addressing catalog tag feedback by @yhakbar in #6073
fix: Fixing symlinks in repos for CAS clones by @yhakbar in #6082
fix: Fixing tag refs in CAS by @yhakbar in #6083
fix: defer in loop causing lock accumulation in report writer by @jackiesre721 in #6085
fix: Moving engine extraction to vfs for path traversal check by @yhakbar in #6101
fix: Fixing CAS symlink bug by @yhakbar in #6102
fix(auto-init): Re-init on source change when modules are cached by @arnaud-dezandee in #6059
fix: respect TG_DOWNLOAD_DIR for dependency blocks by @maonat in #6024
fix: Fixing ordering of nested stacks in terragrunt stack output by @yhakbar in #6113
fix: Fixing run --all early exit by @yhakbar in #6127
docs: Update to robots by @karlcarstensen in #6064
docs: Adding thanks for #5974 by @yhakbar in #6079
docs: Changelog for #6085 by @yhakbar in #6091
docs: Adding Continuous Integration w/ Terragrunt guide by @yhakbar in #6006
docs: Adding redirect to vercel by @karlcarstensen in #6094
docs: Remove changefreq by @karlcarstensen in #6096
docs: Vercel trailing slash fix by @karlcarstensen in #6097
docs: Updating changelog for v1.0.5 by @yhakbar in #6103
docs: Documenting hook exit code control by @yhakbar in #6106
docs: Adding thanks for #6059 by @yhakbar in #6107
docs: Adding changelog entry for #6024 by @yhakbar in #6110
docs: Adding changelog for #6014 by @yhakbar in #6138
chore: fixed macos and windows version setting in CICD by @denis256 in #6054
chore: added handling of draft releases by @denis256 in #6055
chore: Expanding lll coverage to format-options by @yhakbar in #5868
chore: Expanding lll coverage to dag-graph by @yhakbar in #5869
chore: Expanding lll coverage to scaffold by @yhakbar in #5870
chore: Expanding lll coverage to runcfg by @yhakbar in #5871
chore: Expanding lll coverage to runall by @yhakbar in #5872
chore: Expanding lll coverage to telemetry by @yhakbar in #5873
chore: Expanding lll coverage to options by @yhakbar in #5874
chore: Expanding lll coverage to retry by @yhakbar in #5877
chore: Expanding lll coverage to report by @yhakbar in #5880
chore: Expanding lll coverage to codegen by @yhakbar in #5881
chore: Addressing feedback from #6025 by @yhakbar in #6031
chore: Adding TGS --help footer by @yhakbar in #6046
chore: Adding additional telemetry & logs by @yhakbar in #6057
chore: Expanding lll coverage to discovery by @yhakbar in #5883
chore: aws-sdk-go-v2 upgrade by @denis256 in #6065
chore: Avoid cancelling main workflows by @yhakbar in #6069
chore: simplified default patterns initialization by @denis256 in #5808
chore: Adding bug fix release notification workflow by @yhakbar in #6063
chore: Consolidating go-getter routes by @yhakbar in #6030
chore: CICD fixes by @denis256 in #6071
chore(deps): bump astro from 6.1.6 to 6.1.10 in /docs by @dependabot[bot] in #6087
chore(deps): bump jdx/mise-action from 4.0.0 to 4.0.1 by @dependabot[bot] in #5734
chore(deps): bump aws-actions/configure-aws-credentials from 6.0.0 to 6.1.0 by @dependabot[bot] in #5812
chore(deps): bump fast-xml-parser and @aws-sdk/xml-builder in /docs/src/fixtures/terralith-to-terragrunt/app/best-cat by @dependabot[bot] in #5981
chore(deps): bump fast-xml-builder from 1.1.5 to 1.2.0 in /docs/src/fixtures/terralith-to-terragrunt/app/best-cat by @dependabot[bot] in #6105
chore(deps): bump actions/cache from 5.0.3 to 5.0.5 by @dependabot[bot] in #5735
chore(deps): bump sigstore/cosign-installer from 4.0.0 to 4.1.2 by @dependabot[bot] in #5772
chore: add support for Opentofu 1.12 by @denis256 in #6134New Contributors
@jackiesre721 made their first contribution in #6085
@arnaud-dezandee made their first contribution in #6059
@omattsson made their first contribution in #6014
Full Changelog: v1.0.4...v1.0.5
Original source - May 7, 2026
- Date parsed from source:May 7, 2026
- First seen by Releasebot:May 7, 2026
v1.0.4
Terragrunt releases faster command and repo-root caching, smoother fast-copy performance, and broader bug fixes across auth provider calls, include handling, JSON parsing, Windows paths, and the Provider Cache Server. It also expands stack dependencies, CAS, and catalog support.
🏎️ Performance Improvements
run_cmd and Git repo-root results memoized without the Provider Cache Server
Within a single command, repeated run_cmd(...) calls and repeated Git repo-root lookups across units used to share their cached results only when the Provider Cache Server was running. Commands invoked without --provider-cache (the common case for find, list, and run --all against estates that do not need provider caching) re-evaluated each run_cmd and re-shelled to git rev-parse --show-toplevel for every unit.
Both caches are now active for every command, so identical run_cmd arguments and repeated repo-root lookups are reused across units regardless of whether the Provider Cache Server is enabled.
fast-copy strict control
With the new fast-copy strict control enabled, Terragrunt compiles each include_in_copy and exclude_from_copy pattern once and evaluates it inline during a single copy walk. This avoids re-walking subdirectories for every pattern, which should result in noticeable speed improvements for large source modules.
terragrunt run plan --strict-control fast-copy
The new matcher does not collapse ** to zero path segments when a neighbor is a wildcard, so a//.tf matches a/sub/main.tf but not a/main.tf. Patterns that relied on the old collapsing behavior should use brace alternation like {.tf,/*.tf} to cover both depths.
Fewer git rev-parse invocations on large estates
The get_repo_root() HCL function, the runner, and the find and list discovery commands all ask Git for the enclosing repository root. Previously, two units in the same repository each triggered their own git rev-parse --show-toplevel, even when the answer was identical. On large estates this added up to one fork per unit (and sometimes more) for a value that never changed.
A repository discovered for one working directory is now reused for any other working directory inside it, for the duration of the command. Nested repositories (a checkout vendored inside another) still resolve to their own root.
🐛 Bug Fixes
--auth-provider-cmd no longer runs once per dependency cache directory
Resolving dependency outputs ran the configured --auth-provider-cmd again from inside each .terragrunt-cache working directory, on top of the call already made for the unit.
Terragrunt now reuses the credentials already obtained for the dependency when reading outputs from a cached working directory, so --auth-provider-cmd is invoked once per dependency instead of twice.
Fixed exclude block being dropped when defined only in an included parent
A unit that pulled in an exclude block from an include that did not declare its own exclude block saw the include's exclude configurations ignored.
Included exclude blocks now get properly merged into unit configurations.
Reported in #5089. Thanks to @HeikoNeblung for contributing this fix!
Fixed terragrunt find --include failing on relative include paths
Running terragrunt find --include against units whose include blocks reference parent configs with relative paths (../root.hcl, ./common.hcl, bare filenames, etc.) emitted errors like Rel: can't make ../root.hcl relative to /abs/working-dir and dropped those entries from the output.
Relative include paths are now resolved against the unit's directory before being made relative to the working directory, matching how the rest of Terragrunt interprets the path attribute on an include block.
find and list no longer hard-fail when a path cannot be made relative to its base. The condition is logged as a warning and the path is emitted as-is, so output stays complete and the command exits zero.
Tolerate non-JSON warnings in tofu/terraform output -json
Resolving dependency outputs no longer fails when the underlying tofu/terraform output -json invocation prints a deprecation warning to stdout alongside the JSON payload. Terraform 1.15.0 introduced a backend deprecation warning for the S3 dynamodb_table parameter that is emitted on stdout after the JSON object, which broke parsing with errors like invalid character 'W' after top-level value and the misleading downstream message There is no variable named "dependency".
Terragrunt now isolates the first JSON object in the captured stdout, so leading log lines (for example, the long-standing AWS Client Side Monitoring Enabling CSM line) and trailing warning blocks are both ignored when reading dependency outputs.
Resolves #6001. Thanks to @jpke for contributing this fix!
get_repo_root() returns OS-native separators on Windows
git rev-parse --show-toplevel always emits forward-slash paths, even on Windows. Terragrunt returned that string unchanged from get_repo_root(), so configurations that compared the result against path/filepath-style paths or fed it back into helpers expecting OS-native separators saw spurious mismatches and broken joins on Windows.
The output is now normalized to OS-native separators before being returned, so get_repo_root() produces C:\repo\path on Windows and /repo/path on Linux and macOS.
Reported in #5976.
Hardened module manifest handling
Terragrunt now bounds .terragrunt-module-manifest cleanup to the manifest's own folder, skips paths with symlinked parents, and removes invalid manifests after reading any valid entries. Existing manifests keep the same gob format.
Provider Cache Server now supports custom host blocks
Running terragrunt with the Provider Cache Server enabled against a private registry declared via a host block in .terraformrc (or a file referenced by TF_CLI_CONFIG_FILE) failed with errors such as provider registry.opentofu.org/<org>/<provider> was not found, because the cache server proxy did not recognize the custom registry and rewrote requests to registry.opentofu.org.
Terragrunt now registers each custom host block with the cache server, seeds its service discovery from the services map so registries that do not serve .well-known/terraform.json still work, and forwards OPENTOFU_NETRC_* / TF_TOKEN_* credentials so authenticated registries continue to authenticate through the proxy.
# .terraformrc host "registry.example.com" { services = { "providers.v1" = "https://registry.example.com/repository/terraform-hosted/v1/providers/" } }Resolves #5916. Thanks to @elkh510 for contributing this fix!
🧪 Experiments Updated
stack-dependencies — Stricter validation and clearer parse errors for autoinclude
Malformed configuration inside an autoinclude block previously produced misleading messages or, in some cases, was silently ignored during stack discovery.
Two changes tighten this up:
A dependency block inside autoinclude must declare exactly one label. Zero labels (dependency {}) and multiple labels (dependency "a" "b" {}) are now rejected at parse time with a diagnostic that points at the offending block.
Parse failures encountered while expanding autoinclude files during stack generate, find, and list are surfaced with the underlying HCL diagnostic instead of being swallowed or remapped to a generic discovery error.
Reported in #5980.
cas — Local paths supported as stack component sources
CAS-backed stack generation now accepts a local filesystem path as the source of a consumer stack or unit block, in addition to a remote Git URL. Terragrunt copies the referenced directory into a temporary directory, computes a content-addressed root hash over the copy, and applies the same update_source_with_cas rewriting as the remote flow. The original directory is left untouched.
# live/terragrunt.stack.hcl stack "service" { source = "../catalog//stacks/service" path = "service" }This makes a catalog usable against a local checkout under the same update_source_with_cas = true attributes that already work for Git URLs, which is helpful when iterating on a catalog before tagging a release.
See the CAS documentation and Explicit Stacks: Local catalog sources for details.
catalog-redesign — Units and stacks, scaffolded values, and key-binding cleanup
The redesigned terragrunt catalog TUI gains two new component kinds, a guided scaffolding flow for placing them, and a small key-binding cleanup.
Units and stacks join modules and templates
Catalog discovery now classifies units (directories containing a terragrunt.hcl) and stacks (directories containing a terragrunt.stack.hcl) as first-class component kinds, alongside OpenTofu/Terraform modules and boilerplate templates. The list view picks them up automatically and they appear under their own tabs; press tab and shift+tab to cycle.
When more than one classification could apply to the same directory (for example, a stack directory that also contains a unit), Terragrunt resolves it to a single kind under a fixed precedence: template, stack, unit, module.
Copy and scaffolded values
Selecting a unit or stack from the catalog now offers a copy action that materializes the component into your working directory. Terragrunt walks the copied component for values.<name> references and, if it finds any, writes a sibling terragrunt.values.hcl stub. Names referenced outside a try(...) are listed as required with a "TODO" placeholder; names referenced through a try(...) are listed as optional, pre-populated with the literal default from the fallback. An existing terragrunt.values.hcl is left alone.
After the TUI exits, Terragrunt prints a short callout pointing at the directory it wrote to and any follow-up command you need to run, instead of leaving you to find the new directory yourself.
Catalog key bindings
The ctrl+j binding on the catalog list has been removed in favor of enter alone for choosing a focused entry, and dropped from the navigation set used while filtering. The mini help footer is updated to match.
stack-dependencies - Separate filenames for unit vs stack autoincludes
Generated autoinclude files now use distinct filenames depending on the component kind, so tooling (LSP, read_terragrunt_config(), indexers) can identify a file's purpose from its name alone:
- Unit-level autoincludes continue to be written as terragrunt.autoinclude.hcl.
- Stack-level autoincludes (autoinclude blocks declared inside a stack { ... }) are now written as terragrunt.autoinclude.stack.hcl. The .stack.hcl suffix mirrors terragrunt.stack.hcl, matching the convention used elsewhere for stack files.
# terragrunt.stack.hcl unit "app" { source = "../catalog/units/app" path = "app" autoinclude { # Generated as: .terragrunt-stack/app/terragrunt.autoinclude.hcl dependency "vpc" { config_path = unit.vpc.path } } } stack "networking" { source = "../catalog/stacks/networking" path = "networking" autoinclude { # Generated as: .terragrunt-stack/networking/terragrunt.autoinclude.stack.hcl dependency "shared" { config_path = unit.shared.path } } }This change implements the naming convention proposed in the Stack Dependencies RFC so configurations for units and stacks always live in files whose names clearly indicate their purpose.
To learn more, see the experiment documentation.
stack-dependencies — Nested stack paths and discovery integration
The stack-dependencies experiment gains two improvements: nested stack path references at arbitrary depth, and integration with the find and list discovery commands.
Nested stack path references
stack.<name>.<nested_stack>.path now resolves at arbitrary nesting depth. Previously, only units within a stack were reachable via stack.<name>.<unit_name>.path; nested stacks are now first-class references too.
# terragrunt.stack.hcl stack "infra" { source = "../catalog/stacks/infra" path = "infra" } unit "app" { source = "../catalog/units/app" path = "app" autoinclude { dependency "deep" { # infra contains a nested "deep" stack; reference it directly. config_path = stack.infra.deep.path } inputs = { val = dependency.deep.outputs.val } } }Discovery commands surface stack dependencies
The terragrunt find and terragrunt list discovery commands now reflect stack dependencies generated by the autoinclude block. The DAG output correctly orders units by their autoinclude dependencies and shows dependency relationships in JSON, tree, and long formats.
# JSON output includes dependency relationships from autoinclude $ terragrunt find --json --dag --dependencies --experiment stack-dependencies # Long list format shows a Dependencies column $ terragrunt list --long --dependencies --dag --experiment stack-dependencies # Tree format visualizes the dependency hierarchy $ terragrunt list --tree --dag --experiment stack-dependenciesMulti-level dependency trees (for example, A → B,C where B → D,E) are ordered correctly in DAG mode: leaf units appear first, parents appear after all their dependencies.
To learn more, see the experiment documentation.
Cache and plugin directories follow platform conventions
Terragrunt's global cache directory now resolves to the platform's user cache location instead of a hard-coded ~/.cache/terragrunt. On Linux this honors XDG_CACHE_HOME (still ~/.cache/terragrunt by default), on macOS it resolves to ~/Library/Caches/terragrunt, and on Windows it resolves under %LocalAppData%. The CAS content store, the auto provider cache, and the IaC engine plugin directory all move with it.
Existing caches at the previous locations are not migrated. They become orphaned and continue to consume disk space until removed.
Consider deleting the old paths to reclaim that space if you are on macOS or Windows, or have configured a custom XDG_CACHE_HOME:
# CAS store and engine plugins under the legacy ~/.cache layout rm -rf ~/.cache/terragruntWhat's Changed
feat: stack dependencies in find and dag by @denis256 in #5945
feat: Adding support for units and stacks in catalog by @yhakbar in #5971
feat: Adding support for local paths in CAS by @yhakbar in #5933
feat: updated name for stack depednencies by @denis256 in #6018
fix: manifest handling improvements by @denis256 in #6032
fix: Removing extra --auth-provider-cmd call by @yhakbar in #6045
fix: Use FromSlash on return of git rev-parse --show-toplevel by @yhakbar in #5987
fix: Cleaning up #5232 by @yhakbar in #6009
fix: better errors reporting form autoincludes by @denis256 in #5985
fix: Dropping references to ctrl-+j in the catalog key bindings by @yhakbar in #6007
fix: Ensuring relativization is safer by @yhakbar in #6025
fix: tolerate non-JSON warnings in tofu/terraform output -json (#6001) by @jpke in #6029
fix: support custom host blocks in Provider Cache Server by @elkh510 in #5917
perf: Memoizing get_repo_root() better by @yhakbar in #5989
perf: Moving context cache construction earlier by @yhakbar in #6019
docs: Adding a Pull Requests section to the changelog by @yhakbar in #5982
docs: Update buttons on nav by @karlcarstensen in #6000
docs: Calling out update for existing cache locations in v1.0.4 by @yhakbar in #6005
docs: Cleaning up changelog for v1.0.4 by @yhakbar in #6050
docs: Documenting #5917 by @yhakbar in #6044
docs: Optimizing SEO a bit by @yhakbar in #5990
docs: Updating terminology to modernize it a bit by @yhakbar in #6016
chore: Supporting immutable releases by @yhakbar in #5905
chore: Cleaning up other scripts with shellcheck and shfmt by @yhakbar in #5983
chore: Add fast-copy strict control by @yhakbar in #5966
chore: Expanding lll coverage to worktrees by @yhakbar in #5861
chore: Expanding lll coverage to os-exec by @yhakbar in #5862
chore: Expanding lll coverage to runner-creds by @yhakbar in #5865
chore: Expanding lll coverage to tflint by @yhakbar in #5866
chore: Expanding lll coverage to queue by @yhakbar in #5867
chore: Addressing review feedback on #5989 by @yhakbar in #5991
chore: Integrate vexec into engine by @yhakbar in #5957
chore: Moving to XDG-aware paths by @yhakbar in #5941
chore: Optimizing catalog performance by @yhakbar in #5973
chore: Adding checkbox for changelog updates by @yhakbar in #6012
chore: Integrating vexec into Command by @yhakbar in #6004
chore: Addressing #6019 feedback by @yhakbar in #6023
chore: Addressing test flakes by @yhakbar in #6028
chore: Adding thank you to @jpke for fix in #6029 by @yhakbar in #6035
chore: Dropping insignificant OpenTelemetry traces by @yhakbar in #6034
chore: Adding better symlinks experiment tests by @yhakbar in #6038New Contributors
@jpke made their first contribution in #6029
@elkh510 made their first contribution in #5917Full Changelog: v1.0.3...v1.0.4
Original source - Apr 27, 2026
- Date parsed from source:Apr 27, 2026
- First seen by Releasebot:Apr 27, 2026
v1.0.3
Terragrunt releases v1.0.3 with new CAS and stack capabilities, including the --no-cas flag, stack integration for CAS, and broader discovery for catalog templates. It also adds mark-many-as-read and mark_glob_as_read, while fixing crashes, races, and hcl fmt diff output.
✨ New Features
--no-casflag for disabling CAS per command
The new
--no-casflag disables the CAS for a single invocation, even when the cas experiment is enabled. It is available on run, stack generate, and stack run.terragrunt stack generate --experiment cas --no-casThis is useful when you want to fall back to the standard getter path without unwinding experiment configuration.
Generation and runs error when
--no-casis combined withupdate_source_with_cas = trueon any reachable unit, stack, or terraform block, since relative sources in catalog repositories cannot be resolved without the CAS.🐛 Bug Fixes
hcl fmt --diffno longer requires the diff binary
Previously,
terragrunt hcl fmt --diffspawned a diff process discovered in$PATHto render its output. This made it incompatible with minimal container images and Windows installations where that binary was unavailable.The flag now produces unified diff output without depending on any external binary.
Note that the output is not byte-identical to GNU diff -u. Each file diff is now preceded by a
diff old/<path> new/<path>header line, and the ---/+++ lines no longer include a trailing timestamp. Scripts that parsed the previous output may need small adjustments.- Fixed crash when include and locals with read_terragrunt_config coexist
A unit that combined an include block with a locals block calling
read_terragrunt_config(...)could crash during discovery, surfacing as a misleadingCall to function "read_terragrunt_config" failederror pointed at the locals expression.Discovery now reports the underlying error instead of crashing.
Reported in #5949.
- Fixed crash when a root.hcl declares no remote_state block
A root.hcl that only declared locals (or otherwise omitted a remote_state block) could trigger a nil pointer dereference inside Terragrunt's remote-state initialization. Downstream tools that embed the Terragrunt config parser, such as terragrunt-ls, crashed on every such file.
A missing remote_state block now initializes an empty remote-state value instead of panicking, so parsing proceeds normally when no backend is configured.
Reported in terragrunt-ls#134.
Thanks to @SAY-5 for contributing this fix!
- Fixed a race condition in terragrunt stack generate
Fixed a race condition in
terragrunt stack generatethat could produce non-deterministic file errors on nested stack hierarchies. The same stack file could reach the worker pool twice through different path forms and cause the duplicate writes to conflict with each other. Paths are now normalized before dispatch so each stack file is generated exactly once per invocation.When a stack file is legitimately claimed by more than one parent during generation, Terragrunt now logs a warning that names the contending parents and records the latest claimant, so the configuration can be corrected before it causes silent overwrites.
- Fixed data race in --version flag parsing under concurrent CLI invocations
When multiple Terragrunt CLI invocations ran concurrently in the same process, urfave/cli/v2's package-level VersionFlag singleton was mutated concurrently by each invocation's flag-parsing path, producing a
WARNING: DATA RACEon shared flag state.Terragrunt now sets
cli.App.HideVersion = trueat construction, which prevents urfave from auto-appending its shared VersionFlag into each App's flag set. The--version/-vflag is unchanged from the user's perspective — it is handled by Terragrunt's own flag registered ininternal/cli/flags/global.NewHelpVersionFlags.🧪 Experiments Added
mark-many-as-read— Mark many files as read in one step
Enable the new
mark-many-as-readexperiment to turn on two behaviors that each mark many files as read in a single call: automatic marking of files inside a localterraform { source = "..." }block, and the newmark_glob_as_readHCL function.With the experiment on, a unit like this:
# live/unit/terragrunt.hcl terraform { source = "../../modules/service" }records every
*.tf,*.tf.json,*.hcl,*.tofu, and*.tofu.jsonfile found under../../modules/service(recursively) as read for the unit. Non-source files such asREADME.mdare skipped. A reading-based filter expression such as--filter 'reading=../../modules/service/**'then matches every unit that points at the module, so a change to any file in the module cascades to its consumers.The same experiment also enables a new HCL function,
mark_glob_as_read(pattern), which expands a glob using the same gobwas/glob syntax as filter expressions and marks every matching file as read. It returns the list of absolute paths that matched, so it composes with other expressions:locals { configs = mark_glob_as_read("${get_terragrunt_dir()}/config/{*.yaml,**/*.yaml}") }** only collapses the surrounding separators when the adjacent segments are literals, so match-at-any-depth with a wildcard trailing segment is written as
{*.yaml,**/*.yaml}. See the HCL reference for full pattern syntax.This is useful when a unit reads a collection of files indirectly (for example, via
run_cmdortemplatefile) and you want changes to any of them to trigger the unit through reading-based filters. Callingmark_glob_as_readwithout the experiment enabled returns an error.🧪 Experiments Updated
cas— Stack integration via update_source_with_cas
The
casexperiment now integrates with stacks. Units and terraform blocks can setupdate_source_with_cas = trueto use relative source paths in catalog repositories, removing the need to plumb remote Git URLs through values expressions.# stacks/my-stack/terragrunt.stack.hcl (in your catalog repository) unit "service" { source = "../..//units/my-service" update_source_with_cas = true path = "service" }During stack generation, Terragrunt rewrites these relative sources to
cas::references that resolve against content stored in the CAS. The repository is cloned once, and subsequent stack generations resolve content from the local store without network access. Generated.terragrunt-stackfiles contain deterministic CAS references, so regeneration does not produce spurious diffs.CAS also supports SHA-256 repositories now, detected automatically via
git rev-parse --show-object-format. The on-disk store layout was reorganized intoblobs/andtrees/namespaces under~/.cache/terragrunt/cas/store/.To learn more, see the CAS documentation and Explicit Stacks: CAS Integration.
catalog-redesign— Templates and .terragrunt-catalog-ignore
The
catalog-redesignexperiment picked up user-visible improvements to discovery and filtering.Discovery walks the entire repository instead of only a
modules/directory, so modules and templates can live anywhere in the tree. Boilerplate templates (directories containing a.boilerplate/subdirectory or a top-levelboilerplate.yml) are discovered as a distinct component kind alongside OpenTofu/Terraform modules and labeled as templates in the UI. When a directory qualifies as both, it is classified as a template.Catalog authors can commit a
.terragrunt-catalog-ignorefile at the repo root to keep directories such asexamples/ortest/out of discovery. The file uses.gitignore-style semantics: one pattern per line,#for comments,!for negation, and last match wins. Matching is anchored at the repo root; a lone*does not cross/, and**does.# .terragrunt-catalog-ignore examples examples/** test/** !test/keepAn
--ignore-fileflag (also available viaTG_IGNORE_FILE) points at an additional ignore file that is layered on top of the repo's.terragrunt-catalog-ignore. The extra rules are appended under last-match-wins semantics, so the flag can either add new exclusions or re-include paths that the repo file excluded.To learn more, see Excluding paths from discovery.
The list view is split into All, Modules, and Templates tabs, with All selected on launch so every discovered component is visible without switching views. Press tab and shift+tab to cycle between them; each tab keeps its own cursor and search filter.
stack-dependencies— Multi-level nestedstack.<name>.<nested_stack>.pathreferences
The
stack-dependenciesexperiment already supportedstack.<name>.path(a whole stack) andstack.<name>.<unit_name>.path(a unit inside a stack). It now also resolves references where the second segment is itself a nested stack, so an autoinclude block in a parent stack can target a stack that lives inside another stack:# live/terragrunt.stack.hcl stack "infra" { source = "../catalog/stacks/infra" path = "infra" } unit "app" { source = "../catalog/units/app" path = "app" autoinclude { dependency "deep" { config_path = stack.infra.deep.path } } }Here
stack.infra.deep.pathresolves to the generated directory of astack "deep"block declared insidecatalog/stacks/infra/terragrunt.stack.hcl. This makes deeper stack hierarchies addressable from a single dependency expression without flattening the layout.What's Changed
- feat: Mark module sources as read by @yhakbar in #5963
- feat: Adding support for CAS in stacks by @yhakbar in #5911
- feat: Splitting modules from templates by @yhakbar in #5932
- feat: allow units to depend on stacks by @denis256 in #5924
- fix: Addressing panic in read_terragrunt_config() by @yhakbar in #5953
- fix: version flag race condition fix by @denis256 in #5961
- fix: fixing concurrent-write race in stack generate by @denis256 in #5962
- fix(remotestate): survive nil Config passed to New by @SAY-5 in #5965
- docs: Cleaning up changelog for v1.0.3 by @yhakbar in #5977
- docs: Touching up docs for catalog-redesign by @yhakbar in #5940
- docs: Adding Terragrunt Scale callout in README.md by @yhakbar in #5946
- docs: Fixing Kapa integration by @yhakbar in #5942
- chore: Integrating vexec into NewGitRunner by @yhakbar in #5934
- chore: Offboarding Travis by @yhakbar in #5944
- chore: Expanding lll coverage to amazonsts by @yhakbar in #5852
- chore: Expanding lll coverage to runner-common by @yhakbar in #5853
- chore: Expanding lll coverage to runner-graph by @yhakbar in #5854
- chore: Expanding lll coverage to list by @yhakbar in #5855
- chore: stacks generation improvements by @denis256 in #5969
- chore: Expanding lll coverage to errorconfig by @yhakbar in #5856
- chore: Expanding lll coverage to experiment by @yhakbar in #5857
- chore: Expanding lll coverage to externalcmd by @yhakbar in #5858
- chore: Expanding lll coverage to cache-controllers by @yhakbar in #5859
- chore: Expanding lll coverage to vfs by @yhakbar in #5860
- chore: Expanding lll coverage to stack by @yhakbar in #5841
- chore: Expanding lll coverage to backend-delete by @yhakbar in #5842
- chore: Expanding lll coverage to cloner by @yhakbar in #5843
- chore: Expanding lll coverage to engine by @yhakbar in #5844
- chore: Expanding lll coverage to git by @yhakbar in #5845
- chore: Consolidating independent integration tests by @yhakbar in #5938
- chore: Integrating signals into vexec by @yhakbar in #5935
- chore: Expanding lll coverage to prepare by @yhakbar in #5846
- chore: Expanding lll coverage to exec by @yhakbar in #5847
- chore: Expanding lll coverage to find by @yhakbar in #5848
- chore: Expanding lll coverage to stacks-output by @yhakbar in #5850
- chore(deps): bump astro from 6.1.2 to 6.1.6 in /docs by @dependabot[bot] in #5947
- chore: Expanding lll coverage to placeholders by @yhakbar in #5851
- chore: Removing dependency on diff by @yhakbar in #5954
- chore: Addressing feedback on #5953 and #5954 by @yhakbar in #5964
- chore: Windows signing fix by @denis256 in #5979
New Contributors
- @SAY-5 made their first contribution in #5965
Full Changelog: v1.0.2...v1.0.3
Original source - Apr 21, 2026
- Date parsed from source:Apr 21, 2026
- First seen by Releasebot:Apr 21, 2026
v1.0.2
Terragrunt ships bug fixes for backend config serialization, telemetry panics, and stack output exclusions, while adding a redesigned catalog experiment, expanded stack-dependencies support, and install script options for tip and test builds.
🐛 Bug Fixes
shared_credentials_files and other list/map backend config values were serialized incorrectly
Setting shared_credentials_files (or any other list-valued key) in the remote_state.config block produced a broken -backend-config argument:
-backend-config=shared_credentials_files=[/a/creds /b/creds]OpenTofu and Terraform both failed to parse this. The same problem affected map-valued keys. Lists and maps are now written as single-line HCL (["/a/creds","/b/creds"] and {key="value"}), and strings inside them are quoted so embedded quotes, newlines, and tabs survive the round trip.
Thanks to @Rahul-Kumar-prog for contributing this fix!
Panic in get_repo_root() when OpenTelemetry tracing is enabled with TRACEPARENT
Running terragrunt stack generate (or any command that invoked shell commands like git rev-parse) with OpenTelemetry trace exporting enabled (TG_TELEMETRY_TRACE_EXPORTER=http) caused a nil pointer panic:
Call to function "get_repo_root" failed: panic in function implementation: runtime error: invalid memory address or nil pointer dereferenceThe root cause of the panic was fixed, and telemetry codepaths have been hardened against future panics.
stack output now respects the exclude block
terragrunt stack output previously ignored the exclude block on units, attempting to fetch outputs (including directly from S3 state when using --dependency-fetch-output-from-state) for units that should have been excluded.
The fix uses Terragrunt discovery to identify excluded units before reading outputs. Excluded units are now omitted from the stack output entirely, consistent with how they are handled during stack run.
To exclude a unit from stack output, add "output" to the actions list in the exclude block:
exclude { if = true actions = ["plan", "apply", "destroy", "output"] }Special action values "all" and "all_except_output" are also supported.
🧪 Experiments Added
catalog-redesign — Reworked terragrunt catalog TUI
A new catalog-redesign experiment reworks the design of the terragrunt catalog TUI.
terragrunt catalog now launches the TUI right away and runs discovery in the background instead of waiting for discovery to complete before launching the TUI. As a consequence, terragrunt catalog users with large catalogs should see significant speed improvements as they launch the terragrunt catalog TUI.
Modules now stream into the list view of the catalog as they are discovered, so you'll be able to select and use a module even if your entire catalog hasn't been discovered yet.
If catalog.urls is not configured in root.hcl, terragrunt catalog no longer errors. A welcome screen explains how to populate the catalog and can open the catalog documentation on a keypress. In addition, terraform.source values from existing units are automatically included in the set of URLs used for discovery, so users with existing units get a populated catalog pointing to other modules that can be pulled from the same module source without any additional configuration.
This experiment is subject to change, and core elements of the design are being iterated on rapidly.
To try it out, run:
terragrunt catalog --experiment catalog-redesignTo learn more, see the experiment documentation.
🧪 Experiments Updated
stack-dependencies — Cross-stack dependency support and autoinclude improvements
The stack-dependencies experiment now supports cross-stack and nested-stack dependency patterns, expanding the autoinclude block capabilities in terragrunt.stack.hcl files.
New features:
stack.<name>.path references for depending on an entire stack. The DAG expands the stack into its constituent units so that all units in the stack complete before the dependent unit runs
stack.<name>.<unit_name>.path references for depending on a specific unit within a nested stack (fine-grained cross-stack dependencies)
dependency blocks targeting stack directories — aggregated outputs from all units in the stack are accessible as dependency.stack_name.outputs.unit_name.output_key
Partial evaluation of local.* in autoinclude — expressions mixing local.* and dependency.* are partially evaluated during stack generation: locals resolve to literals while dependency references are preserved for evaluation when the unit is applied
Dependency on an entire stack:
stack "infra" { source = "../catalog/stacks/infra" path = "infra" } unit "app" { source = "../catalog/units/app" path = "app" autoinclude { dependency "infra" { config_path = stack.infra.path } inputs = { vpc_id = dependency.infra.outputs.vpc.vpc_id } } }Dependency on a unit within a nested stack:
stack "networking" { source = "../catalog/stacks/networking" path = "networking" } unit "app" { source = "../catalog/units/app" path = "app" autoinclude { dependency "vpc" { config_path = stack.networking.vpc.path } inputs = { vpc_id = dependency.vpc.outputs.vpc_id } } }terragrunt run --all --experiment stack-dependencies -- planTo learn more, see the experiment documentation.
⚙️ Process Updates
Install script now supports tip and test builds
The install script can now install tip builds and on-demand test builds. Three new flags are available:
- --tip installs the latest tip build from main
- --test installs an on-demand test build
- --commit <sha> installs a build for a specific commit
Downloads are verified against GPG/Cosign signatures and SHA256 checksums before installation.
Tip build notifications on referenced issues
When a tip build is produced on main for a merged PR, Terragrunt now posts a comment on any issues that PR references, linking to the build and including instructions for installing and testing it.
What's Changed
- feat: add new hclparse package in internal by @denis256 in #5816
- feat: Adding catalog-redesign experiment by @yhakbar in #5894
- feat: Adding types, sources and versions to catalog by @yhakbar in #5922
- feat: handling of stacks dependencies in run queue / runner pool by @denis256 in #5909
- feat: Supporting catalog with no config by @yhakbar in #5902
- feat: Supporting streaming components to the catalog by @yhakbar in #5914
- fix: Addressing #5895 review comments by @yhakbar in #5897
- fix: correct cloud-nuke config YAML keys and bump to v0.49.0 by @james00012 in #5920
- fix: Fixing panic in telemetry by @yhakbar in #5915
- fix: handling of exclusions when reading outputs by @denis256 in #5900
- fix: Use httptest in ./internal/tf to avoid issues from integration in unit tests by @yhakbar in #5925
- fix(s3): fix shared_credentials_files HCL serialization for backend config by @Rahul-Kumar-prog in #5886
- docs: Avoid indexing changelog in search by @yhakbar in #5928
- docs: Fix bash commands in "Terralith to Terragrunt" guide by @chorrell in #5904
- docs: Fix missing newline in remote_state examples by @thoreinstein in #5921
- docs: Splitting up changelog by @yhakbar in #5930
- docs: updated stack-dependencies implementation roadmap by @denis256 in #5910
- docs: Updating v1.0.2 changelog entries by @yhakbar in #5927
- docs: Updating install docs by @yhakbar in #5923
- chore: add 7-day cooldown to dependabot updates by @diofeher in #5889
- chore: Adding vexec by @yhakbar in #5931
- chore: Adding catalog redesign fork by @yhakbar in #5896
- chore: Adding support for vfs in cas by @yhakbar in #5908
- chore: Adding tests and docs missing from #5886 by @yhakbar in #5926
- chore: Adding tip notification system by @yhakbar in #5895
- chore: bump cloud-nuke to v0.49.0 by @james00012 in #5893
- chore: coverage scripts collection simplifications by @denis256 in #5724
- chore: Dropping CAS test by @yhakbar in #5936
- chore: Expanding lll coverage to configbridge by @yhakbar in #5834
- chore: Expanding lll coverage to errors by @yhakbar in #5833
- chore: Expanding lll coverage to gcphelper by @yhakbar in #5832
- chore: Expanding lll coverage to generate by @yhakbar in #5840
- chore: Expanding lll coverage to help by @yhakbar in #5835
- chore: Expanding lll coverage to middleware by @yhakbar in #5839
- chore: Expanding lll coverage to tips by @yhakbar in #5837
- chore: Expanding lll coverage to tui by @yhakbar in #5836
- chore: Expanding lll coverage to writer by @yhakbar in #5838
- chore: Make workflow dispatch for signing useful by @yhakbar in #5929
- chore: otel dependencies update by @denis256 in #5878
- chore: simplified returned discovery errors by @denis256 in #5664
- chore: Updating install script to support tip builds by @yhakbar in #5892
- chore: Revert "chore: bump cloud-nuke to v0.49.0" by @yhakbar in #5919
New Contributors
- @diofeher made their first contribution in #5889
- @chorrell made their first contribution in #5904
- @thoreinstein made their first contribution in #5921
- @Rahul-Kumar-prog made their first contribution in #5886
Full Changelog: v1.0.1...v1.0.2
Original source - Apr 13, 2026
- Date parsed from source:Apr 13, 2026
- First seen by Releasebot:Apr 14, 2026
v1.0.1
Terragrunt adds new experiments for DAG queue visualization, long-running task progress, and stack dependencies, while improving validation, worktree handling, Windows provider caching, retry behavior, file copy performance, and concurrency handling.
🧪 Experiments Added
dag-queue-display — DAG tree visualization for the run queue
A new dag-queue-display experiment renders the run queue as a dependency tree instead of a flat list, making it easier to understand execution order and dependency relationships at a glance.
$ terragrunt run --all --experiment dag-queue-display -- plan 19:06:59.108 INFO The following units will be run, starting with dependencies and then their dependents: . ├── monitoring ╰── vpc ╰── database ╰── backend-app ╰── frontend-appTo learn more, see the experiment documentation.
slow-task-reporting — Progress reporting for long-running operations
A new slow-task-reporting experiment displays animated progress spinners for operations that take longer than 1 second, such as source downloads, Git worktree creation, and catalog repository cloning. In non-interactive environments (CI/CD, piped output), spinners are replaced with periodic INFO log lines every 30 seconds to prevent CI systems from killing jobs due to output inactivity.
$ terragrunt run --all --experiment slow-task-reporting -- plan INFO Downloading source from git::https://github.com/example/module.git... INFO Downloaded source from git::https://github.com/example/module.git (3.2s)To learn more, see the experiment documentation.
stack-dependencies — Dependency wiring between units in stacks
A new stack-dependencies experiment enables the autoinclude block in terragrunt.stack.hcl files, allowing units and stacks to define dependency relationships and arbitrary configuration overrides during stack generation. This implements RFC #5663.
unit "vpc" { source = "../catalog/units/vpc" path = "vpc" } unit "app" { source = "../catalog/units/app" path = "app" autoinclude { dependency "vpc" { config_path = unit.vpc.path } inputs = { vpc_id = dependency.vpc.outputs.vpc_id } } } terragrunt run --all --experiment stack-dependencies -- planTo learn more, see the experiment documentation.
💡 Tip Added
Windows symlink warning for provider cache users
Terragrunt now warns Windows users when symlink creation fails and provider caching is enabled. OpenTofu and Terraform may silently fall back to copying provider plugins instead of symlinking, which can increase disk usage and slow down operations. For OpenTofu >= 1.12.0, the tip includes guidance on using TF_LOG=warn to detect the fallback.
Thank you to the OpenTofu team for introducing this warning to ensure that Windows users are aware of the fallback behavior.
🐛 Bug Fixes
hcl validate no longer fails on dependency.outputs references
terragrunt hcl validate previously failed with "Unsupported attribute" when a configuration referenced dependency.<name>.outputs.<key> without mock_outputs.
During validation, output resolution is skipped, but the outputs attribute was never added to the dependency evaluation context, causing any output reference to error. The fix provides a dynamic placeholder for dependency outputs (and inputs) during validation so that attribute access evaluates to unknown rather than failing. Additionally, the dependency resolution pipeline is now more resilient during validation. Dependencies with unresolvable config_path values or nonexistent targets no longer cause the entire dependency namespace to disappear from the evaluation context.
Destroy queue now displays units in correct order
Previously, the run queue display showed units in apply order even for destroy commands. The queue now correctly shows dependents before their dependencies when running destroy, matching the actual execution order.
Dependent discovery fixed in worktrees
Dependents are now correctly discovered when units are discovered in worktrees. Previously, dependent discovery could fail to find related units when operating within a git worktree.
Filter exclusions now respected in worktree sub-discoveries
Negated filters (e.g., !./catalog/** from .terragrunt-filters or --filter) are now propagated to worktree sub-discoveries used by git-based filtering (--filter-affected, --filter '[ref...ref]').
Previously, excluded source catalog units in worktrees were still discovered and parsed, causing errors when they referenced values.* or dependency.* variables without the stack generation context.
read_terragrunt_config() behavior in implicit stacks fixed
A regression introduced in v0.99.4 caused read_terragrunt_config() to fail to parse dependency blocks in external configurations during stack execution. This is fixed by resetting parsing context fields that prevented proper evaluation of dependencies in configurations read by read_terragrunt_config().
get_original_terragrunt_dir() now resolves correctly during dependency parsing
A regression introduced in v1.0.0-rc3 caused get_original_terragrunt_dir() to return the dependent directory instead of the dependency's directory when parsing dependency configurations from a unit.
This broke configurations where a dependency's read_terragrunt_config() chain relied on get_original_terragrunt_dir() to locate sibling files. The fix introduces a dedicated WithDependencyConfigPath method that correctly resets the original config path when parsing a dependency as an independent unit.
Chained dependency with exposed include conversion fixed
Chaining dependencies with exposed includes no longer produces a spurious "Could not convert include to the execution ctx to evaluate additional locals" error during partial parsing.
Provider cache fixed on Windows for remote URLs
The provider cache failed on Windows with CreateFile https://...: The filename, directory name, or volume label syntax is incorrect because remote download URLs were passed to os.Stat, and the colon in https: is invalid Windows path syntax. The fix skips the filesystem existence check when the download URL is a remote URL (://), going directly to the download path.
Additional transient network errors now retried automatically
Added retry patterns for provider resolution and registry connection failures commonly seen in CI environments, including TLS handshake timeouts, TCP connection resets, context deadline exceeded errors, and failed discovery document requests. These cover both Terraform and OpenTofu provider workflows.
File copy performance improved
Terragrunt now streams data from source files to target files more often by replacing some instances where files were read into memory in their entirety and written to a target file. This results in improved performance when copying files and reduced memory footprint.
⚙️ Process Updates
Tip builds now available from main
Every successful CI run on the main branch now automatically produces tip build binaries with signed checksums for all supported platforms (Windows and macOS binaries are not codesigned in tip builds). These builds are accessible via the builds API at https://builds.terragrunt.com — see the releases process documentation for API endpoints and usage examples. Maintainers can also trigger on-demand test builds from any branch using the test-build.yml workflow.
Concurrency limits now respect GOMAXPROCS
All internal concurrency limits now use runtime.GOMAXPROCS(0) instead of runtime.NumCPU(). This means Terragrunt correctly honors the GOMAXPROCS environment variable and container CPU quotas (e.g., cgroups), resulting in better behavior in resource-constrained environments like Kubernetes pods and CI runners with CPU limits.
AWS SDK updated to v1.41.5
The aws-sdk-go-v2 dependency has been updated to v1.41.5.
Terragrunt Scale documentation added
A new Terragrunt Scale section has been added to the docs, covering Pipelines, Drift Detection, and Patcher with brief overviews and links to the full Gruntwork documentation.
What's Changed
feat: experiment for reporting long running tasks by @denis256 in #5730
feat: add stack dependencies experiment by @denis256 in #5809
fix: Fixing #5624 by @yhakbar in #5766
fix: Fixing #4153 by @yhakbar in #5746
fix: Fixing macOS linting by @yhakbar in #5775
fix: Refactoring unit display in runs for better communication by @yhakbar in #5752
fix: Discover dependents in worktrees if units are discovered there by @yhakbar in #5763
fix: provider cache path handling in Windows by @denis256 in #5788
fix: Adding Windows symlink tip by @yhakbar in #5778
fix: Addressing test flakes for TestReadTerragruntConfigDependencyInStack by @yhakbar in #5781
fix: Fixing generation in stacks that read files by @yhakbar in #5790
fix: use io.Copy instead of reading files into memory by @thisguycodes in #5608
fix: Fix coverage compare regarding retries by @thisguycodes in #5793
fix: add retry patterns for transient provider/registry network errors by @denis256 in #5779
fix: Fixing get_original_terragrunt_dir() interaction with dependencies by @yhakbar in #5828
fix: Using cty.DynamicVal to avoid 'Unsupported Attribute' errors by @yhakbar in #5827
fix: Preventing parse errors in stack generation in worktrees by @yhakbar in #5826
fix: Addressing #5828 feedback by @yhakbar in #5876
fix: Fixing up lints by @yhakbar in #5887
docs: Adding v1.0.0 callout by @yhakbar in #5768
docs: Disable vercel skew protection by @karlcarstensen in #5789
docs: Updating GTM tag by @yhakbar in #5769
docs: Fixing search by @yhakbar in #5776
docs: Fixing strict controls by @yhakbar in #5782
docs: Fixing up changelog implementation by @yhakbar in #5784
docs: Documenting tip/test build installation instructions by @yhakbar in #5829
docs: Adding TGS docs by @yhakbar in #5831
chore: disabled tmpfs usage in GHA by @denis256 in #5787
chore: Adding tests to confirm #4395 is resolved by @yhakbar in #5761
chore: updated aws-sdk-go-v2 to 1.41.5 by @denis256 in #5771
chore(deps): bump the js-dependencies group across 1 directory with 5 updates by @dependabot[bot] in #5764
chore(deps): bump peter-evans/create-pull-request from 7.0.8 to 8.1.0 by @dependabot[bot] in #5736
chore: Replace runtime.NumCPU() usage with runtime.GOMAXPROCS(0) by @yhakbar in #5794
chore: various lint fixes by @thisguycodes in #5796
chore: Adding tip build workflows by @yhakbar in #5823
chore: Upgrading go deps by @yhakbar in #5795
chore: misc testing and lint updates by @thisguycodes in #5885
Full Changelog: v1.0.0...v1.0.1
Original source - Apr 8, 2026
- Date parsed from source:Apr 8, 2026
- First seen by Releasebot:Apr 9, 2026
alpha-2026040801
Terragrunt ships an alpha release prototype for the stack dependencies RFC, along with fixes for dependency discovery, Windows provider cache path handling, macOS linting, and improved run unit display communication.
⚠️ Alpha Release
Prototype implementation of stack dependencies
RFC: #5663
What's Changed
- chore: Adding tests to confirm #4395 is resolved by @yhakbar in #5761
- fix: Fixing #5624 by @yhakbar in #5766
- docs: Adding v1.0.0 callout by @yhakbar in #5768
- fix: Fixing #4153 by @yhakbar in #5746
- docs: Updating GTM tag by @yhakbar in #5769
- fix: Fixing macOS linting by @yhakbar in #5775
- docs: Fixing search by @yhakbar in #5776
- fix: Refactoring unit display in runs for better communication by @yhakbar in #5752
- chore: updated aws-sdk-go-v2 to 1.41.5 by @denis256 in #5771
- fix: Discover dependents in worktrees if units are discovered there by @yhakbar in #5763
- docs: Fixing strict controls by @yhakbar in #5782
- docs: Fixing up changelog implementation by @yhakbar in #5784
- chore: disabled tmpfs usage in GHA by @denis256 in #5787
- Disable vercel skew protection by @karlcarstensen in #5789
- fix: provider cache path handling in Windows by @denis256 in #5788
Full Changelog: v1.0.0...alpha-2026040801
Original source - Mar 30, 2026
- Date parsed from source:Mar 30, 2026
- First seen by Releasebot:Mar 31, 2026
v1.0.0
Terragrunt releases v1.0.0 with a stable 1.0 promise, cleaner discovery and rendering defaults, better Windows path handling, faster unit filtering, and many fixes for caches, provider downloads, SOPS, logs, and stack runs. It also adds tips, improved errors, and new docs.
v1.0.0 Release
Terragrunt is now v1!
This means that Terragrunt will no longer have any breaking changes in minor releases, with all future breaking changes taking place in (infrequent) future major releases.
For a list of guarantees that will be observed by maintainers for the duration of Terragrunt 1.0, see the Terragrunt 1.0 Guarantees page in the docs.
🛠️ Breaking Changes
Consistent .terragrunt-cache directory generation
Terragrunt now creates a .terragrunt-cache directory for every run, regardless of whether the terragrunt.hcl file defines a terraform block with a source attribute.
This change improves consistency across all Terragrunt executions, as OpenTofu/Terraform will now always run within the .terragrunt-cache directory. This standardized behavior simplifies troubleshooting and makes the execution model more predictable.
Removal of tflint
Terragrunt has been shipping with a version of tflint compiled into the binary to allow for more convenient usage without installing tflint directly. However due to the adoption of a BUSL license in tflint, the version included in Terragrunt was frozen.
The dependency on tflint is now fully removed from Terragrunt. If you want to call tflint using a before_hook using Terragrunt, you will have to have tflint installed locally to do so.
To reduce the burden of this breaking change, Terragrunt will continue to provide conveniences like automatically running tflint init on behalf of users, although it no longer ships with a compiled version of tflint in the terragrunt binary.
To learn more, read the documentation on the integration with tflint.
Discovery commands discover hidden configurations by default
The find and list commands now discover units/stacks in hidden directories by default (this previously required usage of the --hidden flag), notably this now discovers .terragrunt-stack directories by default. The commands also now support an opt-in --no-hidden flag to avoid discovery in hidden directories.
The --hidden flag has been deprecated, and will not be removed in 1.0. Using the flag no longer does anything.
render --format=json no longer discovers dependents by default
Prior to this release, the render --format=json command would automatically start to perform dependent discovery on other units related to the unit being rendered. Avoiding this required usage of the --disable-dependent-modules flag. That behavior has been removed. HCL and JSON rendering of unit configurations will now proceed without the additional overhead of dependent discovery by default.
This functionality is better served by a combination of find and graph-based filters.
e.g. If you want to detect all the dependents of a given unit foo, expecting to find the dependent unit bar you can run the following:
$ terragrunt find --filter '...^foo' barIf you aren't familiar with filters, this reads as "find all dependents of foo, not foo itself"
Windows compatibility in file paths improved
All HCL functions now return operating system native file paths without forward slash normalization.
get_terragrunt_dir()
get_original_terragrunt_dir()
get_parent_terragrunt_dir()
get_path_from_repo_root()
get_path_to_repo_root()
find_in_parent_folders()
path_relative_to_include()
path_relative_from_include()
If you and your team do not work in Windows environments, you are unlikely to see any change as a consequence of this. If you do use Terragrunt in a Windows environment, Terragrunt will now return appropriate Windows file paths, with backslashes as file path separators instead of Unix-like forward slashes.
If you need to normalize paths, you can use the replace function to achieve this.
# root.hcl remote_state { backend = "s3" generate = { path = "backend.tf" if_exists = "overwrite_terragrunt" } config = { bucket = "my-tofu-state" key = "${replace(path_relative_to_include(), "\\", "/")}/tofu.tfstate" region = "us-east-1" encrypt = true dynamodb_table = "my-lock-table" } }Ambiguous unit/stack components now throw errors
Previously, Terragrunt would silently engage in undefined behavior when both a terragrunt.hcl and terragrunt.stack.hcl file existed in the same directory.
With this release, Terragrunt will start to throw warnings and prevent such usage. Users will have to ensure that only one of a unit (terragrunt.hcl) or stack configuration (terragrunt.stack.hcl) exist in a unit or stack directory, respectively.
✨ New Features
Tips added
Terragrunt will now provide helpful tips when it detects usage patterns that might benefit from some additional guidance.
You can disable the display of tips at any time using --no-tips or disable individual tips with --no-tip, (e.g. --no-tip=debugging-docs).
--report-file support for single runs
The --report-file will now generate reports even when runs are performed without the --all flag.
Improved error messages for undefined flags
Detection has been added for scenarios when a user is using a flag that might be meant to be passed to OpenTofu/Terraform in the run command, and suggests using the -- argument to pass it through.
As an example:
$ terragrunt run providers lock -platform linux_amd64 -platform darwin_arm64 14:52:19.496 ERROR flag `-platform` is not a Terragrunt flag. If this is an OpenTofu/Terraform flag, use `--` to forward it (e.g. `terragrunt run -- <command> -platform`).🏎️ Performance Improvements
Discovery performance improved
The way in which Terragrunt discovers and filters units and stacks for runs has improved significantly.
Terragrunt is now better at avoiding parsing units/stacks unnecessarily, based on the filter you use. Previously, the logic used was more coarse, and could result in a requirement to parse some configurations (e.g. presence of a dependency graph expression) to result in parsing all configurations. Discovery has been refactored to allow for much more careful opt-in parsing based on the need to support the filter used by users (or lack thereof).
This will also result in improvements to Terragrunt's ability to ignore broken parts of infrastructure estates when Terragrunt can predictably determine that it won't impact a run.
EncodeSourceVersion execution sped up
The performance of EncodeSourceVersion has been improved by utilizing SkipDir to optimize directory traversals.
Special thanks to @healthy-pod for contributing this improvement!
Provider Cache Server used for fetching outputs from dependencies
The Provider Cache Server is now used when fetching outputs from dependencies, improving performance of output resolution for users using the provider cache server.
🐛 Bug Fixes
Improved filter parsing errors
Parsing errors returned when invalid filter queries are used with --filter have been improved to provide more detailed error messages and actionable recommendations.
Retries added for registry timeouts in provider cache server
The Provider Cache Server will now perform automatic retries on timeouts to OpenTofu/Terraform provider registries.
Discoverability of init-from-module documentation improved
The special internal init-from-module command referenced in hooks has had its documentation improved to make it easier to discover. It was difficult to find in the terraform HCL block documentation, and that resulted in confusion for users.
Over-warning on strict controls prevented
Using --strict-mode resulted in over-warning on completed controls. Those warnings will no longer appear when using strict mode.
Stdout/stderr from run_cmd emitted when included
A bug prevented the run_cmd HCL function from emitting to stdout/stderr when included by a unit. That bug has been fixed.
Provider Cache Server integration with custom registries fixed
The Provider Cache Server now properly integrates with custom registries. You will still need to use the --provider-cache-registry-names flag to ensure that the Provider Cache Server properly handles proxying requests to the custom provider registry.
The no_run attribute of exclude is fixed
A bug prevented the no_run attribute of the exclude block from being respected when being explicitly set to false (as opposed to not being defined at all). This bug has been fixed.
The --report-file is now respected for single runs
The --report-file will now generate reports even when runs are performed without the --all flag.
Path manipulation removed from log messages
Log messages no longer have paths updated automatically. This caused confusion for users when seeing OpenTofu/Terraform stdout and hook stdout emitted through logs, as paths were unconditionally updated to be relative to the unit path. This logic has been moved to logging call sites to ensure that external process stdout/stderr is not manipulated unexpectedly.
Absolute URLs in registry self-discovery integration with Provider Cache Server Fixed
When using the Provider Cache Server in conjunction with a remote registry using absolute URLs for modules, the Provider Cache Server will now properly resolve the module source.
SOPS decryption race condition fixed
A race condition in the concurrent access to SOPS decrypted secrets in different environments combined with usage of the --auth-provider-cmd flag resulted in authentication failures. Synchronization controls have been introduced to ensure authentication proceeds correctly for each environment independently.
Version constraints in stack runs fixed
When running against a stack, a bug prevented Terragrunt + OpenTofu/Terraform version constraints from being respected while using the terragrunt_version_constraint and terraform_version_constraint HCL attributes. That bug has been fixed.
Interrupt signal propagation to OpenTofu/Terraform fixed
The mechanism by which Terragrunt sends interrupt signals to OpenTofu/Terraform processes it started has been made more robust. Terragrunt will now send the interrupt signal in the event that a user explicitly sends an interrupt signal to Terragrunt in addition to scenarios where Terragrunt's context cancellation is triggered (e.g. in the event of a timeout).
Remote state configuration parsing fixed
Remote state configuration parsing (especially S3) is now more tolerant of common input formats, reducing decode-related failures from type mismatches in configuration values.
Parsing behavior has also been made more consistent across related remote configuration blocks in Terragrunt, with regression tests added to prevent future breakages.
Invalid unit configurations cause explicit errors instead of silently being excluded during runs
A bug in discovery logic resulted in units with invalid HCL configurations being silently excluded from runs with a warning. This bug has been fixed, and attempting to parse invalid HCL configurations during a run will result in an error.
Partial parse configuration cache fixed
A bug affecting the partial parse configuration cache (in use when the --use-partial-parse-config-cache flag is supplied) has been resolved, ensuring configurations are cached and read accurately without incorrect cache collisions.
Engine output adjusted
The display and formatting of engine outputs have been updated to be cleaner and more intuitive for users when running Terragrunt workflows.
Stdout/Stderr entries emitted from engines will now have the engine tool listed instead of tofu.
More accurate matching of retryable errors
Fixes a bug where retries were triggered when an expected error is matched against non-stderr output from external process errors.
Duplicate error reporting fixed
Fixes a bug where duplicate errors were reported when running units through the worker pool subsystem.
Interaction between --working-dir and -detailed-exitcode fixed
Fixes a bug where the wrong cache key was used for storing exit codes for OpenTofu/Terraform runs in units when the --working-dir flag was also used.
Variable sanitization via escaping added
Escaping added for interpolation expressions (e.g. ${foo}) that are unlikely to be desired by users.
Removing usage of filepath.Abs and reducing usage of filepath.ToSlash
Usage of the Golang filepath.Abs and filepath.ToSlash standard library functions significantly reduced. Overly broad application of these functions to file paths caused subtle operating system compatibility issues and incompatibility with the --working-dir flag.
The codebase has been updated to only use filepath.Abs early on in initialization of the CLI prior to setting the value of --working-dir (after which, working dir is considered the source of truth for file path canonicalization) and tests. The codebase has been updated to use filepath.ToSlash only where unix-style forward slash normalization is a requirement (e.g. when used in file path globs).
Handling of backend init when disable_init=true
Fixes a bug where disable_init = true affected behavior beyond Terragrunt's bootstrap operations. disable_init now correctly limits its scope to Terragrunt bootstrap steps only.
Fix detection of offline usage in Provider Cache Server
A bug in the detection of offline usage in the Provider Cache Server resulted in attempts to reach the default provider registry for OpenTofu/Terraform to trigger errors even when using the Provider Cache Server to proxy requests to a network or filesystem mirror.
This has been fixed. When the default provider registry isn't available for OpenTofu/Terraform for any reason, the Provider Cache Server will use the provided network/filesystem mirror instead without attempting to use the discovery endpoint. This will help users in air-gapped environments using the Provider Cache Server.
Improved log messages for hooks with errors
Hooks encountering errors will now return errors that better communicate whether an error was caused by failure to execute an external process or successfully running an external process, but receiving a non-zero exit code.
Relative paths in reading files fixed
A bug in the logic for incorporating includes as absolute paths in tracked "read" files has been fixed.
OpenTofu file extensions handled in catalog and scaffold
Terragrunt catalog now lists modules that use .tofu, .tf.json, or .tofu.json files. Terragrunt scaffold now parses variables from .tofu files — previously, variables defined in .tofu files were silently missing from the generated terragrunt.hcl.
Bootstrap use_lockfile boolean handling fixed
A bug in remote state backend configuration caused use_lockfile = true to be emitted as use_lockfile = "true" (quoted string), which OpenTofu/Terraform rejects. Boolean values in backend config are now normalized correctly.
Provider cache lock file corruption fixed
A bug that could cause provider cache lock file corruption has been fixed.
Git filter discovery for read_terragrunt_config fixed
Git-filter discovery now correctly detects stacks affected by changes to sidecar files read via read_terragrunt_config(), by parsing stack files to check FilesRead against diff paths instead of relying on generic directory-based detection.
S3 bucket tagging moved to bucket creation
S3 bucket tagging during backend bootstrapping has been moved to bucket creation. This prevents errors caused when SCPs restrict creation of buckets without appropriate tags.
Windows user input fixed
A bug on Windows caused user input prompts (e.g. for confirming apply) to stop working after subprocess execution. Terragrunt now saves and restores console state around every subprocess execution and re-enables Virtual Terminal processing.
Authentication during queue construction fixed
A bug in the logic for parsing configurations during discovery for use-cases like --filter 'reading=*' where configurations need to be parsed to determine whether or not they end up in the final run queue has been fixed. Configurations will now properly call any configured --auth-provider-cmd authenticator before parsing configurations, preventing errors for HCL functions like sops_decrypt_file that require authentication before parsing can proceed.
hcl fmt on unintended files during scaffold fixed
A bug caused hcl fmt to run on files that weren't generated by scaffold. Formatting is now scoped to only scaffolded content.
Input precision loss fixed
A bug in the way Terragrunt handled setting of OpenTofu/Terraform inputs from numbers resulted in precision loss. That bug has been fixed.
📖 Documentation Updates
1.0 Guarantees
A living document named Terragrunt 1.0 Guarantees has been added to the Terragrunt website clarifying what is and isn't considered a breaking change for the duration of 1.0.
Over time, as ambiguity in edge-cases for what is considered a breaking change are addressed, the page will be updated so that you can be confident your workflows won't be impaired.
llms.txt added
An /llms.txt route has been added to the Terragrunt website to make it easier for LLMs to consume Terragrunt documentation in Markdown format.
New Home for the Terragrunt website!
The Terragrunt website is now hosted at https://terragrunt.com and https://docs.terragrunt.com for marketing and documentation purposes, respectively.
Existing links to https://terragrunt.gruntwork.io should seamlessly redirect to the new domain that hosts the content for that URI.
🧪 Experiments Updated
Engines now use GitHub environment variables for downloads
When downloading engines using the engine experiment, Terragrunt will detect and leverage the GH_TOKEN and GITHUB_TOKEN environment variables if present to authenticate with the GitHub API while performing release discovery and download of engines.
⚙️ Process Updates
Go bumped to v1.26
The version of Golang used to compile the Terragrunt binary has been updated to v1.26.0.
OpenTofu/Terraform Compatibility Updated
Terragrunt is now continuously tested against OpenTofu 1.11.4 and Terraform 1.14.4 in CI.
AWS and GRPC dependencies update
Updated AWS SDK and gRPC dependencies to pick up the latest bug fixes and security patches:
- google.golang.org/grpc to v1.79.1
- github.com/aws/aws-sdk-go-v2/config to v1.32.8
- github.com/aws/aws-sdk-go-v2/credentials to v1.19.8
What's Changed
- feat: Improving filter parsing errors by @yhakbar in #5413
- feat: Adding community invite link redirect by @yhakbar in #5432
- feat: .terragrunt-cache directory creation by @denis256 in #5402
- feat: use github auth for engine release checks / downloads by @thisguycodes in #5447
- feat: Adding --no-hidden flag to discovery commands and deprecating --hidden by @yhakbar in #5450
- feat: Adding tip system by @yhakbar in #5434
- fix: Addressing bucket verification flake by @yhakbar in #5419
- fix: Fixing TestTerragruntDestroyOrder flake by @yhakbar in #5427
- fix: Adding lock files to cache key for provider cache by @yhakbar in #5430
- fix: Fixing TestSopsDecryptOnMissing test by @yhakbar in #5428
- fix: Fixing TestTerragruntStackCommandsWithSymlinks test by @yhakbar in #5426
- fix: Adding timeout and avoiding null caching in GitHub API memoization in docs by @yhakbar in #5429
- fix: fixing TestTerragruntDestroyOrderWithQueueIgnoreErrors flake by @thisguycodes in #5436
- fix: Fixing usage of %w in logs by @yhakbar in #5441
- fix: Updating --auth-provider-cmd schema in flags docs by @yhakbar in #5435
- fix: Fixing TestAwsBootstrapBackendWithAccessLoggingFlake by @yhakbar in #5442
- fix: Fixing null input passing by @yhakbar in #5455
- fix: Fixing flake in TestDeprecatedDefaultCommand_TerraformSubcommandCliArgs by @yhakbar in #5456
- fix: Addressing review feedback on #5455 by @yhakbar in #5459
- fix: Fixing TestAwsS3SSECustomKey by @yhakbar in #5457
- fix: Use helpers.CopyEnvironment wherever there's a test with side-effects by @yhakbar in #5460
- fix: Handle registry timeouts in provider cache server by @yhakbar in #5471
- fix: Adding test for init-from-module and improving discoverability by @yhakbar in #5491
- fix: Fixing over-warning on strict controls by @yhakbar in #5501
- fix: Emit output from run_cmd when included by @yhakbar in #5495
- fix: Fixing provider cache server integration with custom registry by @yhakbar in #5500
- fix: Fixing exclude no_run behavior by @yhakbar in #5506
- fix: Adding --report-file support to single runs by @yhakbar in #5507
- fix: Removing path manipulation in log messages by @yhakbar in #5489
- fix: Fixing cache server absolute URLs in self-discovery by @yhakbar in #5519
- fix: SOPS decryption env variables locking by @denis256 in #5522
- fix: Fixing respect for version constraints when running a stack by @yhakbar in #5516
- fix: Fixing signal propagation by @yhakbar in #5518
- fix: Addressing render --format=json by @yhakbar in #5511
- fix: Fixing partial parse config cache by @yhakbar in #5538
- fix: Using SyncWriter to fix TestTerragruntReportWithUnitTiming flakes by @yhakbar in #5494
- fix: Adjusting engine output by @yhakbar in #5386
- fix: Assume any transport errors to discovery URL are a sign that the user is offline by @yhakbar in #5615
- fix: duplicate error reporting in worker pool by @anuragrao04 in #5526
- fix: Fixing #3514 by @yhakbar in #5739
- fix: Fixing #4556 by @yhakbar in #5640
- fix: Fixing -detailed-exitcode when used in combination with --working-dir by @yhakbar in #5590
- fix: Fixing hcl fmt on unintended files during scaffold by @yhakbar in #5721
- fix: Fixing CORS for terragrunt.com by @yhakbar in #5631
- fix: Fixing incremental lint issue by @yhakbar in #5592
- fix: Fixing provider cache lock file corruption by @yhakbar in #5692
- fix: Fixing redirect for /contact-tgs by @yhakbar in #5636
- fix: Fixing relative paths in tracked reading files by @yhakbar in #5651
- fix: Fixing SOPS call during queue construction by @yhakbar in #5722
- fix: handling of backend init when disable_init=true by @denis256 in #5594
- fix: handling of invalid paths in read_terragrunt_config by @denis256 in #5753
- fix: Improving error message for undefined flags by @yhakbar in #5571
- fix: Increasing accuracy of retryable errors match by @yhakbar in #5568
- fix: Moving tagging to bucket creation by @yhakbar in #5706
- fix: Removing usage of filepath.Abs in production code and reducing usage of filepath.ToSlash by @yhakbar in #5597
- fix: variables values interpolation by @denis256 in #5585
- fix: fixed bootstrap and use_lockfile by @denis256 in #5665
- fix: handling of tofu extensions by @denis256 in #5675
- fix: windows user input fixes by @denis256 in #5710
- fix: worktree fixes for read_terragrunt_config by @denis256 in #5682
- docs: Memoizing latest release call by @yhakbar in #5424
- docs: Adding 1.0 guarantees by @yhakbar in #5425
- docs: Update terminology to use the new root.hcl pattern by @hashlash in #5135
- docs: Change move command to copy and corrected supporting text in quick st… by @therealgglggl in #5332
- docs: Add output_dir to inputs in multiple sections by @therealgglggl in #5334
- docs: add instructions on bypassing tflint integration behavior by @thisguycodes in #5437
- docs: tweak opening wording of stacks generate by @thisguycodes in #5443
- docs: Adding llms.txt by @yhakbar in #5449
- docs: Update provider cache documentation to include a valid command by @CodyRay in #5276
- docs: Adding --tip and --no-tips docs by @yhakbar in #5468
- docs: remove lint meta comment that's getting displayed on the site by @thisguycodes in #5470
- docs: install page checksum signature check by @denis256 in #5473
- docs: New ambassador by @karlcarstensen in #5496
- docs: Simple component for pagefind styles by @karlcarstensen in #5523
- docs: Pagefind css by @karlcarstensen in #5524
- docs: Fix command reference in CLI redesign documentation by @PedroMartinSteenstrup-htg in #5541
- docs: Adding Golang compatibility notes by @yhakbar in #5544
- docs: Breaking down filters docs by @yhakbar in #5552
- docs: Revert css fixes now that docs site is live by @karlcarstensen in #5556
- docs: Making filter docs a bit more consistent by @yhakbar in #5557
- docs: Adding callout for the lack of library compatibility guarantees by @yhakbar in #5564
- docs: Adding a changelog by @yhakbar in #5754
- docs: Adding changelog copy button by @yhakbar in #5755
- docs: Adding more v1.0.0 changelog docs by @yhakbar in #5756
- docs: Adding tgs discord link by @yhakbar in #5750
- docs: Addressing docs gaps by @yhakbar in #5742
- docs: Breaking down features by @yhakbar in #5684
- docs: compatibility table updates by @denis256 in #5609
- docs: Documenting --queue-strict-include deprecation in strict controls by @yhakbar in #5581
- docs: Documenting deprecation of --disable-dependent-modules by @yhakbar in #5539
- docs: Fix 'move' to 'moved' block in documentation by @hashlash in #5661
- docs: Fix typo in overview documentation by @BenjaminHerbert in #5666
- docs: Fixing 404s by @yhakbar in #5637
- docs: Fixing Migrating Deprecated Attributes by @yhakbar in #5638
- docs: Moving docs-starlight to docs by @yhakbar in #5635
- docs: Updating dependency-fetch-output-from-state experiment docs by @yhakbar in #5740
- docs: Updating docs dependencies by @yhakbar in #5686
- docs: Fix theme light/dark by @karlcarstensen in #5669
- docs: Fixing button by @karlcarstensen in #5667
- docs: Hide switcher in hamburger menu by @karlcarstensen in #5668
- docs: Setting up migration to docs.terragrunt.com by @yhakbar in #5514
- chore: removal of unused AssumeAlreadyApplied field by @denis256 in #5417
- chore: IaC tool CLI arguments re-ordering by @denis256 in #5414
- chore: IAC tool cli building improvements by @denis256 in #5448
- chore: Adding fuzz tests for filter by @yhakbar in #5420
- chore: Remove tflint by @thisguycodes in #5433
- chore: Using slim runners where possible by @yhakbar in #5461
- chore: iac cli package by @denis256 in #5462
- chore: removed unused public functions and constants by @denis256 in #5472
- chore: go bump to 1.25.6 by @denis256 in #5481
- chore: IaC update - Terraform 1.14.4 Opentofu 1.11.4 by @denis256 in #5479
- chore: Updates the discord link by @karlcarstensen in #5521
- chore: Adding testing for RelPathForLog by @yhakbar in #5513
- chore: dependencies update - otel, aws, go-git by @denis256 in #5533
- chore: removed unused constatns, simplified noRun checking by @denis256 in #5517
- chore: Adding VFS testing by @yhakbar in #5490
- chore: Bumping Go to 1.26 by @yhakbar in #5543
- chore: Remote config parsing improvements by @denis256 in #5540
- chore: Refactor discovery for nuanced parse handling by @yhakbar in #5477
- chore: Units code cleanup by @denis256 in #5550
- chore(deps): bump aws-actions/configure-aws-credentials from 5 to 6 by @dependabot[bot] in #5553
- chore: SOPS tests improvements by @denis256 in #5554
- chore: Removing options from components by @yhakbar in #5551
- chore: refactor cache dir exclusion code by @healthy-pod in #5559
- chore: Clean up of #5559 by @yhakbar in #5561
- chore: Adding lll lint incrementally by @yhakbar in #5582
- chore: Adding terragrunt-infrastructure-live-stacks-example test by @yhakbar in #5703
- chore: Adding external testing for config by @yhakbar in #5653
- chore: Adding some testing for logs by @yhakbar in #5641
- chore: Adding test to verify that the Provider Cache Server is used when fetching outputs from dependencies by @yhakbar in #5611
- chore: Addressing #5589 feedback by @yhakbar in #5633
- chore: Addressing #5707 feedback by @yhakbar in #5712
- chore: addressing PR #5665 feedback by @denis256 in #5696
- chore: Addressing review feedback from #5597 by @yhakbar in #5604
- chore: aws-sdk-go-v2 dependency update by @denis256 in #5747
- chore: aws-sdk-go-v2 version bump by @denis256 in #5610
- chore: CICD base tests performance improvements by @denis256 in #5505
- chore: Cleaning up shell scripts by @yhakbar in #5707
- chore: Compile filter globs earlier by @yhakbar in #5574
- chore: cosign v4 upgrade by @denis256 in #5676
- chore: dead code removal by @denis256 in #5683
- chore: go dependencies update by @denis256 in #5634
- chore: go-getter upgrade 1.8.5 by @denis256 in #5691
- chore: GRPC and AWS dependencies update by @denis256 in #5572
- chore: handling of terragrunt and stack files by @denis256 in #5645
- chore: improved log message for failing hooks by @denis256 in #5603
- chore: lint cache key update by @denis256 in #5588
- chore: Moving filters to opts by @yhakbar in #5591
- chore: Moving permissions down to job level when possible by @yhakbar in #5705
- chore: Multiple dependencies bump by @denis256 in #5673
- chore: Pinning workflows further by @yhakbar in #5704
- chore: Re-enabling rustfs test by @yhakbar in #5751
- chore: Reducing dependency on opts in config - Part Four by @yhakbar in #5573
- chore: Reducing dependency on opts in config - Part Three by @yhakbar in #5569
- chore: Reducing dependency on opts in config - Part Two by @yhakbar in #5563
- chore: Reducing dependency on opts in config by @yhakbar in #5560
- chore: Removing options from awshelper by @yhakbar in #5587
- chore: Removing options from runner and remotestate by @yhakbar in #5589
- chore: Removing explicit mise cache by @yhakbar in #5694
- chore: Removing imports of options from tf by @yhakbar in #5583
- chore: Removing options from shell by @yhakbar in #5584
- chore: Removing Terratest dependency by @yhakbar in #5614
- chore: Reverting tmpfs mount by @yhakbar in #5744
- chore: sops upgrade to 3.12.2 by @denis256 in #5718
- chore: sops v3.12.1 gcp storage v1.60.0 by @denis256 in #5618
- chore: Temporarily skipping rustfs test by @yhakbar in #5749
- chore: upgraded github.com/buger/jsonparser to v1.1.2 by @denis256 in #5729
- chore: Verifying fix for #3080 by @yhakbar in #5639
- chore(deps): bump @astrojs/vercel from 10.0.0 to 10.0.2 in /docs by @dependabot[bot] in #5741
- chore(deps): bump actions/download-artifact from 7.0.0 to 8.0.0 by @dependabot[bot] in #5626
- chore(deps): bump actions/download-artifact from 8.0.0 to 8.0.1 by @dependabot[bot] in #5698
- chore(deps): bump actions/setup-go from 6.2.0 to 6.3.0 by @dependabot[bot] in #5628
- chore(deps): bump actions/stale from 10.1.1 to 10.2.0 by @dependabot[bot] in #5600
- chore(deps): bump actions/upload-artifact from 6.0.0 to 7.0.0 by @dependabot[bot] in #5627
- chore(deps): bump digicert/ssm-code-signing from 1.1.1 to 1.2.1 by @dependabot[bot] in #5527
- chore(deps): bump fast-xml-parser, @aws-sdk/client-s3, @aws-sdk/client-dynamodb, @aws-sdk/lib-dynamodb and @aws-sdk/s3-request-presigner in /docs-starlight/src/fixtures/terralith-to-terragrunt/app/best-cat by @dependabot[bot] in #5578
- chore(deps): bump github.com/cloudflare/circl from 1.6.1 to 1.6.3 in /test/flake by @dependabot[bot] in #5620
- chore(deps): bump google.golang.org/grpc from 1.79.2 to 1.79.3 by @dependabot[bot] in #5708
- chore(deps): bump handlebars from 4.7.8 to 4.7.9 in /docs/src/fixtures/terralith-to-terragrunt/app/best-cat by @dependabot[bot] in #5745
- chore(deps): bump jdx/mise-action from 3.6.1 to 3.6.2 by @dependabot[bot] in #5647
- chore(deps): bump jdx/mise-action from 3.6.2 to 3.6.3 by @dependabot[bot] in #5678
- chore(deps): bump jdx/mise-action from 3.6.3 to 4.0.0 by @dependabot[bot] in #5699
- chore(deps): bump mikepenz/action-junit-report from 6.1.0 to 6.3.1 by @dependabot[bot] in #5697
- chore(deps): bump the js-dependencies group across 1 directory with 9 updates by @dependabot[bot] in #5602
- chore: tests coverage collection by @denis256 in #5717
- build(deps): bump sigstore/cosign-installer from 3.10.1 to 4.0.0 by @dependabot[bot] in #5486
- chore: Revert "build(deps): bump sigstore/cosign-installer from 3.10.1 to 4.… by @yhakbar in #5656
- perf: speed up EncodeSourceVersion by using SkipDir by @healthy-pod in #4533
- perf: Adding discovery benchmark by @yhakbar in #5562
New Contributors
- @hashlash made their first contribution in #5135
- @therealgglggl made their first contribution in #5332
- @CodyRay made their first contribution in #5276
- @PedroMartinSteenstrup-htg made their first contribution in #5541
- @healthy-pod made their first contribution in #4533
- @anuragrao04 made their first contribution in #5526
- @BenjaminHerbert made their first contribution in #5666
Full Changelog: v0.99.5...v1.0.0
Original source - Mar 26, 2026
- Date parsed from source:Mar 26, 2026
- First seen by Releasebot:Mar 27, 2026
v0.99.5
Terragrunt fixes working-dir exit code handling and improves queue construction authentication, so config parsing now runs auth providers before HCL evaluation and avoids errors with functions like sops_decrypt_file.
🐛 Bug Fixes
--working-dir interaction with exit codes fixed
A bug in the logic for tracking exit codes for plan -detailed-exitcode when users supply the --working-dir flag has been fixed.
Authentication during queue construction fixed
A bug in the logic for parsing configurations during discovery for use-cases like --filter 'reading=*' where configurations need to be parsed to determine whether or not they end up in the final run queue has been fixed. Configurations will now properly call any configured --auth-provider-cmd authenticator before parsing configurations, preventing errors for HCL functions like sops_decrypt_file that require authentication.
What's Changed
chore: Backporting #5590 by @yhakbar in #5593
chore: Backporting #5722 by @yhakbar in #5731
Full Changelog: v0.99.4...v0.99.5
Original source - Mar 20, 2026
- Date parsed from source:Mar 20, 2026
- First seen by Releasebot:Mar 21, 2026
alpha-2026032001
Terragrunt ships an alpha release with WIP fixes for sops_decrypt_file, --auth-provider-cmd, and --filter 'reading=', plus bug fixes, docs updates, dependency bumps, and workflow cleanup.
⚠️ Alpha Release
Alpha release including WIP work to fix the combination of sops_decrypt_file + --auth-provider-cmd + --filter 'reading=' from the following PR:
#5722
What's Changed
- docs: Fix 'move' to 'moved' block in documentation by @hashlash in #5661
- Fix theme light/dark by @karlcarstensen in #5669
- Hide switcher in hamburger menu by @karlcarstensen in #5668
- Fixing button by @karlcarstensen in #5667
- bug: handling of tofu extensions by @denis256 in #5675
- chore: cosign v4 upgrade by @denis256 in #5676
- chore: dead code removal by @denis256 in #5683
- docs: Fix typo in overview documentation by @BenjaminHerbert in #5666
- chore(deps): bump jdx/mise-action from 3.6.2 to 3.6.3 by @dependabot[bot] in #5678
- docs: Updating docs dependencies by @yhakbar in #5686
- chore: Multiple dependencies bump by @denis256 in #5673
- docs: Breaking down features by @yhakbar in #5684
- chore: go-getter upgrade 1.8.5 by @denis256 in #5691
- chore: Removing explicit mise cache by @yhakbar in #5694
- bug: fixed bootstrap and use_lockfile by @denis256 in #5665
- chore: addressing PR #5665 feedback by @denis256 in #5696
- chore(deps): bump mikepenz/action-junit-report from 6.1.0 to 6.3.1 by @dependabot[bot] in #5697
- chore(deps): bump actions/download-artifact from 8.0.0 to 8.0.1 by @dependabot[bot] in #5698
- fix: Fixing provider cache lock file corruption by @yhakbar in #5692
- chore(deps): bump jdx/mise-action from 3.6.3 to 4.0.0 by @dependabot[bot] in #5699
- chore: Adding terragrunt-infrastructure-live-stacks-example test by @yhakbar in #5703
- bug: worktree fixes for read_terragrunt_config by @denis256 in #5682
- chore: Moving permissions down to job level when possible by @yhakbar in #5705
- chore: Pinning workflows further by @yhakbar in #5704
- chore(deps): bump google.golang.org/grpc from 1.79.2 to 1.79.3 by @dependabot[bot] in #5708
- chore: Adding some testing for logs by @yhakbar in #5641
- fix: Moving tagging to bucket creation by @yhakbar in #5706
- chore: Cleaning up shell scripts by @yhakbar in #5707
- chore: Addressing #5707 feedback by @yhakbar in #5712
- bug: windows user input fixes by @denis256 in #5710
- chore: sops upgrade to 3.12.2 by @denis256 in #5718
New Contributors
- @BenjaminHerbert made their first contribution in #5666
Full Changelog: v1.0.0-rc3...alpha-2026032001
Original source - Mar 19, 2026
- Date parsed from source:Mar 19, 2026
- First seen by Releasebot:Mar 19, 2026
alpha-2026031901
Terragrunt releases an alpha-style changelog for v1.0.0-rc3...alpha-2026031901, highlighting testing updates, bug fixes, numerous dependency bumps, and new contributor notes, signaling ongoing development and prep for a broader release.
⚠️ Alpha Release
Release scripts testing
What's Changed
- docs: Fix 'move' to 'moved' block in documentation by @hashlash in #5661
- Fix theme light/dark by @karlcarstensen in #5669
- Hide switcher in hamburger menu by @karlcarstensen in #5668
- Fixing button by @karlcarstensen in #5667
- bug: handling of tofu extensions by @denis256 in #5675
- chore: cosign v4 upgrade by @denis256 in #5676
- chore: dead code removal by @denis256 in #5683
- docs: Fix typo in overview documentation by @BenjaminHerbert in #5666
- chore(deps): bump jdx/mise-action from 3.6.2 to 3.6.3 by @dependabot[bot] in #5678
- docs: Updating docs dependencies by @yhakbar in #5686
- chore: Multiple dependencies bump by @denis256 in #5673
- docs: Breaking down features by @yhakbar in #5684
- chore: go-getter upgrade 1.8.5 by @denis256 in #5691
- chore: Removing explicit mise cache by @yhakbar in #5694
- bug: fixed bootstrap and use_lockfile by @denis256 in #5665
- chore: addressing PR #5665 feedback by @denis256 in #5696
- chore(deps): bump mikepenz/action-junit-report from 6.1.0 to 6.3.1 by @dependabot[bot] in #5697
- chore(deps): bump actions/download-artifact from 8.0.0 to 8.0.1 by @dependabot[bot] in #5698
- fix: Fixing provider cache lock file corruption by @yhakbar in #5692
- chore(deps): bump jdx/mise-action from 3.6.3 to 4.0.0 by @dependabot[bot] in #5699
- chore: Adding terragrunt-infrastructure-live-stacks-example test by @yhakbar in #5703
- bug: worktree fixes for read_terragrunt_config by @denis256 in #5682
New Contributors
- @BenjaminHerbert made their first contribution in #5666
Full Changelog: v1.0.0-rc3...alpha-2026031901
Original source
Curated by the Releasebot team
Releasebot is an aggregator of official product update announcements from hundreds of software vendors and thousands of sources.
Our editorial process involves the manual review and audit of release notes procured with the help of automated systems.