terraform/code-generation/skills/azure-verified-modules/SKILL.md
Azure Verified Modules (AVM) requirements and best practices for developing certified Azure Terraform modules. Use when creating or reviewing Azure modules that need AVM certification.
npx skillsauth add lidge-jun/cli-jaw-skills azure-verified-modulesInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
References: AVM Docs | Terraform Specs
source = "Azure/xxx/azurerm" + version = "1.2.3"git::, github.com/)| Provider | Min Version | Max Version | |----------|-------------|-------------| | azapi | >= 2.0 | < 3.0 | | azurerm | >= 4.0 | < 5.0 |
required_providers block to enforce versions~>)See references/code-examples.md for provider configuration example.
Use lower_snake_case for all locals, variables, outputs, resource symbolic names, and module symbolic names.
Place depended-on resources first. Keep resources with dependencies close to each other.
count for conditional resource creationmap(xxx) or set(xxx) as for_each collection with static literal keysprovider, count, for_eachdepends_on, lifecycle (sub-order: create_before_destroy, ignore_changes, prevent_destroy)Separate sections with blank lines.
source, version, count, for_eachdepends_on, providersUse unquoted attributes: ignore_changes = [tags] (not ["tags"]). Quoted strings cause silent failures.
Wrap parameters requiring conditional creation with object type to avoid "known after apply" issues during plan.
Use for_each = <condition> ? [<item>] : [] pattern for optional nested blocks.
Prefer coalesce() or try() over ternary expressions for default values — shorter and more readable.
provider blocks in modules only for configuration_aliasesAvoid enabled or module_depends_on variables that control entire module operation. Feature toggles for specific resources are acceptable.
Follow HashiCorp naming rules. Use positive statements for feature switches: xxx_enabled instead of xxx_disabled.
Write descriptions targeting module users (not developers). For object types, use HEREDOC format.
type for every variable, as precise as possiblebool for true/false values (not string/number)object instead of map(any)any for adequately justified cases onlyFor object variables with sensitive fields: either set sensitive = true on the entire variable, or extract sensitive fields into separate variables.
Set nullable = false for collection values (sets, maps, lists) used in loops, because null collections cause runtime errors in for_each.
Avoid nullable = true unless null carries specific semantic meaning.
sensitive = false (it is the default)deprecated_variables.tfDEPRECATED and declare the replacement nameOutput discrete computed attributes (anti-corruption layer pattern) rather than entire resource objects, because resource schemas change across provider versions.
name)sensitive = true for sensitive attributesfor_each resources, output computed attributes in a map structureMark outputs containing confidential data with sensitive = true.
Move deprecated outputs to deprecated_outputs.tf. Define new outputs in outputs.tf. Clean up during major version releases.
locals blocks in locals.tf (advanced: declare next to related resources)number for age, not string)terraform.tf requirements:
terraform block, required_version on first line~> #.# or >= #.#.#, < #.#.# formatsource (format: namespace/name) and versionRequired tools: terraform validate/fmt/test, terrafmt, Checkov, tflint (with azurerm ruleset), Go (optional).
Set prevent_deletion_if_contains_resources = false in test provider configs for clean teardown.
Generate docs via terraform-docs. A .terraform-docs.yml file is required in the module root.
New resources in minor/patch versions require a toggle variable defaulting to false to avoid unexpected resource creation.
See references/breaking-changes.md for the full list of patterns that constitute breaking changes in resource, variable, and output blocks.
Set branch protection on the default branch: require PRs, approval, linear history, CODEOWNERS review. Prevent force pushes and branch deletion. No bypass for administrators.
tools
Use only on the Codex CLI for native image generation or image editing without an API key. Save final PNG files under ~/.cli-jaw/uploads, report web-ready absolute-path markdown, and send to Telegram or Discord only when explicitly requested.
tools
Ranked repository structure map via `cli-jaw map`. Use for codebase overview, structure map, symbol overview, unfamiliar codebase exploration, architecture orientation. Triggers: repo map, structure map, codebase overview, 와꾸, project structure, unfamiliar code.
tools
cli-jaw Design workspace: create, preview, run, and export design pages from the right sidebar. Covers panel UX, direct-write workflow, artifact lifecycle, wireframe generation, design system, and Open Design adapter.
development
MUST USE for infrastructure and delivery work — container builds, deploy pipelines, Kubernetes, Infrastructure as Code, SRE foundations, edge/serverless, ML infrastructure. Triggers: Dockerfile, K8s manifests, CI/CD pipeline, Terraform/IaC, release/deploy, devops/infra/deploy or release_cd task_tags.