Agent skill
terraform-style-guide
Write and review OpenTofu-first HCL using current style conventions and safe infrastructure patterns. Use whenever editing Terraform or OpenTofu configuration, modules, variables, outputs, providers, or imports. Prefer OpenTofu commands and OpenTofu documentation unless the user explicitly needs Terraform-only behavior.
Install this agent skill to your Project
npx add-skill https://github.com/ederheisler/agent-skills/tree/main/skills/terraform-style-guide
Metadata
Additional technical details for this skill
- version
- 2.0
SKILL.md
OpenTofu Style Guide
Write HCL that is correct, readable, and OpenTofu-first.
In this repository, OpenTofu is the default runtime. Command examples, validation steps, and workflow choices should therefore use tofu, not terraform, unless the user explicitly asks for Terraform.
Runtime Defaults
- Run infrastructure commands from
terraform/, not from the repository root. - Prefer these commands for verification:
cd terraform
tofu fmt -recursive
tofu validate
tofu plan -var-file=terraform.tfvars
- Treat OpenTofu documentation as the primary reference for language and CLI behavior.
- Keep HCL broadly Terraform-compatible unless the task specifically benefits from an OpenTofu-only feature.
Repository Layout
Follow the repository's existing file structure instead of imposing a generic layout.
For this repo, the expected root layout is:
providers.tfforterraform {}version/provider requirements and provider configurationmain.tffor root wiring and normalizationvariables.tffor input schema and validationoutputs.tffor exported values- modules under
terraform/modules/*
If a file already exists for a concern, extend that file instead of creating a parallel convention.
Style Rules
Formatting
- Use two spaces per nesting level.
- Let
tofu fmtdefine the final formatting. - Keep consecutive single-line assignments aligned when
tofu fmtpreserves alignment.
resource "oci_core_instance" "api" {
availability_domain = var.availability_domain
compartment_id = var.compartment_id
display_name = var.display_name
shape = var.shape
}
Block Ordering
- Put meta-arguments first.
- Put regular arguments next.
- Put nested blocks after arguments, separated by a blank line when that improves readability.
- Put lifecycle and other meta-argument blocks last.
resource "oci_core_instance" "api" {
for_each = var.instances
availability_domain = each.value.availability_domain
compartment_id = each.value.compartment_id
display_name = each.value.display_name
shape = each.value.shape
source_details {
source_type = "image"
source_id = each.value.image_id
}
lifecycle {
create_before_destroy = true
}
}
Naming
- Use lowercase with underscores for variables, locals, outputs, and resource labels.
- Use descriptive singular labels.
- Avoid redundant labels like
instance_instanceorserver_resource. - Use stable, intention-revealing names such as
network,server,public_ip,shape_profiles, ornormalized_servers.
Modeling Guidance
Prefer explicit data flow
- Normalize user input in
localsbefore feeding modules. - Pass resolved values into modules instead of repeating fallback logic in many places.
- Keep raw provider IDs centralized when the repo already follows that pattern.
In this repo specifically:
project_nameis a global name prefix.serversis the map of real server definitions.server_defaultsholds values shared by most servers.compartmentsandcompartment_ocidsshould centralize compartment selection instead of scattering raw OCIDs across resources.
Prefer for_each over count
Use for_each when instances have meaningful keys or when stable addressing matters.
module "server" {
for_each = local.normalized_servers
source = "./modules/server"
project_name = var.project_name
server_name = each.key
compute_compartment_id = each.value.compartment_ocid
}
Use count mainly for simple on/off creation where identity is unimportant.
Variables and outputs
- Every variable should have a clear
descriptionand explicittype. - Add validation when a bad value would otherwise fail late or obscurely.
- Every output should have a
description. - Mark sensitive data as
sensitive = true.
variable "shape_profile" {
description = "Logical shape profile name resolved through shape_profiles."
type = string
validation {
condition = contains(keys(var.shape_profiles), var.shape_profile)
error_message = "shape_profile must reference a key in shape_profiles."
}
}
Security and Safety
- Never hardcode credentials, private keys, tokens, or tenancy secrets.
- Prefer variables for sensitive inputs and mark them sensitive when appropriate.
- Avoid unnecessary public exposure in generated infrastructure.
- Keep imports, state moves, and destructive changes explicit in plans.
Imports and Existing Infrastructure
When adopting existing resources:
- Write the target resource block at its final address first.
- Prefer config-driven
importblocks when the workflow is going into version control. - Use
tofu importonly when a one-off state attachment is more practical than keeping import blocks in code.
What to avoid
- Do not introduce Terraform-only CLI guidance into this repo unless the user asks for it.
- Do not create new top-level conventions that fight the existing repository structure.
- Do not duplicate fallback logic across modules when a single normalized local can own it.
- Do not leave generated or imported configuration full of computed-only attributes.
Completion Checklist
Before finishing a change to OpenTofu code in this repository:
- Run
tofu fmt -recursivefromterraform/. - Run
tofu validatefromterraform/. - If inputs or resource wiring changed materially, run
tofu plan -var-file=terraform.tfvarswhen local credentials and tfvars are available.
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
brainstorming
You MUST use this before any creative work - creating features, building components, adding functionality, or modifying behavior. Explores user intent, requirements and design before implementation.
test-driven-development
Use when implementing any feature or bugfix, before writing implementation code
fastapi
Build Python APIs with FastAPI, Pydantic v2, and SQLAlchemy 2.0 async. Covers project structure, JWT auth, validation, and database integration with uv package manager. Prevents 7 documented errors. Use when: creating Python APIs, implementing JWT auth, or troubleshooting 422 validation, CORS, async blocking, form data, background tasks, or OpenAPI schema errors.
documentation-generation
You are a documentation expert specializing in creating comprehensive, maintainable documentation from code. Generate API docs, architecture diagrams, user guides, and technical references using AI...
session-behavior
mcp-builder
Guide for creating high-quality MCP (Model Context Protocol) servers that enable LLMs to interact with external services through well-designed tools. Use when building MCP servers to integrate external APIs or services, whether in Python (FastMCP) or Node/TypeScript (MCP SDK).
Didn't find tool you were looking for?