Skip to main content
skill CX Codex

terragrunt-generator — Claude Code skill: what it does, how to install

Generates modern Terragrunt HCL files, root configurations, and multi-environment layouts. Helpful when organizing dev, staging, and prod infrastructure.

Install into Claude Code · Skills CLI (Vercel) All methods and platforms ↓
npx skills add akin-ozer/cc-devops-skills --skill terragrunt-generator -a claude-code
Open on GitHub

What terragrunt-generator does

The skill scaffolds root.hcl, child terragrunt.hcl modules, and infrastructure stacks via terragrunt.stack.hcl. It targets modern Terragrunt conventions, preferring find_in_parent_folders("root.hcl") over deprecated root naming. It also includes support for feature flags, exclude blocks, errors handling, and the OpenTofu engine.

Before writing files, the skill outputs a mandatory architecture selection checklist. In multi-environment setups with an agnostic root, root.hcl will fail if configured to read env.hcl via read_terragrunt_config, because that file does not exist at root level. Child modules must handle environment variables instead.

What it helps with

  • Scaffold multi-environment Terragrunt directories for dev, staging, and prod
  • Generate an environment-agnostic root.hcl with dynamic state keys
  • Wire module relationships using dependency and dependencies blocks
  • Create terragrunt.stack.hcl infrastructure blueprints for catalog units

Example prompts for the agent

  • Create a multi-environment Terragrunt layout with an agnostic root.hcl
  • Generate a terragrunt.hcl for an RDS module that depends on VPC
  • Scaffold a terragrunt.stack.hcl file using the OpenTofu engine

How to install terragrunt-generator

1Skills CLI (Vercel)

npx skills add akin-ozer/cc-devops-skills --skill terragrunt-generator -a claude-code

2Manually: put the files in place

~/.claude/skills/terragrunt-generator/SKILL.md

Copy the whole skill folder; for one project use .claude/skills/terragrunt-generator/

Step by step, with commands for each platform: How to install skills in Claude Code: five ways

Questions about terragrunt-generator

How to install terragrunt-generator in Claude Code?

Run npx skills add akin-ozer/cc-devops-skills --skill terragrunt-generator -a claude-code in your terminal.

What does terragrunt-generator do?

It generates validated Terragrunt HCL configurations, module dependencies, and multi-tier directory layouts across environments.

Why does the skill default to root.hcl instead of terragrunt.hcl?

It adheres to Terragrunt guidance recommending root.hcl paired with find_in_parent_folders("root.hcl"). Naming the root file terragrunt.hcl is treated as a legacy pattern.

Source text

SKILL.md · Apache-2.0
---
name: terragrunt-generator
description: Generate/create/scaffold Terragrunt HCL files — root.hcl, terragrunt.hcl, child modules, stacks, multi-env layouts.
---

# 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

> **CRITICAL:** Feature flag `default` values MUST be static (boolean, string, number).
> They CANNOT reference `local.*` values. Use static defaults and override via CLI/env vars.

**Correct:**
```hcl
feature "enable_monitoring" {
  default = false  # Static value - OK
}
```

**Incorrect:**
```hcl
feature "enable_monitoring" {
  default = local.env.locals.enable_monitoring  # Dynamic reference - FAILS
}
```

**Usage:**
```bash
terragrunt apply --feature enable_monitoring=true
# or
export TG_FEATURE="enable_monitoring=true"
```

**Environment-specific defaults:** Use different static defaults per environment file, not dynamic references.

### 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:** For critical production resources, add exclude blocks to prevent accidental destruction:
```hcl
# Protect production databases from accidental destroy
exclude {
  if      = true
  actions = ["destroy"]
  exclude_dependencies = false
}

# Also use prevent_destroy for critical resources
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
> **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.

### Step 3: Read Required Templates
> **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 patterns

### Step 4: Generate with Validation

> **Validation Strategy:** Use a combination of inline checks during generation and batch validation at the end.

**Generation order for multi-environment projects:**

1. **Generate root.hcl first**
   - **Inline checks (during generation):**
     - [ ] 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**
   - **Inline checks (during generation):**
     - [ ] `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 (VPC, etc.) - modules with NO dependencies first**
   - **Inline checks (during generation):**
     - [ ] `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.)**
   - **Inline checks (during generation):**
     - [ ] `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**
   > **Note:** Full CLI validation (`terragrunt hcl fmt`, `terragrunt dag graph`) requires all files to exist, so these are batched at the end.

   ```bash
   # Batch validation commands (run after all files exist):
   terragrunt hcl fmt --check          # Format validation
   terragrunt dag graph                 # Dependency graph validation
   ```

   - Invoke `Skill(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 "Presentation Requirements" section below.

## Validation Workflow

**CRITICAL:** Every generated configuration MUST be validated.

### Incremental Validation Checks

**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 validation skill:**
   ```
   Invoke: Skill(devops-skills:terragrunt-validator)
   ```

2. **If validation fails:**
   - Analyze errors (missing placeholders, invalid syntax, wrong paths)
   - Fix issues
   - **Re-validate** (repeat until ALL errors are resolved)

3. **If validation succeeds:** Present configurations with usage instructions

**Skip validation only for:** Partial snippets, documentation examples, or explicit user request

### Validation Fallbacks (Environment Constraints)

If the normal validation path is unavailable, use this fallback order and report what was skipped:

1. If `terragrunt` is unavailable:
   - Run static checks:
     ```bash
     rg -n "\[[A-Z0-9_]+\]" .
     rg -n "find_in_parent_folders\\(\"env\\.hcl\"\\)" .
     ```
   - Report that runtime Terragrunt validation is pending.
2. If validator skill execution is unavailable:
   - Run direct Terragrunt checks instead:
     ```bash
     terragrunt hcl fmt --check
     terragrunt dag graph
     ```
3. If `tree` is unavailable for presentation:
   - Use:
     ```bash
     find . -maxdepth 4 -type f | sort
     ```

## Presentation Requirements

> **MANDATORY:** After successful validation, you MUST present ALL of the following sections. Incomplete presentation is not acceptable. Copy and fill in the templates below.

### 1. Directory Structure Summary (MANDATORY)
```bash
# Show the generated structure
tree <infrastructure-directory>
```

### 2. Files Generated (MANDATORY)

**Output this table with all generated files:**
```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 (MANDATORY)

> **You MUST include this section.** Copy the template below and fill in the actual values:

```markdown
## Usage Instructions

### Prerequisites
Before running Terragrunt commands, ensure:
1. AWS credentials are 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

# Navigate to infrastructure directory
cd <INFRASTRUCTURE_DIR>

# Initialize all modules
terragrunt run --all init

# Preview changes for a specific environment
cd <ENV>/vpc && terragrunt plan

# Preview all changes
terragrunt run --all plan

# Apply changes (requires approval)
terragrunt run --all apply

# Destroy (use with extreme caution)
terragrunt run --all destroy
```

### 4. Placeholder Replacement and Secrets Check (MANDATORY)

> **You MUST include this section.** Copy the template below and fill in the actual values:

```markdown
## Placeholder and Secrets Check

### Placeholder Replacement
- [ ] All placeholders (`[AWS_REGION]`, `[BUCKET_NAME]`, `[DYNAMODB_TABLE]`, etc.) replaced with real values
- [ ] No legacy placeholder aliases left (for example `[REGION]`)
- [ ] `terraform.source` values point to real module sources and pinned versions

### Secrets Safety
- [ ] No plaintext credentials or access keys in `terragrunt.hcl`, `root.hcl`, `env.hcl`, `account.hcl`, or `region.hcl`
- [ ] Sensitive values sourced via environment variables, secret managers, or CI variables
- [ ] Example values kept non-sensitive and clearly marked as placeholders
```

### 5. Environment-Specific Notes (MANDATORY)

> **You MUST include this section.** Copy the template below and fill in the actual values:

```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 |
```

### 6. Next Steps (Optional)
Suggest what the user might want to do next (add more modules, customize configurations, etc.)

## Best Practices

Reference `../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`. In this case, you may omit generating `required_providers` in `root.hcl` to 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:**
- 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/) |

## Resources

### Templates - MUST Read Before Generating

| 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 |

### References

| 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 |

### 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/)

## Common Issues

### Root.hcl Cannot Find env.hcl

**Symptom:**
```
Error: Attempt to get attribute from null value
  on ./root.hcl line X:
  This value is null, so it does not have any attributes.
```

**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:
```hcl
# DON'T do this in root.hcl for multi-environment setups:
locals {
  env_vars = read_terragrunt_config(find_in_parent_folders("env.hcl"))  # FAILS
}

# DO use static values or get_env():
generate "provider" {
  path      = "provider.tf"
  if_exists = "overwrite_terragrunt"
  contents  = <<EOF
provider "aws" {
  region = "us-east-1"  # Static value, or use get_env("AWS_REGION", "us-east-1")
}
EOF
}
```

### Provider Conflict with Registry Modules

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:**
```
Error: Duplicate required providers configuration
```

**Solutions:**
1. **Remove conflicting generate block** - If using registry modules that manage their own providers, avoid generating duplicate `required_providers`:
   ```hcl
   # In root.hcl - only generate provider config, not required_providers
   generate "provider" {
     path      = "provider.tf"
     if_exists = "overwrite_terragrunt"
     contents  = <<EOF
   provider "aws" {
     region = "us-east-1"
   }
   EOF
   }
   ```

2. **Use if_exists = "skip"** - Skip generation if file already exists:
   ```hcl
   generate "versions" {
     path      = "versions.tf"
     if_exists = "skip"  # Don't overwrite module's versions.tf
     contents  = "..."
   }
   ```

3. **Clear cache** - If conflicts persist after fixes:
   ```bash
   rm -rf .terragrunt-cache
   terragrunt init
   ```

### Feature Flag Validation Errors

If you see `Unknown variable; There is no variable named "local"` in feature blocks, ensure defaults are static values (see Feature Flags section above).

### Child Module Cannot Find env.hcl

**Symptom:**
```
Error: Attempt to get attribute from null value
  on ./dev/vpc/terragrunt.hcl line X:
```

**Cause:** Child module's `find_in_parent_folders("env.hcl")` cannot find env.hcl.

**Solution:** Ensure env.hcl exists in the environment directory:
```
dev/
├── env.hcl           # This file MUST exist
└── vpc/
    └──...

© akin-ozer · Apache-2.0 · akin-ozer/cc-devops-skills

Similar skills

Everything for DevOps and infrastructure →

From the same set28

ansible-validator A skill that runs Ansible playbooks and roles through linters, check mode, Molecule and secret scanners. Useful when the code exists and you need to know what is wrong with it. CX Codex +1 1,300installs k8s-debug Walks through pod failures, stuck rollouts, DNS and storage problems with kubectl. Useful when a cluster misbehaves right after a deploy. CX Codex +1 819installs jenkinsfile-generator Generates declarative and scripted Jenkinsfiles, Kubernetes pod templates, and Jenkins Shared Library scaffolds. Useful when creating CI/CD pipelines with parallel stages or security checks. CX Codex +1 803installs dockerfile-validator Validates Dockerfiles for syntax, security flaws, and build practices using a structured validation script. Useful for hardening images before CI/CD merges. CX Codex +1 740installs dockerfile-generator A skill that writes production-ready Dockerfiles and .dockerignore, validates them, then fixes what the validator flags. Handy when you need to containerize a service without hand-tuning layers. CX Codex +1 699installs gitlab-ci-validator Validates syntax and security rules in .gitlab-ci.yml. Useful before opening a merge request to catch broken pipelines locally. CX Codex +1 679installs bash-script-validator A skill that runs bash and POSIX scripts through syntax checks, ShellCheck and its own security and portability rules. Handy before CI. CX Codex +1 679installs k8s-yaml-validator This skill runs Kubernetes manifests through a linter, schema validation and dry-run, then reports errors with line references. Handy before kubectl apply. CX Codex +1 672installs

Project sponsors

Companies that keep this analytics open
Gold sponsor

Impressions, clicks and code copies — open statistics. We keep the numbers public for the same reason NeBlask itself is public. Become a sponsor