6/18 に Gemini CLI と Gemini Code Assist の IDE 拡張が個人向けの提供を終了し、後継の Antigravity CLI へ移行する、という案内が出ています。私自身、個人開発で複数のサイトの自動投稿を夜間にまとめて回しているので、締切の少し前に移行先を試しておこうと CLI を入れ替えてみました。
入れ替えて最初に気づいたのは、起動が明らかに速くなっていることでした。Antigravity CLI は Go で実装し直されています。旧 Gemini CLI は Node ベースだったので、プロセスの立ち上がりにかかる時間がそもそも違います。ただ「速くなった気がする」だけでバッチの組み方を変えるのは危ういので、まず数字にすることにしました。この記事は、その実測と、数字を見てから夜間バッチをどう組み直したかの記録です。
「速い・遅い」を語る前に、3つの時間を分ける
CLI を自動化に載せて遅いと感じるとき、原因は大きく3つに分かれます。これを混ぜて1つの数字にしてしまうと、改善の打ち手を間違えます。
- 起動時間(cold start): プロセスが立ち上がり、設定の読み込みと認証の初期化が終わるまで。コマンドを投げてから「受け付けた」状態になるまでの時間です。
- 初回応答時間(time to first token): リクエストを送ってから、モデルの最初の出力が返り始めるまで。ネットワークとモデル側のキューイングが効いてくる区間です。
- 本処理時間(throughput): 最初のトークンが出てから、応答が完結するまで。出力が長いほどここが支配的になります。
旧 CLI で「夜間バッチが遅い」と感じていた原因が起動時間なのか本処理なのかで、対策はまったく変わります。起動が重いなら投げる回数を減らす(=まとめる)べきですし、本処理が重いなら出力を短く区切るか、並列に流すべきです。区間を分けずに総時間だけ見ていると、この判断ができません。
ヘッドレス実行でベンチマークを取る
Antigravity CLI には非対話(ヘッドレス)実行があり、プロンプトを引数で渡して結果を標準出力に流せます。これがベンチマークの土台になります。対話モードのまま計測すると、TTY の有無で出力の出方が変わって数字が安定しないので、必ず非対話で計測します。
まず、起動だけを測る最小コマンドを用意します。--version のような即座に返るサブコマンドは、本処理を含まない「起動 + 終了」だけの時間を返してくれるので、cold start の指標になります。
#!/usr/bin/env bash
# bench_startup.sh — 起動時間だけを N 回測って中央値を出す
# 本処理を含まない --version を使うことで cold start を切り出す
set -euo pipefail
CMD="${1:-antigravity}" # 旧CLIと比べるときは引数で gemini を渡す
N="${2:-20}"
times=()
for i in $(seq 1 "$N"); do
start=$(date +%s.%N)
"$CMD" --version >/dev/null 2>&1
end=$(date +%s.%N)
times+=("$(echo "$end - $start" | bc)")
done
# 中央値(外れ値に強い)を出す。平均はウォームアップの影響を受けやすい
printf '%s\n' "${times[@]}" | sort -n | awk '
{ a[NR]=$1 }
END {
if (NR % 2) print "median:", a[(NR+1)/2];
else print "median:", (a[NR/2] + a[NR/2+1]) / 2;
print "min:", a[1], "max:", a[NR];
}'
平均ではなく中央値を出しているのには理由があります。最初の数回はファイルキャッシュやネットワーク接続の確立で遅くなりがちで、平均はその影響を強く受けます。バッチを設計するときに知りたいのは「ふだん何秒で立ち上がるか」なので、外れ値に強い中央値のほうが判断に使えます。
次に、初回応答と本処理を分けて測ります。CLI が応答をストリーミングで流す場合、標準出力に最初の1バイトが届いた時刻を記録すれば、初回応答と本処理の境目が取れます。
#!/usr/bin/env bash
# bench_response.sh — 初回応答と本処理を分けて測る
# 標準出力の最初の1行が出た時刻で区間を分割する
set -euo pipefail
CMD="${1:-antigravity}"
PROMPT="${2:-200文字程度で、ベンチマーク用のダミー文章を書いてください}"
start=$(date +%s.%N)
first_token=""
# run --print は非対話でプロンプトを実行し結果を標準出力へ流す想定
"$CMD" run --print "$PROMPT" 2>/dev/null | while IFS= read -r line; do
if [ -z "$first_token" ]; then
first_token=$(date +%s.%N)
echo "ttft: $(echo "$first_token - $start" | bc)s"
fi
done
end=$(date +%s.%N)
echo "total: $(echo "$end - $start" | bc)s"
ここでのポイントは、while read の中で最初の行が来た瞬間に時刻を打っていることです。最後にまとめて出力を受け取る書き方だと、ストリーミングであっても初回応答の時刻を取り逃します。CLI のサブコマンド名(run --print など)はバージョンによって変わるので、手元の antigravity --help で実際の非対話実行オプションを確認してから合わせてください。
旧 CLI との体感差を数字にする
手元の環境(macOS・有線接続・同一プロンプト20回)で取った中央値は、おおよそ次のような差でした。数値は環境に強く依存するので、絶対値ではなく「区間ごとにどこが効いたか」を見てください。
- 起動時間: 旧 Gemini CLI 約 0.9 秒 → Antigravity CLI 約 0.2 秒。Go 実装で最も差が出たのがここでした。
- 初回応答時間: 旧 約 1.3 秒 → 新 約 0.8 秒。動力が Gemini 3.5 Flash になったことが効いていそうですが、ここはネットワークとモデル側キューの影響が大きく、計測のたびにぶれます。
- 本処理時間(同じ長さの出力): 大きな差はなし。出力トークン数が同じなら、ここは素直にトークン生成速度に比例します。
公称では動力の Gemini 3.5 Flash は競合フロンティアモデルの約4倍速とされますが、私の計測では同じ出力長の本処理時間に大きな差は出ませんでした。公称値はあくまで参考で、ベンチマークは自分の用途で取り直す価値がある、と改めて感じた点です。
つまり、私の用途で効いていた遅さの正体は、本処理ではなく起動時間でした。夜間バッチでは1サイトあたり数十回 CLI を呼んでいたので、1回あたり 0.7 秒の起動短縮が、回数ぶんだけ積み上がっていた計算になります。逆に言えば、本処理が重いタスクではこの差はほとんど体感できません。だからこそ区間を分けて測る価値があります。
実測値から夜間バッチを組み直す
数字が出たので、設計を見直します。私の旧構成は「1サイトずつ直列で、CLI を細かく何度も呼ぶ」というものでした。起動が重かった旧 CLI ではこれが純粋な損失だったのですが、起動が軽くなったことで判断材料が変わります。
考え方はシンプルで、起動が支配的なら呼び出し回数を減らす(バッチ化)、本処理が支配的なら時間帯を分けて並列化する、です。Antigravity CLI では起動が十分軽くなったので、無理に1プロセスへ詰め込むより、サイトごとに独立したプロセスを別の時間帯へずらして流すほうが、失敗時の切り分けが楽でした。
#!/usr/bin/env bash
# nightly.sh — サイトごとに独立プロセスへ分け、開始時刻をずらす
# 起動が軽い前提なので「1プロセスに詰める」より「分けてずらす」を優先
set -euo pipefail
declare -A OFFSET=(
[siteA]=0 # 00:00 起点
[siteB]=900 # +15分
[siteC]=2700 # +45分
[siteD]=3600 # +60分
)
run_site() {
local site="$1"
sleep "${OFFSET[$site]}"
# 1サイトの処理。本処理が重い場合はここをさらに細分化する
antigravity run --print "$(cat prompts/${site}.txt)" \
> "logs/${site}-$(date +%F).log" 2>&1
echo "[$(date +%T)] ${site} done (exit $?)"
}
for site in "${!OFFSET[@]}"; do
run_site "$site" & # 各サイトを独立プロセスで並列起動
done
wait
echo "all sites finished"
私はこの分散構成に切り替えてから、どのサイトの処理で失敗したのかをログ単位で追えるようになり、夜中に原因を探す時間が減りました。
時刻をずらしているのは、同時刻に全プロセスが初回リクエストを投げると、API 側のレート制限とモデルのキューに同時に当たって、結局初回応答が遅くなるからです。起動は速くても、初回応答の区間はネットワークとキューに律速されます。ここを実測で確かめておくと、「並列にしたのに速くならない」という落とし穴を避けられます。オフピークへの分散と、非対話実行をどこまで自動化に委ねるかは、Antigravity CLI を非対話で回す — CI と cron に載せる前の設計 でも整理しています。
計測でハマった落とし穴
実際に測ってみて、数字を歪める要因がいくつかありました。先に知っておくと無駄な再計測を減らせます。
ウォームアップを捨てる。最初の2〜3回は接続確立やキャッシュ未ヒットで遅くなります。中央値を取るか、明示的に最初の数回を捨ててから計測してください。1回だけ測って「遅い」と判断するのが一番危ないパターンです。
出力バッファリングに注意する。パイプ越しに渡すと、CLI 側が出力をブロックバッファリングして、ストリーミングのはずなのに最初の1行がまとめて遅れて届くことがあります。初回応答時間が不自然に本処理時間と一致するときは、これを疑ってください。非TTY 環境で標準出力が消える・遅れる挙動については Antigravity CLI(agy)を CI で非対話実行する — stdout が消える非TTY問題への対処 に詳しくまとめています。
レート制限を計測値と混同しない。短時間に連続で投げると、初回応答時間に見えていたものが実はレート制限の待ち時間だった、ということが起きます。計測ループには各回の間に十分な間隔を入れるか、レート制限のレスポンスを検出して計測から除外してください。
--version が本当に軽いか確認する。CLI によっては --version でも設定ファイルの読み込みやアップデートチェックが走り、純粋な起動時間にならないことがあります。strace や --help との差分で、余計な処理が混ざっていないか一度だけ確認しておくと安心です。
移行のタイミングをどう決めるか
6/18 の締切があるとはいえ、慌てて全部の自動化を一度に載せ替えるのはおすすめしません。私は、まず計測用の小さなプロンプトで起動と初回応答だけを確かめ、自分のバッチで支配的な区間がどこかを特定してから、影響の小さいサイトの1本だけを Antigravity CLI に切り替えて1週間運用しました。それで安定を確認してから残りを移しています。CLI の選び分けそのものの考え方は Gemini CLI と Antigravity を本気で使い分ける — 2026年5月、現場で出した結論 も参考になります。
まず手元で bench_startup.sh を20回回して、自分の環境での起動時間の中央値を出すところから始めてみてください。その1つの数字があるだけで、「呼び出しをまとめるべきか、時間帯を分けて並列にするべきか」の判断が、ぐっと具体的になります。