npx skills add ...
npx skills add akin-ozer/cc-devops-skills --skill terragrunt-generator
Generate/create/scaffold Terragrunt HCL files — root.hcl, terragrunt.hcl, child modules, stacks, multi-env layouts.
npx skills add akin-ozer/cc-devops-skills --skill terragrunt-generator
Generate production-ready Terragrunt configurations following current best practices, naming conventions, and security standards. All generated configurations are automatically validated.
Use this skill when the user asks for:
root.hcl, terragrunt.hcl, or terragrunt.stack.hcldev/staging/prod)dependency or dependencies blocks)tfr:///)catalog/units/*Terragrunt 2025 Features Supported:
terragrunt.stack.hcl (GA since v0.78.0)feature blocksskip)retryable_errors)RECOMMENDED: Use
root.hclinstead ofterragrunt.hclfor root files per migration guide.
| 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.
CRITICAL: Before generating ANY configuration, you MUST determine the architecture pattern and understand its constraints.
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.
Root.hcl constraints:
read_terragrunt_config(find_in_parent_folders("env.hcl")) - env.hcl doesn't exist at root levellocal.environment or local.aws_region that come from env.hclget_env() for runtime configuration${path_relative_to_include()} for state keys (this works dynamically)Child modules read env.hcl:
Use when: Single environment OR all environments share the same root with environment detection.
Root.hcl can detect environment:
Use when: Centralizing environment variables with symlinks or direct references.
env.hcl reads from _env:
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:
Example completed checklist:
Use these starter files for Pattern B and account/region-aware setups.
env.hcl
account.hcl
region.hcl
Create root-level root.hcl or terragrunt.hcl with remote state, provider config, and common variables.
MANDATORY: Before generating, READ the template file:
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:
get_env() for runtime configpath_relative_to_include() - This automatically includes environment pathCreate child modules with dependencies, mock outputs, and proper includes.
MANDATORY: Before generating, READ the template file:
Template: assets/templates/child/terragrunt.hcl
Patterns: references/common-patterns.md → Child Module Patterns
Module source options:
"../../modules/vpc""git::https://github.com/org/repo.git//path?ref=v1.0.0""tfr:///terraform-aws-modules/vpc/aws?version=5.1.0"Self-contained modules without root dependency.
MANDATORY: Before generating, READ the template file:
Template: assets/templates/module/terragrunt.hcl
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.
Complete directory structures for dev/staging/prod.
MANDATORY: Before generating:
- Determine architecture pattern (see Architecture Patterns section)
- Read relevant templates for root, env, and child modules
- Verify env.hcl placement and access patterns:
Patterns: references/common-patterns.md → Environment-Specific Patterns
Typical structure (Pattern A - Environment-Agnostic Root):
Infrastructure blueprints using terragrunt.stack.hcl.
MANDATORY: Before generating, READ the template files:
Docs: Stacks Documentation
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:
Runtime control without code changes.
Docs: Feature Flags Documentation
Patterns: references/common-patterns.md → Feature Flags Patterns
CRITICAL: Feature flag
defaultvalues MUST be static (boolean, string, number). They CANNOT referencelocal.*values. Use static defaults and override via CLI/env vars.
Correct:
Incorrect:
Usage:
Environment-specific defaults: Use different static defaults per environment file, not dynamic references.
Fine-grained execution control (replaces deprecated skip).
Docs: Exclude Block Reference
Patterns: references/common-patterns.md → Exclude Block Patterns
Actions: "plan", "apply", "destroy", "all", "all_except_output"
Production Recommendation: For critical production resources, add exclude blocks to prevent accidental destruction:
Advanced error handling (replaces deprecated retryable_errors).
Docs: Errors Block Reference
Patterns: references/common-patterns.md → Errors Block Patterns
Use OpenTofu as the IaC engine.
Docs: Engine Documentation
Patterns: references/common-patterns.md → OpenTofu Engine Patterns
When generating configs with custom providers:
"[provider] terraform provider [version] documentation"required_providers blockCRITICAL: Follow this workflow for EVERY generation task. Skipping steps leads to validation errors.
MANDATORY: Select and document the pattern BEFORE writing any files.
| 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 |
Complete the Architecture Pattern Selection Checklist (Canonical) above and include it in output before file generation.
MANDATORY: Read the relevant template file(s) BEFORE generating each configuration type.
| Configuration Type | Template to Read | Purpose |
|---|---|---|
| Root configuration | assets/templates/root/terragrunt.hcl | Shared state backend, providers, and common inputs |
| Environment variables | assets/templates/env/env.hcl | Per-environment locals read by child modules (Pattern A) |
| Child module | assets/templates/child/terragrunt.hcl | Environment module wired to root include |
| Standalone module | assets/templates/module/terragrunt.hcl | Independent Terragrunt module without root include |
| Stack file | assets/templates/stack/terragrunt.stack.hcl | Blueprint that generates multiple units |
| Catalog unit | assets/templates/catalog/terragrunt.hcl | Reusable unit template consumed by stacks |
Also read:
references/common-patterns.md - Primary source for generation patternsValidation Strategy: Use a combination of inline checks during generation and batch validation at the end.
Generation order for multi-environment projects:
Generate root.hcl first
read_terragrunt_config(find_in_parent_folders("env.hcl")) if environment-agnosticremote_state block has encrypt = trueerrors block used (not deprecated retryable_errors)Generate env.hcl files for each environment
locals block contains environment, aws_region, and module-specific varsGenerate child modules (VPC, etc.) - modules with NO dependencies first
include block uses find_in_parent_folders("root.hcl")read_terragrunt_config(find_in_parent_folders("env.hcl")) presentterraform.source uses valid syntax (tfr:///, git::, or relative path)Generate dependent modules (RDS, EKS, etc.)
dependency blocks have mock_outputsmock_outputs_allowed_terraform_commands includes ["validate", "plan", "destroy"]prevent_destroy = true and/or exclude blockRun batch validation after ALL files are generated
Note: Full CLI validation (
terragrunt hcl fmt,terragrunt dag graph) requires all files to exist, so these are batched at the end.
Skill(devops-skills:terragrunt-validator) for comprehensive validationIf validation fails:
Follow "Presentation Requirements" section below.
CRITICAL: Every generated configuration MUST be validated.
After generating root.hcl:
After generating each child module:
After all files are generated:
Invoke validation skill:
If validation fails:
If validation succeeds: Present configurations with usage instructions
Skip validation only for: Partial snippets, documentation examples, or explicit user request
If the normal validation path is unavailable, use this fallback order and report what was skipped:
terragrunt is unavailable:
tree is unavailable for presentation:
MANDATORY: After successful validation, you MUST present ALL of the following sections. Incomplete presentation is not acceptable. Copy and fill in the templates below.
Output this table with all generated files:
You MUST include this section. Copy the template below and fill in the actual values:
You MUST include this section. Copy the template below and fill in the actual values:
You MUST include this section. Copy the template below and fill in the actual values:
Suggest what the user might want to do next (add more modules, customize configurations, etc.)
Reference ../terragrunt-validator/references/best_practices.md for comprehensive guidelines.
Key principles:
include blocks to inherit root configuration (DRY)encrypt = true)generate blocks for provider configuration~> 5.0, not >= 5.0) for local/Git modulesNote 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 ownrequired_providers. In this case, you may omit generatingrequired_providersinroot.hclto avoid conflicts. The module's pinned version (?version=X.X.X) provides the version constraint. See "Common Issues → Provider Conflict with Registry Modules" for details.
Anti-patterns to avoid:
| Deprecated | Replacement | Reference |
|---|---|---|
skip | exclude block | Docs |
retryable_errors | errors.retry block | Docs |
run-all | run --all | Migration |
--terragrunt-* flags | Unprefixed flags | CLI Reference |
TERRAGRUNT_* env vars | TG_* env vars | CLI Reference |
| Configuration Type | Template File | Purpose | When to Read |
|---|---|---|---|
| Root configuration | assets/templates/root/terragrunt.hcl | Shared backend, provider, and common inputs | Before generating any root.hcl |
| Environment variables | assets/templates/env/env.hcl | Per-environment locals (environment, region, sizing, feature toggles) | Before generating any env.hcl (Pattern A) |
| Child module | assets/templates/child/terragrunt.hcl | Module include, source, and optional dependency scaffolding | Before generating any child module |
| Standalone module | assets/templates/module/terragrunt.hcl | Module config without root inheritance | Before generating standalone modules |
| Stack file | assets/templates/stack/terragrunt.stack.hcl | Stack blueprint and unit generation | Before generating stacks |
| Catalog unit | assets/templates/catalog/terragrunt.hcl | Reusable unit consumed by stack definitions | Before generating catalog units |
| Reference | Content | Purpose | When to Read |
|---|---|---|---|
references/common-patterns.md | All generation patterns with examples | Pick a compatible pattern before writing files | Always, before generating |
../terragrunt-validator/references/best_practices.md | Comprehensive best practices | Final quality and safety checks | Always, before generating |
Symptom:
Cause: Root.hcl is trying to read env.hcl via find_in_parent_folders("env.hcl"), but env.hcl doesn't exist at the root level.
Solution: Make root.hcl environment-agnostic:
When using Terraform Registry modules (e.g., tfr:///terraform-aws-modules/vpc/aws), they may define their own required_providers block. This can conflict with provider configuration generated by root.hcl.
Symptoms:
Solutions:
Remove conflicting generate block - If using registry modules that manage their own providers, avoid generating duplicate required_providers:
Use if_exists = "skip" - Skip generation if file already exists:
Clear cache - If conflicts persist after fixes:
If you see Unknown variable; There is no variable named "local" in feature blocks, ensure defaults are static values (see Feature Flags section above).
Symptom:
Cause: Child module's find_in_parent_folders("env.hcl") cannot find env.hcl.
Solution: Ensure env.hcl exists in the environment directory:
Before generating, READ these files in order:
references/common-patterns.md - Understand available patterns../terragrunt-validator/references/best_practices.md - Know the rulesassets/templates/ - Structural referenceterragrunt hcl fmt --checkterragrunt hcl validate --inputsSkill(devops-skills:terragrunt-validator)This skill execution is complete only when ALL are true:
tfr:///NAMESPACE/NAME/PROVIDER?version=X.Y.Z formatinfrastructure/
├── 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 - 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")
}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# 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
[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## 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 locationlocals {
environment = "dev"
aws_region = "us-east-1"
project = "platform"
}locals {
account_id = "123456789012"
account_name = "shared-services"
}locals {
aws_region = "us-east-1"
}