Generate Terraform HCL code following HashiCorp's official style conventions and best practices. Use when writing, reviewing, or generating Terraform configurations.
Generates and formats Terraform HCL code following HashiCorp's official style conventions and best practices.
npx claudepluginhub jadecli/jadecli-claude-pluginsThis skill inherits all available tools. When active, it can use any tool Claude has access to.
Generate and maintain Terraform code following HashiCorp's official style conventions and best practices.
Reference: HashiCorp Terraform Style Guide
When 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 |
# terraform.tf
terraform {
required_version = ">= 1.7"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
# variables.tf
variable "environment" {
description = "Target deployment environment"
type = string
validation {
condition = contains(["dev", "staging", "prod"], var.environment)
error_message = "Environment must be dev, staging, or prod."
}
}
# locals.tf
locals {
common_tags = {
Environment = var.environment
ManagedBy = "Terraform"
}
}
# main.tf
resource "aws_vpc" "main" {
cidr_block = var.vpc_cidr
enable_dns_hostnames = true
tags = merge(local.common_tags, {
Name = "${var.project_name}-${var.environment}-vpc"
})
}
# outputs.tf
output "vpc_id" {
description = "ID of the created VPC"
value = aws_vpc.main.id
}
resource "aws_instance" "web" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
subnet_id = "subnet-12345678"
tags = {
Name = "web-server"
Environment = "production"
}
}
Arguments precede blocks, with meta-arguments first:
resource "aws_instance" "example" {
# Meta-arguments
count = 3
# Arguments
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
# Blocks
root_block_device {
volume_size = 20
}
# Lifecycle last
lifecycle {
create_before_destroy = true
}
}
# Bad
resource "aws_instance" "webAPI-aws-instance" {}
variable "name" {}
# Good
resource "aws_instance" "web_api" {}
variable "application_name" {}
Every variable must include type and description:
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."
}
}
variable "database_password" {
description = "Password for the database admin user"
type = string
sensitive = true
}
Every output must include description:
output "instance_id" {
description = "ID of the EC2 instance"
value = aws_instance.web.id
}
output "database_password" {
description = "Database administrator password"
value = aws_db_instance.main.password
sensitive = true
}
# Bad - count for multiple resources
resource "aws_instance" "web" {
count = var.instance_count
tags = { Name = "web-${count.index}" }
}
# Good - for_each with named instances
variable "instance_names" {
type = set(string)
default = ["web-1", "web-2", "web-3"]
}
resource "aws_instance" "web" {
for_each = var.instance_names
tags = { Name = each.key }
}
resource "aws_cloudwatch_metric_alarm" "cpu" {
count = var.enable_monitoring ? 1 : 0
alarm_name = "high-cpu-usage"
threshold = 80
}
When generating code, apply security hardening:
sensitive = trueresource "aws_s3_bucket" "data" {
bucket = "${var.project}-${var.environment}-data"
tags = local.common_tags
}
resource "aws_s3_bucket_versioning" "data" {
bucket = aws_s3_bucket.data.id
versioning_configuration {
status = "Enabled"
}
}
resource "aws_s3_bucket_server_side_encryption_configuration" "data" {
bucket = aws_s3_bucket.data.id
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "aws:kms"
kms_master_key_id = aws_kms_key.s3.arn
}
}
}
resource "aws_s3_bucket_public_access_block" "data" {
bucket = aws_s3_bucket.data.id
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}
terraform {
required_version = ">= 1.7"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0" # Allow minor updates
}
}
}
Version constraint operators:
= 1.0.0 - Exact version>= 1.0.0 - Greater than or equal~> 1.0 - Allow rightmost component to increment>= 1.0, < 2.0 - Version rangeprovider "aws" {
region = "us-west-2"
default_tags {
tags = {
ManagedBy = "Terraform"
Project = var.project_name
}
}
}
# Aliased provider for multi-region
provider "aws" {
alias = "east"
region = "us-east-1"
}
Never commit:
terraform.tfstate, terraform.tfstate.backup.terraform/ directory*.tfplan.tfvars files with sensitive dataAlways commit:
.tf configuration files.terraform.lock.hcl (dependency lock file)Run before committing:
terraform fmt -recursive
terraform validate
Additional tools:
tflint - Linting and best practicescheckov / tfsec - Security scanningterraform fmtterraform validatesensitive = trueBased on: HashiCorp Terraform Style Guide