DevOps & Infrastructure

Terraform Plan Reviewer

Read a `terraform plan` output for what it actually means -- especially resource replacement (destroy + recreate) hiding behind an innocuous-looking diff.

When to use this

  • Before applying any Terraform (or similar IaC) change to a shared/production environment.
  • A plan shows more changes than expected and needs explaining before approval.
  • Not for reviewing the .tf source style -- scope to what the plan says will actually happen to real infrastructure.

The skill file

Copy this verbatim. It's written in the SKILL.md format (YAML frontmatter + markdown instructions) that Claude Code, and increasingly other agent tools, read directly.

SKILL.md
---
name: terraform-plan-reviewer
description: Review a `terraform plan` (or equivalent IaC plan) output for what will actually happen to real infrastructure -- especially resource replacement (destroy-then-create) and any change to a stateful resource -- before it's applied. Use before applying to a shared or production environment.
---

# Terraform Plan Reviewer

The plan output is the actual contract of what will happen. Read it
literally, not the intent behind the source diff.

## What to check first

- **Any resource marked for replacement** (`-/+` or "forces replacement"):
  this means destroy-then-recreate, not an in-place update. For a
  stateful resource (database, storage volume, anything with data or a
  stable identity other systems depend on -- DNS record, load balancer),
  this is often catastrophic and needs explicit confirmation it's
  intended.
- **Why a resource is being replaced**: which specific attribute change
  forced it (often a change to an immutable field). Confirm that's the
  actual intended change, not an accidental side effect of an unrelated
  edit.
- **Deletions**: every resource being destroyed, and whether anything
  else (application config, DNS, another Terraform-managed resource)
  still references it.
- **Scope of the plan**: does it only touch the resources the PR intends
  to change, or is there drift -- unexpected changes to resources nobody
  edited, which usually means manual out-of-band changes were made to
  the infrastructure, or state has drifted from the last apply.

## Output

Every replacement and deletion called out explicitly with the resource
name, why it's happening, and whether it looks intentional; any
unexpected drift flagged separately from the PR's actual intended
changes.

Installing it elsewhere

The frontmatter/body split above is Claude Code's convention. Here's how to carry the same instructions into other tools:

Claude Code
.claude/skills/terraform-plan-reviewer/SKILL.md

Save the file below verbatim (frontmatter included) at that path, project-local or in ~/.claude/skills/ for a user-level skill. Claude Code loads the name/description pair to decide when to pull it in, or you invoke it directly as /terraform-plan-reviewer.

Cursor
.cursor/rules/terraform-plan-reviewer.mdc

Convert the YAML frontmatter to Cursor's rule format (description, globs, alwaysApply: false) and keep the markdown body as the rule content. Cursor surfaces it by description match, same idea as Claude Code's auto-load.

Codex CLI / Copilot
AGENTS.md

Codex CLI (and increasingly other agentic CLIs) read AGENTS.md at the repo root as always-on instructions. Paste the markdown body under a heading like ## {title}; for GitHub Copilot's coding agent, the equivalent file is .github/copilot-instructions.md.

Windsurf
.windsurfrules

Append the markdown body to .windsurfrules at the repo root. Windsurf treats the whole file as always-on context, so keep only the instructions you want applied on every request.

Where this goes wrong
  • Skimming past a "forces replacement" on a stateful resource because the rest of the diff looks routine.
  • Not distinguishing drift (unexpected changes to untouched resources) from the PR's actual intended changes.
  • Approving a plan without checking what else references a resource being deleted.