Install
$ agentstack add skill-aws-samples-sample-apex-skills-terraform-skill ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
Terraform Skill for Claude
Diagnose-first guidance for Terraform and OpenTofu. Core file is a workflow; depth lives in references loaded on demand.
Response Contract
Every Terraform/OpenTofu response must include:
- Assumptions & version floor — runtime (
terraformortofu), exact version, providers, state backend, execution path (local/CI/Cloud/Atlantis), environment criticality. State assumptions explicitly if the user did not provide them. - Risk category addressed — one or more of: identity churn, secret exposure, blast radius, CI drift, compliance gaps, state corruption, provider upgrade risk, testing blind spots.
- Chosen remediation & tradeoffs — what was chosen, what was traded off, why.
- Validation plan — exact commands (
fmt -check,validate,plan -out, policy check) tailored to runtime and risk tier. - Rollback notes — for any destructive or state-mutating change: how to undo, what evidence to keep.
Never recommend direct production apply without a reviewed plan artifact and approval.
Never run terraform destroy (targeted or full) without first running terraform plan -destroy and showing the user every resource that will be deleted — including implicit dependents pulled in via locals or for_each. Get explicit confirmation before proceeding. Never use -auto-approve on destroy.
Workflow
- Capture execution context — runtime+version, provider(s), backend, execution path, environment criticality.
- Diagnose failure mode(s) using the routing table below. If intent spans categories, load both references.
- Load only the matching reference file(s) — do not preload depth the task does not need.
- Propose fix with risk controls — why this addresses the mode, what could still go wrong, guardrails (tests/approvals/rollback).
- Generate artifacts — HCL, migration blocks (
moved,import), CI changes, policy rules. - Validate before finalizing — run validation commands tailored to risk tier.
- Emit the Response Contract at the end.
Diagnose Before You Generate
| Failure category | Symptoms | Primary references | |------------------|----------|--------------------| | Identity churn | Resource addresses shift after refactor, count index churn, missing moved blocks | [Code Patterns: count vs foreach](references/code-patterns.md#count-vs-foreach-deep-dive), [Code Patterns: moved blocks](references/code-patterns.md#moved-blocks-terraform-11), [Code Patterns: LLM mistakes](references/code-patterns.md#llm-mistake-checklist--code-patterns) | | Secret exposure | Secrets in defaults, state, logs, CI artifacts | [Security & Compliance](references/security-compliance.md), [Code Patterns: write-only](references/code-patterns.md#write-only-arguments-terraform-111), [State Management](references/state-management.md) | | Blast radius | Oversized stacks, shared prod/non-prod state, unsafe applies | [State Management](references/state-management.md), [Module Patterns](references/module-patterns.md) | | Destroy cascade | Targeted destroy deletes more than expected; locals referencing a targeted resource make all for_each consumers implicit dependents | Response Contract: plan-destroy first; [State Management: Safe Destroy](references/state-management.md#safe-destroy-protocol) | | CI drift | Local plan ≠ CI plan, apply without reviewed artifact, unpinned versions | [CI/CD Workflows](references/ci-cd-workflows.md), [Code Patterns: versions](references/code-patterns.md#version-management) | | Compliance gaps | Missing policy stage, no approval model, no evidence retention | [Security & Compliance](references/security-compliance.md), [CI/CD Workflows](references/ci-cd-workflows.md) | | Testing blind spots | Plan-only validation of computed values, set-type indexing, mock/real confusion | [Testing Frameworks](references/testing-frameworks.md) | | State corruption / recovery | Stuck lock, backend migration, drift reconciliation | [State Management](references/state-management.md) | | Provider upgrade risk | Breaking-change provider bump, unpinned modules | [Code Patterns: versions](references/code-patterns.md#version-management), [Module Patterns](references/module-patterns.md) | | Provider lifecycle | Removing a provider with resources still in state, orphaned resources, removed block usage | [State Management: Provider Removal](references/state-management.md#provider-removal) | | Bootstrap / orchestration misuse | null_resource + local-exec for bootstrap, remote-exec for setup scripts, provisioner stdout leaking secrets in CI logs | [Code Patterns: Provisioners as Last Resort](references/code-patterns.md#provisioners-as-last-resort) | | Navigation / safe-rename blind spots | Cannot locate symbol defs/refs semantically, value-symbol rename done as blind text replace, grep-only refactor missing refs, hallucinated rg shim | [Code Intelligence](references/code-intelligence-lsp.md#terraform-ls-capability-matrix) | | Cross-cloud / provider mapping | "What's the Azure/GCP equivalent of X", picking a backend/auth model per cloud | [State Management: Cross-cloud equivalents](references/state-management.md#cross-cloud-equivalents) |
When to Use This Skill
Activate when: creating or reviewing Terraform/OpenTofu configurations or modules, setting up or debugging tests, structuring multi-environment deployments, implementing IaC CI/CD, choosing module patterns or state organization, configuring or migrating remote state backends.
Don't use for: basic HCL syntax questions Claude already knows, provider API reference (link to docs), cloud-platform questions unrelated to Terraform/OpenTofu.
Core Principles
Module Hierarchy
| Type | When to Use | Scope | |------|-------------|-------| | Resource module | Single logical group of connected resources | VPC + subnets, SG + rules | | Infrastructure module | Collection of resource modules for a purpose | Multiple resource modules in one region/account | | Composition | Complete infrastructure | Spans multiple regions/accounts |
Flow: resource → resource module → infrastructure module → composition.
Directory Layout
environments/ # prod/ staging/ dev/ — per-env configurations
modules/ # networking/ compute/ data/ — reusable modules
examples/ # minimal/ complete/ — docs + integration fixtures
Separate environments from modules. Use examples/ as both documentation and test fixtures. Keep modules small and single-responsibility.
See [Module Patterns](references/module-patterns.md) for architecture principles, naming conventions, variable/output contracts.
Naming Conventions (summary)
- Descriptive resource names (
aws_instance.web_server, notaws_instance.main) - Reserve
thisfor genuine singleton resources only - Prefix variables with context (
vpc_cidr_block, notcidr) - Standard files:
main.tf,variables.tf,outputs.tf,versions.tf
See [Module Patterns: Variable Naming](references/module-patterns.md) and [Code Patterns: Block Ordering](references/code-patterns.md#block-ordering--structure) for examples.
Block Ordering (summary)
Resource blocks: count/for_each first → arguments → tags → depends_on → lifecycle. Variable blocks: description → type → default → validation → nullable → sensitive.
See [Code Patterns: Block Ordering & Structure](references/code-patterns.md#block-ordering--structure) for the full rules and examples.
Testing Strategy
Decision Matrix: Which Testing Approach?
| Situation | Approach | Tools | Cost | |-----------|----------|-------|------| | Quick syntax check | Static analysis | validate, fmt | Free | | Pre-commit validation | Static + lint | validate, tflint, trivy, checkov | Free | | Terraform 1.6+, simple logic | Native test framework | terraform test | Free-Low | | Pre-1.6, or Go expertise | Integration testing | Terratest | Low-Med | | Security/compliance focus | Policy as code | OPA, Sentinel | Free | | Cost-sensitive workflow | Mock providers (1.7+) | Native tests + mocks | Free | | Multi-cloud, complex | Full integration | Terratest + real infra | Med-High |
Native Test Rules (1.6+)
Before writing test code: validate resource schemas via Terraform MCP so assertions target real attributes.
command = plan— fast, for input-derived values onlycommand = apply— required for computed values (ARNs, generated names) and set-type nested blocks- Set-type blocks cannot be indexed with
[0]— useforexpressions or materialize viacommand = apply - Common set types: S3 encryption rules, lifecycle transitions, IAM policy statements
See [Testing Frameworks](references/testing-frameworks.md) for static-analysis pipelines, native-test patterns, Terratest integration, mock providers, and the full LLM-mistake checklist.
Count vs For_Each — Quick Rule
| Scenario | Use | Why | |----------|-----|-----| | Boolean condition (create / don't) | count = condition ? 1 : 0 | Optional singleton toggle | | Items may be reordered or removed | for_each = toset(list) | Stable resource addresses | | Reference by key | for_each = map | Named access | | Multiple named resources | for_each | Better identity stability |
Never use list index as long-lived identity — removing a middle element reshuffles every address after it. For the decision matrix, safe migration playbook, moved block patterns, and known-at-plan failure cases, see [Code Patterns: count vs foreach](references/code-patterns.md#count-vs-foreach-deep-dive).
Locals for Dependency Management
Using try() in a local to prefer a conditional resource's attribute over its parent is a specialized but high-value pattern — it forces correct deletion order without explicit depends_on. Common use: VPC + secondary CIDR associations + subnets.
See [Code Patterns: Locals for Dependency Management](references/code-patterns.md#locals-for-dependency-management) for the full pattern and worked example.
Module Development
Standard layout:
my-module/
├── README.md # Usage documentation
├── main.tf # Primary resources
├── variables.tf # Typed inputs with descriptions
├── outputs.tf # Output values
├── versions.tf # required_version + required_providers
├── examples/
│ ├── minimal/
│ └── complete/
└── tests/
└── module_test.tftest.hcl # or Go for Terratest
Variable contracts: always description, always explicit type, use validation for complex constraints, use sensitive = true for secrets, prefer optional() with typed defaults (1.3+) over untyped map(any).
Output contracts: always description, mark sensitive outputs, expose stable subsets (not whole provider objects).
See [Module Patterns](references/module-patterns.md) for the full contract patterns, module release checklist, and LLM-mistake checklist.
CI/CD
Pipeline stages: validate → test → plan → apply (with environment protection).
Cost control: mock providers on PR validation, real-cloud integration only on main or scheduled, tag test resources, auto-cleanup.
Drift prevention: pin runtime and providers, commit .terraform.lock.hcl, apply the reviewed plan artifact from the plan stage (do not re-run plan inside the apply job), run policy/security stage on every path to apply.
See [CI/CD Workflows](references/ci-cd-workflows.md) for GitHub Actions, GitLab CI, and Atlantis templates plus the LLM-mistake checklist.
Security & Compliance
Essential checks:
trivy config .
checkov -d .
Don't: store secrets in variables or .tfvars, use default VPC, skip encryption, open security groups to 0.0.0.0/0, use inline ingress/egress blocks in aws_security_group.
Do: source secrets from a cloud secret manager (AWS Secrets Manager / Azure Key Vault / GCP Secret Manager) or use write_only arguments on 1.11+, create dedicated VPCs, enforce encryption at rest and TLS, least-privilege SGs, use separate aws_vpc_security_group_{ingress,egress}_rule resources (e.g. AWS provider v5+).
Marking a variable sensitive = true masks display only — the value still lives in state. Use write_only / *_wo on 1.11+, or keep secret material out of Terraform entirely via runtime lookups.
See [Security & Compliance](references/security-compliance.md) for trivy/checkov pipelines, state-file hardening, compliance mappings, and the LLM-mistake checklist.
State Management
Never use local state in teams or production. Remote backends provide automatic locking, encryption, versioning, audit logging, and safe collaboration.
Choosing a Remote Backend
AWS example (Azure azurerm / GCP gcs / TF Cloud syntax: see [State Management: Choosing a Remote Backend](references/state-management.md#choosing-a-remote-backend)):
terraform {
backend "s3" {
bucket = "my-terraform-state"
key = "prod/vpc/terraform.tfstate"
region = "us-east-1"
encrypt = true
use_lockfile = true # Native S3 locking, 1.10+
}
}
On Terraform 500 resources. Combine when: tightly coupled resources, 1.9" | | Providers | Pin major | version = "~> 5.0" | | Modules (prod) | Pin exact | version = "5.1.2" | | Modules (dev) | Allow patch | version = "~> 5.1"` |
Commit .terraform.lock.hcl intentionally. Keep provider/runtime upgrades in a separate PR from functional changes. See [Code Patterns: Version Management](references/code-patterns.md#version-management) for constraint syntax and upgrade workflow.
Modern Terraform Features (1.0+)
| Feature | Min version | Common use | |---------|-------------|------------| | try() | 0.13+ | Safe fallbacks, replaces element(concat()) | | nullable = false | 1.1+ | Prevent null silently overriding defaults | | moved blocks | 1.1+ | Refactor without destroy/recreate | | optional() with defaults | 1.3+ | Typed object attributes | | import blocks | 1.5+ | Declarative imports, reviewable in VCS | | check blocks | 1.5+ | Runtime assertions | | Native terraform test | 1.6+ | Built-in test framework | | Mock providers | 1.7+ | Cost-free unit testing | | removed blocks | 1.7+ | Declarative resource removal | | Provider-defined functions | 1.8+ | Provider-specific transformations (requires provider to declare functions) | | Cross-variable validation | 1.9+ | Reference other var.* in validation blocks | | write_only arguments | 1.11+ | Secrets never stored in state | | S3 native lock-file | 1.10+ | State locking without DynamoDB |
Before emitting a feature, verify the runtime floor. See [Code Patterns: Feature Guard Table](references/code-patterns.md#feature-guard-table--version-floor--common-llm-errors) for the full table with common LLM error patterns per feature.
Runtime-Specific Guidance
- Terraform 1.0-1.5 (OpenTofu starts at 1.6): Terratest for integration, static analysis + plan validation only (no native tests).
- 1.6+: native
terraform test/tofu testavailable — migrate simple unit tests, keep Terratest for complex integration. - 1.7+: mock providers cut test cost — mock for unit tests, real runs for final integration.
- 1.10+: S3 native lock-file (
use_lockfile) is the correct default for new configurations — DynamoDB locking is no longer required. - 1.11+:
write_onlyarguments for secret handling keep credentials out of state. - Terraform vs OpenTofu: both supported. For licensing, governance, and feature delta, see [Quick Reference: Terraform vs OpenTofu](references/quick-reference.md#terraform-vs-opentofu-comparison).
Code Intelligence (terraform-ls)
Semantic navigation for HCL. terraform-ls is optional; without it every row below degrades to a disclosed rg + Read fallback.
Self-contained terraform-ls layer of a generic code-intelligence discipline
…
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: aws-samples
- Source: aws-samples/sample-apex-skills
- License: MIT-0
- Homepage: https://aws-samples.github.io/sample-apex-skills/
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.