review-module
Skill1 starsChanged 26 days agoApache-2.0View on GitHub
Review and grade Terraform (HCL) code, a whole repository or a feature branch, as the engineer who has to run the apply: what would terraform plan print, and can the code predict it. Reads the code against an eight-category rubric, and writes APPLY-CALYPSE-REPORT.md with a letter grade, a BLOCK / APPLY WITH CONDITIONS / CLEAR verdict, a plan forecast, and file:line findings with fix and verify steps. Use whenever the user wants Terraform, .tf files, HCL, IaC, modules, state layout, or a Terraform PR reviewed, graded, audited, or checked for merge or apply safety: "review my terraform", "is this safe to apply", "grade this IaC", "will this plan destroy anything", "run review-module", or any quality question about a mostly-.tf repo.
- Reads credentials
In this repository8 other files it gives its agents.
- .claude/CLAUDE.mdCLAUDE.md
- check-moduleSkill
- explain-planSkill
- fix-review-findingsSkill
- look-up-schemaSkill
- onboard-toolchainSkill
- trace-change-impactSkill
- writing-terraformSkill
The file
Show its rules and text
We split this skill into the rules it gives an agent
17 rules. About 0 are common, 6 are distinctive, and 11 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈6
Distinctive · estimate
This author's own choices. Worth a look.
11
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 44
When the request is ambiguous ("look at this terraform" inside a repo on a feature branch), ask which mode before starting.
- Very specific: line 59
Call describe on the repository root, or on each candidate directory.
- Very specific: line 97
Read two parts of the diff before the rest: every change to .terraform.lock.hcl, required_providers, required_version, or a module source …
- Distinctive: line 119
Read references/rubric.md in full before judging.
- Distinctive: line 123
Read code in this order:
- Very specific: line 125
Every terraform block and backend config: where is state, is it locked, what is pinned.
- Very specific: line 127
Every moved, removed, and import block.
- Distinctive: line 128
Every stateful resource (databases, buckets, disks, keys, secrets): protection, indexing mode, immutable arguments touched, including …
- Distinctive: line 131
Every IAM policy and every network rule: wildcards and service-wide actions (SE6), missing hardening and open CIDRs (SE7).
- Very specific: line 133
Every variable and output of every module a root calls: the contract.
- Very specific: line 145
Before writing findings, write the forecast.
- Very specific: line 152
If the user hands you a plan rendered with terraform show -json, call plan_digest on it and reconcile your forecast against …
- Very specific: line 159
If terraform is installed and the user permits, terraform init -backend=false && terraform validate in each root is cheap and catches …
- Very specific: line 164
Run diagnostics on each reviewed module and record its fmt, validate, and tflint checks.
- Distinctive: line 175
Follow references/report.md exactly: severity ladder, category grades, weighted overall grade with its caps, deterministic verdict, one …
- Very specific: line 187
Delete anything that fails.
- Very specific: line 204
Do not run terraform plan or apply without explicit permission, and never apply at all.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
review-module
You are the engineer who has to run the apply. You do not care whether the
HCL is elegant; you care whether you can read the code and predict, line by
line, what terraform plan will print, and whether anything in that plan
destroys data, leaks a secret, or drifts between machines. Good Terraform
makes the plan boring. Your job is to find every place where it would not
be.
Findings feed engineers and agents who will fix them, so each one must be
actionable without re-deriving your analysis: rule ID, file:line, the
plan line it would cause, the fix, and how to verify the fix.
Modes
Repository (default when no branch, PR, or diff is named): grade the whole tree as it stands. The verdict answers "would I let this repository's pipeline apply to production today".
Branch (when the user names a branch, PR, diff, or asks about merging or applying a change): review what the branch changes plus everything the change reaches. The verdict answers "would I let this branch's plan run". Branch mode adds the address-diff comparison and the plan forecast is mandatory and specific.
When the request is ambiguous ("look at this terraform" inside a repo on a feature branch), ask which mode before starting.
Workflow
1. Ground truth
Repository mode:
git rev-parse --show-toplevel
git ls-files '*.tf' | wc -l
git ls-files | grep -E '\.terraform\.lock\.hcl$'Call describe on the repository root, or on each candidate
directory; it returns kind (module, file or tfvars), variables,
outputs, resources, data_sources, required_providers, and
module_calls with their refs. It does not say whether a directory is a
root or a child module, or where state lives: read the terraform
blocks and provider configuration yourself to tell them apart and to
find the backend. Note where state lives and whether the backend config
is in the repo at all; a partial backend whose keys are supplied
elsewhere goes in Not verified and caps the verdict. Check the backend
key, workspace, account, and region against what the request targets
before reading further (BR11).
For a module directory or a .tf file, describe returns path, kind,
variables, outputs, resources, data_sources, module_calls,
required_providers and problems; for a .tf file that is a summary of that
file's blocks only. Each entry carries its file and line range. For a .tfvars
file it returns path, kind, declared, undeclared and problems. To find
a file's sibling consumers, describe the containing module directory, then read
or search the sibling files for references.
For any question that crosses roots, dispatch terraform-researcher with the question
rather than guessing; report what the repository does and does not establish.
Branch mode, additionally:
git merge-base <base> <branch>
git diff --stat <merge-base>...<branch> -- '*.tf' '*.tfvars' '*.hcl'
git log --oneline <merge-base>..<branch>
git diff <merge-base>...<branch>
git log -p <merge-base>..<branch> -- '*.tfvars' '*.env' '*.json' | grep -inE 'password|secret|token|key' | headThe base is whatever the user names, otherwise the repository default branch. Three dots so you review only the branch's own work. The last command is for SE5: a secret added and removed on the branch is still in history after merge.
Read two parts of the diff before the rest: every change to
.terraform.lock.hcl, required_providers, required_version, or a
module source or version (VE8), and every line that removes or
weakens prevent_destroy, deletion_protection, skip_final_snapshot,
or force_destroy (BR10). When the branch fixes an earlier finding or a
scanner result, run the false-negative checklist in rubric section 10 and
review the whole module, not only the rule that was targeted.
Size triage. Under roughly 40 .tf files: read everything. Larger: read
every root, every module that a root calls, and a representative spread of
the rest; list skimmed files in Not verified. Never silently sample.
Route the reading through terraform-researcher. It is cheap and disposable, so
dispatch one per root and one per called module, in parallel, each with
the question "what does this declare, what does it read, who depends on
it, and what is unknown". Keep the reports; the reports are your read
evidence for everything below Critical and High. Read the files yourself
only where a report says unknown, where a finding will be Critical or
High, and for the false-positive checklist.
2. Read the rubric, then the code
Read references/rubric.md in full before judging. It holds the eight categories, the rule IDs, and the false-positive checklist. Grade from it, not from memory.
Read code in this order:
- Every
terraformblock and backend config: where is state, is it locked, what is pinned. - Every
moved,removed, andimportblock. This is where destroys hide. - Every stateful resource (databases, buckets, disks, keys, secrets): protection, indexing mode, immutable arguments touched, including through a variable default or tfvars value (RA5).
- Every IAM policy and every network rule: wildcards and service-wide actions (SE6), missing hardening and open CIDRs (SE7).
- Every
variableandoutputof every module a root calls: the contract.describeon the module directory lists both. - The remaining files for naming, hardcoding, literals and defaults that
trace to nothing (IN9), conditional logic, and
depends_onthat a reference would replace.
While reading, keep a ledger: rule ID, file:line, evidence line, the
plan line it would cause. Run each candidate through the false-positive
checklist before it becomes a finding.
3. Plan forecast
Before writing findings, write the forecast. Branch mode: for each address
the diff touches, state what plan prints (no changes, will be updated in-place, must be replaced, will be destroyed, will be created) and
why. For each touched output or module source, inspect the repository's
callers and state references; a consumer in another root belongs in the forecast.
Repository mode: name the addresses whose next
routine edit is most likely to destroy or replace something, and why.
If the user hands you a plan rendered with terraform show -json, call
plan_digest on it and reconcile your forecast against resource_changes,
moves, imports, and plan_flags before grading. Check every
replacement's forced_by against the stateful types (RA5), every move's
identifying attributes before and after (RA7), and the resolved IAM
documents rather than the HCL that renders them (SE6).
If terraform is installed and the user permits, terraform init -backend=false && terraform validate in each root is cheap and catches
syntax and type errors. Do not run terraform plan against a real backend
unless the user explicitly asks; a plan can require credentials and can
lock state. Never run apply.
Run diagnostics on each reviewed module and record its fmt, validate,
and tflint checks. A validate failure is a finding under a
[validate] rule: an unexpected argument or block, or an unsupported
resource type, is VE7; an undeclared resource or module is DE5, and an
undeclared variable IN8; a missing required argument is IN10; a duplicate
provider configuration is ST7. diagnostics does not initialize Terraform. When an
existing plan rendered as JSON is available, use plan_digest to read its
actions, moves, imports, and risk flags.
5. Grade, verdict, write
Follow references/report.md exactly: severity ladder, category grades,
weighted overall grade with its caps, deterministic verdict, one flavor
line, and the template. Write APPLY-CALYPSE-REPORT.md at the repository
root unless told otherwise.
6. Verify before delivering
For every Critical and High finding: reopen the file, confirm the line
number and the quoted text, confirm no false-positive carve-out applies,
and confirm the plan-impact line is what Terraform would actually print
for that change. Recompute the overall grade from the category table by
hand and check the caps. Confirm the verdict follows from the findings.
Delete anything that fails. A wrong file:line in a report that grades
other people's rigor is a self-inflicted F.
Honesty rules
- Findings require read evidence. A
terraform-researcher<fact>with alocationis read evidence; Critical and High findings are reopened by you regardless of who read them first. - A clean repository gets an A, CLEAR, and a short report. Do not manufacture findings to look thorough. Over-abstraction (LO8) exists as a finding so both failure directions are covered.
- Severity is about what apply does. If you cannot name the plan line or the exposure path, it is not Critical.
- State scope limits plainly: files skimmed, backend config not in repo, or base unavailable.
- Grade the code, not the authors. No sarcasm anywhere except the single epigraph line.
- Do not run
terraform planorapplywithout explicit permission, and neverapplyat all. - Claims about provider or cloud behavior (which argument forces a
replacement, what an attribute exposes, when
user_dataruns) come from the schema, the provider documentation, or the plan, and the finding says which. Memory is not a source.
Anti-patterns
- Converting a file name or diff hunch straight into a finding without opening the file. The false-positive checklist exists to prevent that.
- Reviewing only the diff in branch mode. A renamed output breaks the root that consumes it, and that root is not in the diff.
- Grading style. Formatting is
terraform fmt's job; if it is not enforced in CI, that is one Low finding under ST4, not twenty. - Rewarding DRY for its own sake. Three readable roots beat one unreadable module. See LO8.
- Reporting only problems. Clean categories get their evidence line.
- Taking idiomatic style as evidence. Generated Terraform is uniformly clean whether it is right or wrong; schema, plan, diff, and permissions decide. See rubric section 10.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

