Skip to content

Terraform and IaC Rules for Agents

Generic.mdCoding

Guardrails for agents touching Terraform: always plan before apply, module and state layout, what never to do to state files, and mandatory resource tagging.

Use when: Use in any repository containing Terraform when agents write or modify infrastructure code, so changes are planned and reviewed before apply and state is never put at risk.

@library0 upvotes0 remixes0 comments

Get this skill

Add the skill file with the CLI, by hand, or over MCP.

Save the file where your agent reads instructions.

npx goodprompts add terraform-infra-conventions
npx goodprompts add terraform-infra-conventions

Skill file

.md3,591 characters
# Terraform Conventions
Infrastructure changes are higher-stakes than application code: a wrong apply can delete data or take down production. Follow these rules without exception.
## Plan before apply — always
- Never run `terraform apply` without first running `terraform plan -out=tfplan` and reading the full plan output. Apply the saved plan (`terraform apply tfplan`), not a fresh one.
- Summarize the plan before applying: count of resources to add / change / destroy, and call out every **destroy** and every **replacement** (`-/+`) explicitly. Replacements of stateful resources (databases, volumes, buckets) require human confirmation — stop and ask.
- If the plan shows changes you did not make, stop. Someone or something has drifted the environment; investigate before layering your change on top.
- `terraform apply -auto-approve` is permitted only in CI pipelines that gate on a reviewed plan, never interactively.
- Run `terraform fmt -recursive` and `terraform validate` before every commit; CI also runs `tflint` and a policy check — fix findings, do not suppress them.
## Layout
```
modules/<name>/ # reusable building blocks: main.tf, variables.tf, outputs.tf, README.md
envs/dev/ # one root module per environment
envs/staging/
envs/prod/ # each env has its own backend config and tfvars
```
- Environments are separate root modules with **separate state** — never a single workspace switched with `terraform workspace` for prod vs dev, and never an `environment` variable that swaps behavior inside one state.
- Modules take explicit `variables.tf` inputs (typed, described, with `validation` blocks where cheap) and expose explicit `outputs.tf`. No module reaches into another module's resources.
- Pin versions: `required_version` for Terraform, version constraints for every provider, and a version/ref on every module source (`?ref=v1.4.0` for git sources). Renovate-style bumps come as their own PRs.
- No `provisioner` blocks and no `local-exec` escape hatches without sign-off — they are unmanaged side effects.
## State safety
- State lives in the remote backend with locking enabled. Never commit `.tfstate`, never copy state files around, never edit state JSON by hand.
- State surgery (`terraform state mv`, `state rm`, `import`) is a last resort: announce what you intend to run and why, get confirmation, and run `terraform plan` immediately afterwards to prove the result is a no-op.
- Renaming a resource in code? Use a `moved {}` block so Terraform tracks it, instead of letting it plan a destroy-and-create.
- Protect stateful resources with `lifecycle { prevent_destroy = true }` and deletion protection flags on the resource itself where the provider supports it.
- Secrets do not belong in state when avoidable: reference them from <your-secret-manager> via data sources instead of generating/storing them as plain resource attributes. Treat state itself as sensitive regardless.
## Tagging standard
Every taggable resource carries these tags (enforce via `default_tags` on the provider where supported, per-resource otherwise):
```hcl
tags = {
environment = var.environment # dev | staging | prod
service = "<service-name>"
owner = "<team-or-handle>"
managed-by = "terraform"
repo = "<org>/<repo>"
}
```
- `managed-by = "terraform"` is how humans know not to click-edit a resource in the console. Anything missing it is presumed unmanaged.
- Cost-allocation reports key on `service` and `environment`; an untagged resource is a billing mystery — do not create them.
Comments

Comments

Sign in to commentSign in

Remixes

Loading remixes…