- name
- terragrunt-generator
- description
- Generate/create/scaffold Terragrunt HCL files — root.hcl, terragrunt.hcl, child modules, stacks, multi-env layouts. Use when this capability is needed.
- metadata
- {"author":"akin-ozer"}
# Terragrunt Generator
## Overview
Generate production-ready Terragrunt configurations following current best practices, naming conventions, and security standards. All generated configurations are automatically validated.
## Trigger Phrases
Use this skill when the user asks for:
- A new `root.hcl`, `terragrunt.hcl`, or `terragrunt.stack.hcl`
- Multi-environment Terragrunt layouts (`dev/staging/prod`)
- Terragrunt dependency wiring (`dependency` or `dependencies` blocks)
- Terragrunt module source setup (local, Git, Terraform Registry via `tfr:///`)
- Stack catalog unit generation under `catalog/units/*`
**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()` |
**Include standard:** Default to `find_in_parent_folders("root.hcl")` in all new examples and generated configs. Use `find_in_parent_folders()` only when explicitly targeting a legacy root file named `terragrunt.hcl`.
## Architecture Patterns
> **CRITICAL:** Before generating ANY configuration, you MUST determine the architecture pattern and understand its constraints.
### Pattern A: Multi-Environment with Environment-Agnostic Root
**Use when:** Managing multiple environments (dev/staging/prod) with shared root configuration.
**Key principle:** `root.hcl` is **environment-agnostic** - it does NOT read environment-specific files.
```
infrastructure/
├── root.hcl # Environment-AGNOSTIC (no env.hcl references)
├── dev/
│ ├── env.hcl # Environment variables (locals block)
│ ├── vpc/terragrunt.hcl
│ └── rds/terragrunt.hcl
└── prod/
├── env.hcl # Environment variables (locals block)
├── vpc/terragrunt.hcl
└── rds/terragrunt.hcl
```
**Root.hcl constraints:**
- ❌ CANNOT use `read_terragrunt_config(find_in_parent_folders("env.hcl"))` - env.hcl doesn't exist at root level
- ❌ CANNOT reference `local.environment` or `local.aws_region` that come from env.hcl
- ✅ CAN use static values or `get_env()` for runtime configuration
- ✅ CAN use `${path_relative_to_include()}` for state keys (this works dynamically)
**Child modules read env.hcl:**
```hcl
# dev/vpc/terragrunt.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" # Works: env.hcl exists in dev/
}
```
### Pattern B: Single Environment or Environment-Aware Root
**Use when:** Single environment OR all environments share the same root with environment detection.
```
infrastructure/
├── root.hcl # Can be environment-aware via get_env() or directory parsing
├── account.hcl # Account-level config (optional)
├── region.hcl # Region-level config (optional)
└── vpc/
└── terragrunt.hcl
```
**Root.hcl can detect environment:**
```hcl
# root.hcl - environment detection via directory path
locals {
# Parse environment from path (e.g., "prod/vpc" -> "prod")
path_parts = split("/", path_relative_to_include())
environment = local.path_parts[0]
# OR use environment variable
environment = get_env("TG_ENVIRONMENT", "dev")
}
```
### Pattern C: Shared Environment Variables (_env directory)
**Use when:** Centralizing environment variables with symlinks or direct references.
```
infrastructure/
├── root.hcl # Environment-AGNOSTIC
├── _env/ # Centralized environment definitions
│ ├── prod.hcl
│ ├── staging.hcl
│ └── dev.hcl
├── prod/
│ ├── env.hcl # Reads from _env/prod.hcl
│ └── vpc/terragrunt.hcl
└── dev/
├── env.hcl # Reads from _env/dev.hcl
└── vpc/terragrunt.hcl
```
**env.hcl reads from _env:**
```hcl
# prod/env.hcl
locals {
env_vars = read_terragrunt_config("${get_repo_root()}/_env/prod.hcl")
# Re-export for child modules
environment = local.env_vars.locals.environment
aws_region = local.env_vars.locals.aws_region
vpc_cidr = local.env_vars.locals.vpc_cidr
# ... other variables
}
```
### Architecture Pattern Selection Checklist (Canonical)
> **MANDATORY:** Before writing any files, you MUST complete this checklist and OUTPUT it to the user with checkmarks filled in. This is not optional.
**Output this completed checklist before generating any files:**
```
## 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
```
**Example completed checklist:**
```
## Architecture Pattern Selection
[x] Identified architecture pattern: Pattern A (Multi-Environment with Environment-Agnostic Root)
[x] Root.hcl scope: [x] environment-agnostic OR [ ] environment-aware
[x] env.hcl location: dev/env.hcl, prod/env.hcl (one per environment)
[x] Child modules access env via: read_terragrunt_config(find_in_parent_folders("env.hcl"))
[x] Verified: No file references a path that doesn't exist from its location
```
## Quick Variable Definition Examples
Use these starter files for Pattern B and account/region-aware setups.
**env.hcl**
```hcl
locals {
environment = "dev"
aws_region = "us-east-1"
project = "platform"
}
```
**account.hcl**
```hcl
locals {
account_id = "123456789012"
account_name = "shared-services"
}
```
**region.hcl**
```hcl
locals {
aws_region = "us-east-1"
}
```
## When to Use
- Creating new Terragrunt projects or configurations
- Setting up multi-environment infrastructure (dev/staging/prod)
- Implementing DRY Terraform configurations
- Managing complex infrastructure with dependencies
- Working with custom Terraform providers or modules
## Core Capabilities
### 1. Generate Root Configuration
Create root-level `root.hcl` or `terragrunt.hcl` with remote state, provider config, and common variables.
> **MANDATORY:** Before generating, READ the template file:
> ```
> Read: assets/templates/root/terragrunt.hcl
> ```
**Template:** `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_SOURCE]`, `[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 use `get_env()` for runtime config
3. **State key uses `path_relative_to_include()`** - This 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.
> **MANDATORY:** Before generating, READ the template file:
> ```
> Read: assets/templates/child/terragrunt.hcl
> ```
**Template:** `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.
> **MANDATORY:** Before generating, READ the template file:
> ```
> Read: assets/templates/module/terragrunt.hcl
> ```
**Template:** `assets/templates/module/terragrunt.hcl`
### Canonical Placeholder Replacement Map
Use this map for every generated output:
| Placeholder | Meaning | Example Replacement | Notes |
|-------------|---------|---------------------|-------|
| `[AWS_REGION]` | AWS region | `us-east-1` | Canonical region placeholder in all templates |
| `[ENVIRONMENT]` | Environment name | `dev` | Keep lowercase for directory naming |
| `[PROJECT_NAME]` | Project/application name | `payments-platform` | Use the same value in tags and names |
| `[BUCKET_NAME]` | Remote state S3 bucket | `acme-tfstate-prod` | Bucket must exist before first apply |
| `[DYNAMODB_TABLE]` | State lock table | `acme-terraform-locks` | Table must exist before first apply |
| `[PROVIDER_SOURCE]` | Terraform provider source | `hashicorp/aws` | Use fully qualified source |
| `[TERRAFORM_VERSION]` | Required Terraform/OpenTofu version | `1.8.5` | Used in both `terraform_version_constraint` and `required_version`. Keep compatible with module constraints. |
**Legacy alias normalization:** If you see `[REGION]` in older examples, treat it as `[AWS_REGION]` and replace it before validation.
### 4. Generate Multi-Environment Infrastructure
Complete directory structures for dev/staging/prod.
> **MANDATORY:** Before generating:
> 1. Determine architecture pattern (see Architecture Patterns section)
> 2. Read relevant templates for root, env, and child modules
> 3. Verify env.hcl placement and access patterns:
> ```
> Read: assets/templates/env/env.hcl
> ```
**Patterns:** `references/common-patterns.md` → Environment-Specific Patterns
**Typical structure (Pattern A - Environment-Agnostic Root):**
```
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`.
> **MANDATORY:** Before generating, READ the template files:
> ```
> Read: assets/templates/stack/terragrunt.stack.hcl
> Read: assets/templates/catalog/terragrunt.hcl
> ```
**Docs:** [Stacks Documentation](https://terragrunt.gruntwork.io/docs/features/stacks/)
**Template:** `assets/templates/stack/terragrunt.stack.hcl`
**Catalog Template:** `assets/templates/catalog/terragrunt.hcl`
**Patterns:** `references/common-patterns.md` → Stacks Patterns
**Stack path rule:** Keep `no_dot_terragrunt_stack` mode consistent across dependent units. Do not mix direct-path and `.terragrunt-stack` generation in the same dependency chain.
**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
View on GitHub