
「Claude Code派?Gemini CLI派? みんなで比較LT会!」にてTerraformコードをClaude CodeとGemini CLIで作り比べてみたというタイトルで登壇しました
お疲れさまです。とーちです。
Claude Code派?Gemini CLI派? みんなで比較LT会! - connpassというイベントで「TerraformコードをClaude CodeとGemini CLIで作り比べてみた」というテーマで登壇しました。
本記事ではその際に使用した資料の概要をご紹介します。
登壇資料
登壇した際に使用した資料です。
Github リポジトリ
実際に検証した際に出来たファイルを以下のリポジトリに置いてます。CLAUDE.mdなども置いてます。
登壇の概要
今回の登壇では、以下の内容について実際に手を動かしながら比較検証を行いました
- 基本機能の比較:両ツールの特徴的な機能について
- 実践的な検証:Terraformコードの作成を通じた品質比較
基本機能比較
まず、基本的な機能比較から。CLAUDE.mdにあたるメモリ機能や、ファイル読み書き等の操作、MCP対応、会話の履歴機能等の基本的なところは同等だと思いますので、ここでは特徴的な部分だけをピックアップしています。
機能カテゴリ | Claude Code | Gemini CLI |
---|---|---|
カスタマイズ | ✅ カスタムスラッシュコマンド ✅ hooks |
❌ なし ❌ なし |
マルチモーダル | ✅ 画像貼付 | ✅ 画像・PDF |
検索機能 | ✅ Web検索 | ✅ Google Search統合 |
実行環境 | ✅ devcontainer | ✅ サンドボックス |
トークン数 | 200k | 1M |
カスタマイズ機能
Claude Codeの強みは、カスタムスラッシュコマンドとhooks機能にあります。hooksについては以前ブログでも詳しく解説しています
マルチモーダル機能
Claude CodeではCtrl+V
で画像を貼り付けることで画像を読み込ませることができます。
一方、Gemini CLIは扱える幅がより広く、PNG等の一般的な画像形式の他にSVGファイルも読み込めます。SVGに関してはClaude Codeでも読み込めるのですが、Error: File content (27032 tokens) exceeds maximum allowed tokens (25000).
というエラーが出ることからも、画像というよりテキストデータとして読んでいる感じです。
Gemini CLIはSVGファイルをbase64エンコードして画像として読んでいるのでスムーズに読めるという印象です。
また、PDFを読み込むことができるのが大きな特徴で、例えばPDFをマークダウン形式で出力したりすることができます。これはRAG等でPDFで大量にデータがあるというときに便利ではないかと思います。かなり精度が高くマークダウンにしてくれました。
Web検索機能
Web検索に関しては、Claude CodeよりもGemini CLIの方が強いと言われることが多く、Claude CodeでGemini CLIを呼び出して検索させる手法も存在します
サンドボックス機能
Gemini CLIの特徴として、サンドボックス機能が標準で備わっています。これには2つの方式があります。
macOS Seatbelt方式
macOSにはsandbox-exec
というコマンドが備わっており、これを使うと指定したコマンドを、OSレベルでファイルの読み書き、ネットワークアクセス等をブロックさせながら実行することができます。
SEATBELT_PROFILE
環境変数にプロファイル名を指定することで、ネットワークなし、書き込み制限など様々な制限が可能です。
- permissive-open (default): 書き込み制限、ネットワーク接続可
- permissive-closed: 書き込み制限、ネットワーク接続不可
- permissive-proxied: 書き込み制限、プロキシ経由でネットワーク接続可
- restrictive-open: 厳格な制限、ネットワーク接続可
- restrictive-closed: 最大級の制限
gemini-cli/docs/sandbox.md at main · google-gemini/gemini-cli · GitHubより
コンテナベースサンドボックス
export GEMINI_SANDBOX=docker
この環境変数をセットすればコンテナ内でのGemini CLI実行となります。
コンテナを使った実行自体はすんなりいくのですが、問題はGoogleCloudへの認証の部分で、自分が試した範囲だとOAuth認証でのコンテナ使用はうまくいきませんでした。デフォルトでは以下のディレクトリをコンテナボリュームとしてマウントするので認証も通ると思ったのですが、実際には失敗したので他に考慮点があるのだと思います。
- 作業ディレクトリ: Gemini CLIを起動したディレクトリをマウント
- 設定ディレクトリ: ~/.gemini
- gcloud設定: ~/.config/gcloud
APIキーを使って実行すると、コンテナによるサンドボックス実行ができました。具体的には以下の手順で実行できます。
- Google AI StudioでGEMINI_API_KEYを作成
~/.gemini/settings.json
の"selectedAuthType": "gemini-api-key"
にしてexport GEMINI_API_KEY="<払い出したAPIキー>" && GEMINI_SANDBOX=docker gemini
コンテナ内実行になるので、ホストとは隔離されるのが良いところです。また独自イメージも使用できるようなので、チーム間でGemini CLI実行環境を統一するのにも良さそうです。
実践比較:Terraformコード作成
基本機能の比較ができたところで、設計書の作成やTerraformコードの作成を実際に試してみました。
検証環境
今回は以下のような条件で検証しました
- システム構成図と簡単な要件をインプットとしてパラメータシートとTerraformコードを書いてもらう
- モデル:Claude CodeはSonnet 4、Gemini CLIはgemini-2.5-proを使用
- 設定の統一:
~/.gemini/GEMINI.md
と~/.claude/CLAUDE.md
の内容を合わせました
プロジェクトディレクトリ用のCLAUDE.mdとGEMINI.mdについては、Terraform設計ガイドラインの内容を盛り込んで作成しました。
MCP設定
MCP設定も統一しましたが、MCPが使用可能かテストをしてみると、Gemini CLIの方はどう見てもTerraform-mcpが設定されているのに明確に指示しても使ってくれず、不安がよぎりました。/mcp
コマンドの結果を提示するとようやく認識してくれました。
{
"mcpServers": {
"awslabs.aws-documentation-mcp-server": {
"command": "uvx",
"args": [
"awslabs.aws-documentation-mcp-server@latest"
],
"timeout": 30000
},
"terraform-mcp": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"hashicorp/terraform-mcp-server"
],
"timeout": 30000
}
}
}
検証手順
Claude Codeを例にした手順は以下の通りです(Gemini CLIでも同様の手順を実施)
1. 以下のファイルを用意したディレクトリを準備
- システム構成図
- 要件定義
2. パラメータシート作成
以下のプロンプトを実行しパラメータシートを作成させる。
@securityhub-architecture.jpg @securityhub-notification-requirements.mdを元に、SecurityHub通知システムのTerraform実装用パラメータシートを作成してください。
以下の形式で作成してください:
- Terraformリソース別に分類
- 設定値を具体的に記載
- variables.tfで使用する変数を明記
- outputs.tfで出力すべき値を記載
ファイル名: terraform-parameters.md
3. Terraformコード作成
以下のプロンプトを実行しパラメータシートからTerraformコードを作成させる。
作成したパラメータシートを元に、Terraformファイルをterraform-codeディレクトリに作成してください
リージョン: ap-northeast-1
4. Terraformコードのテスト
# Terraform初期化
terraform init
# 構文チェック
terraform validate
# Terraform linter(tflint)
tflint --format compact
# セキュリティスキャン(Trivy)
trivy config . --format table --exit-code 0 > security-scan.txt
# 実行計画確認
terraform plan
# 実装
terraform apply
5. AWS環境に展開して動作確認
実際にAWS環境でセキュリティイベントを発生させ、通知までの動作を確認する
パラメータシート比較
ここからは実際に各結果を比較しての所感を書いていきます。なお、今回は試行回数としてはそれぞれ1回のみになります。生成AIの特性上、実行するたびに結果は変わりますので、あくまで参考程度に捉えていただければと思います。
Claude Codeのほうが❌が多いように見えるかもしれませんが、これは設計方針の違いによるものだと思います。Gemini CLIのほうは、全体的にシンプルな作り、Claude Codeのほうは実践的な作りになっており、複雑な分、ミスが目立ったという感じです。
実務で人間がレビューしていきながら、完成させていくことを考えるとClaude Codeのほうが優れているかなと感じました(が、このあたりは好みにもよるかも)
Claude Code パラメータシート結果
生成されたパラメータシートですが、Claude Codeについては以下のような結果となりました。
評価結果
- ✅ 不足サービスがない:EventBridge、Step Functions、SNS、IAMロールの4つのサービスが明記
- ✅ 命名規則:ほぼ従っている(
_
が-
になっていた程度) - ❌ イベントパターン:SecurityHubとGuardDutyの1ルール、IAM Access Analyzerで1ルールという方針だが、SecurityHubとGuardDutyの方のイベントパターンにProductNameのパラメータが抜けているのでIAM Access Analyzerのイベントが2重で通知される結果に
- ❌ ステートマシン定義:なぜかステートマシンTypeをEXPRESSで作成、ステートマシン定義は送信時の整形などもされており、良さそうに見えたが後述の通り動作しない定義になっていた。
- ❌ IAM権限:StepFunctions実行なのにLambda実行権限が含まれているなど不適切
- ✅ リソース間の接続設定:EventBridge→StepFunctions→SNSの順で正しい
- △ パラメータの充実度:必要最低限のパラメータは記述
Gemini CLI パラメータシート結果
次にGemini CLIのパラメータシートです。パッと見の印象としては、ちゃんと表形式になっているのが良いなと思いました。
評価結果
- ✅ 不足サービスがない:EventBridge、Step Functions、SNS、IAMロールの4つのサービスが明記
- ❌ 命名規則:本来は
${var.prefix}-sechub-notification-sfn
と書かれているべきところが、var.prefix-sechub-notification-sfn
といったように{}
が抜けており読みづらい。 - ✅ イベントパターン:SecurityHubの全てのイベントを一つのEventBridgeルールで検知する設計のよう。ステートマシン定義でフィルタリングする方針
- ✅ ステートマシン定義:ステートマシン定義の条件分岐で、CRITICAL・HIGH重要度のみ通知、Access AnalyzerについてはMEDIUM・LOW重要度も通知対象という条件をクリア
- ✅ IAM権限:最低限動作するための権限は設定されていた
- ✅ リソース間の接続設定:EventBridge→StepFunctions→SNSの順で正しい
- △ パラメータの充実度:大差ない印象、この辺りは明確な指示が必要
テスト結果比較
続いて、tflintやterraform plan・applyを試した際の結果について比較します。
ここでもClaude Codeのほうが❌が多く見えますが、上記の通りClaude Codeは実践的なコードであるため多少複雑になっており、そこでミスが発生したと考えます。
Claude Code テスト結果
✅ 正常終了項目
- terraform init: 正常終了
- terraform validate: 正常終了
⚠️ 警告・問題項目
tflint結果(3件の警告):
- 未使用変数: project_name変数が宣言されているが使用されていない
- 未使用データソース: aws_caller_identity.currentが宣言されているが使用されていない
- 未使用データソース: aws_region.currentが宣言されているが使用されていない
Trivyセキュリティスキャン(2件の問題):
- LOW: CloudWatchログループが暗号化されていない
- HIGH: SNSトピックで暗号化が有効になっていない
❌ terraform plan(致命的エラー)
- Step Functions定義エラー: SubjectフィールドがSTRING型である必要があるが、異なる型が指定されている
Gemini CLI テスト結果
✅ 正常終了項目
- terraform init: 正常終了
- terraform validate: 正常終了(出力なし)
- terraform plan: 正常終了
- terraform apply: 正常終了 ⭐
⚠️ 警告・問題項目
Trivyセキュリティスキャン(1件の問題):
- HIGH: SNSトピックで暗号化が有効になっていない(Claude Codeと同じ問題)
両ツール比較サマリー
項目 | Claude Code | Gemini CLI |
---|---|---|
terraform init | ✅ 正常 | ✅ 正常 |
terraform validate | ✅ 正常 | ✅ 正常 |
tflint | ❌ 3件の警告 | ✅ 問題なし |
Trivy | ❌ 2件(暗号化不備) | ❌ 1件(暗号化不備) |
terraform plan | ❌ Step Functions定義エラー | ✅ 正常 |
terraform apply | ❌ 実行不可 | ✅ 成功 |
Claude Code リトライ
Claude Codeには以下のようなプロンプトで修正を依頼し、リトライしてもらいました。当たり前ですが、tflintやtrivyの違反項目を自動で直してくれるのが良いですね。最終的には(少し人間が手伝ったものの)apply成功しました。
以下を実行し、aws環境にリソースをデプロイしてください。\
認証は `***` コマンドで取得してください \
# Terraform初期化
terraform init
# 構文チェック
terraform validate
# Terraform linter(tflint)
tflint --format compact
# セキュリティスキャン(Trivy)
trivy config . --format table --exit-code 0 > claude-security-scan.txt
# 結果を保存
terraform plan -out=gemini-cli.tfplan\
\
terraform apply
Terraformコードの品質比較
続いてTerraformのコードの書き方の部分を見てみます。ここでは各コードをみての感想という形で比較しています。結論から言うと、どちらが好みかで言えばClaude Codeの方です。柔軟性がある作りになっていたり、コメントをちゃんと入れてくれたりするところが良いと思います。
Claude Code
所感
- variables.tfで環境名を定義しているのが良い
- validationもちゃんと入っている
- tagもプロジェクト、環境名、Terraformで管理されていることを示すタグなどがついており良い
- terraform.tfvarsで環境ごとに変わる値を柔軟に変えられるようにしているのも良い
- 各リソースが見やすくコメントで区切られている
# ===============================================
# SNS Topic for SecurityHub Notifications
# ===============================================
resource "aws_sns_topic" "securityhub_notifications" {
name = "${var.environment}-securityhub-notifications"
Gemini CLI
所感
- コメントは一切ない
- terraform.tfvarsのような配慮はなかった
- シンプルが故に一発でちゃんと動作したのは良い
まとめ
- まだまだプロンプトの良し悪しで決まる部分が多いと思っています
- 作成したコードでCLAUDE.mdに従っていない部分があるか聞いたら、ファイル構成・モジュール構造、命名規則、バックエンド設定など8つ以上の項目を挙げてきました。ルールの強制力はやっぱりそれほど高くないですね。
- プロンプトの良し悪しで決まるのだとしたら、プロンプトを管理、チーム展開できるカスタムスラッシュコマンドがあるClaude Code は強いのかなと思いました。
- ルールの補助的仕組みとしてhooksも良いですね。特にlinter実行やセキュリティチェック実行の自動化が良いと思います。
- 一方で多彩なマルチモーダル対応やWeb検索のうまさなどGemini CLI独自の部分もあるので、こういった部分は活かしていきたいです。
この記事が、皆様の参考になれば幸いです。
以上、とーちでした。