Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Module composition, state management, workspace strategy, provider versioning, and infrastructure-as-code best practices.
.claude/skills/terraform-patterns/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-12 | ✗→✓ | ▲ Improved | — | — |
| case-03 | ✓→✓ | = Same ✓ | — | — |
| case-01 | ✗→✗ | = Same ✗ | — | — |
| case-20 | ✗→✗ | = Same ✗ | — | — |
| case-08 | ✗→✗ | = Same ✗ | — | — |
Production Terraform patterns for maintainable infrastructure-as-code.
hcl# modules/vpc/main.tf - Reusable VPC module variable "name" { type = string description = "VPC name prefix" } variable "cidr" { type = string default = "10.0.0.0/16" } variable "azs" { type = list(string) default = ["us-east-1a", "us-east-1b", "us-east-1c"] } resource "aws_vpc" "main" { cidr_block = var.cidr enable_dns_hostnames = true enable_dns_support = true tags = { Name = var.name ManagedBy = "terraform" Environment = terraform.workspace } } resource "aws_subnet" "private" { count = length(var.azs) vpc_id = aws_vpc.main.id cidr_block = cidrsubnet(var.cidr, 8, count.index) availability_zone = var.azs[count.index] tags = { Name = "${var.name}-private-${var.azs[count.index]}" Tier = "private" } } output "vpc_id" { value = aws_vpc.main.id } output "private_subnet_ids" { value = aws_subnet.private[*.id] }
hcl# environments/production/main.tf terraform { required_version = ">= 1.5.0" required_providers { aws = { source = "hashicorp/aws" version = "~> 5.0" # Pin major version, allow minor updates } } backend "s3" { bucket = "mycompany-terraform-state" key = "production/terraform.tfstate" region = "us-east-1" dynamodb_table = "terraform-locks" # State locking encrypt = true } } module "vpc" { source = "../../modules/vpc" name = "prod" cidr = "10.0.0.0/16" azs = ["us-east-1a", "us-east-1b", "us-east-1c"] } module "database" { source = "../../modules/rds" vpc_id = module.vpc.vpc_id subnet_ids = module.vpc.private_subnet_ids instance_class = "db.r6g.xlarge" allocated_storage = 100 multi_az = true } module "app" { source = "../../modules/ecs-service" vpc_id = module.vpc.vpc_id subnet_ids = module.vpc.private_subnet_ids container_image = "myapp:${var.app_version}" desired_count = 3 cpu = 512 memory = 1024 environment_variables = { DATABASE_URL = module.database.connection_string LOG_LEVEL = "info" } }
hcl# Remote state data source: reference other state files safely data "terraform_remote_state" "networking" { backend = "s3" config = { bucket = "mycompany-terraform-state" key = "networking/terraform.tfstate" region = "us-east-1" } } # Use outputs from networking state module "app" { source = "../../modules/ecs-service" vpc_id = data.terraform_remote_state.networking.outputs.vpc_id subnet_ids = data.terraform_remote_state.networking.outputs.private_subnet_ids }
hclresource "aws_instance" "app" { ami = var.ami_id instance_type = var.instance_type lifecycle { # Create new before destroying old (zero-downtime replacement) create_before_destroy = true # Prevent accidental deletion of critical resources prevent_destroy = true # Ignore changes made outside Terraform (e.g., auto-scaling tags) ignore_changes = [tags["LastScaleEvent"]] } } # Import existing resources import { to = aws_s3_bucket.existing id = "my-existing-bucket-name" }
hclvariable "environment" { type = string description = "Deployment environment" validation { condition = contains(["development", "staging", "production"], var.environment) error_message = "Environment must be development, staging, or production." } } variable "instance_count" { type = number default = 2 validation { condition = var.instance_count >= 1 && var.instance_count <= 20 error_message = "Instance count must be between 1 and 20." } } # Local values for computed configuration locals { common_tags = { Environment = var.environment Project = var.project_name ManagedBy = "terraform" Team = var.team } is_production = var.environment == "production" replica_count = local.is_production ? 3 : 1 }
hcl# for_each over map (preferred over count for named resources) variable "services" { type = map(object({ port = number health_path = string replicas = number })) } resource "aws_ecs_service" "services" { for_each = var.services name = each.key cluster = aws_ecs_cluster.main.id desired_count = each.value.replicas task_definition = aws_ecs_task_definition.tasks[each.key].arn } # Dynamic block for security group rules resource "aws_security_group" "app" { name = "${var.name}-sg" vpc_id = var.vpc_id dynamic "ingress" { for_each = var.ingress_rules content { from_port = ingress.value.port to_port = ingress.value.port protocol = "tcp" cidr_blocks = ingress.value.cidr_blocks description = ingress.value.description } } }
~> (allow patch, lock major/minor)prevent_destroy on databases, S3 buckets, and IAM roleslocals applied to every resourcefor_each over count (survives reordering without recreation)terraform plan in CI, terraform apply requires approvalcount with lists: removing item N recreates items N+1 through end.tf files: use AWS Secrets Manager or Vault references| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-20 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-08 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-23 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-14 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-18 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-13 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-07 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-10 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-19 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-04 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-11 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-22 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-21 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-02 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-16 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-09 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-03 | pass→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-05 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-06 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-12 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-15 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-17 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-24 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-25 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 25 cases were attempted. The headline lift of +4 percentage points is the difference between those two pass rates over the 25 comparable cases.
The per-case answers from this run were removed by the retention sweep, so the case table below shows the verdicts without the text either arm produced. The counts above were recorded at the time and are unaffected. Answers are now kept for 180 days.
Other measured skills in the registry, with their headline benchmark lift.