Claude Code / Codexの最終回答を自動でクリップボードへコピーする

Claude Code / Codexの最終回答を自動でクリップボードへコピーする

AIエージェントを使った開発を毎日行っていると、意外に面倒なのが「AI同士の結果の受け渡し」です。

私の場合、普段は次のような流れで作業しています。

  1. ChatGPTで次の作業内容や指示文を作る
  2. 指示文をClaude CodeやCodexへコピー&ペーストする
  3. Claude Code / Codexで実行する
  4. 実行結果をコピーしてChatGPTへ戻す
  5. ChatGPTで結果を評価し、次の指示文を作る
  6. これを繰り返す

1日に10〜20往復程度行うこともあります。

この中で特に面倒だったのが、Claude CodeやCodexのターミナルに表示された長い最終回答を、

  • マウスで範囲選択
  • Ctrl+C
  • ChatGPTへ戻る
  • Ctrl+V

とする作業でした。

今回、この最後の「範囲選択+コピー」を、Claude CodeとCodexのStop hookを利用して自動化しました。

結果として、現在は、

AIエージェントの処理が終了
→ 最終回答が自動的にWindowsのクリップボードへ入る
→ ChatGPTへ戻ってCtrl+Vするだけ

という運用ができています。


最初に試した方法:AI間relay

最初からStop hookに辿り着いたわけではありません。

当初考えたのは、

ChatGPT

instruction

local relay

Claude Code / Codex

result.md

ChatGPT

というAI間のrelayでした。

実際にCodex用の最小prototypeを作り、

node automation/relay.js <instruction-file>

という1コマンドで、

  • Markdown指示文を読む
  • Codexを起動
  • read-only sandboxで実行
  • model / reasoning levelを設定
  • 最終結果をresult.mdへ保存

まで動かしました。

技術的には問題なく動きました。

実測では、従来9操作程度だったものが4操作程度まで減りました。

しかし、実際に使ってみると問題がありました。

instruction.mdを作る方が面倒

relayを使うには、

  1. ChatGPTの指示文をコピー
  2. instruction.mdへ保存
  3. relayコマンドを実行
  4. result.mdを開く
  5. ChatGPTへ貼る

という新しい手順が必要です。

これは技術的には自動化されていますが、実際の操作感としてはあまり良くありませんでした。

特に私は普段、

ChatGPTの指示文をそのままClaude Code / Codexへ貼る

だけなので、わざわざファイル化する方が面倒でした。

一方で、relayを使って明確に便利だった点がありました。

最終回答がresult.mdにまとまっているので、ターミナル上で長い範囲をマウス選択する必要がない

ことです。

ここで、本当の問題が見えてきました。


本当に解決したかった問題

私が困っていたのは、AIエージェントを起動することではありませんでした。

入力側は、

ChatGPT
→ Ctrl+C
→ Claude Code / Codex
→ Ctrl+V

で十分に簡単です。

また、Claude Code / Codexが処理している途中は、

  • 何を調査しているか
  • どのファイルを読んでいるか
  • testを実行しているか
  • どこで時間が掛かっているか

といった情報をターミナルで見たいので、headless実行へ完全移行したいわけでもありません。

一番面倒なのは最後でした。

ターミナル上の長い最終回答
→ マウスで開始位置を探す
→ ドラッグして末尾まで選択
→ Ctrl+C
→ ChatGPTへ戻る
→ Ctrl+V

ここだけ消せれば十分だったわけです。

そこで方向転換しました。


Stop hookを使う

調査したところ、Claude CodeとCodexの両方にStop hookがあり、turn終了時の情報として、

last_assistant_message

を受け取れることが分かりました。

つまり、

AIエージェントのturn終了
        ↓
Stop hook
        ↓
last_assistant_message
        ↓
Windows clipboard

とすればよいことになります。

この方式なら、通常のinteractive sessionを一切変える必要がありません。


Claude Code

確認したClaude Codeのバージョンは、

Claude Code 2.1.235

でした。

Stop hookから渡されるJSONの、

last_assistant_message

だけをPowerShellで取り出し、Set-Clipboardへ渡します。

概念的には次の処理だけです。

stdin JSON
    ↓
ConvertFrom-Json
    ↓
last_assistant_message
    ↓
Set-Clipboard

実際には、

  • malformed JSON
  • fieldが存在しない
  • null
  • 空文字
  • Set-Clipboard失敗

などでもClaude Code本体を止めないようにしています。

また、Windows PowerShell 5.1ではBOMなしUTF-8の.ps1に日本語literalを書くと文字化けする場合があるため、hook script自体はASCIIだけで記述しました。

Windows clipboardへの書き込みには、

Set-Clipboard

を使用しています。

clip.exeはcodepage依存による日本語文字化けの可能性があるため使いませんでした。


Claude Codeの実利用結果

interactive Claude Codeを通常どおり使用しました。

つまり、

  • -pなどのheadless modeは使わない
  • tool callや途中経過は従来どおり画面に表示
  • 作業終了後もClaude Code側でCtrl+Cしない

という条件です。

最終回答が出たあと、そのままChatGPTへ戻り、

Ctrl+V

だけを実行しました。

結果は正常でした。

確認できた項目は、

  • Stop hook実発火
  • 最終回答がclipboardへ入る
  • 日本語正常
  • 長文の途中切れなし
  • thinking / tool progressの混入なし
  • interactive progress維持
  • 日常の追加操作0

です。

Claude Codeについては、この方式をそのまま実用できると判断しました。


Codex

次にCodexでも同じことを試しました。

テスト中にCodexが更新され、

codex-cli 0.145.0
↓
codex-cli 0.148.0

となりました。

Codexでもhooks機能は利用可能で、

Stop hookから、

last_assistant_message

を取得できます。

構成はClaude Codeとほぼ同じです。

Codex turn終了
    ↓
Stop hook
    ↓
last_assistant_message
    ↓
PowerShell Set-Clipboard

Codexでは一度問題が発生した

最初のCodexテストでは、長い最終報告全文ではなく、

HEAD: ...

未コミット変更は private-data/ 配下のみ...

という短い2行だけがclipboardへ入りました。

最初は、

Codexのlast_assistant_messageは、画面に表示された最終回答全文とは違うのではないか?

と疑いました。

そこでCodexのrollout JSONLまで調査しました。

しかし、実際にはもっと特殊な原因でした。


親Codexと子Codexが同時に存在していた

問題が起きたテストでは、親Codex自身がStop hookを検証するために、別のCodex TUIプロセスを子として起動していました。

親Codex側には、

実利用テストは PASS です。
...

という長い最終報告がありました。

一方、子Codex側の最終回答が、

HEAD: ...

未コミット変更は...

という短い2行でした。

親と子の両方が同じユーザーhookを利用していたため、同じWindows clipboardへ書き込んでいました。

このため、

Stop hookそのものの問題なのか
子Codexによるclipboard上書きなのか

が分かりにくい状態になっていました。


SHA-256で経路を確認

そこで、次の3箇所について、

  • 文字数
  • UTF-8 byte数
  • SHA-256

を比較する診断を行いました。

Codex rollout
task_complete.last_agent_message
          ↓
Stop hook
last_assistant_message
          ↓
Set-Clipboard後のclipboard内容

1275文字の日本語を含む実際の回答で測定したところ、

rollout
= hook payload
= clipboard

となり、SHA-256も完全一致しました。

つまり、

  • Codex内部のfinal message
  • Stop hookへ渡されるmessage
  • Windows clipboard

のどこでも内容は失われていませんでした。

少なくとも通常の単一interactive sessionでは、Stop hook経路は正常です。


Codex特有のhook trust

Codexではもう1つ注意点がありました。

hook scriptを変更したあとCodexを起動すると、

Hooks need review

1 hook is new or changed.

1. Review hooks
2. Trust all and continue
3. Continue without trusting

という確認が表示されます。

今回は、

2. Trust all and continue

を選択しました。

このtrust確認後、通常interactive Codexでテストすると、

  • live progress正常
  • 最終回答全文がclipboardへ入る
  • 日本語正常
  • truncationなし
  • thinking混入なし
  • mouse selection不要

となり、実利用テストも成功しました。

Codexではhook scriptを変更した場合にtrust再確認が発生するため、hookを一度確定した後は不用意に変更しない方が運用は安定しそうです。


最終的な操作

現在の操作は非常に単純です。

Claude Code

1. ChatGPTの指示文をCtrl+C
2. Claude CodeへCtrl+V
3. Enter
4. 普通に処理状況を見る
5. Claude Codeの回答終了
6. ChatGPTへ戻る
7. Ctrl+V

Claude Code側で回答を選択してコピーする必要はありません。

Codex

Codexも同じです。

1. ChatGPTの指示文をCtrl+C
2. CodexへCtrl+V
3. Enter
4. 普通に処理状況を見る
5. Codexの回答終了
6. ChatGPTへ戻る
7. Ctrl+V

Stop hookがturn終了時にclipboardを書き換えるため、

指示文
↓
AIの最終回答

という順番で自然にclipboard内容が入れ替わります。

この点も実際のワークフローとうまく噛み合いました。

設定

今回の対応で、以前の環境から実際に変わったのは以下です。

Claude CodeにStop hookを追加

  • C:\Users\{user}\.claude\settings.json
    • hooks 設定を追加
  • C:\Users\{user}\.claude\hooks\copy-last-response.ps1
    • 新規作成
  • Claude Codeのturn終了時に last_assistant_messageSet-Clipboard でWindowsクリップボードへ自動コピーするようになりました。

CodexにStop hookを追加

  • C:\Users\{user}\.codex\hooks.json
    • Stop hook設定を追加
  • C:\Users\{user}\.codex\hooks\copy-last-response.ps1
    • 新規作成
  • hook変更後にCodex起動時のtrust確認が出て、Trust all and continue を一度承認しました。

relay prototypeはどうなったか

実際、

9操作 → 4操作

途中で作成したCodex relay prototypeも技術的には動作しました。

程度まで削減できました。

しかし、実利用すると、

  • instruction.mdを作る
  • relay用commandを実行する
  • result pathを扱う

といった新しい概念が入ってきます。

結果取得は楽になる一方、入力側の操作が重くなりました。

Stop hookなら、

現在のClaude Code / Codexの使い方をほぼ一切変えず、最も面倒だった最終回答の選択操作だけを消せます。

そのため、今回の用途ではStop hookの方がシンプルで実用的でした。

relay prototypeは、AI間連携の技術検証としては有用でしたが、少なくとも「最終回答コピー問題」の解決策としては過剰だったという結論です。


今回学んだこと

今回一番大きかったのは、

最初から大きく自動化しない

ことでした。

最初は、

ChatGPT
↔
Claude Code / Codex

そのものを自動連携させようとしていました。

model選択やquota対応、agent routingまで含めれば、かなり大きな仕組みになります。

しかし実際に自分の作業を観察してみると、本当に面倒だったのは、

長い最終回答をマウスで選択する作業

でした。

そこだけをStop hookで消すと、

  • 新しいUI不要
  • 新しいサーバー不要
  • DB不要
  • browser automation不要
  • ChatGPT連携API不要
  • interactive terminalを維持
  • 日常追加操作0

で解決できました。

AIを使った自動化でも、

技術的に自動化できる範囲

ではなく、

人間が実際に面倒だと感じている最小の部分

から削る方が、結果的に使いやすいものになると改めて感じました。


注意点

今回の環境固有の点もあります。

  • Claude Code: 2.1.235
  • Codex: 最終確認時 0.148.0
  • Windows
  • PowerShell
  • clipboard書き込みは Set-Clipboard
  • Codexではhook変更後にtrust確認が発生
  • PowerShell 5.1でBOMなしUTF-8 .ps1に日本語literalを書く場合は文字コードに注意
  • Stop hookはclipboardを上書きするため、turn終了時に別のclipboard内容を残しておきたい場合には注意が必要

CLIやhook仕様は今後変わる可能性があるため、実際に利用する際は使用中バージョンの公式ドキュメントも確認した方がよいと思います。


まとめ

今回の最終形はとても小さなものになりました。

ChatGPT
    ↓ copy
Claude Code / Codex
    ↓ normal interactive execution
Stop hook
    ↓ last_assistant_message
Windows clipboard
    ↓ Ctrl+V
ChatGPT

最初に考えていたAI間relayより、ずっと単純です。

しかし毎日何度も行う作業では、この程度の小さな改善でも効果があります。

特に、

「最終回答をマウスで選択してコピーする」

という、毎回数秒〜数十秒掛かる単純作業がなくなったのは快適です。

AIエージェントを高度に自律化する前に、まず人間がAI同士の間で繰り返している小さな手作業を1つずつ消していく。

今のところ、この方向が自分のAI開発環境には合っていそうです。