◉ANTIGRAVITY LABEN
記事一覧/連携・プラグイン
⬡ 連携・プラグイン/2026-11-06中級

Conductor を Gemini CLI 拡張から Antigravity CLI のプラグインへ。spec.md と plan.md は動かさず、導入の前後だけ見比べる

Conductor が Gemini CLI の拡張機能からプラグインになり、Antigravity CLI でも使えるようになりました。conductor/ に溜めた spec.md と plan.md は移す必要がなく、導入の前後で何も変わっていないことを確かめる小さなスクリプトと手順をお伝えします。

ConductorAntigravity CLI43プラグイン仕様駆動開発移行13

Gemini CLI の拡張機能として使っていた Conductor が、プラグインに変わったと知ったのは、ちょうど進行中のトラックを二つ抱えていた週のことでした。agy plugins install の一行で入るらしい——と分かっても、指が止まります。plan.md の「作業中」の印がずれたり、spec.md が書き換わったりしたら、途中までの判断の履歴ごと失うことになるからです。

最初にお伝えしたいのは、移すものは実質ありませんということです。Conductor の成果物は、拡張機能の中ではなくリポジトリの conductor/ ディレクトリに置かれる Markdown です。Google の開発者ブログ(2026年7月16日)も、spec.md と plan.md は「どこにも行かない」と書いています。動くのは、それらを読み書きする側だけです。

それでも私は、個人開発で壁紙アプリの企画メモを Conductor に預けている身として、導入の前後に一度だけ状態を見比べることにしました。移行そのものより、「何も壊れていない」と言い切れる状態に自分を置くための作業です。

何が変わって、何が変わらないのか

公式ブログと Conductor リポジトリの README から確認できる範囲で整理します。

項目変わらない変わる
成果物の置き場所conductor/ 配下の product.md、tech-stack.md、workflow.md、tracks.mdなし
トラックの構成conductor/tracks/<id>/ の spec.md、plan.md、metadata.jsonなし
起動のしかた従来のスラッシュコマンドも使えると公式が説明自然な会話でも動くようになった
入れ方—agy plugins install(Antigravity)、Claude Code ではマーケットプレイス登録
プラグイン本体の置き場所—グローバルなら ~/.gemini/config/plugins/、プロジェクト限定なら .agents/plugins/

プラグイン本体の場所と成果物の場所が別だ、という点が肝心です。アンインストールしても conductor/ は残りますし、逆に導入だけで conductor/ が書き換わる理由は、本来ありません。ただ、これは「書き換わらないはず」という設計上の話で、手元で確かめた話ではありません。確かめる道具を先に作りました。

導入の前後を見比べるスクリプト

やることは三つです。必須ファイルの有無、トラックごとの三つのファイルのハッシュ、plan.md のチェックボックス集計([ ] 未着手、[~] 作業中、[x] 完了)を JSON に保存し、あとで同じ計測と突き合わせます。

#!/usr/bin/env python3
"""conductor/ の状態を JSON に残し、プラグイン導入の前後で差分を取る。"""
import hashlib
import json
import re
import sys
from pathlib import Path
 
CORE = ["product.md", "product-guidelines.md", "tech-stack.md", "workflow.md", "tracks.md"]
BOX = re.compile(r"^\s*[-*]\s*\[( |x|~)\]", re.M)  # [ ] 未着手 / [~] 作業中 / [x] 完了
 
 
def digest(p: Path) -> str:
    return hashlib.sha256(p.read_bytes()).hexdigest()[:12]
 
 
def snapshot(root: Path) -> dict:
    base = root / "conductor"
    out = {"missing_core": [c for c in CORE if not (base / c).exists()], "tracks": {}}
    for tdir in sorted((base / "tracks").glob("*/")) if (base / "tracks").exists() else []:
        entry = {"files": {}, "boxes": {" ": 0, "~": 0, "x": 0}}
        for name in ("spec.md", "plan.md", "metadata.json"):
            f = tdir / name
            entry["files"][name] = digest(f) if f.exists() else None
        plan = tdir / "plan.md"
        if plan.exists():
            for m in BOX.findall(plan.read_text(encoding="utf-8")):
                entry["boxes"][m] += 1
        out["tracks"][tdir.name] = entry
    listed = (base / "tracks.md").read_text(encoding="utf-8") if (base / "tracks.md").exists() else ""
    out["unlisted_tracks"] = [t for t in out["tracks"] if t not in listed]
    return out
 
 
def diff(a: dict, b: dict) -> list:
    msgs = []
    for t in sorted(set(a["tracks"]) | set(b["tracks"])):
        x, y = a["tracks"].get(t), b["tracks"].get(t)
        if x is None or y is None:
            msgs.append(f"{t}: {'追加' if x is None else '消失'}")
        elif x != y:
            changed = [n for n in x["files"] if x["files"][n] != y["files"][n]]
            msgs.append(f"{t}: 変更 {changed}")
    return msgs
 
 
if __name__ == "__main__":
    mode, root = sys.argv[1], Path(sys.argv[2])
    if mode == "save":
        snap = snapshot(root)
        Path(sys.argv[3]).write_text(json.dumps(snap, ensure_ascii=False, indent=1))
        print(f"tracks={len(snap['tracks'])} missing_core={snap['missing_core']} unlisted={snap['unlisted_tracks']}")
    elif mode == "compare":
        before = json.loads(Path(sys.argv[3]).read_text())
        msgs = diff(before, snapshot(root))
        print("\n".join(msgs) if msgs else "差分なし")
        sys.exit(1 if msgs else 0)

ハッシュを 12 桁に切っているのは、人が目で見て比べられる長さにしたかったからです。セキュリティ用途ではないので、この長さで足ります。

試すために、トラックを二つ(dark-mode と login-fix)持つ小さなダミーの conductor/ を作り、保存と比較を回しました。

python3 conductor_snapshot.py save . before.json
# tracks=2 missing_core=[] unlisted=[]
 
python3 conductor_snapshot.py compare . before.json
# 差分なし
 
# plan.md の「作業中」を手で完了に変えたあと
python3 conductor_snapshot.py compare . before.json
# dark-mode_20261020: 変更 ['plan.md']   (終了コード 1)

終了コードが 1 になるので、手順書やシェルスクリプトに組み込めます。逆に言えば、plan.md を普通に進めている最中は差分が出て当然です。比べるのは「導入の直前」と「導入の直後」の二点だけにしておきます。

導入の手順(私の順番)

  1. 進行中のトラックを一区切りまで進め、git status が空の状態にします。手が入った plan.md が未コミットのままだと、あとで差分の原因が自分なのかプラグインなのか分からなくなります。
  2. python3 conductor_snapshot.py save . before.json を実行し、before.json はリポジトリの外(ホーム直下など)に置きます。リポジトリの中に置くと、それ自体が差分になります。
  3. agy plugins install https://github.com/gemini-cli-extensions/conductor を実行します。
  4. もう一度 compare を実行し、「差分なし」と git status が空であることを両方確認します。
  5. 差分が出たら、git diff conductor/ を読みます。意図しない書き換えなら、そこで止めて git checkout -- conductor/ で戻します。

手順 4 で差分が出なければ、移行の主作業はそこで終わりです。残るのは使い方の側、つまり「従来のコマンドで続けるか、会話で続けるか」の選択です。

落とし穴と判断

トラックが一覧から漏れている場合があります。 unlisted_tracks は、conductor/tracks/ にディレクトリがあるのに tracks.md に名前が出てこないトラックを拾います。手で作ったトラックや、途中でコピーしたトラックに出ます。導入とは関係なく起きるので、前後の比較とは別に、保存時に一度見ておくと整理になります。

Gemini CLI 側の拡張機能は、そのままにするか外すかを決めます。 二つの経路から同じ conductor/ を書くと、plan.md のチェックボックスを両方が更新しうるからです。私は、しばらく併存させて、新しい側で一つトラックを最後まで回してから古い側を外す、という順番にしました。どちらが正しいと断言できる材料は持っていません。ただ、同じトラックを二つの道具から同時に進めない、という線引きだけは守っております。

トークン消費の増え方は公式も注意を書いています。 README には、仕様駆動の進め方は文脈の読み込みが増えるため、大きなプロジェクトでは消費が増えうると明記されています。会話で進められるようになった分、気軽に呼び出して消費が膨らむ、ということは起こりえます。

次にやること

プラグインへの移行は、ファイルを移す作業ではなく、ファイルが動いていないことを確かめる作業でした。導入の直前に保存し、直後に比べるだけです。この二回の実行は、合わせても一分とかかりません。最初に指が止まったのは、確かめる手段を持っていなかったからなのだと、いまは感じています。

まずは進行中のトラックを一つ選び、save を実行するところから始めていただければと思います。設定の持ち運びは 設定ファイルを開かずに MCP サーバーを足す — agy mcp サブコマンドで構成を持ち運ぶ に、無人実行の前に CLI の応答を確かめる方法は スケジュール実行の直前に、Antigravity CLI が本当に応答するかを1回だけ確かめる に書き残しています。

シェア

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

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

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

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

関連記事

⬡ 連携・プラグイン2026-11-02
Marketplace のパートナープラグインを入れる前に、導入ページで確かめる三つのこと
Antigravity 2.28.2 で Marketplace にパートナープラグインが並びました。入れる前に導入ページの開発元とリポジトリを見て、入れたあとは Accounts タブで接続を管理する——その線引きと、リポジトリの状態を確かめる短いコマンドをまとめます。
⬡ 連携・プラグイン2026-10-22
プロジェクト直下の mcp_config.json が読まれているのに MCP が立ち上がらない — プローブ 1 本で確かめる
Antigravity CLI のログには project-local の設定ファイルを使うと出るのに、MCP サーバーは起動しない。公式リポジトリの Issue 報告をもとに、ログの文言が指すものと、起動の有無を自分で確かめる最小のプローブサーバーをまとめます。
⬡ 連携・プラグイン2026-10-19
Antigravity CLI に GitHub MCP を繋ぐ最初の 1 本 — 書き換えるのは url の 1 語だけでした
Antigravity CLI で GitHub MCP を使うには、設定の url を serverUrl に書き換える必要があります。公式の MCP ドキュメントを根拠に、リモート接続と Docker 接続の書き方、読み込む前の検査スクリプト、トークンの置き場所と切り分けの順番をまとめます。