6/18 に Gemini CLI が消費者向けに提供終了したとき、私は夜間バッチのいくつかを慌てて書き直しました。呼び出しコマンドが直に埋め込まれていたぶん、移行の影響がスクリプト全体に散らばっていたのです。
7/1 の発表で、Antigravity 2.0 と Antigravity CLI が Gemini Enterprise Agent Platform 経由でも Google Cloud 顧客に提供され始めました。今のところ個人開発では手元のコンシューマ版で十分ですが、配布経路が複数になったという事実は無視できません。同じ轍を踏まないために、自動化を「どの経路の CLI でも動く」形に抽象化しておく設計を、実際のスクリプトとともに書いていきます。
なぜ配布経路を意識した設計が要るのか
同じ Antigravity CLI でも、どの経路で入手したかによって、周辺の前提が変わりえます。認証の通し方、既定モデル、利用上限の当たり方、環境変数の名前といった部分です。コマンド本体が同じでも、この周辺が違うと、経路をまたいだ瞬間にスクリプトが黙って失敗します。
私が Gemini CLI 停止で痛かったのは、機能が消えたことそのものより、呼び出しの詳細がコードのあちこちに直書きされていたことでした。移行とは本来「入口を一か所差し替える」作業のはずが、実際には全ファイルの grep から始まりました。
ここから得た教訓は単純です。外部ツールの呼び出しは、経路が変わりうる前提で一枚のレイヤに閉じ込めておく。そうしておけば、次に配布形態が動いても、直すのはそのレイヤだけで済みます。
呼び出しを一枚のラッパーに閉じ込める
まず、自動化スクリプトから CLI を直に叩くのをやめ、薄いラッパー越しに呼ぶ形にします。経路ごとの差はすべてこのラッパーの中だけに置きます。
#!/usr/bin/env bash
# agy-invoke.sh — Antigravity CLI 呼び出しの単一入口
# どの配布経路でも、上位スクリプトはこのラッパーだけを呼ぶ
set -euo pipefail
# 経路を環境変数で選ぶ。既定はコンシューマ版
: "${AGY_CHANNEL:=consumer}" # consumer | gcp
case "$AGY_CHANNEL" in
consumer)
AGY_BIN="${AGY_BIN:-agy}"
# コンシューマ版の認証はローカルのログイン状態に依存
;;
gcp)
AGY_BIN="${AGY_BIN:-agy}"
# Gemini Enterprise Agent Platform 経由。プロジェクトと認可を明示
export GOOGLE_CLOUD_PROJECT="${GOOGLE_CLOUD_PROJECT:?gcp 経路では必須}"
;;
*)
echo "unknown AGY_CHANNEL: $AGY_CHANNEL" >&2; exit 2 ;;
esac
# 上位からはモデルやプロンプトだけを渡す。経路の詳細は見せない
exec "$AGY_BIN" run \
--model "${AGY_MODEL:-gemini-3.5-flash}" \
"$@"
上位のバッチはこのラッパーを agy-invoke.sh --prompt "..." の形でだけ呼びます。経路を切り替えるときは AGY_CHANNEL を変えるだけで、個々のタスクは書き換えません。入口を一か所にする、この単純な原則が効きます。
実行前に CLI の能力を検出する
経路が違えば、使えるフラグやモデルが揃っているとは限りません。私は本番のバッチを流す前に、必要な能力が揃っているかを検出する preflight を挟んでいます。存在しない前提で走らせて途中で落ちるより、入口で明示的に止めるほうが、無人運用では圧倒的に扱いやすいです。
#!/usr/bin/env bash
# agy-preflight.sh — バッチ開始前に CLI の能力と経路を確認する
set -euo pipefail
fail() { echo "PREFLIGHT FAIL: $1" >&2; exit 1; }
# 1. バイナリが呼べるか
command -v "${AGY_BIN:-agy}" >/dev/null || fail "CLI が見つかりません"
# 2. 必要なモデルが利用可能か(--list-models の出力で確認)
want_model="${AGY_MODEL:-gemini-3.5-flash}"
"${AGY_BIN:-agy}" --list-models 2>/dev/null | grep -q "$want_model" \
|| fail "モデル $want_model が現在の経路で使えません"
# 3. 非対話・JSON 出力に対応しているか(自動化に必須)
"${AGY_BIN:-agy}" run --help 2>/dev/null | grep -q -- "--json-events" \
|| fail "--json-events 非対応。この経路では自動化前提が崩れます"
# 4. gcp 経路ならプロジェクト認可を確認
if [ "${AGY_CHANNEL:-consumer}" = "gcp" ]; then
[ -n "${GOOGLE_CLOUD_PROJECT:-}" ] || fail "GOOGLE_CLOUD_PROJECT 未設定"
fi
echo "preflight ok (channel=${AGY_CHANNEL:-consumer} model=$want_model)"
この preflight を各バッチの先頭に置くだけで、経路差による事故の大半を「開始前の 1 行」で止められます。私は 4 つのブログの夜間更新すべてにこれを入れており、経路を試験的に切り替えたときも、壊れる箇所が即座に一覧で分かりました。
経路ごとに変わりうる点を表で持っておく
どこが経路依存かを、頭の中ではなく表として明示しておくと、移行時の確認漏れが減ります。私が実際に管理している対応表の抜粋です。中身は自分の構成に合わせて埋めていく前提のテンプレートです。
| 観点 | コンシューマ版 | Cloud 提供版(Enterprise Agent Platform 経由) | 吸収先 |
| 認証 | ローカルのログイン状態 | プロジェクト+認可情報 | ラッパーの case 節 |
| 既定モデル | アカウントのプラン依存 | プロジェクト設定依存 | AGY_MODEL を明示 |
| 利用上限 | 個人プランの上限 | 組織の割り当て | backoff とバッチ間隔 |
| 環境変数 | 最小限 | GOOGLE_CLOUD_PROJECT ほか | preflight で検証 |
大切なのは、この表の「吸収先」列です。経路依存の差を、必ずラッパーか preflight のどちらかに寄せておく。上位のタスクロジックに経路の知識を漏らさないことが、抽象化を保つ肝になります。
経路を切り替える日の段取り
実際に経路を試したり移したりする日には、次の三手だけを踏むようにしています。手順を固定しておくと、本番の夜間バッチを止めずに検証できます。
- まず
AGY_CHANNEL=gcp を付けた preflight だけを単発で流し、能力検出が通るかを確認します。ここで落ちれば、バッチ本体は一切動かしません。
- 次に、影響の小さいタスクを 1 本だけ新経路で走らせ、出力が従来と同じ形かを目視します。壁紙アプリの AdMob 設定を読むだけの軽い処理を、私はこの試験台に使っています。
- 問題がなければ
AGY_CHANNEL を切り替え、翌朝のログで全タスクの成否を確認します。
この段取りで気をつける注意点は、いきなり全バッチを新経路へ倒さないことです。App Store と Google Play の両方にアプリを出していると、夜間更新が一斉に壊れたときの影響が大きいので、私は必ず 1 本ずつの慣らしを推奨します。
今すぐ経路を変える必要はない、が備えは軽い
正直に言えば、個人開発の今の私にとって、Cloud 提供版へ移る動機はまだ強くありません。コンシューマ版で夜間の自動更新は十分に回っています。それでもこの抽象化を先に入れておくのは、備えのコストが極めて軽いからです。
ラッパーと preflight を足すのは半日の作業で、既存のバッチは呼び出し行を 1 か所ずつ差し替えるだけで移せます。対して、経路が実際に動いてから慌てて直す作業は、以前の Gemini CLI 停止で身をもって知ったとおり、はるかに高くつきます。
外部ツールに依存する自動化を長く回すなら、「入口を一枚に閉じる」習慣そのものが資産になります。派手さはありませんが、配布形態が動くたびに助けられてきた設計です。同じように外部の CLI へ依存を抱えている方の、備えの一助になれば幸いです。