Covers HashiCorp Terraform across all versions: HCL, providers, state management, modules, workspaces, and infrastructure provisioning. WHEN: \"Terraform\", \"terraform plan\", \"terraform apply\", \"HCL\", \".tf files\", \"Terraform state\", \"Terraform module\", \"Terraform provider\", \"Terraform workspace\", \"tfstate\", \"Terraform Cloud\", \"Terraform Enterprise\". Do NOT use for Terraform against network-device providers (ACI, Meraki, PAN-OS, FortiOS, F5 BIG-IP) — that's the `terraform...
Pro scans all 9 files and shows the line behind each finding
Scanned 9/24/2026
npx -y skills add chrishuffman5/domain-expert --skill terraform --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Terraform?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/chrishuffman5-terraform)More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.
---
name: terraform
description: "Covers HashiCorp Terraform across all versions: HCL, providers, state management, modules, workspaces, and infrastructure provisioning. WHEN: \"Terraform\", \"terraform plan\", \"terraform apply\", \"HCL\", \".tf files\", \"Terraform state\", \"Terraform module\", \"Terraform provider\", \"Terraform workspace\", \"tfstate\", \"Terraform Cloud\", \"Terraform Enterprise\". Do NOT use for Terraform against network-device providers (ACI, Meraki, PAN-OS, FortiOS, F5 BIG-IP) — that's the `terraform-network` skill (in the networking plugin)."
license: MIT
---
# Terraform Technology Expert
This skill covers HashiCorp Terraform across all supported versions (1.6 through 1.15), including:
- HCL syntax, expressions, functions, and meta-arguments
- Provider architecture and configuration (AWS, Azure, GCP, Kubernetes, and 4000+ providers)
- State management (backends, locking, import, migration, state surgery)
- Module design (inputs, outputs, composition, versioning, registry)
- Workspaces and environment management
- Terraform Cloud / Enterprise (remote execution, policy, VCS integration)
- Testing framework (`terraform test`, Terratest, Checkov, tfsec)
- Migration and upgrades between versions
When a question is version-specific, read the matching file under `references/versions/`. When the version is unknown, provide general guidance and note where behavior differs across versions.
## How to Approach Tasks
1. **Classify** the request:
- **Troubleshooting** -- Load `references/diagnostics.md` for common errors, state issues, and debugging workflows
- **Architecture / module design** -- Load `references/architecture.md` for provider internals, state mechanics, and module patterns
- **Best practices** -- Load `references/best-practices.md` for code organization, naming, security, and CI/CD integration
- **Terraform Cloud / HCP Terraform** -- Load `references/terraform-cloud.md` for workspaces, runs, VCS integration, policies, agents, dynamic credentials, API, and tfe provider
- **State management** -- Cover backends, locking, import, moved blocks, state surgery
- **Provider issues** -- Authentication, version constraints, data sources, resource lifecycle
2. **Identify version** -- Determine which Terraform version the user runs. Features like `terraform test` (1.6+), `import` blocks (1.5+), `moved` blocks (1.1+), `check` blocks (1.5+), provider-defined functions (1.8+), and ephemeral resources (1.10+) are version-gated. If version is unclear, ask.
3. **Load context** -- Read the relevant reference file for deep technical detail.
4. **Analyze** -- Apply Terraform-specific reasoning. Consider provider version, backend type, state structure.
5. **Recommend** -- Provide actionable guidance with HCL examples and CLI commands.
6. **Verify** -- Suggest validation steps (`terraform plan`, `terraform validate`, `terraform state list`).
## Core Architecture
### How Terraform Works
```
┌──────────────┐
│ .tf files │ HCL configuration
└──────┬───────┘
│
┌──────▼───────┐
│ terraform │ Core binary
│ plan │
└──────┬───────┘
│
┌────────────┼────────────┐
│ │ │
┌──────▼──────┐ ┌──▼──────┐ ┌───▼─────┐
│ State File │ │Provider │ │Provider │ Plugin protocol
│ (backend) │ │ AWS │ │ Azure │ (gRPC)
└─────────────┘ └────┬────┘ └────┬────┘
│ │
┌────▼────┐ ┌────▼────┐
│ AWS │ │ Azure │ Cloud APIs
│ APIs │ │ APIs │
└─────────┘ └─────────┘
```
1. **Parse** -- Terraform reads all `.tf` files in the current directory, builds a configuration graph
2. **Plan** -- Compares desired state (config) + known state (state file) against real state (provider API calls). Produces a diff (plan).
3. **Apply** -- Executes the plan: creates, updates, or destroys resources via provider APIs. Updates state file.
### State File
The state file (`terraform.tfstate`) is Terraform's record of what it manages:
- Maps resource addresses (`aws_instance.web`) to real resource IDs (`i-0abc123def`)
- Stores all resource attributes for computing diffs and dependencies
- **Must be stored remotely** for team use (S3, GCS, Azure Blob, Terraform Cloud, Consul)
- **Must be locked** during operations to prevent concurrent writes
- Contains sensitive values — treat as a secret, encrypt at rest
### Resource Lifecycle
```
resource "aws_instance" "web" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t3.micro"
lifecycle {
create_before_destroy = true # Replace: create new, then destroy old
prevent_destroy = true # Block terraform destroy
ignore_changes = [tags] # Don't detect drift on tags
replace_triggered_by = [ # Force replacement when dependency changes
aws_ami.latest.id
]
}
}
```
Lifecycle meta-arguments control how Terraform handles resource changes:
| Meta-Argument | Effect |
|---|---|
| `create_before_destroy` | New resource created before old is destroyed (avoids downtime) |
| `prevent_destroy` | `terraform destroy` or replacement fails (safety net) |
| `ignore_changes` | Listed attributes excluded from drift detection |
| `replace_triggered_by` | Force replacement when referenced resource/attribute changes |
| `precondition` | Validate assumptions before applying (1.2+) |
| `postcondition` | Validate results after applying (1.2+) |
## Module Design
### Module Structure
```
modules/
vpc/
main.tf # Resources
variables.tf # Input variables
outputs.tf # Output values
versions.tf # Required providers + Terraform version
README.md # Documentation
```
### Module Best Practices
1. **Single responsibility** -- A module does one thing (creates a VPC, or an EKS cluster, not both)
2. **Expose only what's needed** -- Outputs are the module's API. Don't expose internal details.
3. **Version constraints** -- Pin provider and module versions. Use `~>` for minor version flexibility.
4. **No hardcoded values** -- Everything configurable via variables with sensible defaults
5. **Validate inputs** -- Use `validation` blocks on variables to catch bad input early
```hcl
variable "environment" {
type = string
description = "Deployment environment"
validation {
condition = contains(["dev", "staging", "prod"], var.environment)
error_message = "Environment must be dev, staging, or prod."
}
}
```
## State Management
### Backend Configuration
```hcl
terraform {
backend "s3" {
bucket = "mycompany-terraform-state"
key = "network/vpc/terraform.tfstate"
region = "us-east-1"
dynamodb_table = "terraform-locks"
encrypt = true
}
}
```
### State Operations
| Operation | Command | Use Case |
|---|---|---|
| List resources | `terraform state list` | Inventory of managed resources |
| Show resource | `terraform state show aws_instance.web` | Inspect a resource's state |
| Move resource | `terraform state mv aws_instance.old aws_instance.new` | Refactor without destroy/recreate |
| Remove from state | `terraform state rm aws_instance.web` | Stop managing (don't destroy) |
| Import existing | `terraform import aws_instance.web i-0abc123` | Adopt existing infrastructure (CLI) |
| Import block | `import { to = aws_instance.web; id = "i-0abc123" }` | Adopt existing infrastructure (1.5+ config) |
### Moved Blocks (Refactoring)
```hcl
moved {
from = aws_instance.web
to = module.compute.aws_instance.web
}
```
Moved blocks (1.1+) let you refactor resource addresses without destroying and recreating. Terraform generates a plan that moves the state, not the infrastructure.
## Common Patterns
### Data Source Lookups
```hcl
data "aws_ami" "ubuntu" {
most_recent = true
owners = ["099720109477"] # Canonical
filter {
name = "name"
values = ["ubuntu/images/hvm-ssd/ubuntu-*-24.04-amd64-server-*"]
}
}
```
### Dynamic Blocks
```hcl
resource "aws_security_group" "web" {
name = "web-sg"
dynamic "ingress" {
for_each = var.ingress_rules
content {
from_port = ingress.value.port
to_port = ingress.value.port
protocol = "tcp"
cidr_blocks = ingress.value.cidrs
}
}
}
```
### For Expressions
```hcl
# Map transformation
locals {
instance_ids = { for k, v in aws_instance.web : k => v.id }
public_ips = [for i in aws_instance.web : i.public_ip if i.public_ip != ""]
}
```
## Version-Specific Guidance
| Version | Reference | What's new |
|---|---|---|
| 1.14 | `references/versions/1.14.md` | Ephemeral resources fully stabilized, expanded provider-defined functions, `for_each` on import blocks, multiple validation blocks per variable |
| 1.15 | `references/versions/1.15.md` | Latest HCL enhancements, stacks improvements, enhanced testing framework, provider ecosystem updates |
## Reference Files
- `references/architecture.md` — Provider plugin protocol, state file internals, dependency graph, plan/apply mechanics, backend deep dive
- `references/best-practices.md` — Code organization, naming conventions, module design, CI/CD integration, security hardening, cost management
- `references/diagnostics.md` — Common errors (state lock, provider auth, dependency cycles, plan drift), debugging workflows, state recovery
- `references/terraform-cloud.md` — HCP Terraform / Terraform Cloud workspace management, VCS integration, run workflow, policy enforcement, dynamic credentials, agents, API automation, tfe provider, troubleshooting
## Diagnostic Scripts
Ready-made validation/drift scripts (read-only; drift preview never writes state) in `scripts/`.
- `scripts/01-validate-and-fmt.sh` -- fmt/validate/lock-file gate without backend access
- `scripts/02-drift-preview.sh` -- -refresh-only plan with exit-code decoding (drift vs clean)
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!