為你的 AI Agent 掛上 Hooks 吧!
文章目錄

2026/07/17更新:通知腳本改為參數化,通知文字會顯示是哪一套 CLI。
2026/07/12更新:新增 Antigravity CLI hooks 設定。
Claude Code、Cursor、Codex,這些 AI coding agent,相信你已經耳熟能詳,甚至每天都在用了。
那你聽過 agent hooks 嗎?
本文將介紹我目前「唯二」使用的 agent hooks,並說明它們為何重要。
涵蓋工具包括 GitHub Copilot、Claude Code、OpenAI Codex、OpenCode CLI 以及 Antigravity CLI。
不過,僅限於 macOS,其餘平台,就靠大家努力了☺️
什麼是 Agent Hooks
引領風騷的 Claude Code 最早發明了 agent hooks 這個概念。因為太過實用,後來其它工具也競相模仿。
簡單說,agent hooks 是這些 AI coding agent 提供的事件機制:當 agent 完成任務、需要確認,或發生特定事件時,自動執行你指定的腳本或指令。
如果你用過 Git hooks,比如最常見的 pre-commit hooks——在 commit 前跑腳本,agent hooks 就是同樣的概念:事件發生,執行特定指令。
只是觸發點從 Git 操作變成 agent 行為。
為什麼不能只靠指令遵循
我們固然可以在 prompt 裡寫下「產完程式碼後記得跑 lint」之類的要求,但 AI 不一定每次都會照做,尤其當上下文愈來愈長、指示愈來愈複雜時,它往往更傾向偷懶。
至於「做完記得通知我」就更不用說了,AI 根本沒這能力——它沒辦法「主動」播放音效或彈出系統通知。
而 hooks 保證了確定性——事件發生,腳本執行,不依靠 AI 的自主判斷。甚至做到了 AI 本來不能做的事,比如上述的播放音效🔔
我只設兩種 hook
Agent hooks 能做的事很多,基本上能變成指令、腳本的內容都行,比如自動跑 lint、formatter,把結果寫進檔案等等。
但這些並非本文重點——我自己只設兩種 hook:完成通知和權限請求通知,都是為了在 agent 停下來時,能即時提醒我。
為什麼「通知」是最重要的 Hooks
沒有通知,AI 幹活時你只有兩種選擇:在前景盯著它,或不停來回確認。顯然兩種都不太有效率😅
有通知,我們才好真正「非同步」使用它:把任務交給 agent,去做別的事,聽到聲音再回來。
至於 lint、formatter,另有替代方案——pre-commit 這類工具、CI/CD 都能做。但對沒有內建通知機制的工具,只能透過 agent hooks 來達成。
所以,其他 hooks 可以不設,但這個必須有!
通用性的偏好
我總共幫五個 AI coding agent 設定過 hooks:GitHub Copilot、OpenAI Codex、Claude Code、OpenCode CLI、Antigravity CLI。
至於 Google 的 Antigravity 2.0 app,有內建通知機制,如果沒用 CLI 可以不必設定。如果同時設定了 hooks 通知,則都會觸發,建議關掉內建通知。
我只寫全域 hooks,不寫 project-level。這些設定放在 home 目錄,透過 yadm 在不同機器之間同步。
我的 agent skills 也是採取相同策略——幾乎都是全域的,很少寫 project-level。關於「通用 vs 專用」,之前文章有討論過。
接下來直接看設定,腳本也一併附上。
GitHub Copilot:直接共用 Claude Code 設定
GitHub Copilot 能讀取 Claude Code 的設定檔中,有關 hooks 的設定,所以可以直接共用,不一定要另外寫。
不過目前 Copilot 支援的事件種類沒有 Claude Code 多——Stop 事件有支援;不支援的事件會跳過,不會出錯。
考慮到我目前已經暫時棄用 GitHub Copilot 了,這部分請容我略過😆
如有需求,可參考官方文件。
Claude Code
設定位置:~/.claude/settings.json,內容如下:
1 | "hooks": { |
Stop 是完成通知:agent 停下來了。
PermissionRequest 是權限請求通知:當 agent 執行到需要額外權限時,需要你確認才能繼續。這個很有用,因為有時候你離開太久,回來發現 agent 早就在等你,白白浪費了時間。
上面的 command 的 path 請改成你放置腳本的地方,還有檔名。
OpenAI Codex
Codex 的設定對 app 和 CLI 都會生效,下面的 Antigravity 也是如此。
設定位置:~/.codex/config.toml
1 | [hooks] |
Codex 設定檔採用 TOML 格式,和 Claude Code 的 JSON 語法不同,但結構類似。
第一次設定,重啟 Codex app 時,會需要你確認 hooks 的內容與安全性。
OpenCode CLI
OpenCode 比較特別:不能在設定檔裡寫 hooks,必須用 plugin。
而 plugin/ 目錄要放在 opencode 設定檔(opencode.json)所在的目錄底下。即:
1 | ~/.config/opencode/ |
本體是一個 js 檔,內容如下(這是我用 AI Vibe 的,你可以自行調整):
1 | export const NotifyPlugin = async ({ $ }) => { |
另外要注意的是,event type 是 session.idle,不是 Stop。不過意思差不多啦!
透過 Attention 設定
其實,OpenCode CLI 還可以透過 Attention 功能——需要另外寫 tui.json,方便你設定通知,不一定要靠 plugin。
但我不確定它是否適用於「非互動模式」(即 opencode run),而且我感覺這做法的通用性,還不如直接寫 plugin。畢竟通知腳本可以共用。
Antigravity CLI
Antigravity CLI 是 Google 用來取代 Gemini CLI 的命令列工具。所以它的部分設定檔位置,還是延用了 Gemini CLI。
Google 真是狠,財大氣粗,說換就換😆
設定位置:~/.gemini/config/hooks.json,內容如下:
1 | { |
幾個注意事項:
- 必須用絕對路徑:Antigravity 在
-p模式下,相對路徑會失敗 - 腳本必須輸出合法 JSON:Antigravity 會檢查 stdout,所以結尾補上
; echo '{}' - 沒有 PermissionRequest:Antigravity 目前不支援這個事件
Antigravity CLI 已將舊 Gemini CLI 的多個 hook,精簡成僅剩 5 個核心事件。所以沒有 PermissionRequest——但 5 個也太少了吧!
共用的通知腳本
上述工具的 hooks 都呼叫同一組 shell 腳本。腳本接受第一個參數作為 CLI 名稱,這樣多個 agent 並行時,看到通知就知道該回去哪個工具,不用一個個檢查。
沒傳參數時,則顯示預設的 Agent。程式碼如下:
notify-agent-stop.sh
1 |
|
afplay 是 macOS 內建的指令,而音效名稱 Glass 也是內建的。
可以到系統的「設定 > 聲音 > 提示聲」去聆聽每一種內建音效,換成自己喜歡的。
也可以用 afplay 播放任何路徑下的音效檔(如 mp3、wav),只要檔案存在,指令就能正常運作。
而 osascript 則能在通知中心發出文字提醒。這兩個指令搭配起來,就能在任務完成時,同時播放音效和彈出通知,讓你知道 agent 已經處理完畢。
覺得這樣有點吵的話,可以二選一就好。
notify-agent-permission-request.sh
1 |
|
我覺得 Funk 音效很適合當「確認」使用XD
工具會換,需求長存
儘管不同的工具有不同的設定,但「通知」這個需求是一樣的。
所以我在每個工具中都實作了它,讓核心行為保持一致。
如此一來,你想換工具或退掉其中一部分時,體驗上不會受到太大影響。你只需要維護一組通知腳本,所有 agent 都能共用。
畢竟,工具只是工具,不要依戀它。