Codex CLI Hook 整合

不用自己動手執行指令,燈是怎麼知道 Codex CLI 正在做什麼的。

執行一次 andon-light install-hooks --agent codex 之後,燈就會自己更新。日常不需要你執行任何指令。這篇講講這個設定到底做了什麼,為什麼這樣設計,方便你在遇到奇怪的情況時能有個參考。

Codex CLI 也支援和 Claude Code 一樣的「hook」機制:在它自身生命週期裡的一些節點,可以自動幫你執行一條指令。裝好這個整合之後,每個這樣的節點都會被接上,呼叫 andon-light 並傳入對應的顏色。用的是同一個 andon-light 程式、同一條 USB 連線、同一套韌體(參見Claude Code Hook 整合)。變的只是你電腦上執行的軟體,裝置那一端什麼都沒變。

什麼時候觸發哪種顏色

時機顏色原因
新工作階段開始時閒置(紅)工作階段還沒被交代要做什麼。
你送出一則提示詞時工作中(綠)你剛給了它一個任務。
每次使用工具之前工作中(綠)這會在每一次工具呼叫前觸發,所以在一長串密集呼叫工具的過程中,燈會一直保持綠色。
Codex 正要請求你的授權時等待中(黃)比如,正在等你核准執行某條指令。
內部整理(「整理中」)依序點亮模式內部維護:還在運作,只是在忙別的事。
一輪對話正常結束時閒置(紅)回到閒置狀態。
工作階段因為任何原因結束時閒置(紅)涵蓋那些「正常結束」節點可能漏掉的情況。

Claude Code 有一個 Codex 沒有的東西:一個通用的「需要你關注」通知。Codex 唯一的「等你處理」時刻就是上面的授權請求,所以黃色也只由這一個 hook 負責。詳見下面的為什麼沒有通用通知 hook。

這些指令是一條接一條按順序執行的,不是放在背景執行,和 Claude Code 一樣的理由(參見為什麼不放在背景執行)。Claude Code 的設定會合併進一個更大的設定檔,而 Codex 的 hook 放在自己專屬的檔案裡,所以這個整合會直接寫入(或合併進)那個檔案,具體是全域的 ~/.codex/hooks.json,還是某一個專案自己的,取決於你安裝時選的範圍。如果你編輯了這個檔案,需要重新啟動 Codex CLI(或開一個新工作階段)才會生效。

執行前先信任它

在你親自在 CLI 裡查看並核准之前,Codex 不會執行一個新增或變動過的 hook 檔案。沒有辦法從外部授予這個信任。執行完 andon-light install-hooks --agent codex 之後,啟動 Codex CLI,執行 /hooks,確認新的設定內容。

如果跳過這一步,燈沒反應,先查這個:不受信任的 hook 不會報錯,只會悄悄地不執行。

如果你用的是 ChatGPT 桌面應用程式,而不是終端機

在 Windows 上,「Codex 應用程式」通常指的是 ChatGPT 桌面應用程式(Microsoft Store 上那個)裡的 Codex 分頁,這是一個聊天視窗,不是你在終端機裡打的 codex 指令。這一點很重要,因為上面說的信任步驟只能在互動式的終端機工作階段裡完成,ChatGPT 應用程式本身沒有 /hooks 介面。

不過信任設定本身和是從哪個應用程式授予的沒有關係,終端機和 ChatGPT 應用程式讀的是同一份 ~/.codex 設定。所以就算你平常只用 ChatGPT 應用程式,也需要一次性開啟終端機裡的 Codex CLI 工作階段,在那裡執行 /hooks 並核准。之後 ChatGPT 應用程式就會自動套用同一份受信任的 hook 設定。

在完成這一步之前,ChatGPT 應用程式裡的燈就是安安靜靜地沒反應,也不會顯示任何錯誤。和前面說的「不受信任的 hook」是同一種表現。

如果在終端機裡輸入 codex 顯示不是可識別的指令,那是因為 ChatGPT 應用程式內建了自己的一份 CLI,沒有把它加進系統 PATH。在 PowerShell 裡找到並執行它的方法:

  1. 先直接查看設定本身,這樣你看到的是真實的值,而不是盲目相信某個指令碼:

    Get-Content "$env:USERPROFILE\.codex\config.toml" | Select-String CODEX_CLI_PATH

    會印出類似 CODEX_CLI_PATH = "C:\Users\you\AppData\...\codex.exe" 這樣一行。

  2. 把這個路徑原樣加上引號,前面加 &(PowerShell 的「執行這個程式」運算子),把下面範例裡的路徑換成你剛才找到的那個:

    & "C:\Users\you\AppData\...\codex.exe"
  3. 這會開啟一個真正的終端機 Codex CLI 工作階段。在裡面執行 /hooks,查看內容並核准。

  4. 關掉那個視窗就行。ChatGPT 應用程式的 Codex 分頁之後會自動套用這份受信任的 hook 設定。信任狀態存在磁碟上,不依賴於是哪個視窗核准的。

幾個設計上的考量

為什麼「每次使用工具之前」這麼重要

和 Claude Code 一樣的理由:上表裡的大多數時機每輪只會發生一次,但 Codex 的一次回覆裡可能會連續呼叫幾十次工具。把 hook 掛在「每次工具呼叫之前」,意味著整個過程中燈會持續被重新整理,而不會因為中途沒人更新而變成「連線中斷」的閃爍狀態。一整輪完全沒有呼叫任何工具、純粹在思考的情況沒被顧到,不過這種情況的時長通常遠短於韌體 30 分鐘的看門狗逾時,所以實際上不構成問題。參見韌體概覽。

為什麼沒有通用通知 hook

Claude Code 除了專門的授權請求 hook 之外,還有一個更廣泛的「需要你關注」hook。Codex 的生命週期 hook 裡沒有對應的東西。最接近的是一個叫 notify 的獨立設定項,但它只在一輪結束時觸發,而這已經被上面的「一輪結束」hook 涵蓋了。這樣一來,授權請求就是 Codex 以 hook 形式公開出來的唯一「等你處理」時刻,黃色也就只由這一個 hook 負責。

為什麼內部整理要有專屬的顯示效果

和 Claude Code 一樣的理由:如果沒有專屬的圖案,整理期間要嘛保持之前的顏色不變(如果之前是紅色/閒置,容易讓人誤解),要嘛就得再加一個 hook,專門用來在整理結束後把顏色改回去。依序點亮模式一眼就能看出「還活著,在做後續整理」,而且等下一個 hook 觸發時會自然過渡到下一個狀態。

為什麼工作階段開始和結束都特意設成閒置

在工作階段開始時明確設成閒置,能保證新工作階段不會繼承上一個可能中途當機的工作階段留下的顏色。在工作階段結束時(不管 Codex 回報的是什麼原因)也同樣設成閒置,能涵蓋一般「一輪結束」hook 顧不到的情況,比如被中斷或突然關閉的工作階段。

為什麼不放在背景執行

和 Claude Code 一樣的取捨:把每條 andon-light 呼叫放在背景執行,只能保證它按順序「開始」,不能保證按順序「完成」。每條呼叫都是一個獨立的短生命週期程式,雖然快(大約 40-50 毫秒),但也不是瞬間完成。所以在工具呼叫密集的時候,後開始的呼叫有時會比先開始的更早跑完,悄悄地把正確的顏色又覆蓋成過時的顏色。改成一條接一條按順序執行,每次多花一點點等待時間,換來的是燈始終反映事件的真實順序。完整的推理過程參見 Claude Code Hook 整合。

為什麼每條指令都被設計成「靜默失敗」

和 Claude Code 一樣的理由:如果板子被拔掉了,或者在一台根本沒接裝置的電腦上執行 Codex,沒有這個設計的話,每一個 hook 都會在每次觸發時跳出一條顯眼的錯誤訊息。這就違背了「安靜地待在背景」這個狀態燈本該有的定位。等到工具具備自動重新連線的能力時,這個做法就值得重新考慮。詳見 Claude Code Hook 整合。