目次

1.はじめに
2.Plan Modeについて
3.Plan Modeを使ってみた
4.おわりに

1.はじめに

Plan Mode とは Gemini CLI が実装を始める前に調査・計画のプロセスを踏み、ユーザーとの合意を得て実装を行うモードとなります。

本ブログでは Terraform の AWS ネットワークリソースのコードに対して Plan Mode を試してみます。

具体的にはネットワークの設定において後から NACL の設定要件が追加されたというシナリオを想定。
この追加作業を Plan Mode で実行し、どのように実装まで落とし込まれていくか、試してみた結果を紹介します。
※ 本ブログの趣旨は Gemini CLI の Plan Mode の動作をお見せすることなので、Terraform コードの掲載は省略します。

環境情報

  • macOS:Tahoe 26.3.1
  • Node.js のバージョン( node --version ):24.11.1
  • Gemini CLI のバージョン( gemini --version ):0.33.1

2.Plan Modeについて

Gemini CLI には CLI Help Agent という Gemini CLI の設定やコマンドについて質問すると教えてくれる Subagent が組み込まれているので、これを使って Plan Mode が何たるか聞いてみました。

Gemini CLI を立ち上げユーザープロンプトに以下を入力し実行します。

> @cli_help "Plan Mode(プランモード)」について教えてください" 


応答結果は以下です。

✦ Plan Mode(プランモード)は、実装を開始する前に安全な読み取り専用環境で調査・設計・計画を行うためのモードです。

主な活用シーン
* 複雑なタスクの検討: 大規模なリファクタリングや新機能追加など、影響範囲が広い作業の前段階。
* 安全なコード調査: ファイルを誤って書き換えるリスクを排除しつつ、既存のコードベースを深く理解したい時。
* 実装方針の合意: 具体的なコード修正を行う前に、アプローチや手順を整理してユーザーと確認し合いたい時。

メリット
* 安全性: 書き込みが制限されるため、意図しない破壊的変更を防げます。
* 思考の質の向上: 調査結果に基づいた詳細なプラン(背景、影響、代替案など)を作成し、推論能力の高いモデルで最適な設計を導き出します。
* 効率的な実行: 承認されたプランに基づき、その後の実装フェーズをスムーズに進めることができます。

使い方
* 開始: プロンプトで /plan と入力するか、「〜のプランを立てて」と指示します。
* 切り替え: Shift + Tab キーで Default / Auto-Edit / Plan モードを切り替えられます。

複雑な課題に取り組む際は、まず Plan Mode で「急がば回れ」の精神で設計を行うのがおすすめです。

要するに、実装を行う前に AI と一緒に設計を練ることで、安全かつ精度が高い実装の実現をサポートする機能となります。

3.Plan Modeを使ってみた

前提条件

ネットワークリソースの tf ファイルを用意した状態から開始します。
ディレクトリ構成は以下です。

project/
├── envs/
│   └── dev/
│       ├── README.md            # dev環境の仕様書(CIDR・サブネット特徴など)
│       ├── main.tf
│       ├── variables.tf
│       ├── provider.tf
│       ├── outputs.tf
│       └── terraform.tfvars
└── modules/
    └── vpc/
        ├── main.tf
        ├── variables.tf
        └── outputs.tf

以下は README.md の内容で、これに沿ったリソースが tf ファイルに定義されています。

# dev環境 インフラ仕様書

## 基本情報

- リージョン: ap-northeast-1(東京)
- AZ: ap-northeast-1a / ap-northeast-1c

## VPC

| 項目 | 値 |
|---|---|
| VPC CIDR | 10.0.0.0/16 |

## サブネット設計

> 全サブネット共通: VPC CIDR (10.0.0.0/16) 内のプライベート通信は許可

| 名前 | AZ | CIDR | 特徴 |
|---|---|---|---|
| public-1a  | 1a | 10.0.0.0/24  | IGW経由でIN/OUT可能 |
| public-1c  | 1c | 10.0.1.0/24  | IGW経由でIN/OUT可能 |
| protected-1a | 1a | 10.0.10.0/24 | NATGWで外にOUTのみ |
| protected-1c | 1c | 10.0.11.0/24 | NATGWで外にOUTのみ |
| private-1a | 1a | 10.0.20.0/24 | インターネット完全遮断 |
| private-1c | 1c | 10.0.21.0/24 | インターネット完全遮断 |

## 命名規則

**基本フォーマット:** `{sys}-{env}-{リソース種別}-{識別子}`

| リソース | 命名例 |
|---|---|
| VPC | `test-dev-vpc` |
| パブリックサブネット | `test-dev-subnet-public-1a` |
| プロテクトサブネット | `test-dev-subnet-protected-1a` |
| プライベートサブネット | `test-dev-subnet-private-1a` |
| IGW | `test-dev-igw` |
| NAT Gateway | `test-dev-natgw` |
| ルートテーブル | `test-dev-rtb-public` |

ちなみに、Gemini CLI には Codebase Investigator というプロジェクト内のコードを分析し、どのようなプロジェクトかを教えてくれる Subagent が組み込まれているので、これを使ってみます。

ユーザープロンプトに以下を入力し実行します。

> @codebase_investigator


応答結果は以下です。

✦ codebase_investigatorによる調査の結果、このプロジェクトは環境別の設定(envs/dev)と、再利用可能なネットワーク構成(modules/vpc)に分かれた、クリーンなTerraform構造であることが確認されました。

プロジェクト構成の概要
依存関係とデータの流れ
* envs/dev/main.tf が modules/vpc をソースとして呼び出し、環境固有のパラメータを渡しています。
* 具体的なパラメータ値(CIDR、AZ、環境名など)はenvs/dev/terraform.tfvars で定義されており、これが variables.tfを経由してモジュールに供給されます。

modules/vpc で管理されている主要リソース
* VPC (aws_vpc): ネットワークの基盤。
* Subnets: パブリック、プロテクテッド(NAT経由)、プライベートの3層構造。
* Internet Gateway (aws_internet_gateway): インターネット接続ポイント。
* NAT Gateway (aws_nat_gateway): プロテクテッドサブネットから外への通信用。
* Route Tables: 各サブネット層に対応したルーティング設定。

モジュールのインターフェース
* 入力(modules/vpc/variables.tf): VPC CIDRや各サブネットのCIDRリスト、利用するAZなどを柔軟に設定可能です。
* 出力(modules/vpc/outputs.tf): 作成されたVPC IDや各サブネットのIDを返し、envs/dev/outputs.tfを通じて外部から参照できるようになっています。

この構造により、ネットワーク定義を共通化しつつ、環境ごとに異なるネットワーク設計を容易に流し込めるようになっています。

さらに詳しく知りたい特定のファイルや、この構成に基づいた具体的な変更・追加の作業(例:新しい環境の作成、リソースの追加など)のご要望はありますか?

ここでお伝えしたい事としては、

  • 3層構造のサブネットとしている。
  • modules/vpc には NACL に関する情報がない。つまり、コードとして明記していない。

ということです。

今のコードを terraform plan/apply した場合、作成される NACL の設定は、すべての通信を許可するものとなります。

これに対して、3層構造としている各サブネットに指定ルールに即した NACL を設定します。

この対応を Plan Mode で実行します。

ちなみに事前準備しておいたコードは terraform plan が成功するところまで確認しております。
terraform apply は実行しておりません。

$ terraform plan
〜〜省略〜〜
Plan: 19 to add, 0 to change, 0 to destroy.

Plan Modeの実行

NACL の設定要件として1つのルールにて、すべてのポートと IP を許可する形はインバウンド、アウトバウンドともに NG とします。

サブネットは3層構造で、インターネットへの直接的な出入りが可能なパブリックサブネット、NAT ゲートウェイ経由でインターネットへのアウトバウンドアクセスが可能なプロテクトサブネット、インターネットへのルートを持たない(内部通信用)プライベートサブネットとなっています。

パブリックサブネットには ALB、プロテクトサブネットには EC2(Linux)、プライベートサブネットには RDS(MySQL)の配置を見込む形で NACL のルールを設定します。

NACL のルールに関する方向性は事前にまとめており、Plan Mode を実行する中で以下の情報を AI に連携します。

## 前提
- NACLはサブネット種別(public / protected / private)ごとに個別に作成してください。
- 既存のコードはmodules/vpc/配下にあります。
- エフェメラルポートはLinux カーネル (Amazon Linux カーネルを含む) を前提に32768-61000を使用してください。
- NATGWおよびALBが使用するエフェメラルポートは1024-65535を使用してください。

## パブリックサブネット
【インバウンド】
- TCP 443: 0.0.0.0/0 許可
- TCP 1024-65535: 0.0.0.0/0 許可

【アウトバウンド】
- TCP 80: 両AZのprotected subnet CIDR 許可
- TCP 443: 0.0.0.0/0 許可
- TCP 1024-65535: 0.0.0.0/0 許可

## プロテクトサブネット
【インバウンド】
- TCP 80: 両AZのpublic subnet CIDR 許可
- TCP 32768-61000: 0.0.0.0/0 許可

【アウトバウンド】
- TCP 443: 0.0.0.0/0 許可
- TCP 3306: 両AZのprivate subnet CIDR 許可
- TCP 1024-65535: 両AZのpublic subnet CIDR 許可

## プライベートサブネット
【インバウンド】
- TCP 3306: 両AZのprotected subnet CIDR 許可

【アウトバウンド】
- TCP 32768-61000: 両AZのprotected subnet CIDR 許可

では Gemini CLI を立ち上げ、/plan コマンドを実行し Plan Mode に切り替えます。

ユーザープロンプトに以下を入力し、やり取りを開始します。

> このプロジェクトにはAWSのネットワークリソースのTerraformコードが記載されています。追加要件として、NACLの設定が必要となりました。 まずはプロジェクトの構成とREADME.mdの仕様書を確認してください。

プロジェクトの内容を読み込んだ上で、NACL の設定方針に関する質問が来ました。
1の層ごとに専用NACLを作成を選択します。

次に NACL のルールについて質問をされたので、4 の自由回答を選択し、先ほどの方向性の情報を渡す形とする文章を記載しました。

最後に質問に対する回答のレビューをし、問題なければエンターを押下します。

エンターを押下すると、Ask User のステップが完了し、次のステップが始まります。

実装計画ファイルなるものを作成の上、実装計画に関する承認が求められました。

NACL 用の tf ファイルを新規作成しようとしているので、main.tf に追記する形のフィードバックを入れます。

フィードバックを反映したNACL設定追加計画を再提示してくれました。

1を選択し、計画に合意、ツールの実行を許可します。

実行の許可に伴い、実装が開始されました。

tf ファイルへのコードの追加後、terraform init と terraform validate の実行を要求されたので許可します。

実装完了とのことです。
このまま terraform plan の実行も許可します。

terraform plan の実行に成功したとのことで、ここでやり取りは終了となりました。

Plan Mode を通じて NACL の設定コードが追加されました。
terraform apply が問題なく実行できるか、NACL が3種類のサブネットごとに作成され、方針通り NACL のルールが設定されているか、コンソールで見てみます。

まず、terraform apply は問題なく成功しました。

$ terraform apply
〜〜省略〜〜
Apply complete! Resources: 40 added, 0 changed, 0 destroyed.

続いて コンソールにて NACL の設定を見てみます。

3層構造のサブネットに対して、それぞれの NACL が関連付けされています。

各 NACL についても方針通りのルールが設定されています。

パブリックサブネット用 NACL

プロテクトサブネット用 NACL

プライベートサブネット用 NACL

以上が Plan Mode を試してみた結果となります。
※ 本ブログの趣旨は Gemini CLI の Plan Mode の動作をお見せすることであり、今回設定した NACL のルールが意図した通信の実現を保証するものではありません。
NACL はセキュリティグループと異なりステートレスであるため、インバウンド・アウトバウンド双方向のルール設定が必要であり、設定ミスが通信断に直結します。
実際のインフラ構築・保守対応においては、EC2などのリソースを配置しセキュリティグループも設定した上で、各サブネット間の通信が成功するかネットワークテストで確認することをおすすめします。

4.おわりに

Plan Mode を実際に動かしてみましたが、プロジェクトの内容を読み込んだ上で NACL 構成とルールの設定方針を自由回答の選択肢も含めて提示、承認プロセスを踏ませて実装を開始する形でした。

一見、この段取りを踏む形が手間に感じるかもしれませんが、チャットボット感覚で大雑把に AI と何度もやりとりするより、Plan Mode を活用して計画を立て、建設的に作業を行う方が手戻りなく要件通りの実装が実現できるかと思います。

AI ツールにはさまざまな機能があり、用途ごとの使い分けが重要かと思います。
Plan Mode が最適と感じるタイミングでぜひ活用してみてください。