AlphaMoatによると、2026-09時点でTerraformのダウンロード数は4,634、スター数は3で、AIスキル全体5,078件中2,057位、IT運用・セキュリティでは264件中106位です。
| プラットフォーム | インストール数 | ダウンロード数 | スター数 | コメント |
|---|---|---|---|---|
| ClawHub ↗ | 122 | 4634 | 3 | - |
| SkillHub ↗ | 120 | 3902 | 3 | — |
プラットフォームごとに集計方法と集計時点が異なります。
保存済み plan を適用前にレビューする変更契約として扱い、state 操作の前にバックアップを求め、破棄や置換を確認します。state、plan ファイル、ログには平文の秘密情報が含まれる可能性があるため、変更を確認し、apply、state push、state rm、force-unlock の前に明示的な承認を得てください。
資料公開日 2026-10-29
スキルのドキュメントをもとに生成した例であり、実際の実行結果ではありません。
2026-09 から集計方法を変更し、同名スキルを作者ごとに分けて集計し、全スキルを対象にしました。破線は変更前の月で、変更後のデータとは直接比較せず、変更をまたぐ増減も計算していません。
| 月 | ダウンロード数 | 前月比 | スター数 |
|---|---|---|---|
| 2026-09 | 4634 | — | 3 |
| 2026-08 | 4339 | +13.9% | 3 |
| 2026-07 | 3811 | +19.5% | 3 |
| 2026-06 | 3190 | +7.2% | 3 |
| 2026-05 | 2977 | — | 3 |
| 2026-03 | 2143 | — | 3 |
作者が公開した元のファイルをテキストのまま表示しています。AlphaMoat による編集や審査はしていません。リンクはクリックできません。コマンドは内容を確認してから実行してください。取得日 2026-10-23。
--- name: Terraform slug: terraform version: 1.0.4 description: >- Writes, debugs, and refactors Terraform — HCL and modules, plan and apply failures, state surgery, drift, and provider pinning. Use when writing or reviewing HCL, when terraform plan or apply errors out, when a plan shows a permanent diff, an unexplained destroy, or "forces replacement", when renaming, importing, or moving resources between modules and states, when a state lock is stuck or state is lost or corrupted, when for_each fails because a value is
not known until apply, when pinning providers or surviving a major version upgrade, or when
wiring plan-on-PR, apply-on-merge, drift detection, and policy gates. Covers OpenTofu,
tfstate, backends, workspaces, and infrastructure-as-code review. Not for choosing which
cloud services to build — see aws, gcp, or azure.
homepage: https://clawic.com/skills/terraform
changelog: "Display name shown correctly"
metadata:
clawdbot:
emoji: 🟪
requires:
anyBins:
- terraform
- tofu
os:
- linux
- darwin
- win32
displayName: Terraform
configPaths:
- ~/Clawic/data/terraform/
---
User preferences and memory live in `~/Clawic/data/terraform/` (see `setup.md` on first use, `memory-template.md` for the file format). If you have data at an old location (`~/terraform/` or `~/clawic/terraform/`), move it to `~/Clawic/data/terraform/`.
## When To Use
- Writing or reviewing HCL: resource design, count vs for_each, module boundaries, variable types and validation
- Debugging plan/apply failures, permanent diffs, cycles, unknown-at-plan errors, stuck locks, drift
- Refactoring live infrastructure: renames, module extraction, imports, splitting or merging state
- Pinning providers, upgrading the CLI or a provider major version, moving between Terraform and OpenTofu
- Designing backends, environment layout, and CI plan/apply gates with policy, tests, and drift detection
- Recovering after damage: lost or corrupted state, wrong `state rm`, unintended destroy, interrupted apply
- Not for choosing which cloud resources to build (→ `aws`, `gcp`, `azure`) or configuring what runs inside them (→ `ansible`)
## Quick Reference
| Situation | Play |
|---|---|
| Renamed a resource or module in code | `moved` block (>=1.1); apply everywhere, delete the block in a later PR → `refactoring.md` |
| Cloud object exists but is not in state | `import` block (>=1.5) + `plan -generate-config-out=gen.tf`; rewrite the draft, merge at zero diff → `refactoring.md` |
| Stop managing something without destroying it | `removed` block with `destroy = false` (>=1.7); `state rm` only as one-off surgery → `refactoring.md` |
| Permanent diff on every plan | Find the writer (autoscaler, console, another pipeline, provider normalization) before reaching for `ignore_changes` → `debug.md` |
| "Invalid for_each argument" / "Invalid count argument" | Key on values known at plan time, never on resource attributes → `expressions.md` |
| A variable value is ignored, or an old value keeps winning | Precedence: `-var`/`-var-file` > `*.auto.tfvars` > `terraform.tfvars` > `TF_VAR_` > the declared default → `expressions.md` |
| "Error: Cycle: ..." | Break the mutual reference into a standalone rule/attachment resource → `debug.md` |
| "Provider produced inconsistent final plan" | Provider bug: upgrade the provider, then pin and report → `debug.md` |
| "Saved plan is stale" | State moved between plan and apply; re-plan, re-review, re-apply → `ci.md` |
| Stuck state lock | Prove the holder is dead, then `force-unlock <LOCK_ID>` → `recovery.md` |
| State lost, corrupted, or pushed wrong | Bucket object versions are the only undo; rebuild by import if there are none → `recovery.md` |
| "Inconsistent dependency lock file" or a checksum error on install | The lock lacks that provider or that platform → `providers.md` |
| Two regions, two accounts, one config | Provider `alias` + explicit `providers` map into modules → `providers.md` |
| Plan takes minutes | `-refresh=false` while iterating, then split state by blast radius → `performance.md` |
| Throttling or "Rate exceeded" during apply | Lower `-parallelism` (default 10) → `performance.md` |
| Moving to a remote backend or between backends | Pull a backup, then `init -migrate-state` → `state.md` |
| Secret landed in state, a plan file, or a log | Rotate first; state is plaintext and old versions keep it → `secrets.md` |
| Provider major upgrade (v4 → v5) | Upgrade guide, one canary stack, explained diff per environment → `upgrades.md` |
| Module design, versioning, or nesting question | Exact pins for third-party, `~>` for internal, two levels max → `modules.md` |
| Resource must never be destroyed, must rotate with another, or keeps diffing on one attribute | `lifecycle` meta-arguments and what each one costs → `lifecycle.md` |
| A `destroy` fails or a teardown leaves debris | Deletion protection, retained objects, reverse-order dependencies → `lifecycle.md` |
| Wiring plan-on-PR and apply-on-merge | OIDC role, saved plan artifact, one concurrency group per state → `ci.md` |
| Need tests or policy gates | `.tftest.hcl` (>=1.6), plan-JSON assertions, policy engine → `testing.md` |
| Need the exact command under pressure | → `commands.md` |
| Anything else | Smallest possible change; `plan -out=tfplan`; read the destroy count and every "forces replacement" line before applying |
Depth on demand: `debug.md` plan/apply symptom→cause chains · `state.md` backends, locking, layout · `refactoring.md` moved/import/removed · `modules.md` design and versioning · `expressions.md` HCL loops, types, functions · `lifecycle.md` replacement, protection, ignored drift · `providers.md` pinning, lock file, aliases · `secrets.md` sensitive values and state exposure · `ci.md` pipelines, OIDC, drift detection · `testing.md` validate, `terraform test`, policy · `upgrades.md` CLI and provider majors, OpenTofu · `performance.md` slow plans and big states · `recovery.md` after the damage · `commands.md` incident toolkit.
## Core Rules
1. **The saved plan is the contract.** `terraform plan -out=tfplan` → review → `terraform apply tfplan`. A bare `apply` re-plans against a world that may have changed since you read the diff: you approve one change and execute another.
2. **Back up before state surgery.** `terraform state pull > backup-$(date +%s).tfstate`; restore with `terraform state push`. One wrong `state rm` orphans a live resource that keeps running and billing with nothing tracking it.
3. **Read the destroy count from the resource lines, not the summary.** A replacement is counted once as an add and once as a destroy, so `2 to add, 0 to change, 2 to destroy` can be two replacements rather than two creations plus two deletions. Machine gate: `terraform show -json tfplan | jq '[.resource_changes[] | select(.change.actions | index("delete"))] | length'` — compare against `destroy_gate`.
4. **Pin everything.** Providers via `required_providers` plus a committed `.terraform.lock.hcl`; third-party modules to an exact version; git module sources to a tag, never a branch. Unpinned means CI breaks on someone else's release day.
5. **Key `for_each` on stable, human-chosen strings** (environment names, logical roles) — never IDs, list indices, or computed values. Changing a key is destroy + create of the real object; `count` indices renumber, so removing item 0 shifts everything after it.
6. **Refactor declaratively.** `moved`, `import`, and `removed` blocks put the change in the PR diff and replay in every environment. `state mv`/`state rm` are out-of-band: unreviewable, unreplayable, invisible to the next reader.
7. **Nothing sensitive is safe in state.** `sensitive = true` masks CLI output; the value sits in plaintext in the state file, the saved plan, and `TF_LOG` output. Encrypt the backend, restrict who can read state, and prefer ephemeral values (>=1.10) and write-only arguments (>=1.11).
8. **Drift is a question, not an error.** When the cloud changed under you, decide explicitly: `apply -refresh-only` accepts reality into state, a normal apply overwrites reality with the code. Applying without choosing is how a console hotfix gets silently reverted at 2am.
## Plan Triage
Read the symbols before the summary:
| Marker | Means | Reaction |
|---|---|---|
| `+` | create | Expected count matches the change you made? |
| `~` | update in place | Safe class; still check the attribute is the one you edited |
| `-/+` | destroy then create | Downtime and a new ID; find the `# forces replacement` line |
| `+/-` | create then destroy | `create_before_destroy` is on; unique names will collide |
| `-` | destroy | Needs an explanation you could give in an incident review |
| `(known after apply)` | value unresolved at plan | Anything keyed on it will fail `for_each`; anything printed from it is unverifiable now |
| `Note: Objects have changed outside of Terraform` | drift detected during refresh | Rule 8 — decide before you apply |
- `terraform show tfplan` re-renders a saved plan; `terraform show -json tfplan` is the machine-readable form every gate should read (`ci.md`).
- `plan -detailed-exitcode` exit codes: 0 no changes · 1 error · 2 changes present.
- "No changes" plus a real-world difference you can see means the attribute is not managed (missing from config, or hidden by `ignore_changes`).
## Count vs for_each
- `count` is positional. Reserve it for identical replicas and the enable flag: `count = var.enabled ? 1 : 0`, referenced as `one(aws_x.y[*].id)`.
- `for_each` is keyed and stable, but needs a map or a set of strings (`toset()` for lists) whose **keys** are known at plan time. Values may be unknown; keys may not. Keys built from resource attributes fail with "Invalid for_each argument" (`expressions.md`).
- Migrating `count` to `for_each` without one `moved` block per index destroys and recreates every instance. Get the index→key mapping from `terraform state list`, not from memory (worked example in `refactoring.md`).
- Sensitive values cannot be `for_each` keys — a map that merges in one sensitive input becomes sensitive as a whole and the plan rejects it.
## Version Floors
`required_version` in the root module turns "my colleague gets a parse error" into a clear message. Floors for the syntax this skill recommends:
| Feature | Floor |
|---|---|
| `moved` blocks | terraform >=1.1 |
| `precondition` / `postcondition`, `replace_triggered_by` | terraform >=1.2 |
| `optional()` object attributes with defaults | terraform >=1.3 |
| `terraform_data` (replaces `null_resource`) | terraform >=1.4 |
| `import` blocks, `check` blocks, `plan -generate-config-out` | terraform >=1.5 |
| `terraform test` with `.tftest.hcl` | terraform >=1.6 |
| `removed` blocks, `for_each` in `import`, `mock_provider` | terraform >=1.7 |
| Provider-defined functions | terraform >=1.8 |
| Ephemeral values and resources, S3 backend `use_lockfile` | terraform >=1.10 |
| Write-only arguments | terraform >=1.11 |
OpenTofu forked at the 1.6 line: floors above 1.6 do not transfer — check `tofu version` against its own changelog before using a newer block (`upgrades.md`).
## Output Gates
Before emitting HCL or proposing an apply:
- Plan saved to a file, and the thing applied is that file?
- Destroy count read from the resource lines, with every "forces replacement" attribute named out loud?
- Every `for_each` keyed on a plan-time-known string?
- Providers pinned and `.terraform.lock.hcl` covering every platform in `lock_platforms`?
- New variables typed, with `validation` wherever a wrong value is expensive?
- No secret in a committed `.tfvars`, a variable default, or an unmasked output?
- If this is a refactor: does the plan read `0 to add, 0 to change, 0 to destroy`?
## Configuration
User-dependent variables. Defaults apply until the user states a preference; store them in `~/Clawic/data/terraform/config.yaml`.
| Variable | Type | Default | Effect |
|---|---|---|---|
| terraform_binary | terraform \| tofu | terraform | Command name in every example; `tofu` switches version-floor checks to the OpenTofu changelog and enables its native state-encryption guidance |
| primary_provider | aws \| gcp \| azure \| other | aws | Which provider's examples, auth model, and backend appear first in explanations |
| backend_type | s3 \| gcs \| azurerm \| tfc \| local | s3 | Locking mechanism, versioning advice, and CI credential wiring |
| env_layout | dir-per-env \| workspace-per-env \| single-state | dir-per-env | Refactoring and CI examples; `workspace-per-env` turns on the workspace-safety warnings instead of suppressing them |
| lock_platforms | list | linux_amd64, darwin_arm64 | Platforms passed to `terraform providers lock` and checked in the Output Gates |
| destroy_gate | number (>=0) | 0 | Destroy count above which the agent stops, names every destroyed address, and asks before proposing an apply |
| parallelism | number (1-50) | 10 | Value used in generated plan/apply commands; lower it when the provider throttles |
| plan_summary_detail | full \| destructive-only \| counts | destructive-only | How much plan output gets surfaced (chat and the PR comment in `ci.md`): `full` renders every changed resource, `destructive-only` posts counts plus every destroyed, replaced, and "forces replacement" line and collapses the rest, `counts` posts the summary line and the destroy list only |
Preference areas — customizable dimensions; a stated preference gets recorded in `config.yaml` and applied:
- **Tooling**: wrappers (Terragrunt, Terramate), pre-commit hooks, plan-summary tooling — affects which pipeline shape gets proposed
- **Conventions**: resource and module naming, tagging standard, file split (main/variables/outputs vs per-domain) — affects every generated block
- **Platform**: clouds, regions, and accounts in play, and the cross-account role-assumption pattern — affects provider aliases and backend keys
- **Safety posture**: appetite for `state` surgery vs declarative blocks, whether `-auto-approve` is ever acceptable — affects which refactoring path is offered first
- **Workflow**: where apply happens (laptop, CI, managed platform), review gates, who holds production credentials — affects the CI examples
- **Compliance**: mandatory policy engine, required tags, encryption and public-access rules — affects the testing and gate recommendations
- **Output format**: plan-summary verbosity beyond `plan_summary_detail`, HCL-vs-explanation ratio in answers, proactive warnings versus on-demand — affects how every plan and review is reported
- **Cadence**: drift-detection schedule and provider-upgrade rhythm — affects what gets scheduled versus run on demand
## Traps
| Trap | Why it fails | Do instead |
|---|---|---|
| CLI workspaces for dev/prod separation | Same backend, same credentials; the active workspace is invisible CLI state — applying in the wrong one looks identical to the right one | Directory per environment with separate backends and separate cloud roles (`state.md`) |
| Routine `-target` applies | Leaves the graph partially applied; the next full plan is a surprise diff nobody scoped | Emergencies only, always followed by a clean full plan |
| Interpolation in the `backend` block | Backends cannot read variables or locals — the block is evaluated before anything else exists | Partial config: omit the keys and pass `-backend-config=env/prod.tfbackend` |
| Provisioners for configuration | Not idempotent, untracked in state; a failed provisioner taints the whole resource | `user_data`/cloud-init, config management, or `terraform_data` (>=1.4) |
| Hand-editing state JSON | Serial and lineage mismatch corrupts the backend copy — or worse, the push succeeds | `state mv`/`rm`/`push` on a pulled backup (Core Rules 2) |
| `ignore_changes = all` | Freezes the entire resource forever; future config edits become silent no-ops | Ignore the one attribute, with a comment saying who writes it (`lifecycle.md`) |
| Treating plan success as apply safety | Plan validates config against state, not against the cloud: quotas, IAM, name collisions, and eventual consistency all surface at apply | Apply early in a sandbox account; keep changes small so failures are attributable |
| `apply -auto-approve` outside CI | Removes the only human checkpoint between a typo and deleted production | Auto-approve only in a pipeline applying a reviewed saved plan |
| Committing `terraform.tfstate` or `.terraform/` | Ships every secret in state to git history and leaves everyone on a different copy | Gitignore both; commit `.terraform.lock.hcl` |
| Module source pinned to a branch (`?ref=main`) | The build changes under you with no diff in your repo | Tag refs (`?ref=v1.2.3`) or registry versions |
| `depends_on` sprinkled to fix ordering | Hides a missing attribute reference and, at module level, defers every data source inside to apply time | Reference the attribute you actually need; pass explicit values between modules |
## Where Experts Disagree
- **Vanilla Terraform vs wrapper tooling (Terragrunt and friends)**: the frontier is duplication — one team with a handful of stacks loses more to wrapper complexity than it saves; once environments × stacks means maintaining dozens of near-identical backend and provider blocks, DRY tooling earns its cost.
- **Exact module pins vs `~>` constraints**: exact pins for third-party registry modules (supply-chain surface); pessimistic minor constraints acceptable for internal modules gated by your own CI.
- **One shared state vs many micro-states**: the frontier is change coupling — resources that always ship together belong in one state; every cross-state reference costs a data-source hop and an ordering problem between pipelines.
- **Terraform vs OpenTofu**: the frontier is licensing exposure and feature need, not ideology — OpenTofu is a drop-in for most existing code and adds state encryption; teams already on a managed HashiCorp platform, or depending on features that landed after the fork, pay a migration cost for nothing. Decide once, per organization (`upgrades.md`).
## Related Skills
More Clawic skills, get them at https://clawic.com/skills/terraform (install if the user confirms):
- **[aws](https://clawic.com/skills/aws)** — provider-specific resource and service guidance
- **[devops](https://clawic.com/skills/devops)** — pipeline and delivery design around plan/apply gates
- **[github-actions](https://clawic.com/skills/github-actions)** — wiring plan-on-PR / apply-on-merge workflows
- **[ansible](https://clawic.com/skills/ansible)** — configuring what lives inside the instances Terraform creates
- **[k8s](https://clawic.com/skills/k8s)** — workloads on the clusters Terraform provisions
## Feedback
- If useful, star it: https://clawic.com/skills/terraform
- Latest version: https://clawic.com/skills/terraform
Part of [Clawic](https://clawic.com), the verified skill library. Get this skill: https://clawic.com/skills/terraform.
使う前にスキルパッケージの安全性を調べ、結果に応じて導入を止めるスキルです。
OpenClaw に OpenRouter の無料モデルとフォールバック連鎖を設定するツールです。
OpenClaw の設定、資格情報、ワークスペースをバックアップし復元するスキルです。
1Password CLI でシークレットを扱うための設定と使い方です。
プロンプト注入や危険なコマンドを検出すると説明されている OpenClaw 用セキュリティプラグインです。
tmux セッションを遠隔操作し、対話型 CLI にキーを送って出力を取得します。
アプリケーションセキュリティ技術者の視点でコードと構成を監査します。
Tencent Cloud のオブジェクトストレージとデータ処理サービスを管理するスキルです。
利用者の訂正と自己点検を層構造の記憶に蓄え、使われ方に応じて昇格や保管を行うスキルです。
数式、書式、ブックの構造を保ったまま Excel ファイルを作成・点検・編集するスキルです。
Word と DOCX 文書を扱うための作業指針で、編集後にスタイルや番号、レイアウトが崩れないことに重点を置きます。
データベースや表計算、書き出した生データを意思決定に使える結論へ変えるデータ分析スキルです。
PPT を編集した後もきれいに表示されるようにするための作業規範です。
データ月:2026-09 · ダウンロード数、スター数、インストール数は公開スキルレジストリ(ClawHub、SkillHub)から月単位で集計しています。詳しくはデータの方法論をご覧ください。