Terraform — Claude Code rules
Follow the official HashiCorp Terraform Style Guide. These conventions keep configuration readable, reviewable, and safe to apply.
Formatting
- Run
terraform fmtandterraform validatebefore committing. Useterraform fmt -recursiveto format subdirectories. - Indent two spaces per nesting level.
- Align the
=signs when consecutive single-line arguments sit at the same level. - Use
#for both single- and multi-line comments. Avoid//and/* */. - Separate top-level blocks with one blank line; group logically related arguments with blank lines.
File & module structure
- Use the standard file layout so maintainers know where to look:
terraform.tf—terraformblock withrequired_versionandrequired_providers.providers.tf— provider blocks (default provider first).backend.tf— backend configuration.main.tf— resources and data sources.variables.tf—variableblocks, alphabetical.outputs.tf—outputblocks, alphabetical.locals.tf— local values referenced across files.
- For larger codebases, split
main.tfby logical group (network.tf,compute.tf,storage.tf). - Create a module only when it introduces a new abstraction. Don't write thin wrappers around a single resource type. Keep the module tree flat and prefer composition over deep nesting.
- Name module repositories
terraform-<PROVIDER>-<NAME>. Store local modules in./modules/<name>.
Naming
- Use descriptive nouns with underscores:
snake_case. - Do NOT include the resource type in the resource name — the address already
has it:
resource "aws_instance" "web_api", not"web_api_instance". - Order resources for readability. Define data sources before the resources that reference them.
Variables & outputs
- Define a
typeanddescriptionfor every variable and output. - Give optional variables a reasonable
default. - Mark passwords and private keys
sensitive = true(note: still stored plaintext in state). - Use input variable
validationonly for uniquely restrictive requirements. - Don't hardcode values that vary by environment — use variables or locals.
- Avoid overusing variables and local values; use locals sparingly.
Resource arguments
- Recommended argument order inside a resource:
count/for_eachmeta-argument- non-block parameters
- block parameters
lifecycleblock (if needed)depends_on(if needed)
- Use
countfor near-identical resources; usefor_eachwhen values can't be derived from an integer. Use both in moderation and comment non-obvious effects.
Versions & dependencies
- Set
required_versionin theterraformblock. - Pin providers in
required_providerswith explicit version constraints. - Pin modules to specific major and minor versions.
- Commit the
.terraform.lock.hcldependency lock file.
Don't
- Don't commit
*.tfstate/*.tfstate.*,.terraform/,.terraform.tfstate.lock.info, saved plan files, or*.tfvarswith secrets. - Don't store secrets in code — use env vars, Vault, or your CI secret store.
- Don't include the resource type in resource/output names.
- Don't use
//or/* */comments.