$ 接收,方法分組在命名空間中,例如 $.ui 和 $.fs。事件決定何時執行 hook,mods API 是 hook 執行後呼叫的內容。
在開始之前,請先建立您的第一個 mod。對於每個方法,請參閱 mods API 方法或閱讀您的建置類型。
新增命令或工具
mod 可以新增供使用者執行的命令和供 Claude 呼叫的工具。在session.start hook 中註冊兩者。Claude Code 在第一個提示之前等待該 hook,因此您註冊的內容從第一個回合開始就可用。
新增命令
命令是供使用者使用的。註冊它,然後為其名稱處理command.run。此範例新增了一個 /standup 命令,該命令採用可選的天數:
/standup 會與其描述一起出現在您輸入 / 時看到的列表中。argumentHint 在您輸入命令和空格後顯示在提示中,如 /standup [days]。當您執行 /standup 3 時,第二個 hook 會傳回 Summary for the last 3 day(s): ...,並且文字記錄會在外掛程式名稱後顯示該文字。hook 永遠不會呼叫 next,因為命令除了您的行為外沒有其他行為。
您傳回的 text 會列印在文字記錄中,Claude 會讀取它。若要不列印任何內容,如只開啟窗格的命令,請傳回 {}。若要讓命令在 Claude 工作時執行,請將 immediate: true 新增到註冊中。
選擇沒有內建命令使用的名稱。在工作階段中輸入 / 以查看它們。$.command.register 會針對已佔用的名稱擲回,並顯示類似 "/focus" refused: it is the built-in /focus 的訊息。擲回的 hook 會被跳過,因此該 session.start hook 的其餘部分也不會執行。在該 hook 中最後註冊命令,或將呼叫包裝在 try 和 catch 中。
新增工具
工具是供 Claude 使用的。使用名稱、Claude 讀取的描述和其輸入的 JSON Schema 來註冊它。Claude 會在由mcp__、您的外掛程式名稱、兩個底線和您註冊的名稱組成的較長名稱下看到它。您在 tool.call hook 中處理其呼叫,該 hook 已篩選為該完整名稱。此範例來自名為 my-mod 的外掛程式,註冊 ticket,因此完整名稱是 mcp__my-mod__ticket。它為 Claude 提供了一個在問題追蹤器中查詢票證的工具:
mcp__my-mod__ticket。第二個 hook 會擷取票證並傳回回應本文,Claude 會將其讀取為工具的結果。當伺服器以錯誤狀態回答時,Claude 會讀取 Lookup failed with status 和數字。
呼叫模型
mod 可以向模型發送自己的請求,用於分類或摘要文字等小工作。$.model.complete 會單獨發送您的提示詞,而 $.model.fork({ prompt }) 則會發送目前的對話,並將您的提示詞附加在最後。
下表比較每種請求所包含的內容:
fork 會重複對話的最後一次請求,因此在對話仍在快取中時,Claude API 會從提示快取提供大部分內容。
這兩種呼叫都使用工作階段的憑證,因此會計費至使用者的方案、API 金鑰或雲端供應商。您的建置類型記載了每個
$.model 方法。
發送單一提示詞
將model 和 prompt 傳給 $.model.complete。prompt 會成為使用者訊息。若要給模型指令,例如角色或輸出格式,請同時傳入 system,它會成為系統提示詞。
此 hook 透過要求小型模型標記在其後輸入的文字來回答 /triage 命令(註冊為命令):
/triage the export button does nothing 時,mod 會將該文字傳送給模型並列印其答案,例如 Label: bug。當模型沒有回答時,標籤為 unknown。
Claude API 失敗不會拒絕呼叫,因此請檢查 r.isAnswered,當其為 false 時請讀取 r.reason。呼叫會因為 Claude Code 不會傳送的請求而被拒絕,例如您的組織封鎖的模型。
您的建置類型列出其他選項,例如 effort,而限制提供 maxTokens 預設值。
使用提示快取
$.model.complete 支援 Claude API 的提示快取。API 會快取請求的開頭部分(稱為前綴),直到您設定的快取斷點為止。當每次呼叫都以相同的冗長靜態內容開頭時,例如指令或參考資料,請在該內容的結尾設定斷點。之後的呼叫便會從快取讀取該內容,而不必為其支付完整的輸入費用。
若要設定斷點,請將 prompt 以 { text } 區塊陣列的形式傳入,而非字串,並在靜態內容的最後一個區塊加上 cache: true。Claude Code 會以 API 的 cache_control 欄位發送該區塊。system 也接受相同的陣列形式。若要決定使用哪一個,請參閱在 prompt 與 system 之間選擇。
區塊陣列需要 Claude Code v2.1.292 或更新版本。較早的版本會拒絕
prompt 中的陣列,並顯示以 takes { model, prompt } (host check) 結尾的錯誤,且會將 system 中的陣列排除在請求之外。/triage hook 會在要標記的文字之前發送一長串標記規則,並在規則之後設定斷點。RULES 是您自己的字串:
- TTL:快取項目在最後一次使用後會保留五分鐘。TTL 來自使用者的 Claude Code 設定,而非來自呼叫。若要設為一小時,請將
subagentPromptCacheTtl設為1h。 - 每個請求的斷點數:API 接受最多四個,再多一個則會在
r.reason中以api-error傳回
在 prompt 與 system 之間選擇
除非您確定您的請求會直接送往 Claude API,否則請將呼叫共用的靜態內容放在 prompt 的開頭:
- 直接送往 Claude API,使用 API 金鑰或 Claude 訂閱:兩個欄位皆可
- 透過 Amazon Bedrock、Claude Platform on AWS、Google Cloud’s Agent Platform、Microsoft Foundry 或 LLM 閘道:請使用
prompt。Claude Code 會以一段歸屬區塊作為系統提示詞的開頭,其指紋來自使用者訊息的開頭。api.anthropic.com端點會在快取前移除該區塊。其他端點則會將其作為提示詞的一部分接收,因此當prompt的開頭不同時,system中的斷點可能無法命中。 - 在其他人執行的 mod 中:請使用
prompt,因為您無法選擇他們的供應商
system 位於 prompt 之前,因此 prompt 中的斷點也會涵蓋 system,而使用不同 system 的呼叫將無法命中快取。
檢查快取命中
$.model.complete 的結果包含一個 usage 物件,其中有 API 的快取欄位。usage.cache_creation_input_tokens 計算呼叫寫入快取的 token 數,而 usage.cache_read_input_tokens 計算從快取讀取的 token 數。預期第一次呼叫會寫入,而在 TTL 內的後續呼叫會讀取。
如果每次呼叫都寫入而從未讀取,表示各次呼叫的前綴不同,或呼叫之間的間隔超過 TTL。關於前綴不同的情況,請參閱在 prompt 與 system 之間選擇。
如果在模型有回答的呼叫中,兩個欄位都維持為零,表示沒有任何內容被快取。請逐一檢查以下原因:
- 前綴太短:API 不會快取短於模型最小長度的前綴,且不會傳回錯誤
- 提示快取已停用:當
DISABLE_PROMPT_CACHING變數套用於該模型時,Claude Code 會移除斷點,並以未快取的方式發送文字 - 您的閘道移除了
cache_control:閘道可能會移除該欄位但仍傳回成功 - 另一個 mod 改寫了文字的開頭:此時 Claude Code 會在沒有斷點的情況下發送
model.complete hook 接收的內容
如果您 hook model.complete 事件以檢查或變更其他 mod 的請求,請從以下欄位讀取文字:
e.prompt:一律為字串。當呼叫者傳入陣列時,它是各區塊文字依序串接的結果。e.system:以相同方式建構的字串,若呼叫者未傳入system則不存在e.promptBlocks和e.systemBlocks:呼叫者的陣列,各自在呼叫者為該欄位傳入陣列時存在
next 的字串,並使用您一併傳入的陣列來放置快取斷點。它會保留仍與字串開頭相符的前導區塊及其斷點,並在沒有斷點的情況下發送字串的其餘部分。例如,next({ ...e, prompt: e.prompt + NOTE }) 會保留呼叫者的斷點,而變更 prompt 開頭的 hook 則會移除這些斷點。
在背景執行工作
超越一個事件的工作,例如每分鐘檢查一次,在您從session.start 啟動的計時器上執行。hook 本身為一個事件執行,並對其自身的執行時間有時間限制。在 next 或 mods API 呼叫上花費的時間不計算,除了 $.clock.sleep。$.clock.every 和 $.clock.after 取代 setInterval 和 setTimeout,延遲以毫秒為單位首先:$.clock.after(5000, fn) 在五秒後呼叫 fn 一次。每個都傳回一個具有 cancel() 方法的計時器,而 await $.clock.now() 給出以毫秒為單位的時間。
此 hook 每分鐘查詢一次提取請求的檢查,並在提示下方顯示結果。summarize 是您自己的函式,將命令的 JSON 輸出轉換為幾個單詞:
⚠、mod 的名稱,然後是 checks: 和您的摘要。之後每分鐘會被取代一次。計時器的回呼在任何事件之外執行,因此它在回合之間保持執行,不會啟動一個。如果回呼擲回,錯誤會進入偵錯日誌,計時器在下一個間隔再次執行。
顯示某些內容而不啟動回合
背景工作可以向使用者顯示某些內容而不啟動回合。這些呼叫中的每一個都將文字放在不同的位置:
在 VS Code 擴充功能中,狀態列和快顯通知改為顯示在提示詞輸入框上方,而日誌行則顯示在對話中。
從背景工作啟動回合
當背景工作發現需要 Claude 注意的內容時,它可以透過使用$.prompt.submit({ text }) 提交提示來啟動回合。Claude 讀取文字後面有一句話,該句話將您的 mod 命名為寄件者。若要將其作為使用者自己的話語傳送,不帶該句話,請新增 asUser: true。呼叫會等待直到工作階段閒置,然後啟動新回合。它在該回合啟動時解析,因此不要在 Claude 工作時執行的處理程式中 await 它。
停止背景工作
當模組重新載入時,計時器停止。對於 hook 內的長時間執行工作,next.signal 是一個 AbortSignal,當您的 hook 正在處理的事件被放棄時中止,例如當使用者中斷時,因此將其傳遞給任何長時間執行的內容。
在工作階段之間傳送和接收訊息
mod 可以向您的另一個工作階段、此工作階段的某個 subagent,或其 agent team 中的隊員傳送純文字訊息。它也可以觀察到達和離開的訊息。 若要傳送訊息,請呼叫$.session.send({ to, text }),它會進行與 SendMessage 工具相同的傳遞。依據接收訊息的對象設定 to:
- 您的另一個工作階段:
{ sessionId } - subagent 或隊員:
{ agentId },使用來自$.agent.list()的 id - 您所收到訊息的寄件者:該訊息來源的字串位址
{ isDelivered: true }。當沒有任何內容被傳遞時,它會以 { isDelivered: false, reason } 解析,reason 說明原因。
此 hook 透過詢問您在其後輸入的 id 的工作階段的狀態,來回答 /ping 命令(註冊為命令):
Status? One line.。當沒有任何內容被傳遞時,toast 通知會顯示原因。
session.receive 和 session.send 讓 mod 觀察訊息。從兩者都返回 next(e) 以不變地傳遞每個訊息:
設定為拒絕入站訊息的工作階段在
session.receive 觸發之前拒絕訊息,因此 hook 永遠不會看到它。為您的批准而保留的訊息首先到達 hook,因此 mod 可以讀取您尚未批准的訊息。hook 的 next(e) 在訊息未被傳遞時拒絕。
接收訊息上的寄件者名稱是寄件者寫的任何內容,因此不要基於它做出決定。
存取檔案、程序和網路
mod 透過 mods API 存取檔案系統、程序和網路,具有與執行 Claude Code 的使用者相同的權限。hook 模組本身沒有 Node.js API、沒有計時器全域變數(例如setTimeout),也沒有自己的網路或檔案存取。標準 JavaScript 和網路 API(例如 URL、TextEncoder、AbortController 和 crypto.subtle)可用。下面的每個命名空間涵蓋一種存取:
檔案、程序和請求有幾個自己的規則:
- 路徑:相對路徑會相對於工作階段的工作目錄解析,或相對於該 hook 正在處理其事件的 subagent 的工作目錄解析
$.fs.list:將一個目錄的項目傳回為{ name, kind, size, isLink },不會遞迴$.process.run:採用引數列表,不使用 shell。無論退出碼如何,它都解析為{ exitCode, stdout, stderr }。如果程式無法啟動或在逾時時仍在執行,它會拒絕,預設為 30 秒,因此將其包裝在try和catch中。$.http.fetch:最多追蹤五次重新導向。當重新導向至不同的來源時,它只會保留您設定的accept、accept-language、content-type和user-agent請求標頭,並捨棄其餘標頭,因此依賴其他標頭(例如Authorization)的請求可能會在該重新導向之後失敗。限制列出了它的逾時和本文大小。
$.,例如 $.fs.read 的 fs.read。鏈中較早的 mod 可以觀察、重寫或拒絕您的呼叫,這是組織限制 mod 到達的方式。
mod 可以在命令已產生輸出或已退出之後拒絕您的 $.process.spawn 呼叫,而命令已執行的任何動作都不會被復原。此時該呼叫會以一則訊息拒絕,訊息結尾為下列其中一個字串以及拒絕的 mod 所給的原因:
$.process.spawn started, and a plugin withheld its result::拒絕的 mod 尚未將命令的輸出讀取到結尾。如果命令仍在執行,Claude Code 會將其停止。$.process.spawn ran, and a plugin withheld its result::拒絕的 mod 已將命令的輸出讀取到結尾,因此命令已經退出