Skip to main content
mods API 是 mod 呼叫以執行動作的方法集合:新增命令和工具、呼叫模型、在事件之間執行工作,以及存取檔案系統、程序和網路。每個 hook 都會將其作為第一個引數 $ 接收,方法分組在命名空間中,例如 $.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 提供了一個在問題追蹤器中查詢票證的工具:
當您詢問票證時,Claude 可以使用其 id 呼叫 mcp__my-mod__ticket。第二個 hook 會擷取票證並傳回回應本文,Claude 會將其讀取為工具的結果。當伺服器以錯誤狀態回答時,Claude 會讀取 Lookup failed with status 和數字。
當 MCP Tool Search 延遲載入已註冊的工具時,Claude 會看到其名稱,但在搜尋該工具之前看不到其描述。若 Claude 應在每個回合都考慮此工具,請在註冊中新增 isDeferred: false,以預先載入完整工具。此欄位需要 Claude Code v2.1.293 或更新版本,較早的版本會忽略它。

呼叫模型

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:快取項目在最後一次使用後會保留五分鐘。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 之間選擇。 如果在模型有回答的呼叫中,兩個欄位都維持為零,表示沒有任何內容被快取。請逐一檢查以下原因:

model.complete hook 接收的內容

如果您 hook model.complete 事件以檢查或變更其他 mod 的請求,請從以下欄位讀取文字:
  • e.prompt:一律為字串。當呼叫者傳入陣列時,它是各區塊文字依序串接的結果。
  • e.system:以相同方式建構的字串,若呼叫者未傳入 system 則不存在
  • e.promptBlocks 和 e.systemBlocks:呼叫者的陣列,各自在呼叫者為該欄位傳入陣列時存在
Claude Code 會發送您的 hook 傳給 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 命令(註冊為命令):
當訊息排隊時,您的工作階段中不會出現任何內容,另一個工作階段的 Claude 會讀取 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 已將命令的輸出讀取到結尾,因此命令已經退出

後續步驟