terraform-module-scaffold
Create production-ready, reusable Terraform modules with complete documentation, examples, and tests
Best use case
terraform-module-scaffold is best used when you need a repeatable AI agent workflow instead of a one-off prompt.
Create production-ready, reusable Terraform modules with complete documentation, examples, and tests
Teams using terraform-module-scaffold should expect a more consistent output, faster repeated execution, less prompt rewriting.
When to use this skill
- You want a reusable workflow that can be run more than once with consistent structure.
When not to use this skill
- You only need a quick one-off answer and do not need a reusable workflow.
- You cannot install or maintain the underlying files, dependencies, or repository context.
Installation
Claude Code / Cursor / Codex
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/terraform-module-scaffold/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How terraform-module-scaffold Compares
| Feature / Agent | terraform-module-scaffold | Standard Approach |
|---|---|---|
| Platform Support | Not specified | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/A |
Frequently Asked Questions
What does this skill do?
Create production-ready, reusable Terraform modules with complete documentation, examples, and tests
Where can I find the source code?
You can find the source code on GitHub using the link provided at the top of the page.
SKILL.md Source
# Terraform Module Scaffold
You are a Terraform module development expert. When this skill is invoked, you help users create complete, production-ready Terraform modules following HashiCorp best practices and community standards.
## Your Task
When a user requests a new Terraform module:
1. **Gather Requirements**:
- Module purpose and description
- Provider (azurerm, aws, google, etc.)
- Resources to encapsulate
- Input variables needed
- Outputs to expose
2. **Generate Module Structure**:
```
terraform-{module-name}/
├── main.tf # Main resource definitions
├── variables.tf # Input variable declarations
├── outputs.tf # Output value declarations
├── versions.tf # Terraform and provider version constraints
├── README.md # Complete module documentation
├── examples/
│ └── basic/
│ ├── main.tf # Example usage
│ └── README.md # Example documentation
├── tests/ # Optional: automated tests
│ └── basic_test.go
└── .gitignore
```
3. **Follow Module Best Practices**:
- Single responsibility principle
- Flexible and configurable
- Sensible defaults
- Comprehensive validation
- Clear documentation
- Working examples
## Module File Templates
### versions.tf
```hcl
terraform {
required_version = ">= 1.6"
required_providers {
{provider} = {
source = "hashicorp/{provider}"
version = ">= {min_version}"
}
}
}
```
### variables.tf
Follow this pattern for all variables:
```hcl
variable "name" {
description = "Clear description of what this variable does"
type = string
validation {
condition = length(var.name) >= 3 && length(var.name) <= 24
error_message = "Name must be between 3 and 24 characters."
}
}
variable "location" {
description = "Azure region where resources will be created"
type = string
}
variable "resource_group_name" {
description = "Name of the resource group"
type = string
}
variable "tags" {
description = "Tags to apply to all resources"
type = map(string)
default = {}
}
variable "enable_feature" {
description = "Whether to enable optional feature"
type = bool
default = false
}
```
### outputs.tf
Always include:
- Resource IDs
- Resource names
- Important attributes
- Helpful descriptions
```hcl
output "id" {
description = "ID of the {resource}"
value = azurerm_{resource}.main.id
}
output "name" {
description = "Name of the {resource}"
value = azurerm_{resource}.main.name
}
output "resource" {
description = "Full {resource} object for advanced use cases"
value = azurerm_{resource}.main
}
```
### main.tf
Structure resources logically:
```hcl
# Local values for computed/combined variables
locals {
# Combine tags with defaults
tags = merge(
{
Module = "terraform-{module-name}"
ManagedBy = "Terraform"
},
var.tags
)
# Resource naming
name = var.name_override != null ? var.name_override : "${var.project}-${var.environment}-${var.name_suffix}"
}
# Main resource(s)
resource "azurerm_{resource}" "main" {
name = local.name
location = var.location
resource_group_name = var.resource_group_name
# Required arguments
required_arg = var.required_arg
# Optional features
dynamic "optional_block" {
for_each = var.enable_feature ? [1] : []
content {
# Block configuration
}
}
tags = local.tags
}
# Supporting resources
resource "azurerm_{supporting_resource}" "support" {
count = var.create_supporting_resource ? 1 : 0
name = "${azurerm_{resource}.main.name}-support"
# ...
}
```
### README.md
Create comprehensive documentation:
```markdown
# Terraform Module: {Module Name}
{Brief description of what this module does}
## Features
- Feature 1
- Feature 2
- Feature 3
## Usage
### Basic Example
```hcl
module "{module_name}" {
source = "path/to/module"
name = "my-resource"
location = "eastus"
resource_group_name = "my-rg"
tags = {
Environment = "Production"
}
}
```
### Advanced Example
```hcl
module "{module_name}" {
source = "path/to/module"
name = "my-resource"
location = "eastus"
resource_group_name = "my-rg"
enable_feature = true
additional_config = "value"
tags = {
Environment = "Production"
}
}
```
## Requirements
| Name | Version |
|------|---------|
| terraform | >= 1.6 |
| {provider} | >= {version} |
## Providers
| Name | Version |
|------|---------|
| {provider} | >= {version} |
## Resources
| Name | Type |
|------|------|
| {resource_type}.{name} | resource |
## Inputs
| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| name | Name of the resource | `string` | n/a | yes |
| location | Azure region | `string` | n/a | yes |
| tags | Resource tags | `map(string)` | `{}` | no |
## Outputs
| Name | Description |
|------|-------------|
| id | Resource ID |
| name | Resource name |
## Examples
See the [examples](./examples/) directory for complete examples.
## Contributing
Contributions are welcome! Please see [CONTRIBUTING.md](CONTRIBUTING.md).
## License
[License Type]
```
### examples/basic/main.tf
```hcl
terraform {
required_version = ">= 1.6"
}
# Example resource group (in real use, this might already exist)
resource "azurerm_resource_group" "example" {
name = "rg-example"
location = "eastus"
}
# Module usage
module "example" {
source = "../.." # Points to root of module
name = "example-resource"
location = azurerm_resource_group.example.location
resource_group_name = azurerm_resource_group.example.name
tags = {
Environment = "Example"
Purpose = "Testing"
}
}
# Outputs to verify
output "resource_id" {
value = module.example.id
}
```
### examples/basic/README.md
```markdown
# Basic Example
This example demonstrates the basic usage of the {module-name} module.
## Usage
1. Update the variables in this file as needed
2. Run:
```bash
terraform init
terraform plan
terraform apply
```
## What This Creates
- Resource group (for example purposes)
- {Main resource}
## Cleanup
```bash
terraform destroy
```
```
## Module Design Principles
### 1. Single Responsibility
Each module should do ONE thing well.
**Good**: `terraform-azurerm-virtual-network` creates a VNet
**Bad**: `terraform-azurerm-infrastructure` creates VNet, VMs, databases, etc.
### 2. Sensible Defaults
Provide defaults for optional variables:
```hcl
variable "enable_https" {
description = "Enable HTTPS"
type = bool
default = true # Secure by default
}
```
### 3. Validation
Validate inputs to fail fast:
```hcl
variable "environment" {
type = string
validation {
condition = contains(["dev", "staging", "prod"], var.environment)
error_message = "Environment must be dev, staging, or prod."
}
}
```
### 4. Flexibility
Use `dynamic` blocks for optional features:
```hcl
dynamic "network_rules" {
for_each = var.network_rules != null ? [var.network_rules] : []
content {
default_action = network_rules.value.default_action
# ...
}
}
```
### 5. Output Everything Important
Users might need any attribute:
```hcl
output "resource" {
description = "Complete resource object"
value = azurerm_resource.main
}
```
## Common Module Patterns
### Optional Resource Creation
```hcl
resource "azurerm_resource" "optional" {
count = var.create_resource ? 1 : 0
# ...
}
output "resource_id" {
value = var.create_resource ? azurerm_resource.optional[0].id : null
}
```
### Multiple Instances
```hcl
resource "azurerm_resource" "multiple" {
for_each = var.instances
name = each.key
# Use each.value for configuration
}
```
### Conditional Configuration
```hcl
resource "azurerm_resource" "main" {
name = var.name
sku_name = var.environment == "prod" ? "Premium" : "Standard"
}
```
## Module Naming Convention
Follow this pattern:
- `terraform-{provider}-{resource}`
- Examples:
- `terraform-azurerm-virtual-network`
- `terraform-aws-vpc`
- `terraform-google-compute-network`
## Variable Naming
- Use descriptive names: `storage_account_name` not `san`
- Group related variables: `network_*`, `security_*`
- Boolean variables: `enable_*`, `create_*`, `use_*`
## Script Integration
If `scripts/scaffold-module.js` exists, use it:
```bash
node scripts/scaffold-module.js \
--name virtual-network \
--provider azurerm \
--description "Create and manage Azure Virtual Networks" \
--output ./modules
```
## Testing (Optional)
For critical modules, add automated tests using Terratest:
```go
package test
import (
"testing"
"github.com/gruntwork-io/terratest/modules/terraform"
)
func TestBasicExample(t *testing.T) {
terraformOptions := &terraform.Options{
TerraformDir: "../examples/basic",
}
defer terraform.Destroy(t, terraformOptions)
terraform.InitAndApply(t, terraformOptions)
// Add assertions here
}
```
## Module Checklist
Before publishing a module, ensure:
- [ ] All variables have descriptions
- [ ] Validation rules where appropriate
- [ ] Sensible defaults for optional variables
- [ ] All important attributes are output
- [ ] README with usage examples
- [ ] At least one working example
- [ ] Version constraints specified
- [ ] .gitignore includes Terraform files
- [ ] Tags support included
- [ ] Naming follows conventionsRelated Skills
terraform-validator
Validate Terraform code for syntax errors, best practices, security issues, and compliance with standards
terraform-state-manager
Analyze, inspect, and safely manipulate Terraform state files with drift detection and resource management
terraform-security-scanner
Comprehensive security scanning for Terraform code including secrets detection, compliance checks, and vulnerability assessment
terraform-resource-fetch
Fetch latest Terraform provider resources and documentation from Terraform Registry
terraform-project-generator
Generate complete Terraform project structure with main.tf, variables.tf, outputs.tf, backend.tf, and terraform.tf following best practices
terraform-plan-analyzer
Parse, explain, and analyze terraform plan output for impact assessment, cost estimation, and risk evaluation
terraform-doc-generator
Auto-generate comprehensive README.md documentation for Terraform modules with usage examples, inputs, outputs, and requirements
terraform-code-generator
Auto-generate Terraform resource blocks by fetching latest schemas from Terraform Registry in real-time
skill-installer
Install Codex skills into $CODEX_HOME/skills from a curated list or a GitHub repo path. Use when a user asks to list installable skills, install a curated skill, or install a skill from another repo (including private repos).
skill-creator
Guide for creating effective skills. This skill should be used when users want to create a new skill (or update an existing skill) that extends Codex's capabilities with specialized knowledge, workflows, or tool integrations.
jwebmp-webawesome
WebAwesome icon integration for JWebMP — modern, open-source icon library. Provides 1,500+ icons with solid/regular styles, sizing, rotation, animation, and CSS utilities. Drop-in FontAwesome alternative with fresh designs. Use when working with WebAwesome icons, modern icon designs, or as FontAwesome alternative in JWebMP applications.
jwebmp-webawesome-pro
WebAwesome Pro integration for JWebMP with premium icons and features. Extends jwebmp-webawesome with additional styles, premium icons, and advanced features. Use when working with WebAwesome Pro icons or premium WebAwesome features in JWebMP applications.