Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Design reusable Terraform modules with variable validation, output schemas, module composition, and testing (Terratest).
.claude/skills/williamzujkowski-terraform-module-best-practices/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-03 | ✗→✓ | ▲ Improved | 27% | 0% |
| case-01 | ✗→✓ | ▲ Improved | -1% | 0% |
| case-02 | ✗→✓ | ▲ Improved | 121% | 0% |
| case-05 | ✗→✓ | ▲ Improved | 43% | 0% |
| case-14 | ✗→✓ | ▲ Improved | 690% | 0% |
Use when designing reusable Terraform modules that require:
Trigger conditions:
NOW_ET to ISO 8601 in America/New_York using NIST/time.gov semantics: 2025-10-26T02:31:29-0400module_type is one of: network, compute, database, composite>= 1.0 for validation features terraform-<name>/ main.tf # Primary resources variables.tf # Input variables with validation outputs.tf # Output values with descriptions versions.tf # Provider version constraints README.md # Usage documentation examples/ # Usage examples basic/ tests/ # Terratest tests
variables.tf with validation:type constraints (string, number, bool, list, map, object, set, tuple, any)validation blocks for business logic constraintsdescription and default where appropriatesensitive = true for secretsoutputs.tf with clear contracts:description for all outputssensitive = trueversions.tf:required_version = ">= 1.5"~> for minor updatesdata sources for discovery/lookupsfor_each with maps for dynamic resourcesterraform-<PROVIDER>-<NAME>v1.0.0README.md with inputs/outputs tablesLICENSE file (Apache-2.0, MIT, etc.)go get github.com/gruntwork-io/terratest/modules/terraformterraform.InitAndApply(t, terraformOptions)defer terraform.Destroy(t, terraformOptions)terraform fmt -check, terraform validatetfsec, checkov, terrascanterraform-docsterraform fmt -recursiveterraform validateterraform-docs markdown table --output-file README.mdtfsec .module_type == "composite" → require Tier 2 composition patternstesting_required == true → require Tier 3 Terratest implementationobject type for groupingmodule_structure:
json{ "root": ["main.tf", "variables.tf", "outputs.tf", "versions.tf", "README.md"], "examples": ["basic", "complete"], "tests": ["<module_name>_test.go"], "docs": ["README.md", "CHANGELOG.md"] }
variables_tf: String containing Terraform variable definitions with:
type constraintdescription fieldvalidation blocks where applicabledefault values for optional inputssensitive flag for secretsoutputs_tf: String containing output definitions with:
description for each outputsensitive flag where neededtest_code: Go test file using Terratest framework with:
examples: Directory structure with runnable examples:
examples/basic/main.tf — minimal configurationexamples/complete/main.tf — all features enabledREADME.md explaining usageExample (≤30 lines): AWS VPC Module with Validation
hcl# variables.tf variable "vpc_cidr" { type = string description = "CIDR block for VPC" validation { condition = can(cidrhost(var.vpc_cidr, 0)) error_message = "Must be valid IPv4 CIDR block." } } variable "subnet_count" { type = number description = "Number of subnets to create" validation { condition = var.subnet_count >= 2 && var.subnet_count <= 16 error_message = "Subnet count must be between 2 and 16." } } # outputs.tf output "vpc_id" { description = "ID of the created VPC" value = aws_vpc.main.id } output "subnet_ids" { description = "List of subnet IDs" value = aws_subnet.main[*].id }
SKILL.md; full examples in examples/ directorydescription; validation rules for business logicdescription fieldsensitive flag; scan with tfsecversions.tfterraform fmt| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-21 | pass→pass | 11,588 | 6,172 | -47% | 1 | 1 | 0% | 2,394 | 3,708 | +55% | 0 | 0 | — |
case-03 | fail→pass | 22,108 | 19,066 | -14% | 1 | 1 | 0% | 5,456 | 6,926 | +27% | 0 | 0 | — |
case-20 | fail→fail | 15,535 | 9,909 | -36% | 1 | 1 | 0% | 3,359 | 4,431 | +32% | 0 | 0 | — |
case-01 | fail→pass | 21,671 | 13,445 | -38% | 1 | 1 | 0% | 5,397 | 5,350 | -1% | 0 | 0 | — |
case-02 | fail→pass | 9,566 | 12,142 | +27% | 1 | 1 | 0% | 2,310 | 5,113 | +121% | 0 | 0 | — |
case-04 | pass→pass | 8,652 | 8,154 | -6% | 1 | 1 | 0% | 1,739 | 4,117 | +137% | 0 | 0 | — |
case-05 | fail→pass | 12,856 | 7,054 | -45% | 1 | 1 | 0% | 2,624 | 3,752 | +43% | 0 | 0 | — |
case-06 | pass→pass | 9,736 | 5,957 | -39% | 1 | 1 | 0% | 1,923 | 3,565 | +85% | 0 | 0 | — |
case-07 | pass→pass | 9,741 | 7,129 | -27% | 1 | 1 | 0% | 1,813 | 3,654 | +102% | 0 | 0 | — |
case-08 | pass→pass | 6,240 | 4,615 | -26% | 1 | 1 | 0% | 1,140 | 3,083 | +170% | 0 | 0 | — |
case-09 | pass→pass | 9,071 | 6,174 | -32% | 1 | 1 | 0% | 1,830 | 3,463 | +89% | 0 | 0 | — |
case-10 | pass→pass | 3,237 | 2,687 | -17% | 1 | 1 | 0% | 545 | 2,751 | +405% | 0 | 0 | — |
case-11 | pass→pass | 7,873 | 3,253 | -59% | 1 | 1 | 0% | 1,397 | 2,888 | +107% | 0 | 0 | — |
case-12 | pass→pass | 7,162 | 4,012 | -44% | 1 | 1 | 0% | 1,492 | 3,098 | +108% | 0 | 0 | — |
case-13 | pass→pass | 10,313 | 4,850 | -53% | 1 | 1 | 0% | 1,889 | 3,186 | +69% | 0 | 0 | — |
case-14 | fail→pass | 1,966 | 1,329 | -32% | 1 | 1 | 0% | 315 | 2,489 | +690% | 0 | 0 | — |
case-15 | pass→pass | 3,238 | 2,059 | -36% | 1 | 1 | 0% | 694 | 2,696 | +288% | 0 | 0 | — |
case-16 | pass→pass | 5,176 | 2,044 | -61% | 1 | 1 | 0% | 856 | 2,595 | +203% | 0 | 0 | — |
case-17 | pass→pass | 4,224 | 4,111 | -3% | 1 | 1 | 0% | 804 | 3,039 | +278% | 0 | 0 | — |
case-18 | pass→pass | 6,982 | 5,386 | -23% | 1 | 1 | 0% | 1,277 | 3,198 | +150% | 0 | 0 | — |
case-19 | pass→pass | 4,921 | 4,512 | -8% | 1 | 1 | 0% | 981 | 3,239 | +230% | 0 | 0 | — |
case-22 | fail→fail | 14,741 | 14,236 | -3% | 1 | 1 | 0% | 2,877 | 5,338 | +86% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of +23 percentage points is the difference between those two pass rates over the 22 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.