coding agent の CLI を 4 つ入れています。Claude Code(claude)、OpenAI の Codex CLI(codex)、GitHub Copilot CLI(copilot)、Google の Antigravity CLI(agy)です。

使い分けは単純で、コードも文章も書くのは Claude Code だけです。残りの 3 つには書かせず、Claude Code が書いたものを読ませています。

この割り当てで回していて、分かったことが 2 つあります。1 つは、どの CLI がどんな指摘をするかは 1 回の出力では決められないこと。もう 1 つは、終了コードが 0 なのに査読が取れていない失敗を、3 つの CLI で踏んだことです。それを数える自分のスクリプトも、黙って間違えていました。なので CLI をレビュー役に足すなら、出力が空でないか、短すぎないか、査読の形になっているかを見る検査も一緒に入れるのがおすすめです。

モデルも CLI も数か月で変わるので、ここに書くのは 2026 年 10 月時点の話です。版とモデルは、10 月 13〜14 日に確かめた時点で次のとおりでした。

CLI版中で動いているモデル(設定とログで確認)
claude2.1.296Claude の既定モデル(具体名は記録していない)
codex0.162.1gpt-6-astra
copilot1.0.96claude-sonnet-5.5
agy1.3.3Gemini 3.6 Flash

同じプロンプトを 2 回流した比較だけは 10 月 10 日に取ったもので、そのときの版は少し古いです(codex は 0.154.0)。

書くのは Claude Code、読むのは残りの 3 つ

4 つを並べて「どれが一番か」を決めるより、別の目を足すほうに使っています。自分の書いたものを同じセッションで見直しても、書いたときの思い込みが残りやすいからです。

読ませる場面は 2 つあります。

  • コードのレビュー: 自作のスラッシュコマンド /self-review が、Claude Code 自身と 3 つの CLI に同じ差分を並列で渡し、指摘を突き合わせます
  • 文章の査読: このブログの記事は、公開前に 4 者へ「編集者」として読ませています。視点が散るように、少しずつ違う役を割り当てました
CLI文章の査読で割り当てている役
claude(別インスタンス)書籍の編集者(構成・内容の深さ)
codex校閲担当(事実確認・表記ゆれ・機密漏れ)
agy校閲担当(同上)
copilot技術雑誌の編集者(言い回し・読みやすさ)

役の振り分けは、「この CLI はこれが得意」と測って決めたものではありません。

ひとつ白状すると、「違うモデルの目を足す」つもりで 4 つ並べていたのに、この記事を書くために確かめたら、copilot の中身は Claude Sonnet 5.5 でした。Copilot CLI はモデルを選べて、私の環境ではそれが使われていました。つまり 4 者のうち 2 者は Claude の系統で、系統で数えると 3 つです。CLI ごとにシステムプロンプトや道具の使い方は違いますが、「違うモデル」を狙うなら CLI の数ではなく、中のモデルを確かめる必要がありました。

同じプロンプトを 2 回流すと、[must] の顔ぶれが変わった

査読では、指摘に重要度のラベルを付けさせています。[must] は「事実と違う・証明できない・再現できない・機密」のどれかに当たるもので、直さないと公開できない指摘です。

10 月 10 日に、まったく同じプロンプトを同じ記事に 2 回流して、出力を比べました。

1 回目2 回目1 回目の [must] を 2 回目も [must] にしたか
codex13 件(must 6)13 件(must 3)6 件中 3 件
claude22 件(must 3)15 件(must 2)3 件中 1 件

agy と copilot は 2 回目を測っていません。

codex は件数こそ同じでしたが、[must] は半分になりました。1 回目の 6 件のうち 3 件が [must] から外れ、新しい [must] はありませんでした。claude は、1 回目に [must] を付けた 3 件のうち、2 回目も [must] だったのは 1 件だけです。残りは、1 件が [imo](直したほうが良いが公開はできる)に下がり、1 件は指摘自体が出ませんでした。代わりに、1 回目には無かった論点が [must] に上がっています。

件数は 3〜6 件と少なく、どちらも 1 組だけの観測ですが、1 回の出力で「この CLI はこういう指摘をする」と決めるのは早そうです。差が CLI の性格なのか、その回の揺れなのか、1 回では区別できなさそうです。

CLI の「得意なこと」も、測り方で見え方が変わります。9 月の 3 記事では「agy は事実誤りをほとんど指摘しない」と記録していましたが、[must] の定義をプロンプトに足したあとの 1 記事では、agy の [must] 3 件が全部事実・機密・論理の指摘でした。条件も数も違うので、ここから何かを言うことはできません。

そのため割り当ては、「どれが優れているか」より**「別の目が何人いるか」で考えています**。1 者が拾わなかった論点を別の 1 者が拾えば十分です。実際、同じ日の測定では、記事中の数字の矛盾を 3 者が独立に指摘していました。

4 者に公開前の原稿を 4 周読ませた数字

この揺れを踏まえたうえで、もう少し大きい数字も載せておきます。10 月 13 日に、SKILL.md の行数を CI で縛った話の公開前の原稿を、4 者に 4 周読ませました。周ごとに指摘を反映して書き直しているので、周をまたぐ差には改稿の効果と出力の揺れが混ざっています。

1 周目2 周目3 周目4 周目
claude16 件(must 4)14 件(must 2)17 件(must 4)13 件(must 1)
codex12 件(must 7)9 件(must 3)6 件(must 3)5 件(must 0)
copilot14 件(must 5)19 件(must 3)13 件(must 2)15 件(must 4)
agy7 件(must 2)6 件(must 1)4 件(must 1)4 件(must 0)

件数は、各 CLI が出した指摘を自作のスクリプトで数えた値です(claude の 3 周目だけは手で数え直しました)。あとで書くとおり、このスクリプトは補足の行まで数えることがあるので、タイトル案より前の範囲に絞って数え直し、同じ値になることを確かめています。妥当だと確かめた不備の数ではありません。

所要時間は 2〜4 周目でおおよそ次のとおりでした。プロンプトのファイルを作ってから出力のファイルが最後に更新されるまでの時間で、概算です。1 周目は、copilot が起動できず、agy もやり直したので除いています(どちらもあとで書きます)。

所要
agy49〜72 秒
copilot37〜101 秒
claude181〜214 秒
codex193〜231 秒

この表から言えるのは、agy と copilot がおおむね 2 分以内、claude と codex が 3 分以上と、2 つに分かれたことくらいかなと思います(各 3 回の概算です)。件数の差は、前の節の揺れを見たあとだと、性格の差とは読みにくいです。

終了コード 0 のまま、査読が取れていなかった

並列で回していていちばん困ったのは、指摘の質より、失敗に気づけないことでした。3 つの CLI で、終了コードが 0 なのに査読が取れていない形を踏んでいます。

CLI起きたこと見え方原因
claude186 秒走って、出力が 0 バイトexit=0。再実行したら通った分からない
agyheadless で権限が自動拒否されると、1 行のエラーだけ返すexit=0。303 バイトあるので「空ではない」headless では権限を確認できない仕様
copilot-p を付けると、パイプで渡した入力がモデルに届かない「標準入力にはアクセスできず」と普通に返答して exit=0-p と標準入力を併用したときの挙動(実測)

agy の 1 行は次のような形でした。

jetski: no output produced — a tool required the "command" permission that
headless mode cannot prompt for, so it was auto-denied.

前日まで同じ呼び方で通っていたので、プロンプトの中身次第で起きるようです。記事の数字を確かめようとして、リポジトリを読みに行くコマンドを使おうとしたときに起きたように見えます。プロンプトに「コマンドは実行できない環境なので、本文だけで判断してください」と書き足したら通りました。

copilot は、-p で指示を渡して記事を標準入力に流す、という自然な書き方が通りません。--help には標準入力が -p と並ぶ入力モードとして書かれていますが、両方渡したときにどうなるかは書かれていません。標準入力にマーカーの番号を仕込んで答えさせると、-p の指示だけが読まれ、番号は答えられませんでした。いまは -p を使わず、指示文と記事をまとめて標準入力に流しています。

claude と codex で踏んだのは、こちらの保存の仕方だった

出力に余計なものが混ざった件が 2 つあって、最初はどちらも CLI の癖だと思っていました。

1 つは claude です。-p で標準入力を塞がずに呼ぶと、3 秒待ってから警告を出して、そのまま普通に続行します。

$ sleep 6 | claude -p "1+1 の答えを数字だけで" > out.txt 2> err.txt; echo "exit=$?"
exit=0
$ cat out.txt
2
$ cat err.txt
Warning: no stdin data received in 3s, proceeding without it. If piping from a slow command, redirect stdin explicitly: < /dev/null to skip, or wait longer.

警告は標準エラーに出ていて、標準出力には答えだけが入っています。もう 1 つは codex で、査読本文は 12.8 KB なのにファイルが 262 KB になり、推論の経過まで入っていました。codex exec も、最終の回答だけを標準出力に、進行ログを標準エラーに分けて出しています。

どちらも、私が 2>&1 でまとめて保存していたのが原因でした。codex はすでに -o で査読本文だけを書かせていますが、ほかの 3 つを呼ぶ自分のスキルはまだ 2>&1 のままで、この記事を書いていて気づきました。下の起動例は、それを直した形にしてあります。agy の 1 行エラーも同じくまとめて保存していたので、標準出力と標準エラーのどちらに出たのかは分かりません。

参考: Codex - Non-interactive mode

失敗と分かる失敗でも、原因の見立てを間違えた

終了コードが 0 でない失敗は気づけます。それでも原因の見立ては 2 回間違えました。

copilot は入っていないのではなく、このリポジトリの中で見えていなかった

しばらく「copilot は未インストール」と思い込んでいて、記事のネタ帳にもそう書いていました。

実際には入っていました。Node は mise で入れていて、copilot はグローバル設定の Node 23.10.0 の下に npm で入れてあります。ところが作業しているリポジトリは、mise.toml で Node を 24.15.0 に固定しています。そのためリポジトリの中でだけ command -v copilot が何も返さず、そこで動いている Claude Code から呼ぶと exit=127 で落ちていました。

$ cd ~ && mise exec -- command -v copilot
~/.local/share/mise/installs/node/23.10.0/bin/copilot
$ cd ~/path/to/repo && mise exec -- command -v copilot; echo "exit=$?"
exit=1

(ホームディレクトリは ~ に、リポジトリのパスは例に置き換えています。)

ホームディレクトリで試していたら見つかっていたはずで、「無い」と判定するのが速すぎました。いまはフルパスで呼んでいますが、これは応急処置で、旧い Node のインストール先に依存します。Node を上げたあとでそのディレクトリを消せば、また呼べなくなります。リポジトリ側の Node にも入れておくほうが筋は良さそうです。

codex exec には -a が無い

codex exec -a never ... は unexpected argument '-a' で落ちます。これを「-a が廃止された」と思い込んでいましたが、0.162.1 の --help を見ると、-a(--ask-for-approval)は codex 本体の引数として残っていて、exec サブコマンドに無いだけでした。版で変わったのではなく、置き場所の問題です。

数える側も間違えていた

4 者の指摘を比べるために、ラベルの件数を数える小さなスクリプトを書いています。これも黙って間違えました。

1 回目は、agy の件数を 0 と数えていました。ラベルの書き方が CLI ごとに違っていたからです。

claude:  - **[must]** ...
codex:   - [must] ...
agy:     #### `[must]` ...

行頭の - や # やバッククォートを剥がしてから判定するように直しました。

2 回目は、この記事の「4 周読ませた数字」の表を作っていて見つけました。claude の 3 周目が 0 件になっていたのです。出力を開くと、こう書いてありました。

**1. [must] 「あと 3 行足すと落ちます」の計算が違います**

太字の中に番号が入る形は、いまのスクリプトでは拾えません。手で数えると 17 件([must] 4 件)でした。指摘そのものはその場で読んで記事に反映していたので実害はありませんでしたが、表だけを見ていたら「claude は 3 周目に何も言わなかった」と読むところでした。

3 回目は、この記事の査読で見つかりました。「2 回流した比較」の数字を、初稿では claude について「16 件、[must] の論点は 3 件中 0 件」と書いていました。10 月 10 日に自分でまとめたメモの数字です。codex の査読で指摘されて、元の出力と突き合わせて数え直すと、誤りは 2 つありました。16 件は、スクリプトが指摘一覧の外にある補足の行(行頭が `[imo]`)まで数えた値で、正しくは 15 件です。取りこぼすだけでなく、余計に数えることもあります。もう 1 つの「3 件中 0 件」は件数ではなく、どの指摘が同じ論点かの突き合わせの誤りで、正しくは 3 件中 1 件でした。言い方が毎回違う指摘を同じ論点と見なすのは、結局人の目でやるしかありません。

LLM の出力の書式は、同じ CLI でも回によって変わります。数える仕組みも、書式が変わるたびに直すことになりそうです。

終了コードを見たうえで、出力の形も見る

いまは、レビューを回したら次の 3 つを見てから先へ進んでいます。

  1. 終了コードが 0 でも、出力が空でないことを確かめる
  2. 1,000 バイト未満なら中身を開く。 agy の 1 行エラーは 303 バイトでした
  3. 査読の形になっているかを見る。 総評と指摘の一覧があるか
for r in claude codex agy copilot; do
  out="out-$r.md"
  if [ ! -s "$out" ]; then
    echo "$r はスキップ(出力が空)"
  elif [ "$(wc -c < "$out")" -lt 1000 ]; then
    echo "$r は中身を見る(出力が短すぎる)"
  fi
done

ここまでは機械で見られますが、3 つ目は結局、出力を開いて目で見ています。件数のスクリプトも、0 件が出たら、まず数える側が壊れていないかを疑うようにしました。

起動の形は次のようにするのがおすすめです。私のスキルでは、引数で渡す(claude / agy)、- を付けて標準入力から読ませる(codex)、-p を付けずに標準入力へ流す(copilot)の 3 通りで渡しています。ほかの渡し方ができる CLI もありますが、copilot だけは、確かめた版で -p と標準入力を併用すると標準入力の本文が届きませんでした。

# claude: 引数で渡す。標準入力は塞ぐ
claude -p "$(cat prompt.txt)" < /dev/null > out-claude.md 2> err-claude.txt

# codex: 標準入力で渡す。査読本文だけを -o で別ファイルに書かせる
codex exec -s read-only --skip-git-repo-check -o out-codex.md - < prompt.txt > log-codex.txt 2> err-codex.txt

# agy: 引数で渡す。既定のタイムアウト 5 分では足りないことがある
agy -p "$(cat prompt.txt)" --sandbox --print-timeout 15m > out-agy.md 2> err-agy.txt

# copilot: 標準入力で渡す。-p は付けない
# (私の環境ではリポジトリの中から呼ぶので、copilot はフルパスに置き換えている)
copilot -s --no-ask-user --allow-all-tools \
  --deny-tool='write' --deny-tool='shell(rm)' --deny-tool='shell(git:*)' \
  < prompt.txt > out-copilot.md 2> err-copilot.txt

copilot の指定は 1.0.96 で動いているものです。非対話モードで --allow-all-tools が必須なので、付けたうえで、ファイル編集のツールと rm と git を --deny-tool で塞いでいます。--deny-tool は --allow-all-tools より優先されます。ただ、write で塞げるのはシェル以外のファイル編集ツールなので、シェル経由の書き込みを全部防ぐ設定ではありません。

参考: About GitHub Copilot CLI - Using the approval options / Claude Code の CLI リファレンス

まとめ

  • coding agent の CLI を 4 つ入れているが、書くのは Claude Code だけで、残りの 3 つはレビューにだけ使っている。ただし copilot の中身は Claude Sonnet 5.5 だった。「違うモデルの目」を狙うなら、CLI の数ではなく中のモデルを確かめる
  • 同じプロンプトを 2 回流すと、1 回目の [must] が 2 回目も [must] だったのは、codex で 6 件中 3 件、claude で 3 件中 1 件だった(各 1 組の観測)。1 回の出力で CLI の性格を決めるのは難しい
  • 件数を数えるスクリプトは、ラベルの書式の違いで取りこぼし、補足まで余計に数えもした。数字がおかしいときは、まず数える側を疑う
  • 私の環境では、mise でリポジトリごとに Node を固定していたため、別の Node にグローバルで入れたツールがそのリポジトリでだけ見えなくなっていた。「入っていない」と判定する前に、別のディレクトリやフルパスで探す
  • 3 つの CLI で、終了コードが 0 なのに査読が取れていない失敗を踏んだ。これとは別に、出力に余計なものが混ざった件が 2 つあり、そちらは 2>&1 でまとめて保存していたこちらのせいだった。CLI をレビュー役に足すなら、終了コードに加えて、出力が空でないか・短すぎないか・査読の形になっているかを見る検査を一緒に入れる