terragrunt-generator
Comprehensive toolkit for generating best-practice Terragrunt configurations (HCL files) following current standards and conventions. Generates terragrunt.hcl files, root configurations, child modules, stacks, and environment setups; configures remote state backends, dependency blocks, include blocks, feature flags, exclude blocks, and errors blocks; supports DRY Terraform patterns, multi-environment layouts (dev/staging/prod), and OpenTofu engine integration. Use when creating new Terragrunt projects or resources, scaffolding multi-environment infrastructure, implementing DRY Terraform wrapper configurations, setting up terragrunt.hcl files with remote state or provider config, managing module dependencies, or building infrastructure modules with Terragrunt stacks.
Install this skill
Choose your coding agent and copy a project or personal installation command.
npx skills add https://github.com/pantheon-org/tekhne/tree/4a79b500f771a61b6b4bf63751e038649d6535bc/skills/infrastructure/terragrunt/generator -a codex -ynpx skills add https://github.com/pantheon-org/tekhne/tree/4a79b500f771a61b6b4bf63751e038649d6535bc/skills/infrastructure/terragrunt/generator -a codex -g -ynpx skills add https://github.com/pantheon-org/tekhne/tree/4a79b500f771a61b6b4bf63751e038649d6535bc/skills/infrastructure/terragrunt/generator -a claude-code -ynpx skills add https://github.com/pantheon-org/tekhne/tree/4a79b500f771a61b6b4bf63751e038649d6535bc/skills/infrastructure/terragrunt/generator -a claude-code -g -ynpx skills add https://github.com/pantheon-org/tekhne/tree/4a79b500f771a61b6b4bf63751e038649d6535bc/skills/infrastructure/terragrunt/generator -a github-copilot -ynpx skills add https://github.com/pantheon-org/tekhne/tree/4a79b500f771a61b6b4bf63751e038649d6535bc/skills/infrastructure/terragrunt/generator -a github-copilot -g -ynpx skills add https://github.com/pantheon-org/tekhne/tree/4a79b500f771a61b6b4bf63751e038649d6535bc/skills/infrastructure/terragrunt/generator -a cursor -ynpx skills add https://github.com/pantheon-org/tekhne/tree/4a79b500f771a61b6b4bf63751e038649d6535bc/skills/infrastructure/terragrunt/generator -a cursor -g -ynpx skills add https://github.com/pantheon-org/tekhne/tree/4a79b500f771a61b6b4bf63751e038649d6535bc/skills/infrastructure/terragrunt/generator -a gemini-cli -ynpx skills add https://github.com/pantheon-org/tekhne/tree/4a79b500f771a61b6b4bf63751e038649d6535bc/skills/infrastructure/terragrunt/generator -a gemini-cli -g -ygemini skills install https://github.com/pantheon-org/tekhne.git --scope workspace --path skills/infrastructure/terragrunt/generatorSkill instructions
View source on GitHub ↗# Terragrunt Generator
## Overview
Generate production-ready Terragrunt configurations following current best practices, naming conventions, and security standards. All generated configurations are automatically validated.
**Terragrunt 2025 Features Supported:**
- [Stacks](https://terragrunt.gruntwork.io/docs/features/stacks/) - Infrastructure blueprints with `terragrunt.stack.hcl` (GA since v0.78.0)
- [Feature Flags](https://terragrunt.gruntwork.io/docs/features/feature-flags/) - Runtime control via `feature` blocks
- [Exclude Blocks](https://terragrunt.gruntwork.io/docs/reference/config-blocks-and-attributes/#exclude) - Fine-grained execution control (replaces deprecated `skip`)
- [Errors Blocks](https://terragrunt.gruntwork.io/docs/reference/config-blocks-and-attributes/#errors) - Advanced error handling (replaces deprecated `retryable_errors`)
- [OpenTofu Engine](https://terragrunt.gruntwork.io/docs/features/engine/) - Alternative IaC engine support
## Root Configuration Naming
> **RECOMMENDED**: Use `root.hcl` instead of `terragrunt.hcl` for root files per [migration guide](https://terragrunt.gruntwork.io/docs/migrate/migrating-from-root-terragrunt-hcl).
| Approach | Root File | Include Syntax |
|----------|-----------|----------------|
| **Modern** | `root.hcl` | `find_in_parent_folders("root.hcl")` |
| **Legacy** | `terragrunt.hcl` | `find_in_parent_folders()` |
## Architecture Patterns
> **CRITICAL:** Before generating ANY configuration, determine the architecture pattern and understand its constraints.
### Pattern Selection
| Pattern | Use When | Root Behavior | Structure |
|---------|----------|---------------|-----------|
| **A: Multi-Env Agnostic** | Multiple environments with shared root | Root reads NO env files; uses static values or `get_env()` | `root.hcl` + `{env}/env.hcl` per environment |
| **B: Single/Env-Aware** | Single environment OR environment detection needed | Root can parse path or read `get_env()` | `root.hcl` with optional `account.hcl`/`region.hcl` |
| **C: Centralized Vars** | Shared environment definitions | Root is agnostic; `env.hcl` reads from `_env/` | `root.hcl` + `_env/{env}.hcl` + `{env}/env.hcl` |
### Pattern A: Multi-Environment Agnostic Root
**Key principle:** `root.hcl` does NOT read `env.hcl`. Child modules read `env.hcl` directly.
```
infrastructure/
├── root.hcl # Environment-AGNOSTIC
├── dev/env.hcl # locals { environment = "dev" }
│ └── vpc/terragrunt.hcl
└── prod/env.hcl # locals { environment = "prod" }
└── vpc/terragrunt.hcl
```
**Child module pattern:**
```hcl
include "root" { path = find_in_parent_folders("root.hcl") }
locals { env = read_terragrunt_config(find_in_parent_folders("env.hcl")) }
inputs = { name = "${local.env.locals.environment}-vpc" }
```
### Pattern B: Environment-Aware Root
**Key principle:** Root detects environment from path or environment variable.
```hcl
# root.hcl
locals {
path_parts = split("/", path_relative_to_include())
environment = local.path_parts[0] # OR: get_env("TG_ENVIRONMENT", "dev")
}
```
### Pattern C: Centralized Variables
**Key principle:** Each `env.hcl` reads from centralized `_env/{env}.hcl`.
```hcl
# prod/env.hcl
locals {
env_vars = read_terragrunt_config("${get_repo_root()}/_env/prod.hcl")
environment = local.env_vars.locals.environment
aws_region = local.env_vars.locals.aws_region
}
```
**Decision:** Multi-env + shared root → **A** | Single env / env detection → **B** | Centralized vars → **C**
## Core Capabilities
### 1. Generate Root Configuration
Create root-level `root.hcl` or `terragrunt.hcl` with remote state, provider config, and common variables.
**Read before generating:** `assets/templates/root/terragrunt.hcl`
**Patterns:** `references/common-patterns.md` → Root Configuration Patterns
**Key placeholders to replace:**
- `[BUCKET_NAME]`, `[AWS_REGION]`, `[DYNAMODB_TABLE]`
- `[TERRAFORM_VERSION]`, `[PROVIDER_NAME]`, `[PROVIDER_VERSION]`
- `[ENVIRONMENT]`, `[PROJECT_NAME]`
**Root.hcl Design Principles:**
1. **Environment-agnostic by default** — Don't assume env.hcl exists at root level
2. **Use static values for provider/backend region** — Or `get_env()` for runtime config
3. **State key uses `path_relative_to_include()`** — Automatically includes environment path
4. **Provider tags can be static** — Environment-specific tags go in child modules
### 2. Generate Child Module Configuration
Create child modules with dependencies, mock outputs, and proper includes.
**Read before generating:** `assets/templates/child/terragrunt.hcl`
**Patterns:** `references/common-patterns.md` → Child Module Patterns
**Module source options:**
- Local: `"../../modules/vpc"`
- Git: `"git::https://github.com/org/repo.git//path?ref=v1.0.0"`
- Registry: `"tfr:///terraform-aws-modules/vpc/aws?version=5.1.0"`
### 3. Generate Standalone Module
Self-contained modules without root dependency.
**Read before generating:** `assets/templates/module/terragrunt.hcl`
### 4. Generate Multi-Environment Infrastructure
Complete directory structures for dev/staging/prod.
Before generating:
1. Determine architecture pattern (see Architecture Patterns section)
2. Read relevant templates for root and child modules
3. Verify env.hcl placement and access patterns
**Patterns:** `references/common-patterns.md` → Environment-Specific Patterns
**Typical structure (Pattern A):**
```
infrastructure/
├── root.hcl # Environment-AGNOSTIC root config
├── dev/
│ ├── env.hcl # Dev environment variables
│ └── vpc/terragrunt.hcl
└── prod/
├── env.hcl # Prod environment variables
└── vpc/terragrunt.hcl
```
### 5. Generate Terragrunt Stacks (2025)
Infrastructure blueprints using `terragrunt.stack.hcl`.
**Read before generating:** `assets/templates/stack/terragrunt.stack.hcl` and `assets/templates/catalog/terragrunt.hcl`
**Docs:** [Stacks Documentation](https://terragrunt.gruntwork.io/docs/features/stacks/)
**Patterns:** `references/common-patterns.md` → Stacks Patterns
**Commands:**
```bash
terragrunt stack generate # Generate unit configurations
terragrunt stack run plan # Plan all units
terragrunt stack run apply # Apply all units
terragrunt stack output # Get aggregated outputs
terragrunt stack clean # Clean generated directories
```
### 6. Generate Feature Flags (2025)
Runtime control without code changes.
**Docs:** [Feature Flags Documentation](https://terragrunt.gruntwork.io/docs/features/feature-flags/)
**Patterns:** `references/common-patterns.md` → Feature Flags Patterns
> **CRITICAL:** Feature flag `default` values MUST be static (boolean, string, number) — they CANNOT reference `local.*` values.
```hcl
# Correct: static default
feature "enable_monitoring" {
default = false
}
# Incorrect: dynamic reference — FAILS
feature "enable_monitoring" {
default = local.env.locals.enable_monitoring
}
```
**Usage:**
```bash
terragrunt apply --feature enable_monitoring=true
# or
export TG_FEATURE="enable_monitoring=true"
```
### 7. Generate Exclude Blocks (2025)
Fine-grained execution control (replaces deprecated `skip`).
**Docs:** [Exclude Block Reference](https://terragrunt.gruntwork.io/docs/reference/config-blocks-and-attributes/#exclude)
**Patterns:** `references/common-patterns.md` → Exclude Block Patterns
**Actions:** `"plan"`, `"apply"`, `"destroy"`, `"all"`, `"all_except_output"`
**Production recommendation:** Protect critical resources from accidental destruction:
```hcl
exclude {
if = true
actions = ["destroy"]
exclude_dependencies = false
}
prevent_destroy = true
```
### 8. Generate Errors Blocks (2025)
Advanced error handling (replaces deprecated `retryable_errors`).
**Docs:** [Errors Block Reference](https://terragrunt.gruntwork.io/docs/reference/config-blocks-and-attributes/#errors)
**Patterns:** `references/common-patterns.md` → Errors Block Patterns
### 9. Generate OpenTofu Engine Configuration (2025)
Use OpenTofu as the IaC engine.
**Docs:** [Engine Documentation](https://terragrunt.gruntwork.io/docs/features/engine/)
**Patterns:** `references/common-patterns.md` → OpenTofu Engine Patterns
### 10. Handling Custom Providers/Modules
When generating configs with custom providers:
1. **Identify** the provider name, source, and version
2. **Search** using WebSearch: `"[provider] terraform provider [version] documentation"`
3. **Or use Context7 MCP** if available for structured docs
4. **Generate** with proper `required_providers` block
5. **Document** authentication requirements in comments
## Generation Workflow
> **CRITICAL:** Follow this workflow for EVERY generation task. Skipping steps leads to validation errors.
### Step 1: Understand Requirements
- What type of configuration? (root, child, standalone, stack)
- Single or multi-environment?
- What dependencies exist between modules?
- What providers/modules will be used?
### Step 2: Determine Architecture Pattern and Complete Checklist
| Scenario | Pattern | Root.hcl Scope |
|----------|---------|----------------|
| Multi-env with shared root | Pattern A | Environment-agnostic |
| Single environment | Pattern B | Environment-aware |
| Centralized env vars | Pattern C | Environment-agnostic |
> **MANDATORY:** Before writing any files, complete and output this checklist to the user.
```
## Architecture Pattern Selection
[x] Identified architecture pattern: Pattern ___ (A/B/C)
[x] Root.hcl scope: [ ] environment-agnostic OR [ ] environment-aware
[x] env.hcl location: ___________________
[x] Child modules access env via: ___________________
[x] Verified: No file references a path that doesn't exist from its location
```
### Step 3: Read Required Templates
| Configuration Type | Template to Read |
|-------------------|------------------|
| Root configuration | `assets/templates/root/terragrunt.hcl` |
| Child module | `assets/templates/child/terragrunt.hcl` |
| Standalone module | `assets/templates/module/terragrunt.hcl` |
| Stack file | `assets/templates/stack/terragrunt.stack.hcl` |
| Catalog unit | `assets/templates/catalog/terragrunt.hcl` |
Also read: `references/common-patterns.md` — primary source for all generation patterns.
### Step 4: Generate with Validation
**Generation order for multi-environment projects:**
1. **Generate root.hcl first**
- [ ] No `read_terragrunt_config(find_in_parent_folders("env.hcl"))` if environment-agnostic
- [ ] `remote_state` block has `encrypt = true`
- [ ] `errors` block used (not deprecated `retryable_errors`)
2. **Generate env.hcl files for each environment**
- [ ] `locals` block contains environment, aws_region, and module-specific vars
- [ ] No references to files that don't exist at that directory level
3. **Generate child modules — modules with NO dependencies first**
- [ ] `include` block uses `find_in_parent_folders("root.hcl")`
- [ ] `read_terragrunt_config(find_in_parent_folders("env.hcl"))` present
- [ ] `terraform.source` uses valid syntax (tfr:///, git::, or relative path)
4. **Generate dependent modules (RDS, EKS, etc.)**
- [ ] `dependency` blocks have `mock_outputs`
- [ ] `mock_outputs_allowed_terraform_commands` includes `["validate", "plan", "destroy"]`
- [ ] Production modules have `prevent_destroy = true` and/or `exclude` block
5. **Run batch validation after ALL files are generated:**
```bash
terragrunt hcl fmt --check # Format validation
terragrunt dag graph # Dependency graph validation
```
Invoke `devops-skills:terragrunt-validator` for comprehensive validation.
### Step 5: Fix and Re-Validate
If validation fails:
1. Analyze errors (path resolution, missing variables, syntax errors)
2. Fix issues in the specific file(s)
3. Re-validate the fixed file(s)
4. Repeat until ALL errors are resolved
### Step 6: Present Results
Follow the Presentation Requirements section below.
## Validation Workflow
Every generated configuration MUST be validated.
### Incremental Validation
**After generating root.hcl:**
```bash
cd <infrastructure-directory>
terragrunt hcl fmt --check
```
**After generating each child module:**
```bash
cd <module-directory>
terragrunt hcl fmt --check
# If no dependencies on other modules:
terragrunt hcl validate --inputs
```
### Full Validation
After all files are generated:
1. Invoke `devops-skills:terragrunt-validator` skill
2. If validation fails: analyze errors, fix, and re-validate until all pass
3. If validation succeeds: present configurations with usage instructions
**Skip validation only for:** Partial snippets, documentation examples, or explicit user request.
## Presentation Requirements
After successful validation, present ALL of the following sections.
### 1. Directory Structure Summary
```bash
tree <infrastructure-directory>
```
### 2. Files Generated
```markdown
| File | Purpose |
|------|---------|
| root.hcl | Shared configuration for all child modules (state backend, provider) |
| dev/env.hcl | Development environment variables |
| prod/env.hcl | Production environment variables |
| dev/vpc/terragrunt.hcl | VPC module for development |
| ... | ... |
```
### 3. Usage Instructions
```markdown
## Usage Instructions
### Prerequisites
1. AWS credentials configured (`aws configure` or environment variables)
2. S3 bucket `<BUCKET_NAME>` exists for state storage
3. DynamoDB table `<TABLE_NAME>` exists for state locking
### Commands
cd <INFRASTRUCTURE_DIR>
terragrunt run --all init # Initialize all modules
cd <ENV>/vpc && terragrunt plan # Preview a specific module
terragrunt run --all plan # Preview all changes
terragrunt run --all apply # Apply changes (requires approval)
terragrunt run --all destroy # Destroy (use with extreme caution)
```
### 4. Environment-Specific Notes
```markdown
## Environment Notes
### Required Environment Variables
| Variable | Description | Example |
|----------|-------------|---------|
| AWS_PROFILE | AWS CLI profile to use | `my-profile` |
| AWS_REGION | AWS region (or set in provider) | `us-east-1` |
### Prerequisites
- [ ] S3 bucket `<BUCKET_NAME>` must exist before first run
- [ ] DynamoDB table `<TABLE_NAME>` must exist for state locking
- [ ] IAM permissions for Terraform state management
### Production-Specific Protections
| Module | Protection | Description |
|--------|------------|-------------|
| prod/rds | `prevent_destroy = true` | Prevents accidental database deletion |
| prod/rds | `exclude { actions = ["destroy"] }` | Blocks destroy commands |
```
### 5. Next Steps (Optional)
Suggest what the user might want to do next (add more modules, customize configurations, etc.)
## Best Practices
Reference `../devops-skills:terragrunt-validator/references/best_practices.md` for comprehensive guidelines.
**Key principles:**
- Use `include` blocks to inherit root configuration (DRY)
- Always provide mock outputs for dependencies
- Enable state encryption (`encrypt = true`)
- Use `generate` blocks for provider configuration
- Specify bounded version constraints (`~> 5.0`, not `>= 5.0`) for local/Git modules
- Never hardcode credentials or secrets
- Configure retry logic for transient errors
> **Note on Version Constraints with Registry Modules:** When using Terraform Registry modules (e.g., `tfr:///terraform-aws-modules/vpc/aws?version=5.1.0`), they typically define their own `required_providers`. Omit generating `required_providers` in `root.hcl` to avoid conflicts — the module's pinned version provides the constraint.
**Anti-patterns to avoid:**
- Hardcoded account IDs, regions, or environment names
- Missing mock outputs for dependencies
- Duplicated configuration across modules
- Unencrypted state storage
- Missing or loose version constraints (except when using registry modules that define their own)
- Root.hcl trying to read env.hcl that doesn't exist at root level
## Deprecated Attributes
| Deprecated | Replacement | Reference |
|------------|-------------|-----------|
| `skip` | `exclude` block | [Docs](https://terragrunt.gruntwork.io/docs/reference/config-blocks-and-attributes/#exclude) |
| `retryable_errors` | `errors.retry` block | [Docs](https://terragrunt.gruntwork.io/docs/reference/config-blocks-and-attributes/#errors) |
| `run-all` | `run --all` | [Migration](https://terragrunt.gruntwork.io/docs/migrate/migrating-from-run-all/) |
| `--terragrunt-*` flags | Unprefixed flags | [CLI Reference](https://terragrunt.gruntwork.io/docs/reference/cli-options/) |
| `TERRAGRUNT_*` env vars | `TG_*` env vars | [CLI Reference](https://terragrunt.gruntwork.io/docs/reference/cli-options/) |
## Common Issues
For troubleshooting guidance, see [`references/troubleshooting.md`](references/troubleshooting.md), which covers:
- Root.hcl cannot find env.hcl errors
- Provider conflicts with registry modules
- Feature flag validation errors
- Child module env.hcl resolution issues
## Anti-Patterns
### NEVER use `path_relative_to_include()` as a module source path
- **WHY**: This function returns a path relative to the INCLUDING file, not the included root file; using it as a module source creates path resolution failures that vary by directory depth.
- **BAD**: `source = "..//${path_relative_to_include()}"` in a child module's `terraform.source`.
- **GOOD**: Use `get_parent_terragrunt_dir()` or construct explicit relative paths from the root `terragrunt.hcl` location.
### NEVER duplicate backend configuration in every unit's `terragrunt.hcl`
- **WHY**: Copy-pasted `remote_state {}` blocks drift across units over time, creating inconsistent state key schemes and locking configurations that are difficult to audit.
- **BAD**: A full `remote_state { backend = "s3" ... }` block repeated in every leaf module.
- **GOOD**: Define remote state once in the root `root.hcl` and inherit it in every unit via `include "root" { path = find_in_parent_folders("root.hcl") }`.
### NEVER ignore `dependency` output mismatches between plan and apply
- **WHY**: When a `dependency.outputs` reference is evaluated and the dependency has not been applied, Terragrunt substitutes `mock_outputs` silently; if mock types differ from actual output types, the apply will fail with a type error.
- **BAD**: Leave `mock_outputs` blocks with placeholder types and dismiss `mock_outputs` substitution warnings during `terragrunt plan`.
- **GOOD**: Define `mock_outputs` whose types exactly match the actual dependency outputs, and use `mock_outputs_allowed_terraform_commands = ["validate", "plan"]` to limit substitution scope.
### NEVER run `terragrunt run --all apply` without awareness of external dependency scope
- **WHY**: By default, units outside the current directory tree are excluded from `run --all` operations, which can produce partial applies that leave infrastructure in an inconsistent state.
- **BAD**: Run `terragrunt run --all apply` from a subdirectory expecting all transitive dependencies to be included automatically.
- **GOOD**: Run from the repository root or pass `--terragrunt-include-external-dependencies` explicitly to ensure the full dependency graph is evaluated.
### NEVER use the same `terragrunt.hcl` for both `dev` and `prod` environments without environment-level variable overrides
- **WHY**: Sharing configuration without environment isolation causes prod deployments to silently inherit dev defaults (instance sizes, replica counts, retention policies).
- **BAD**: A single `terragrunt.hcl` with no `inputs` block differentiation between environments.
- **GOOD**: Use environment-level `env.hcl` files with `inputs = { environment = "prod", instance_type = "m5.xlarge" }` overrides that layer on top of shared defaults from the root configuration.
## References
### Templates — Read Before Generating
| Configuration Type | Template File | When to Read |
|-------------------|---------------|--------------|
| Root configuration | `assets/templates/root/terragrunt.hcl` | Before generating any root.hcl |
| Child module | `assets/templates/child/terragrunt.hcl` | Before generating any child module |
| Standalone module | `assets/templates/module/terragrunt.hcl` | Before generating standalone modules |
| Stack file | `assets/templates/stack/terragrunt.stack.hcl` | Before generating stacks |
| Catalog unit | `assets/templates/catalog/terragrunt.hcl` | Before generating catalog units |
### References
| Reference | Content | When to Read |
|-----------|---------|--------------|
| `references/common-patterns.md` | All generation patterns with examples | Always, before generating |
| `references/troubleshooting.md` | Common issues and fixes | When encountering errors |
| `../devops-skills:terragrunt-validator/references/best_practices.md` | Comprehensive best practices | Always, before generating |
### Official Documentation
- [Terragrunt Docs](https://terragrunt.gruntwork.io/docs/)
- [Configuration Reference](https://terragrunt.gruntwork.io/docs/reference/config-blocks-and-attributes/)
- [CLI Reference](https://terragrunt.gruntwork.io/docs/reference/cli-options/)
- [Stacks](https://terragrunt.gruntwork.io/docs/features/stacks/)
- [Feature Flags](https://terragrunt.gruntwork.io/docs/features/feature-flags/)
- [Engine](https://terragrunt.gruntwork.io/docs/features/engine/)
- [Migration Guides](https://terragrunt.gruntwork.io/docs/migrate/)