Generate Terraform HCL code following HashiCorp's official style conventions and best practices. Use when writing, reviewing, or generating Terraform configurations.
Generate and maintain Terraform code following HashiCorp's official style conventions.
Reference: HashiCorp Terraform Style Guide
Supplementary references (load as needed):
moved blocks, and reusable module designfor_each vs count vs dynamic blocksWhen generating Terraform code:
| File | Purpose |
|------|---------|
| terraform.tf | Terraform and provider version requirements |
| providers.tf | Provider configurations |
| main.tf | Primary resources and data sources |
| variables.tf | Input variable declarations (alphabetical) |
| outputs.tf | Output value declarations (alphabetical) |
| locals.tf | Local value declarations |
For modules, add README.md and follow the structure in references/modules.md.
Align equals signs for consecutive arguments. Place meta-arguments first, then arguments, then nested blocks, with lifecycle last:
resource "aws_instance" "example" {
# Meta-arguments first
count = 3
# Arguments (aligned =)
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
# Nested blocks
root_block_device {
volume_size = 20
}
# Lifecycle last
lifecycle {
create_before_destroy = true
}
}
main when only one instance exists and a specific name adds no clarity# Bad
resource "aws_instance" "webAPI-aws-instance" {}
resource "aws_instance" "web_apis" {}
variable "name" {}
# Good
resource "aws_instance" "web_api" {}
resource "aws_vpc" "main" {}
variable "application_name" {}
Every variable requires type and description. Every output requires description. Mark secrets with sensitive = true:
variable "instance_type" {
description = "EC2 instance type for the web server"
type = string
default = "t2.micro"
validation {
condition = contains(["t2.micro", "t2.small", "t2.medium"], var.instance_type)
error_message = "Instance type must be t2.micro, t2.small, or t2.medium."
}
}
output "instance_id" {
description = "ID of the EC2 instance"
value = aws_instance.web.id
}
Prefer for_each over count for multiple named resources. Use count only for conditional creation (0 or 1). For the full decision guide and dynamic block patterns, see references/dynamic-resources.md.
# for_each — stable keys, safe to add/remove
resource "aws_instance" "web" {
for_each = toset(["web-1", "web-2", "web-3"])
instance_type = "t2.micro"
tags = { Name = each.key }
}
# count — conditional creation only
resource "aws_cloudwatch_metric_alarm" "cpu" {
count = var.enable_monitoring ? 1 : 0
alarm_name = "high-cpu-usage"
threshold = 80
}
Use modules to encapsulate reusable infrastructure. Pin registry modules with version, git modules with ref:
module "vpc" {
source = "hashicorp/vpc/aws"
version = "~> 5.0"
cidr_block = var.vpc_cidr
environment = var.environment
}
For module structure, naming, versioning, moved blocks, and input/output design, see references/modules.md.
Apply these defaults when generating code:
sensitive = truePin both Terraform and provider versions in terraform.tf:
terraform {
required_version = ">= 1.7"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
Constraint operators: = 1.0.0 (exact), >= 1.0.0 (minimum), ~> 1.0 (allow rightmost increment), >= 1.0, < 2.0 (range).
provider "aws" {
region = "us-west-2"
default_tags {
tags = {
ManagedBy = "Terraform"
Project = var.project_name
}
}
}
terraform plan -out=tfplan and review before applying saved planslifecycle { prevent_destroy = true } on critical stateful resourcesdepends_onFor anti-patterns, dependency cycle resolution, state backend configs, import/check blocks, and recovery commands, see references/error-prevention.md.
Run before every commit:
terraform fmt -recursive # Format
terraform validate # Syntax + type check
Additional tools: tflint (linting), checkov/tfsec (security scanning).
terraform fmtterraform validatetype and descriptiondescriptionsensitive = trueBased on: HashiCorp Terraform Style Guide
Search for places (restaurants, cafes, etc.) via Google Places API proxy on localhost.
Interact with GitHub using the `gh` CLI. Use `gh issue`, `gh pr`, `gh run`, and `gh api` for issues, PRs, CI runs, and advanced queries.
Create or update AgentSkills. Use when designing, structuring, or packaging skills with scripts, references, and assets.
Start voice calls via the OpenClaw voice-call plugin.
Notion API for creating and managing pages, databases, and blocks.
Gemini CLI for one-shot Q&A, summaries, and generation.
Category:developer