Design and create Terraform modules from real infrastructure requirements. Use when asked to create a Terraform module, build a module from a requirement, turn repeated Terraform into a module, design module inputs and outputs, review whether a Terraform pattern should become a module, refactor existing Terraform into a reusable module, or assess whether a module is over-abstracted. Covers Azure-focused modules with KISS/DRY principles, module boundary definition, interface design, and practical file structure generation. Do NOT use for general Terraform coding with no module boundary, provider version upgrades (use terraform-provider-upgrade skill), or non-Terraform IaC.
npx skills add https://github.com/thomast1906/github-copilot-agent-skills --skill terraform-module-creator
Use this skill to help design and create Terraform modules from real infrastructure requirements.
This skill is intended to do more than generate Terraform files. It should help decide whether a module is justified in the first place, define a clear module responsibility, shape a clean interface, and avoid over-engineering.
The goal is to produce Terraform modules that are understandable, maintainable, and genuinely useful in practice.
The following tools must be installed locally before using this skill. The skill references them during generation and validation steps.
| Tool | Purpose | Install |
|------|---------|---------|
| Terraform | Core IaC tool — init, validate, fmt | brew install hashicorp/tap/terraform |
| terraform-docs | Generates README inputs/outputs from module source | brew install terraform-docs |
| tflint | Static analysis — catches deprecated args, provider-specific issues | brew install tflint |
| tflint-ruleset-azurerm | Azure-specific tflint rules | configured via .tflint.hcl (see VALIDATION.md) |
Minimum versions: Terraform ≥ 1.2 (required for lifecycle preconditions/postconditions). terraform-docs ≥ 0.16. tflint ≥ 0.50.
If any tool is missing, the skill will flag this and suggest the install command before running validation steps.
This skill makes active use of the HashiCorp Terraform Registry MCP and the Azure MCP Server. Use the tools below at the indicated stages of the workflow. Full parameter reference and example call sequences are in references/MCP-TOOLS.md.
| Tool | Stage | Purpose |
|------|-------|---------|
| azure-azureterraformbestpractices | Step 1 — Understand the ask | Get Azure Terraform best practices before starting design |
| azure-get_azure_bestpractices | Step 1 — Understand the ask | Get platform-level best practices for the specific Azure service |
| azure-documentation | Step 1 — Understand the ask | Look up CAF naming standards, DNS zone names, service feature behaviour |
| azure-wellarchitectedframework | Step 1 / Step 6 | Get WAF pillar recommendations to inform secure, reliable defaults |
| mcp_terraform_search_modules | Step 2 — Decide module type | Check if an Azure Verified Module or registry module already exists |
| mcp_terraform_get_module_details | Step 2 — Decide module type | Review an existing module's inputs/outputs to assess fit |
| mcp_terraform_get_provider_capabilities | Step 3 — Define boundary | Discover what azurerm resources exist for the service area |
| mcp_terraform_search_providers | Step 4 — Design interface | Find provider resource documentation by service slug |
| mcp_terraform_get_provider_details | Step 4 — Design interface | Get full argument reference and attribute reference for a resource |
| mcp_terraform_get_latest_provider_version | Step 6 — Generate module | Get the current latest azurerm version for versions.tf |
Important: Before invoking any Azure MCP tool, run a discovery call with learn=true or tool_search_tool_regex to confirm the exact tool name. Do not hardcode names that may change.
Always optimise for the following:
Follow this process for every request.
Call azure-azureterraformbestpractices and azure-get_azure_bestpractices for the target Azure service before starting design. Call azure-documentation for CAF naming conventions, private endpoint DNS zone names, or any service feature behaviour that needs current guidance. Call azure-wellarchitectedframework to understand which WAF pillar recommendations should inform the module's default values. This grounds decisions in current Azure platform guidance rather than assumptions.
Identify:
Where useful, restate the module intent in one sentence before generating anything.
Example:
> This module is intended to provision a standard Azure Storage Account pattern with consistent naming, tagging, diagnostics, and access configuration for shared platform use.
Check the Terraform Registry for reference. Call mcp_terraform_search_modules to see what existing modules look like for the resource. Use this to understand common interface patterns and what other teams have found necessary — not to replace the custom module. AVM and registry modules are often over-abstracted and do not align with the KISS principle this skill applies. Review them for ideas, not as a recommendation to adopt.
If a candidate is found, call mcp_terraform_get_module_details to review its interface. Use this to identify what arguments matter in practice and what complexity to avoid.
Work out whether the module is:
Prefer building block modules unless a composition module clearly maps to a repeated platform pattern. Do not create composition modules that bundle unrelated concerns together.
State clearly:
A good module boundary should be easy to explain in a few lines.
Use mcp_terraform_search_providers to find the resource documentation by service slug, then call mcp_terraform_get_provider_details with the returned provider_doc_id to get the full argument reference. Use this to understand all available arguments before deciding which to expose as variables. See references/MCP-TOOLS.md for common service slug values.
Design variables and outputs with discipline.
Variables
validation {} blocks to enum-style variables (SKU, tier, kind) and name format constraints — catch bad inputs at plan time with a clear error message, not a cryptic provider errorOutputs
sensitive = true on any output containing a secret: connection strings, access keys, passwords, SAS tokensprincipal_id (managed identity) over connection strings — guide consumers toward keyless authenticationLocals
Start simple. A typical module structure:
module/
├── main.tf
├── variables.tf
├── outputs.tf
├── versions.tf
├── .terraform-docs.yml
├── README.md
└── examples/
└── basic/
├── main.tf
├── variables.tf
├── outputs.tf
├── versions.tf
└── README.md
Add locals.tf if it improves clarity. Only add more files if there is a clear readability benefit. Do not create file sprawl for the sake of neatness.
Always create an examples/basic/ folder alongside the module. Each example is a standalone, independently runnable Terraform root module — it needs its own main.tf (the module call), variables.tf, outputs.tf, versions.tf, and README.md. The main.tf should demonstrate minimum viable usage with hardcoded values; keep variables.tf minimal and only expose what a caller genuinely needs to parameterise (e.g., resource group name, location). For modules with distinct usage patterns (e.g., with and without private endpoint), add a second subfolder such as examples/private-endpoint/ with the same full file set.
Always include .terraform-docs.yml — the README inputs and outputs table is generated by terraform-docs, not written by hand. The README contains a static description and usage example written by the author, with <!-- BEGIN_TF_DOCS --> / <!-- END_TF_DOCS --> markers where terraform-docs injects the generated content.
Before generating versions.tf, call mcp_terraform_get_latest_provider_version(namespace="hashicorp", name="azurerm") to get the current latest version and use it as the minimum constraint.
For modules with dependent optional variables (e.g., private_endpoint.enabled = true requires subnet_id), add lifecycle { precondition {} } blocks on the resource to surface misconfigurations clearly before any resource is created. See MODULE-PATTERNS.md for the pattern.
When generating code:
Always generate the following alongside the Terraform files:
.terraform-docs.yml — terraform-docs configuration (see MODULE-PATTERNS.md)README.md — static purpose description and usage example with <!-- BEGIN_TF_DOCS --> / <!-- END_TF_DOCS --> markers; do not hand-write the inputs/outputs table — that is generated by running terraform-docs .examples/basic/main.tf — the module call with sensible defaults; use hardcoded values appropriate for an example, not variablesexamples/basic/variables.tf — any inputs the example exposes to the caller (e.g., subscription ID, resource group name); keep this minimalexamples/basic/outputs.tf — relevant outputs from the module call (e.g., resource ID, connection string reference)examples/basic/versions.tf — provider required_providers block pinned to the same constraint as the module itself; the example is a real Terraform root and must be independently runnableexamples/basic/README.md — one-sentence description of what this example demonstratesAdd further subfolders (e.g., examples/private-endpoint/) for distinct usage patterns, each with the same full file set.
Tell the consumer to run terraform-docs . after any variable or output changes to regenerate the inputs/outputs table in the README. If a pre-commit hook is in use, provide the hook config from MODULE-PATTERNS.md.
Before finalising, check:
If the module feels hard to explain, it is probably doing too much.
Before handing off, run:
terraform fmt -check -recursive . # formatting
terraform init -backend=false && terraform validate # syntax and references
tflint --init && tflint # provider-specific issues, deprecated args, naming
terraform-docs . # README in sync with variables and outputs
Before running these commands, verify each tool is available (terraform -version, terraform-docs --version, tflint --version). If a tool is missing, output the install command from the Prerequisites section and stop — do not silently skip the validation step.
See references/VALIDATION.md for full tool setup, .tflint.hcl config, and CI pipeline guidance.
Before creating a module, stop and assess whether a module is actually the right answer.
Ask:
If a module is not justified, say so clearly. Do not create modules just because something appears more than once. A module should exist because it improves clarity, consistency, and supportability.
Depending on the request, produce one or more of the following:
If the user already has Terraform or a draft module, review it by asking:
Provide direct, practical feedback.
If the user has repeated Terraform code and wants to extract a module:
moved {} blocks for any renamed or restructured resources to prevent destructive plan changes for existing consumers (see MODULE-PATTERNS.md)When working on Azure Terraform modules, follow the platform standards in references/AZURE-STANDARDS.md. Key areas:
Do not assume a new custom module is always the best answer.
Apply these consistently:
Do not:
Supporting reference material for this skill:
moved blocks, tagging.tflint.hcl config), pre-commit hooks, CI pipeline exampleAssess Kubernetes workloads and cluster configuration for AKS Automatic compatibility. Identifies incompatibilities, generates fixes, and guides migration from AKS Standard to AKS Automatic. WHEN: migrate to AKS Automatic, check AKS Automatic readiness, validate manifests for Automatic, assess cluster for Automatic compatibility, fix deployment for Automatic compatibility, identify AKS Automatic migration blockers, is my cluster ready for AKS Automatic.
Discovers available Azure OpenAI model capacity across regions and projects. Analyzes quota limits, compares availability, and recommends optimal deployment locations based on capacity requirements. USE FOR: find capacity, check quota, where can I deploy, capacity discovery, best region for capacity, multi-project capacity search, quota analysis, model availability, region comparison, check TPM availability. DO NOT USE FOR: actual deployment (hand off to preset or customize after discovery), quota increase requests (direct user to Azure Portal), listing existing deployments.
Interactive guided deployment flow for Azure OpenAI models with full customization control. Step-by-step selection of model version, SKU (GlobalStandard/Standard/ProvisionedManaged), capacity, RAI policy (content filter), and advanced options (dynamic quota, priority processing, spillover). USE FOR: custom deployment, customize model deployment, choose version, select SKU, set capacity, configure content filter, RAI policy, deployment options, detailed deployment, advanced deployment, PTU deployment, provisioned throughput. DO NOT USE FOR: quick deployment to optimal region (use preset).
Unified Azure OpenAI model deployment skill with intelligent intent-based routing. Handles quick preset deployments, fully customized deployments (version/SKU/capacity/RAI policy), and capacity discovery across regions and projects. USE FOR: deploy model, deploy gpt, create deployment, model deployment, deploy openai model, set up model, provision model, find capacity, check model availability, where can I deploy, best region for model, capacity analysis. DO NOT USE FOR: listing existing deployments (use foundry_models_deployments_list MCP tool), deleting deployments, agent creation (use agent/create), project creation (use project/create).
Intelligently deploys Azure OpenAI models to optimal regions by analyzing capacity across all available regions. Automatically checks current region first and shows alternatives if needed. USE FOR: quick deployment, optimal region, best region, automatic region selection, fast setup, multi-region capacity check, high availability deployment, deploy to best location. DO NOT USE FOR: custom SKU selection (use customize), specific version selection (use customize), custom capacity configuration (use customize), PTU deployments (use customize).
This skill should be used when working with LaminDB, an open-source data framework for biology that makes data queryable, traceable, reproducible, and FAIR. Use when managing biological datasets (scRNA-seq, spatial, flow cytometry, etc.), tracking computational workflows, curating and validating data with biological ontologies, building data lakehouses, or ensuring data lineage and reproducibility in biological research. Covers data management, annotation, ontologies (genes, cell types, diseases, tissues), schema validation, integrations with workflow managers (Nextflow, Snakemake) and MLOps platforms (W&B, MLflow), and deployment strategies.
Latch platform for bioinformatics workflows. Build pipelines with Latch SDK, @workflow/@task decorators, deploy serverless workflows, LatchFile/LatchDir, Nextflow/Snakemake integration.
Run Python code in the cloud with serverless containers, GPUs, and autoscaling. Use when deploying ML models, running batch processing jobs, scheduling compute-intensive tasks, or serving APIs that require GPU acceleration or dynamic scaling.
Take thomast1906/terraform-module-creator from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.
The instructions reference brew.
Without those the skill loads but fails at the first command.