Codexの確認画面でEnterを自動送信するAppleScriptを作りました。現時点の最終版
CodexをTerminalで使っていると、ときどき確認画面で止まります。
内容を確認してEnterを押せば進めるのですが、長めの処理を任せているときは、ちょうど席を外しているタイミングで止まってしまうことがあります。
そこで、Codexの確認画面だけを検出して、Terminalを前面に出したうえでEnterを送るAppleScriptを作りました。
最初はもっと単純に「特定の文字列が出たらEnterを押す」だけのスクリプトにしていました。ただ、それだと別の場面で誤操作する可能性があります。
そのため最終的には、以下のような形にしました。
Terminalの全ウィンドウを監視する
各ウィンドウの現在選択中タブだけを見る
表示内容の末尾1,200文字だけを判定対象にする
Codexの確認画面に特有の文言がそろった場合だけEnterを送る
同じ確認画面に対しては、3秒以内に連打しない
対象ウィンドウを前面に出してから入力する
この記事では、現時点で使っている最終版を残しておきます。
1. 何を自動化しているのか
このスクリプトが対象にしているのは、Codexの操作確認画面です。
たとえば、以下のような選択肢と確認文が画面上に出ているときだけ、承認候補として扱います。
Yes, proceed (y)
Yes, and don't ask again for commands
Press enter to confirm
単に「Yes」という文字があるだけでは動かず、選択肢と確認メッセージの両方が検出された場合だけEnterを送るようにしています。
もちろん、これはコマンドの内容を安全と判断する仕組みではありません。あらかじめCodexに任せる作業内容を確認したうえで、「この確認は自動で通してよい」と判断できる場面だけで使うためのものです。
2. 先に書いておきたいこと
この内容は、詳しい方から見ると「わざわざ記事にするほどでもない」と感じるかもしれません。
また、このスクリプトは表示された確認内容を理解して、安全性を判断するものではありません。Codexに任せる作業をあらかじめ確認したうえで、表示された確認画面を通過させているだけです。
そのため、コマンドの内容を1つずつ確認したい方や、安全性を厳密に管理したい方には、あまり参考にならないと思います。
本職でエンジニアをされている方や、業務環境、チーム開発、本番環境に関わる作業では、むしろやらない方がよい、あるいはやってはいけない内容かもしれません。
あくまで個人の開発環境で、作業内容を把握したうえでCodexに長めの処理を任せるとき、「確認のたびに席へ戻る手間を少し減らす」ために作ったものです。
この前提で問題なければ、以下が現時点の最終版です。
3. 現時点の最終版
property lastHandledWindowID : ""
property lastHandledTime : 0
on run
set lastHandledWindowID to ""
set lastHandledTime to 0
log "Codex auto-enter monitor started"
repeat
try
tell application "Terminal"
set terminalWindows to every window
end tell
on error errMsg number errNum
log "ERROR: Window list failed [" & errNum & "] " & errMsg
set terminalWindows to {}
end try
repeat with targetWindow in terminalWindows
try
tell application "Terminal"
set targetWindowID to (id of targetWindow) as text
-- 対象ウィンドウで現在選択中のタブの表示内容を取得する
set terminalText to (contents of selected tab of targetWindow) as text
end tell
if terminalText is not "" then
set textLength to length of terminalText
-- 末尾1200文字だけを判定対象にする
if textLength > 1200 then
set recentText to text (textLength - 1199) thru textLength of terminalText
else
set recentText to terminalText
end if
set hasProceedOption to false
set hasConfirmMessage to false
set recentLines to paragraphs of recentText
repeat with oneLine in recentLines
set lineText to oneLine as text
-- A または B が表示されたら承認候補とみなす
if (lineText contains "Yes, proceed (y)") or (lineText contains "Yes, and don't ask again for commands") then
set hasProceedOption to true
end if
-- Codex の確認画面であることも確認する
if lineText contains "Press enter to confirm" then
set hasConfirmMessage to true
end if
end repeat
if hasProceedOption and hasConfirmMessage then
set secondsSinceLastEnter to 9999
if targetWindowID is lastHandledWindowID then
set secondsSinceLastEnter to (current date) - lastHandledTime
end if
-- 初回は即時実行。同じ確認画面が残る場合のみ3秒後に再試行する
if secondsSinceLastEnter > 3 then
log "Approval prompt found in Terminal window ID: " & targetWindowID
tell application "Terminal"
activate
-- 対象ウィンドウを最前面に移動する
try
set index of targetWindow to 1
on error errMsg number errNum
log "ERROR: Window fronting failed [" & errNum & "] " & errMsg
end try
end tell
-- 前面化とCodexの入力受付を待つ
delay 1.0
tell application "System Events"
tell process "Terminal"
set frontmost to true
key code 36
end tell
end tell
log "Return sent to Terminal window ID: " & targetWindowID
set lastHandledWindowID to targetWindowID
set lastHandledTime to current date
-- 1件処理したら残りのウィンドウは次回の監視周期で確認する
exit repeat
end if
end if
end if
on error errMsg number errNum
log "ERROR: Window scan failed [" & errNum & "] " & errMsg
end try
end repeat
delay 0.5
end repeat
end run4. 入れている安全策
確認画面らしい文言がそろうまで動かない
Yes, proceed (y) だけでは実行しません。
Press enter to confirm も同時に検出できた場合だけ、Codexの確認画面として扱います。
確認画面らしい文言が複数そろっていることを条件にすることで、別のログや通常の操作画面でEnterを送る可能性を減らしています。
画面全体ではなく末尾だけを見る
Terminalの表示内容すべてを解析すると、過去ログに残った文言まで拾ってしまう可能性があります。
そこで、判定対象は末尾1,200文字に絞っています。これなら、現在画面に出ている直近の確認画面を見やすくなります。
同じ画面への連打を防ぐ
確認画面が消えるまで少し時間がかかる場合もあるため、同じウィンドウに対しては3秒以内の再入力を抑制しています。
初回はすぐにEnterを送りますが、同じ確認画面が残っている場合だけ、少なくとも3秒待ってから再試行します。
対象のTerminalを前面に出してから入力する
AppleScriptからキー入力を送る場合、意図しないアプリに入力されるのが一番困ります。
そのため、対象のTerminalウィンドウを先頭に移動し、少し待ってからSystem Events経由でReturnキーを送るようにしました。
複数のTerminalウィンドウを開いているときでも、検出したウィンドウに対して入力するための処理です。
5. 使うときの注意点
このスクリプトは便利ですが、何でも自動承認してよいわけではありません。
特に、次のような場面では止めておいた方がよさそうです。
削除や上書きなど、取り消しにくい操作をCodexに任せるとき
実行内容をまだ自分で確認したいとき
TerminalでCodex以外の作業も並行しているとき
複数の重要なTerminalウィンドウを開いているとき
自分の場合は、作業内容を最初に確認したうえで、長時間のファイル整理や実装作業など、承認のたびに止まりたくない場面で使う想定です。
「確認を自動化する」ためのものではありますが、最初に任せる内容を確認することまでは自動化しない方がよいと思っています。
6. おわりに
最初は「Enterを送るだけ」の小さな自動化でした。
ただ、実際に使うことを考えると、どの画面を対象にするのか、過去ログを拾わないか、連打しないか、どのTerminalに入力されるかまで考える必要がありました。
結果として、数十行のスクリプトではありますが、自分の使い方に合わせた監視ツールになったと思います。
Codexに長めの作業を任せることが増えてきたので、こういう小さな自動化も少しずつ整えていきたいです。
