[!CAUTION]
この実装案は superseded(廃案)です。 Phase 0 の実機調査で、agyは Gemini CLI の1:1後継ではなく、副作用を伴う自律エージェントであることが判明しました。本書は判断履歴として凍結し、以後は74_Antigravity CLIへの移行_実装案_v2.mdを正本とします。廃案日: 2026-06-21 / 理由: コマンド・出力・権限モデルの前提崩壊
関連 issue: #74 Gemini CLIが使えなくなったのでAntigravity CLIに移行する
個人向け Gemini CLI は 2026-06-18 にリクエスト提供を終了し、Google は後継として Antigravity CLI(agy)を案内している。butler2 は個人向け認証の Gemini CLI に依存して実装・レビュー・Wiki 要約を実行しているため、現状ではこれらが動かない。agy へ移行して機能を復旧する。
単純なコマンド名置換ではない。現行は 3 系統の異なる起動契約を持ち、出力形式・認証・プロセス監視・エラー判定がそれぞれ違うため、契約ごとに移行方針を決める。
| 用途 | 実装 | 起動コマンド | 入出力 | プロセス監視 | 認証検出 |
|---|---|---|---|---|---|
| 実装メイド | butler/maids/gemini_cli_implement_maid.py |
gemini --approval-mode auto_edit --output-format json -p <prompt>(GEMINI_CLI_COMMAND で上書き可、registry の command/approval_mode/output_format 由来) |
プロンプトは引数。JSON 出力を解析し session_id / response / stats(totalRequests / tokens.total)を抽出 |
あり: start_new_session=True でプロセスグループ起動、os.killpg で SIGTERM→grace→SIGKILL、git status 停滞検出(stagnation_timeout_seconds=90, progress_poll_seconds=10) |
8 パターン(Please set an Auth method / GEMINI_API_KEY / GOOGLE_GENAI_USE_GCA / token expired / 401 unauthorized / unauthorized client / sign in with google / authentication required) |
| レビューメイド | butler/maids/gemini_cli_review_maid.py |
quick: gemini --output-format text -p <prompt> / thorough: gemini --approval-mode plan --output-format text -p <prompt> |
diff を stdin で渡す、出力は text をそのまま review_text に | なし(単純な subprocess.run(timeout=180/300)、子プロセス停止保証なし) |
3 パターン(Auth method / GEMINI_API_KEY / Sign in) |
| Wiki 要約 | butler/wiki_doc_summarizer.py |
gemini --skip-trust -p <prompt>(GEMINI_CLI_COMMAND で上書き可) |
プロンプトは引数、出力 text をそのまま要約に。maid_registry を経由せず直接起動 | なし(subprocess.run(timeout=30)) |
なし(失敗時は空文字列を返すだけ) |
config/maid_registry.yml
gemini_cli_implement(launch_config: command, command_env, approval_mode, output_format, command_env_vars={GOOGLE_GENAI_USE_GCA, GEMINI_CLI_TRUST_WORKSPACE}, progress_poll_seconds, stagnation_timeout_seconds, terminate_grace_seconds, max_attempts: 2)gemini_cli_review(launch_config: command_env_vars のみ)config/intent_maid_routes.yml
intent: implement → goose_openrouter_grok41fast_implement(優先, grok_fast_safe)+ gemini_cli_implement(フォールバック, max_attempts:2)intent: review → gemini_cli_review のみ(フォールバックなし)butler/mcp_facade.py
GEMINI_CLI_COMMAND / GEMINI_CLI_TRUST_WORKSPACE / GOOGLE_GENAI_USE_GCA / GEMINI_API_KEYtests/test_wiki_non_llm_maid.py のヒットはドキュメントのファイル名のみ)。壊れても自動検知できないため、移行時にテストを追加する。agy 上で復旧する。agy に存在しない(Phase 0 で確定)ため、実装メイドの evidence は「JSON をそのまま維持」ではなく「agy の出力から得られる範囲で再構築」する。取得不能な項目(stats 等)は null を許容する。unavailable)。gemini_cli_* を残すのはこの層向けの互換経路という位置づけ)。unavailable を返す」とし、別 provider が必要なら別 issue とする。agy v1.0.3→1.0.10 を実機で probe した。詳細ログと fixtures は docs/検討用/74_agy_live_probe.md / docs/検討用/fixtures/agy_probe/。当初の「コマンド名+フラグ置換」前提は実機で覆った。
agy の契約| 項目 | 結果 |
|---|---|
| 非対話実行 | -p / --print / --prompt(--print-timeout 既定 5m)。ただし単発出力ではない(下記) |
| 権限モード | --dangerously-skip-permissions(全権限自動承認)。--sandbox(ターミナル制限)。--approval-mode plan のような読み取り専用/計画モードの明示フラグは無い |
| 出力形式 | --output-format json 相当が無い。出力は「I will …」形式の自然言語 narration ストリーム。stderr 空・終了コード 0 |
| 認証 | 既存 Gemini と共有(~/.gemini/oauth_creds.json、~/.antigravitycli/<uuid>.json は ~/.gemini/config/projects/... への symlink)。agy 固有設定は ~/.gemini/antigravity-cli/settings.json |
| 環境変数 | ANTIGRAVITY_CONVERSATION_ID / ANTIGRAVITY_REVIEW / ANTIGRAVITY_BROWSER 等。ANTIGRAVITY_CLI_COMMAND 相当の起動コマンド上書き変数は未発見 |
| バージョン | probe 中に 1.0.3→1.0.10 へ自己更新(再現性の前提が崩れる) |
| その他 | --add-dir(workspace 追加)、-c/--continue・--conversation(会話再開)、サブコマンド install/update/plugin/changelog |
agy -p は副作用ありのフル自律エージェント最小プロンプト(Reply with exactly the word: PONG)でも、agy はタスクとして解釈してエージェントループを起動し、--dangerously-skip-permissions 無しで workspace 探索・git status・uv run pytest・git commit を自律実行した(最終的に --print-timeout 5m で timeout)。これは Gemini CLI の -p(単発応答)とは根本的に異なる。
--output-format json が無いため、session_id / response / stats(totalRequests / tokens.total)を機械抽出できない。現行 gemini_cli_implement_maid.py の JSON 解析・統計 evidence・出力警告抽出は作り直しが必要。代替(plugin / SDK / 隠し --json(バイナリ内に文字列あり、help 非掲載)/ 別の機械可読口)の有無を Phase 0 残調査で確認する。agy -p をそのまま使えない: 副作用(ファイル変更・commit・コマンド実行)を伴うため、「読み取り専用で応答だけ欲しい」用途には --sandbox 等で副作用を確実に抑制できることを確認してからでないと採用できない。--dangerously-skip-permissions 未指定でも操作した。非対話実行で確実に読み取り専用へ落とす方法を確定するまで、implement/review の agy 有効化はブロックする(実装案の Phase 0 ゲートが妥当だったことが裏付けられた)。GOOGLE_GENAI_USE_GCA 系とは別系統の可能性。認証エラー文言は未採取で、Phase 0 残調査が必要。agy update の抑制・バージョン固定方法を確認し、テストは固定 fixture 駆動にする。--json / 設定)の有無。--sandbox の制限範囲(ファイル書き込み・コマンド実行・ネットワークを止められるか)を副作用の出ない最小プロンプトで確認。現行 3 系統はコマンド文字列・フラグ・出力スキーマ・認証パターンが各所にハードコードされている。移行で同じ分散を繰り返さないため、CLI 固有部分を集約する。ただし「実行ライフサイクル」「出力方言」「use-case 固有ポリシー」を混ぜず、3 層に分ける(実装メイド固有の監視ロジックが review / Wiki へ漏れないようにするため)。
butler/maids/cli_backends/gemini.py / antigravity.py): command 構築、フラグ、認証判定、出力 parse(JSON スキーマ・出力警告パターン)。gemini / agy の方言を吸収する。あわせて:
_build_gemini_command() でハードコードしているので config 化する)。GEMINI_CLI_COMMAND 直読みをやめ、共通の CLI 解決関数(共通 runner + backend adapter)を使う。| 対象 | 方針 | 理由 |
|---|---|---|
| maid_id | 新規に antigravity_cli_implement / antigravity_cli_review を追加し、gemini_cli_* は enabled: false で残す |
gemini 経路を即時には壊さない(ただし下記のとおり個人向けでは実効ロールバックにならない点に注意) |
| 環境変数 | agy backend は ANTIGRAVITY_CLI_* と registry の agy 既定値だけを読む。GEMINI_CLI_* は gemini backend 専用に限定する。ANTIGRAVITY_CLI_COMMAND 未設定時に GEMINI_CLI_COMMAND へフォールバックしない |
GEMINI_CLI_COMMAND には通常 gemini ... が入っており、agy backend がこれを読むと終了済みの gemini を起動してしまう(設定互換ではなくバックエンドの取り違え)。移行補助が要る場合は起動 argv[0] を検証し、backend と不一致なら明示エラーにする |
| evidence キー | gemini ブロック名は当面維持し、内部に cli: "antigravity" を付与。新規参照は CLI 中立な構造へ寄せ、撤去条件を Phase 4 に明記する |
既存の evidence 解析・テストを壊さない |
gemini_cli_* を enabled:false で残しても、個人向けでは Gemini CLI 自体がリクエストを受けないため復旧先にならない。これは「企業 / Gemini Code Assist Standard・Enterprise / 有料 API キー利用者向けの互換経路」と位置づけるのが正確。
個人向けのロールバックは次のいずれかになる:
unavailable(agy 不調で実行不可)を返す別 provider の用意を本 issue の対象外にするなら、その制約を明記する(後述の非目標に追記済み)。
intent_maid_routes.yml の切替で gemini ↔ agy を行き来できるのは review / implement のみ。Wiki 要約は maid registry / intent route を経由しないため、現案でも切替点が複数残る。3 系統を一括で切り替えたい場合は、共通 backend resolver の選択設定を正本にし、maid と Wiki の双方がそれを参照する設計にする。一括切替を求めないなら、切替は review / implement の routing に限定し、Wiki 要約は共通解決関数側の設定で切り替える。
一次調査は 2026-06-21 に実施済み(結果は前述「Phase 0 実機調査の結果」と 74_agy_live_probe.md)。インストール済み(~/.local/bin/agy)・Gemini 共有認証済みで、基本フラグ・print モードがエージェントであること・JSON 出力の不在・自己更新を確認した。
残りの確認項目(implement / review の agy 有効化前に必須):
--json / 設定)の有無。無ければ実装メイドの evidence 設計を JSON 非依存で作り直す。--sandbox の制限範囲(ファイル書き込み・コマンド実行・ネットワークを止められるか)。review / Wiki を副作用なしで動かせるかの可否判断に必須。agy update 抑制等)。完了条件:
agy の起動コマンド・機械可読出力の有無・認証・停止挙動が固定バージョン込みで文書化され、テスト用 fixture が記録されている。agy -p がエージェントとして副作用(ファイル変更・commit・コマンド実行)を起こすため、review / Wiki は --sandbox 等で副作用を確実に抑制できると確認できるまで有効化しない。agy 切り替え前に CLI 固有部分を集約してリグレッションのない土台を作る。個人向けでは Gemini CLI は既に実行不能なため、「現行 gemini を動かしたまま」ではなく、Gemini adapter の既存契約を fixture / mock テストで維持したまま進める。
_build_gemini_command() をやめ、launch_config から quick/thorough のフラグを読む(gemini_cli_review の launch_config に command / approval_mode_thorough 等を追加)。cli_backends/gemini.py)へ切り出す。実装メイド/レビューメイドはこの adapter を呼ぶだけにする。GEMINI_CLI_COMMAND 直読みを共通解決関数に置き換える。現在の summarize_doc(title, content_head) -> str は全失敗(timeout / CLI 失敗 / 例外)を空文字列に畳んでおり、戻り値からは失敗種別を区別できない。
当初検討した「戻り値 str 維持・区別は内部 reason のみ(旧 A 案)」は、#73 の partial evidence と整合しない。#73 の Wiki worker は呼び出し側で reason="summary_timeout" / pending_pages / failed_pages / operation_deadline_insufficient / 生成件数・未生成件数・未生成理由を構築する必要があり、内部 reason がログ内だけでは利用できない。「全呼び出し側を Result 型へ変更(旧 B 案)」は既存呼び出しを壊す。
そこで A/B の二択ではなく 互換ラッパー方式を採る:
summarize_doc_result(...) -> SummaryResult
summary / status(ok / timeout / failed / skipped)/ reason / 必要なら stderr_excerptsummarize_doc(...) -> str
summary、失敗時は空文字列を返す(既存呼び出しは無改修)これなら既存呼び出しを壊さず、#73 の要約サブタスク状態管理も満たせる。Phase 1 で内部 API を実装し、Wiki worker 側の利用は #73 の枠組みに合わせる。
cli_backends/antigravity.py を追加し、agy の方言(コマンド・フラグ・出力解釈・認証パターン)を実装する。--output-format json 相当が無いと確定したため、agy backend は自然言語 narration ストリームから「最終応答」「変更ファイル」等を取り出す解釈ロジックを持つ。session_id / stats(totalRequests / total_tokens)は機械可読の口がなければ取得せず、evidence で null を許容する。隠し --json / plugin / SDK など機械可読の口が Phase 0 残調査で見つかればそれを優先する。--sandbox 等で読み取り専用に固定し、ファイル変更・commit・コマンド実行が起きないことを backend / use-case policy で保証する。implement は意図的に編集させるが、ブランチ保護・baseline 比較・AI 直接 commit 検出(現行 _detect_ai_commits)は維持する。agy が自分で commit する挙動(Phase 0 で観測)に対し、Butler 管理外 commit を検出して扱いを決めるガードを必ず入れる。--approval-mode plan 相当)は --sandbox で代替できるか Phase 0 残調査で確認し、不可なら thorough の代替方法を決める。実装メイドの watchdog は git status の変化を進捗とみなす。ファイルを変更しない review / Wiki 要約へこの watchdog をそのまま共通化すると、正常実行でも stagnation_timeout_seconds 経過で誤停止する。
共通化するのは「実行ライフサイクル」だけに限定する:
start_new_session=True)git status による停滞検出は implement 専用ポリシーとして残す。review / Wiki は deadline timeout のみを適用する(agy が進捗イベントを提供するなら、Phase 0 で確認のうえ別ポリシーを検討する)。
need_input(認証要求)を返せるようにする。intent_maid_routes.yml を更新する。
切替順は移行優先順位どおり review → Wiki 要約 → implement とする。
intent: review → antigravity_cli_review(gemini が個人向け提供終了済みのため実質フォールバック不可。agy 失敗時は明示的に unavailable を返す)。work_publish / wiki_sync 経由)を agy で動かす(共通解決関数側の backend 設定で切替)。intent: implement → grok 優先のまま、Gemini フォールバックを antigravity_cli_implement に差し替え。mcp_facade.py のレビュー tool description の「Gemini CLI」固定文言を CLI 中立な表現へ更新する。
各機能を実環境でスモークテストする(テストグリーン後に切替。下記「実装順」参照)。
スモークが安定したら、Gemini backend の扱いを次のどちらかに明示的に決める(中途半端に環境変数だけ消すと残した Gemini backend の設定経路を壊すため):
gemini_cli_* maid を残し、GEMINI_CLI_* もその backend 専用設定として残す。gemini_cli_* maid・GEMINI_CLI_* 環境変数・専用テストを同時に撤去する。いずれの場合も、Phase 2 で廃止するのは「agy backend から GEMINI_CLI_* へのフォールバック」だけであり、Gemini backend 専用変数は自動的には削除対象にしない。この切り分けを Phase 4 着手時に確認する。
need_input(Google 認証を促す)。実装メイドは 8 パターン、レビューメイドは 3 パターンと現状ばらつくため、adapter に集約して統一する。failed(exit code と stderr 抜粋を evidence に)。invalid_json_output で failed。worker_timeout / watchdog_stagnation を区別済み。レビューは timeout を failed で区別して返す。Wiki 要約は内部 API summarize_doc_result() が status/reason(timeout 等)を返し、#73 Wiki worker がそれを partial evidence に反映する。既存互換 API summarize_doc() -> str は従来どおり失敗時に空文字列を返す。プロセスツリーが残らないことをテストで保証する。tests/test_gemini_cli_implement_maid.py(104 箇所): adapter 化後も既存契約が維持されることを確認。agy adapter 版の JSON 解析・統計抽出・認証検出・watchdog を追加。tests/test_gemini_cli_review_maid.py(43 箇所): quick/thorough のコマンド組み立てが config 駆動になっても従来フラグを生成すること。agy 版の stdin diff・認証検出・timeout。butler/wiki_doc_summarizer.py に新規テストを追加(現状ゼロ)。互換 API summarize_doc() は成功で summary・timeout/失敗で空文字列を返すこと(後方互換)。内部 API summarize_doc_result() は status(ok/timeout/failed/skipped)と reason を正しく区別して返すこと。コマンド解決の後方互換も確認。need_input を返すこと。intent_maid_routes.yml 切り替えで review/implement が agy maid にルートされること。null を許容するが、統計値の 0(実際に 0 回)と「取得不能(null)」を混同しないことを確認するテストを追加。GEMINI_CLI_* を前提にしたテストは、後方互換読み取りが効くことを確認する形で残す。テストは routing 切替の前に置く。自動検証できない状態で切り替えないこと。
74_agy_live_probe.md)。残調査(機械可読出力の口・--sandbox の副作用抑制範囲・プロセスツリー停止・自動更新抑制・認証エラー文言)を完了し、副作用ゲート/停止保証ゲートを判定。summarize_doc のテストを先に追加(移行前のカバレッジ確保)。summarize_doc_result() -> SummaryResult を追加し、summarize_doc() -> str を互換ラッパーにする。null)、副作用抑制(--sandbox 等)と Butler 管理外 commit 検出ガード、実行ライフサイクル(process tree 停止)の共通化(git-status stagnation は implement 専用に限定)、認証検出統一。ANTIGRAVITY_CLI_* 環境変数(gemini backend とは分離、フォールバックなし)と antigravity_cli_* maid を registry に追加。mcp_facade.py の文言更新。GEMINI_CLI_*・専用テストを一体で整理する。セットアップ手順をドキュメントへ反映。Phase 0→1 は採用推奨。
理由:
summarize_doc のテスト追加もここで先行する。Phase 2 以降は Phase 0 の確認結果に依存する。Phase 0 一次調査で、想定したより非互換が大きいことが判明した: agy -p は副作用ありの自律エージェントで、--output-format json 相当も --approval-mode plan 相当も無い。したがって実装メイドは「JSON 応答パース」を作り直し、review/Wiki は副作用抑制(--sandbox 等)を前提にする。これらの代替が Phase 0 残調査で確認できなければ、当該系統の agy 有効化はブロックする。
移行優先順位は review(代替なし)→ wiki 要約(テストなし・別認証)→ implement(フォールバックあり) とする(Phase 3・実装順もこの順に統一)。
実機 probe(74_agy_live_probe.md)の結果を本実装案へ反映済み:
null」へ。--sandbox で副作用抑制を確認するまで有効化しない)を追加。--sandbox 範囲・プロセスツリー停止・自動更新抑制・認証エラー文言)を明示。本実装案は Codex(codex-mcp-client)のレビュー(issue #74 コメント)を受けて以下を修正済み:
GEMINI_CLI_COMMAND へフォールバックしない(終了済み gemini の誤起動防止)。gemini_cli_* 温存は個人向けロールバックにならない点を明記し、ロールバックを「routing 戻し+unavailable」と定義。別 provider はスコープ外。str 維持か Result 型か)を Phase 1 の決定事項として明示。改訂版に対する Codex 再レビューで前回 7 点の反映が承認され、最終 2 点+軽微修正を反映済み:
summarize_doc_result() -> SummaryResult + 互換 summarize_doc() -> str)へ変更。#73 の partial evidence を構築可能にしつつ既存呼び出しを壊さない。GEMINI_CLI_* も backend 専用設定として残す / (b) backend ごと撤去」の二択に明確化。Phase 2 で消すのは agy→Gemini 変数フォールバックのみで、Gemini 専用変数は自動削除対象にしない、と切り分け。採用判断: Codex 再レビューにて、上記 2 点修正を条件に承認済み。Phase 0 の実機調査は先行着手可。 反映は完了しており、Phase 0 → テスト先行の Phase 1 → Phase 2 の順で進める。