Claude Code × Terraform——「applyは人間が押す」原則とterraform-skill・HashiCorp MCPでハルシネーションを排除するIaC自動化設計

はじめに

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はインフラ作業の強力な相棒になる。

コメント

タイトルとURLをコピーしました