◉ANTIGRAVITY LABEN
記事一覧/AIツール
⚙ AIツール/2026-10-29中級

agy と gemini-api のどちらに頼むか迷う日の、54 行の玄関スクリプト

10 月 27 日にベータで加わった Gemini API CLI(gemini-api)と Antigravity CLI(agy)を、リポジトリを書き換える依頼と、読むだけの依頼で振り分けるシェルスクリプトを書きます。14MB の入力上限、終了コード 0〜3、タイムアウトの 124 まで、スタブで確かめた分岐だけを残します。

Antigravity CLI42agy8Gemini API CLIgemini-api8シェルスクリプト4使い分け

10 月 27 日の Gemini API の更新履歴を読んでいて、gemini-api というコマンドラインのクライアントがベータで加わったことを知りました。手が止まったのは、その一行を読んだ直後です。

名前が似ていて、どちらも Google のモデルを呼びます。agy -p で足りる用事を別のコマンドに分けるべきなのか、逆に、読むだけの用事までリポジトリを触れる agy に任せてよいのか。個人開発で一人きりのレビューをしている身には、使い始める前に線を引いておきたい話でした。

最初にお伝えしておきます。私が手元で確かめたのは、振り分けスクリプトの分岐です。gemini-api 本体はベータで、実行ファイルを取り込むことはせず、引数を記録して終了コードを返す偽のコマンドで検証しました。gemini-api の仕様は、公式ドキュメントに書かれていることだけを根拠にしています。

公式ドキュメントで確かめた gemini-api の輪郭

Gemini API CLI のガイドと、10 月 27 日の更新履歴から、振り分けに関わる部分だけを抜き出します。

  • ステートレスで依存ゼロのクライアントとされています。Interactions API を通じて、テキストや画像の生成、ファイルの分析、Gemini のマネージドエージェントの実行を行います
  • オープンソースのベータで、マイナー版のあいだに破壊的変更が入りうると明記されています。自動化の環境では版を固定します
  • analyze -i <ファイル> は PDF・画像・音声・動画・CSV・テキストを読みます。インラインの入力は生データで 14MB までで、それを超える場合は files upload を使います。アップロードしたファイルは 48 時間で削除されます
  • 終了コードは 0(成功)、1(実行時エラー・API エラー)、2(引数や検証の誤り)、3(認証・認可の失敗)です
  • generate は既定で標準出力にストリームします。-o json や --jq と組み合わせるときは --stream=false が必要です

一方の agy -p は、プロンプトを 1 つ実行して終了する headless モードです。承認が必要な操作は soft-deny になり、終了コードは 0 のまま stderr に通知が出ます。詳しくは以前の記事にまとめました。

線引きは「書き換えるか、読むだけか」

最初は、依頼文の中身を見て自動で振り分けるやり方を考えました。「直して」「修正」といった語を拾う方法です。けれども、語の拾い方で判定を決めると、「この表を直す必要があるか教えて」のような読むだけの依頼が書き換え側に流れてしまいます。判断を機械にまかせるより、呼ぶ側が一語で宣言するほうが、あとで事故の理由を追いやすいと私は考えました。

そこで玄関には edit、analyze、ask の三つだけを置きました。

種類行き先向いている依頼
editagy -pリポジトリのファイルを読み書きさせたい依頼
analyzegemini-api analyze1 つのファイルを読ませて答えだけ欲しい依頼
askgemini-api generate状態を持たない単発の質問

54 行のスクリプト

#!/usr/bin/env bash
# route.sh — 依頼の種類を見て agy と gemini-api を振り分ける小さな玄関
set -uo pipefail
 
LIMIT="${ROUTE_TIMEOUT:-5m}"
INLINE_MAX=$((14 * 1024 * 1024))   # gemini-api の -i は生データ 14MB まで
 
die() { echo "route: $1" >&2; exit "${2:-64}"; }
need() { command -v "$1" >/dev/null 2>&1 || die "$1 が見つかりません" 127; }
 
kind="${1:-}"; [ -n "$kind" ] || die "使い方: route.sh edit|analyze|ask  ..."
shift
 
case "$kind" in
  edit)
    # リポジトリを読み書きさせたい依頼は agy に渡す
    need agy
    [ "$#" -gt 0 ] || die "依頼文がありません"
    timeout "$LIMIT" agy -p "$*"
    rc=$?
    ;;
  analyze)
    # 1 つのファイルを読ませて答えだけ欲しい依頼は gemini-api に渡す
    need gemini-api
    file="${1:-}"; shift || true
    [ -f "$file" ] || die "ファイルがありません: $file"
    [ "$#" -gt 0 ] || die "質問文がありません"
    size=$(wc -c < "$file")
    if [ "$size" -gt "$INLINE_MAX" ]; then
      uri=$(timeout "$LIMIT" gemini-api files upload "$file" --wait) || die "アップロードに失敗しました" 1
      input="$uri"
    else
      input="$file"
    fi
    timeout "$LIMIT" gemini-api analyze -i "$input" --stream=false "$*"
    rc=$?
    ;;
  ask)
    # 状態を持たない単発の質問は gemini-api の generate
    need gemini-api
    [ "$#" -gt 0 ] || die "質問文がありません"
    timeout "$LIMIT" gemini-api generate --stream=false "$*"
    rc=$?
    ;;
  *) die "未知の種類です: $kind" ;;
esac
 
case "$rc" in
  0)   ;;
  124) echo "route: ${LIMIT} で打ち切りました" >&2 ;;
  2)   echo "route: 引数の組み立てが誤っています(終了コード 2)" >&2 ;;
  3)   echo "route: 認証に失敗しました。GEMINI_API_KEY か whoami を確認してください" >&2 ;;
esac
exit "$rc"

ポイントは三つあります。

1 つめは、14MB の線です。analyze はファイルの大きさを測り、上限を超えるときだけ files upload --wait で受け取った files/<id> を -i に渡します。小さなファイルまでアップロードすると、48 時間で消える一時ファイルが増えるだけだからです。

2 つめは、timeout で全体を囲んでいることです。打ち切られた場合の終了コードは、どちらの CLI のものでもなく timeout の 124 になります。公式の 0〜3 と混ざらないので、後段で見分けられます。

3 つめは、終了コードを握りつぶさないことです。2 と 3 だけは理由を一行添え、そのまま呼び出し元へ返します。

手元で確かめた分岐

偽の agy と偽の gemini-api を PATH の先頭に置き、引数を記録するだけにして、次の結果を確かめました。

呼び方結果
edit "…"agy -p … が 1 回呼ばれ、終了コード 0
小さなファイルで analyzeanalyze -i a.txt --stream=false … のみ
約 15MB のファイルで analyzefiles upload big.bin --wait のあと -i files/…
偽の CLI が 3 を返す認証の案内が出て、終了コード 3
偽の CLI が 2 を返す引数の誤りの案内が出て、終了コード 2
ROUTE_TIMEOUT=1s で 5 秒かかる偽の agy打ち切りの案内が出て、終了コード 124
未知の種類/コマンドが無いそれぞれ 64/127

注意点と、まだ確かめていないこと

  • 実機の gemini-api は動かしていません。ベータなので、フラグ名が変わる可能性があります。使う前に gemini-api --usage で確かめてください
  • 公式の例には、インストールを curl ... | bash で行う方法があります。内容を読んでから実行するか、版を固定した配布物を使うほうが安心です
  • agy の終了コード 0 は、soft-deny が起きた場合も含みます。edit の結果は、終了コードだけでなく差分を見て判断してください
  • API キーは YOUR_API_KEY のようなダミーを置き、環境変数 GEMINI_API_KEY で渡します。スクリプトに書き込みません

次のアクション

書き換える依頼は agy へ、読むだけの依頼は gemini-api へ、迷ったら呼ぶ側が一語で宣言します。 この線引きは、ベータの CLI が増えるたびに見直しながら、守っていくつもりです。

まずは手元のシェル履歴から、最近の agy -p を五つ拾い、書き換えを頼んだものと読むだけだったものに分けてみていただければ幸いです。この確認から始めるのが、いちばん手戻りが少ないと考えております。

参考にした情報

シェア

お読みいただきありがとうございます

Antigravity Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • ✦コピー&ペーストで使える実装コード付き
  • ✦毎日新しい上級ガイドを追加
  • ✦¥580/月 または ¥1,480 の永久アクセス
メンバーシップを見る →

もしこの記事がお役に立ちましたら、チップ(¥150)で応援いただけると大変励みになります。広告なしでの運営を続けるため、皆さまのご支援が大きな力になっています。

関連記事

⚙ AIツール2026-10-15
agy の headless モードに日本語の校閲を任せる 50 行のラッパー
Antigravity CLI(agy)の headless モードを、日本語の校閲用シェルスクリプトに包みます。stdin の渡し方、終了コード 0 でも応答が空になる場合、引数の長さ上限、2027 年 1 月の単価改定を含めた費用の見積もりまで、手元で確かめた順に書き残します。
⚙ AIツール2026-09-15
役割で分けるのをやめた日 — Antigravity CLI と Claude Code の預け先を決める3つの問い
無人で回していた処理が承認待ちのまま黙って止まりました。二つのエージェント CLI を得意分野で分けるのをやめ、承認の境界で振り分け直すまでの記録と、判断に使っている3つの問いを書き残します。
⚙ AIツール2026-09-11
AGY_CLI_HIDE_LOGO から始める、狭い端末とスクリーンリーダーと録画のための Antigravity CLI 設定
ロゴアート、メールアドレス、長すぎる出力、勝手に走る自動コピー。Antigravity CLI の見た目を抑える環境変数と設定を、狭い端末・スクリーンリーダー・画面録画という三つの場面ごとに並べました。