# Terraform — Claude Code rules Follow the official HashiCorp Terraform Style Guide. These conventions keep configuration readable, reviewable, and safe to apply. ## Formatting - Run `terraform fmt` and `terraform validate` before committing. Use `terraform fmt -recursive` to 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` — `terraform` block with `required_version` and `required_providers`. - `providers.tf` — provider blocks (default provider first). - `backend.tf` — backend configuration. - `main.tf` — resources and data sources. - `variables.tf` — `variable` blocks, alphabetical. - `outputs.tf` — `output` blocks, alphabetical. - `locals.tf` — local values referenced across files. - For larger codebases, split `main.tf` by 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--`. Store local modules in `./modules/`. ## 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 `type` and `description` for 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 `validation` only 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: 1. `count` / `for_each` meta-argument 2. non-block parameters 3. block parameters 4. `lifecycle` block (if needed) 5. `depends_on` (if needed) - Use `count` for near-identical resources; use `for_each` when values can't be derived from an integer. Use both in moderation and comment non-obvious effects. ## Versions & dependencies - Set `required_version` in the `terraform` block. - Pin providers in `required_providers` with explicit version constraints. - Pin modules to specific major and minor versions. - Commit the `.terraform.lock.hcl` dependency lock file. ## Don't - Don't commit `*.tfstate` / `*.tfstate.*`, `.terraform/`, `.terraform.tfstate.lock.info`, saved plan files, or `*.tfvars` with 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.