はじめに
Claude CodeにTerraformを書かせると、こんなコードが出てくることがある。
resource "aws_s3_bucket" "example" {
bucket = "my-bucket"
acl = "private" # ← v4以降でdeprecated
region = "ap-northeast-1" # ← このargumentは存在しない
}
acl引数はTerraform AWS Provider v4以降でdeprecatedになっており、region引数はS3バケットリソースには存在しない。terraform validate は構文エラーがないので通る。しかしterraform applyを実行するとAWS APIエラーが返ってくる。
「AIはTerraformでハルシネーションする」——この結論に至って使うのをやめたエンジニアは少なくない。
しかしTerraformコミュニティの著名人でterraform-best-practices.comの著者でもあるAnton Babenko はこう指摘している。「HashiCorp MCPとterraform-skillを使えば、AIの回答がリアルなドキュメントに基づいたものになる。2026年になってもAIはハルシネーションすると言い続けないでほしい」(Xポスト: https://x.com/antonbabenko/status/2012917839745659170)
問題は「AIの能力が低い」のではなく、「正しいツール構成で使っていない」ことにある。この記事では、Claude Code × Terraform を安全に使うための3層設計を解説する。
3層設計の全体像
Claude Code × Terraform を安全に使えるようにするまで、何度かインフラを壊しかけた。試行錯誤の末に落ち着いたのが、次の3層構成だ。
Layer 1: CLAUDE.md
→ 「何を担当し何を担当しないか」を明確にする(applyは人間が押す)
Layer 2: terraform-skill + HashiCorp MCP
→ ハルシネーションをゼロにする(最新ドキュメントに基づいたコード生成)
Layer 3: Hooks による自動検証
→ .tfファイル変更時に terraform fmt / validate を自動実行
terraform apply --auto-approve をブロック
それぞれを順に見ていく。
Layer 1: CLAUDE.md——「applyは人間が押す」を明文化する
Terraform専用のCLAUDE.mdで最も重要な設計は「何を担当しないか」を明確に書くことだ。
## 役割と責任分担
Claude Codeの担当:
- terraform init / fmt / validate の実行
- terraform plan の実行とプランの解釈
- モジュールのコード生成・修正
- tflintによるLintチェック
絶対に担当しないこと:
- terraform apply は絶対に実行しない(人間が承認・実行する)
- terraform destroy は絶対に実行しない
- terraform state の直接操作
- --auto-approve フラグの使用
Claude Codeは「次のステップ」を考えて行動する。指示しなければterraform applyまで実行しようとする。禁則を明文化しないと、意図せず本番インフラが変更されるリスクがある。
作業フローもCLAUDE.mdに書いておくと、毎回指示しなくて済む。
## 作業フロー
1. 変更前に terraform plan で現状確認
2. コード生成・修正
3. terraform fmt でフォーマット統一
4. terraform validate で構文チェック
5. terraform plan でプランを確認して結果を報告
6. 「人間が terraform apply を実行してください」と報告して終了
コーディング規約も合わせて書いておく。「全リソースにtagsブロックを付与すること」「IAMポリシーは最小権限の原則に従うこと」「ワイルドカード("*")の使用禁止」といったチーム固有のルールをここに置けば、毎回プロンプトで言わなくて済む。
Layer 2: terraform-skill + HashiCorp MCP——ハルシネーションをゼロにする
terraform-skillのインストール
antonbabenko/terraform-skill はTerraform・OpenTofuのベストプラクティスをClaude Codeのスキルとして提供するOSSだ。Anton Babenko(terraform-best-practices.comの著者)が作成・メンテナンスしている。
# グローバルにインストール
curl -sL https://raw.githubusercontent.com/antonbabenko/terraform-skill/master/SKILL.md \
-o ~/.claude/skills/terraform/SKILL.md --create-dirs
# プロジェクトにインストール
git clone https://github.com/antonbabenko/terraform-skill
cp terraform-skill/SKILL.md .claude/skills/terraform/SKILL.md
このスキルはClaude Codeに4つの枠組みを強制する。正しいライフサイクルの強制(init→fmt→validate→tflint→plan→applyは人間)、ショートカットのブロック(ワイルドカードIAM・ハードコード値・--auto-approveを禁止)、複雑なHCLパターンの正確な処理(dynamic blocks・for_each・locals・countを正しく使う)、そして実ドキュメントの参照要求だ。
代替として LukasNiessen/terrashark もある。公式HashiCorpドキュメントに基づいてハルシネーションを排除し、モジュラーかつセキュアなコード設計に特化している。
HashiCorp MCPで最新ドキュメントをリアルタイム参照
terraform-skillと組み合わせるのがHashiCorp MCPだ。Claude Codeの知識カットオフは2025年8月で、それ以降のTerraform AWS Provider変更(引数の追加・deprecated化・挙動変更)は把握していない。HashiCorp MCPを使うとコード生成時にTerraform Registryの最新ドキュメントをリアルタイムで参照する。
{
"mcpServers": {
"hashicorp": {
"command": "npx",
"args": ["-y", "@hashicorp/mcp-server-terraform"]
}
}
}
~/.claude/settings.json にこれを追加するだけだ。
2つを組み合わせると効果が掛け算になる。HashiCorp MCPが現在のProvider versionで有効な引数だけを参照できるようにし、terraform-skillがベストプラクティスに基づいたコード生成を担保する。冒頭のacl問題のようなdeprecated引数の混入は、この構成で原理的に発生しなくなる。
Layer 3: Hooks——.tfファイル変更時の自動検証
Hooksを使うと、Claude Codeが.tfファイルを編集するたびに自動でフォーマットと検証が走る。
.tfファイル変更時の自動フォーマット・検証
{
"hooks": {
"PostToolUse": [{
"matcher": "Edit|Write",
"hooks": [{
"type": "command",
"command": "jq -r '.tool_input.file_path' | { read fp; if [[ \"$fp\" =~ \\.tf$ ]]; then terraform fmt \"$fp\" && terraform validate; fi; }"
}]
}]
}
}
terraform apply --auto-approve の自動ブロック
CLAUDE.mdに書いただけでは不十分なケースに備えて、Hooksでもapply --auto-approveをブロックする。フックへの入力はstdin経由のJSONを使う($CLAUDE_TOOL_INPUT環境変数はGitHub Issue #9567で「空になるバグ」が報告されており信頼できない)。
{
"hooks": {
"PreToolUse": [{
"matcher": "Bash",
"hooks": [{
"type": "command",
"command": "cmd=$(jq -r '.tool_input.command // \"\"'); if echo \"$cmd\" | grep -qE 'terraform apply --auto-approve|terraform destroy'; then echo 'このコマンドはブロックされています。applyとdestroyは人間が手動で実行してください' >&2; exit 2; fi"
}]
}]
}
}
このHookにより、Claude Codeが誤ってterraform apply --auto-approveを実行しようとするとブロックされ、エラーメッセージが返る。CLAUDE.mdとHooksの二重構造にすることで、どちらか一方が機能しなくても安全を保てる。
Kubernetes manifestの自動検証も同様のパターンで実装できる。.yamlファイルの変更時にkubectl apply --dry-run=clientを走らせ、privilegedコンテナの検出も自動化できる。
何をClaude Codeに任せ、何を人間が担当するか
責任分担を明確にしておくと、チームへの展開がスムーズになる。
Claude Codeに任せる作業は次の通りだ。Terraformモジュールのスケルトン生成、既存モジュールのリファクタリング、terraform planの結果解釈・影響分析、セキュリティ設定のレビュー(IAMポリシー・S3設定など)、テスト(terraform-compliance / Terratest)のコード生成、READMEとvariables.tfのドキュメント生成、CI/CD yaml(GitHub Actions)の生成。
人間が担当するのは次の作業だ。terraform applyの実行(承認)、terraform destroyの実行、terraform stateの操作、Terraform CloudのWorkspace設定、シークレット・クレデンシャルの管理。
実際のプロンプトパターン
# モジュール生成(terraform-skillが自動有効化)
「AWSのVPCモジュールを生成して。
要件:パブリック/プライベートサブネット各2つ、NATゲートウェイ1つ、
環境変数(dev/stg/prod)でCIDRを切り替える設計。
Terraform Best Practicesに準拠して、
variables.tf・outputs.tf・README.mdも生成して。
完了したら terraform plan を実行して問題がないか確認して」
# Plan結果の解釈
「この terraform plan の出力を解釈して。
デストラクティブな変更(destroy・replace)があれば
その原因と影響を詳しく説明して」
Before/After
Before(ツール構成なし)
「S3バケットを作るTerraformを書いて」
↓
deprecated な acl 引数を使ったコードが生成される
↓
terraform validate は通る(構文エラーではない)
↓
terraform apply → AWS APIエラー
↓
エラーを貼り付け → 修正 → また別のエラー
↓
「AIはTerraformでハルシネーションする」という結論
After(3層構造を設定済み)
「S3バケットを作るTerraformを書いて」
↓
terraform-skillが自動有効化(ベストプラクティス適用)
↓
HashiCorp MCPで最新ドキュメントを参照
↓
現在のProvider versionで正しい引数を使ったコードが生成
(aws_s3_bucket_acl リソースを分離、パブリックアクセスブロック設定あり)
↓
PostToolUse Hookが自動で terraform fmt + validate を実行
↓
terraform plan でプランをレポート
「人間が terraform apply を実行してください」
↓
人間がプランを確認・承認して apply
まとめ
「AIはTerraformでハルシネーションする」という感想は、私も最初は持っていた。3層を揃えてから、その感想はほとんど消えた。
導入の優先順位はこんな感じで考えると動きやすい。
今すぐ(5分):TerraformプロジェクトのCLAUDE.mdに「terraform applyは実行しない」「--auto-approveは使わない」を追記する。これだけで最大のリスクをCLAUDE.mdレベルで抑えられる。
今日中:curlでterraform-skillをインストールし、次のTerraformタスクで動作確認する。HashiCorp MCPも.claude/settings.jsonに3行追記するだけで設定完了だ。
チーム展開:terraform apply --auto-approveのブロックHookをチームリポジトリの.claude/settings.jsonにコミットして、全員が同じ安全設定を使う状態にする。CLAUDE.mdと合わせてリポジトリに入れれば、git cloneした全員に設定が適用される。
インフラコードは間違えたときのリカバリーコストが高い。「planまでは自動、applyは人間」という分担が明確であれば、Claude Codeはインフラ作業の強力な相棒になる。

コメント