Claude Code mods 隨 v2.1.287 在 2026 年 10 月 1 日預設開啟,沒有沙箱,能讀 API key,也能搶在你之前核准工具呼叫。 依 Anthropic 的 Mods overview 文件,mod 是用 JavaScript 或 TypeScript 寫的外掛,直接跑在 Claude Code 的行程裡。每一次工具呼叫和每一段提示詞都會先經過它。最容易漏看的一條寫在權限文件。機器上沒有受管理設定(managed settings)、也沒用 Team 或 Enterprise 方案登入時,mod 可以核准 deny 規則已經拒絕的呼叫。下面先講這個缺口,再依序說明安裝前怎麼稽核別人的 mod、怎麼寫一個最小的 mod、組織怎麼把 mods 鎖住。

Anthropic 官方範例 mod Token Weather 在 Claude Code 提示框上方畫出脈絡用量列,顯示 Storm 與 81% of context

個人方案的機器上,deny 規則擋不住 mod 的核准

沒有受管理設定、也沒用 Team 或 Enterprise 方案登入的機器上,Claude Code mods 可以核准 deny 規則已拒絕的工具呼叫。原因在守門 mod 沒有載入。Claude Code 內建一個守門 mod,叫 sec-default@builtin,排在所有使用者自裝的 mod 前面。/plugin 裡看到的名字是 cc-plugin-sec-default。它只在兩種情況載入:機器上有受管理設定,或使用者用 Team、Enterprise 方案登入。用 API key 的人只有機器上有受管理設定才拿得到它。Amazon Bedrock、Google Cloud 的 Agent Platform 和 Microsoft Foundry 的使用者也一樣。

沒有守門 mod 會怎樣,權限文件寫得很直接。處理 tool.check 的 mod 在規則和 PreToolUse hook 決定之後才回答,它的答案可以蓋過前面的決定。

既有的檢查 守門 mod 有載入 守門 mod 沒載入
ask 規則 mod 可以直接核准 mod 可以直接核准
非受管理設定的 PreToolUse hook 封鎖 mod 可以核准 mod 可以核准
auto mode 分類器 mod 核准的呼叫不再經過分類器 mod 核准的呼叫不再經過分類器
deny 規則 預設守得住,除非組織開了 allowModsToOverrideDenyRules mod 可以核准被拒絕的呼叫
受管理設定裡的 PreToolUse hook 封鎖 最終決定,mod 看不到這次呼叫 沒有受管理設定,不適用
mod 自己的 $.fs.read、$.process.run 不受 deny 規則約束 不受 deny 規則約束

最後一列連企業也躲不掉。管理文件的原話是:就算 Read(.env) 被 deny,mod 還是能用 $.fs.read 讀那個檔案,或啟動一個程式去讀。沙箱也一樣,開了沙箱隔離的是 Claude 執行的 Bash 指令,mod 自己啟動的程式跑在沙箱外面。組織的網路政策管得到 $.http.fetch,管不到 $.process.run 啟動的程式。唯一動不了的是權限提示本身,mod 不能改提示顯示的內容,只能讓提示根本不出現。

Anthropic 的發表文章說,守門 mod 會擋下使用者自裝的 mod 去推翻 deny 規則這類高風險動作。這句話只對有守門 mod 的機器成立,文章沒有補上另一半。用個人方案或自備 API key 的開發者,剛好落在沒被涵蓋的那一邊。

mods 的權限邊界上線後還在修。依 Claude Code changelog,2026 年 10 月 3 日的 v2.1.289 有兩項修正跟這條邊界有關。第一個發生在受管理機器上:複合 shell 指令的巢狀部分,deny 或 ask 規則壓不住使用者 mod 的核准。第二個是使用者自裝的外掛能改寫組織管理的 MCP server 登入工具的描述。changelog 沒有點名守門 mod,把這兩項讀成守門範圍的修補是本文的推論。mods 上線兩天後就有這兩項修正,依賴守門 mod 的團隊應該把 v2.1.289 當成最低版本。

版本也決定你現在有沒有 mods。MIXED 在 2026 年 10 月 2 日的報導指出,v2.1.287 在 10 月 1 日 16:59 UTC 發布到 npm。隔天 npm 的 stable 標籤仍指向 2.1.285。走 stable 的人當時還沒拿到 mods,升上去之後就是預設開啟。

個人使用者有三個開關,範圍由小到大:

  • 關掉單一 mod:在 /plugin 的 Installed 分頁停用或移除它的外掛。
  • 這一個工作階段全關:用 claude --safe-mode 啟動,其他自訂也會一起停用。
  • 每個工作階段都關:在 ~/.claude/settings.json 設 "disableAllHooks": true。代價是設定檔 hook 和自訂 status line 一起停。

搶先體驗時期的環境變數 CLAUDE_CODE_ENABLE_FUNCTION_HOOKS 已經失效。v2.1.287 之後設成 0 也關不掉 mods。後兩個開關(--safe-mode、disableAllHooks)停不了內建 mod。內建 mod 要到 /plugin 個別停用,守門 mod 則無法停用。

安裝前先跑 claude plugin validate,讀 hooks 與 calls 兩行

mod 要碰檔案、啟動程式、連網,只能透過 $ 這組 API。mod 的寫法還必須讓 Claude Code 的靜態分析讀得懂,讀不懂的 mod 會被 Claude Code 拒絕載入。所以不用執行,就能列出一個 mod 掛了哪些事件、呼叫了哪些能力。先把外掛的檔案抓下來,例如 clone 它的 repository,再執行:

claude plugin validate ./some-mod

輸出裡有兩行在描述程式碼,管理文件給的例子是:

  ❯ ./register.js hooks: session.start, tool.call, ui.render{component=Pane}
  ❯ ./register.js calls: $.fs.read, $.http.fetch, $.store.set, $.ui.open

calls: 這一行對照下表:

呼叫 代表什麼
$.fs.read、$.fs.write 讀寫你的帳號碰得到的任何檔案
$.process.run、$.process.spawn 以你的身分啟動程式
$.http.fetch 發出網路請求
$.env.get、$.settings.read 讀環境變數與設定檔,裡面可能有 API key;輸出另有 env reads: 一行列出變數名
$.env.set 改掉 Claude Code 之後啟動的每個指令和 MCP server 的環境變數
$.model.complete 用你的方案額度或 API key 呼叫模型
$.prompt.submit、$.session.send 以你的名義送出提示詞,或傳訊息給另一個工作階段

hooks: 這一行要找四個事件。tool.call 和 prompt.submit 代表它看得到、也改得了每次工具呼叫與每段提示詞;session.append 代表它能在對話存檔前改寫每一列;tool.check 代表它能在權限提示出現之前就核准或拒絕。同一行出現 $.fs.read 配 $.http.fetch,再加上 prompt.submit,就該打開原始碼讀。

Anthropic 官方範例 mod Replay Theater 的面板,逐步重播 Claude 上一回合對 greet.js 的檔案修改,顯示 step 1 of 5

公開的 mod 有多少會碰這些能力,Anthropic 沒有公布數字。社群清單 awesome-claude-code-mods 每晚用同一個 validate 指令掃 GitHub。截至 2026 年 10 月 2 日,它掃了 359 個 mod。其中 127 個會啟動程式,95 個會寫檔,75 個會連網,111 個看得到每一段提示詞。另有 21 個在 v2.1.287 驗證失敗。本文換算,會啟動程式的占 35%,看得到所有提示詞的占 31%。這份清單的 README 自己加了但書:「A footprint is a static inventory, not a runtime safety guarantee.」掃到的是靜態盤點。它不是執行時的安全保證。Digital Applied 在 2026 年 10 月 2 日的安裝前檢查清單給了一個實用的分法。只旁觀的可以裝。會連網或啟動程式、而且理由說得清楚的,先讓一位開發者試。會核准工具或改寫提示詞的要逐行審。讀機密又連網、卻說不出理由的直接拒絕。

mod 跑在 Claude Code 行程內,旁觀、改寫、接管都做得到

Claude Code 每次要動作之前都會發出事件,例如執行工具、送出提示詞、畫出介面的某一塊。mod 的 hook 是一個收三個參數的函式:$ 是 mods API,e 是事件內容,next 把事件交給下一個處理者。回傳 next(e) 是旁觀;把改過的副本交給 next 是改寫;完全不呼叫 next、直接回傳結果就是接管,原本的工具根本不會執行。

Anthropic 在 2026 年 10 月 1 日的發表文章把動機講得很白。原本的 hooks 沒辦法改寫事件、畫新介面或換掉內建功能,mods 可以。連內建的 /diff 現在都是一個 mod。

Mod 設定檔 hook Skill MCP server
是什麼 外掛裡的函式,在 Claude Code 行程內被呼叫 生命週期事件觸發的 shell 指令、HTTP 請求或提示詞 Claude 會讀的 SKILL.md 指示 提供工具的外部行程或服務
能改什麼 工具呼叫、提示詞、指令、回合、介面 呼叫或提示詞是否放行、工具參數與結果、補給 Claude 的脈絡 Claude 知道什麼、怎麼做 Claude 有哪些工具
能不能畫介面 可以 不行 不行 不行
你要寫什麼 JavaScript 或 TypeScript 一支腳本加一筆 settings.json Markdown 任何語言的伺服器
適合的時機 要面板、提示框上方的資訊列、自訂指令,或要改寫事件 已經有腳本,只想擋、放行或記錄事件 同一段指示一直重貼 Claude 要連外部系統

表格整理自官方文件的比較表。設定檔 hook、skill 和 MCP server 都從外面跟 Claude Code 互動,只有 mod 住在裡面。文件還列了一件容易被當成細節的事。mod 的 hook 在 VS Code 擴充套件、claude -p 和 Agent SDK 裡照樣會跑,只是畫不出介面。CI 裡的無頭執行也在範圍內。

三個檔案就能寫出第一個 mod

依 Create a mod 教學,寫 mod 不需要 Node.js、打包工具或建置步驟,Claude Code 直接載入 .js 與 .ts。先用 claude --version 確認版本在 v2.1.287 以上,再建兩個資料夾:

mkdir -p first-mod/.claude-plugin first-mod/hooks

第一個檔案是外掛的 manifest,存成 first-mod/.claude-plugin/plugin.json:

{
  "name": "first-mod",
  "version": "0.1.0",
  "description": "Counts Claude's tool calls and shows the count beside the spinner",
  "author": { "name": "Your Name" }
}

第二個檔案 first-mod/hooks/hooks.json 只做一件事,用 modules 指到程式檔。有這個鍵,外掛才算 mod:

{
  "description": "The first-mod hooks module",
  "modules": ["./register.js"]
}

第三個檔案 first-mod/hooks/register.js 是程式本體。下面是官方文件的範例,計算 Claude 用了幾次工具,把數字接在 spinner 後面:

// 兩個 hook 共用的計數
let calls = 0

// mod 載入時,Claude Code 會呼叫一次
export function register(on) {
  // Claude 每次要用工具之前執行
  on('tool.call', async ($, e, next) => {
    calls += 1
    // 請 Claude Code 重畫介面,新的數字才會出現
    $.ui.invalidate('ui.render')
    // 讓工具照常執行
    return next(e)
  })

  // Claude Code 每次畫 spinner 時執行
  on('ui.render', { component: 'Spinner' }, async ($, e, next) => {
    // 保留原本的 spinner,在文字後面加上計數
    return next({ ...e, props: { ...e.props, suffix: ' · tool calls: ' + calls + '…' } })
  })
}

用 --plugin-dir 載入,只對這一個工作階段生效,存檔後會熱重載:

claude --plugin-dir ./first-mod

請 Claude 列出檔案再讀 README,spinner 會依序出現 Thinking · tool calls: 1…、2…、3…。在提示框輸入 /plugin,分頁下方有一行 1 mod active · first-mod,代表載入成功。

第一個 hook 是旁觀,第二個是改寫。接管長這樣,取自 React to events 文件的範例,擋下強制推送:

// matcher 把 hook 限定在 Bash 呼叫,e.command 就是 shell 指令
on('tool.call', { tool: 'Bash' }, async ($, e, next) => {
  if (/git push .*--force/.test(e.command)) {
    // 不呼叫 next 就回傳,指令不會執行
    return { deny: 'Force pushes are not allowed in this repository. Push to a new branch instead.' }
  }
  // 其他指令繼續走權限檢查,再交給 Bash
  return next(e)
})
Anthropic 官方範例 mod Blast Radius 攔下 rm -rf build,在面板列出會刪除的 9 個檔案,並提供 Proceed 與 Cancel 兩個選項

上面的程式碼與輸出都引自官方文件,本文沒有另外實測。

守門型 hook 預設失敗即放行,要自己接 .catch

Claude Code mods 的守門型 hook 預設失敗即放行。沒有 .catch 的 hook 一旦丟出例外或逾時,Claude Code 會跳過它,指令照跑。依 v2.1.289 的 Mods reference,hook 處理單一事件的上限是 10 秒。要改成失敗即拒絕,得在註冊後面接 .catch,在裡面回傳 { deny }。這個處理函式自己的上限只有 1 秒。

組織用 allowManagedModsOnly 一個選項擋掉自帶的 mod

管理者要擋掉使用者帶進來的所有 mod,不必自己寫 mod。在受管理設定的 pluginConfigs 底下,替守門 mod 開 allowManagedModsOnly:

{
  "pluginConfigs": {
    "cc-plugin-sec-default@builtin": {
      "options": {
        "allowManagedModsOnly": true
      }
    }
  }
}

設定之後,使用者自己安裝的、用 --plugin-dir 載入的、請 Claude 在工作階段裡寫出來的 mod 全部不載入。他們的設定檔 hook、status line 和 /goal 不受影響,內建 mod 照常執行。這個選項只從受管理設定讀取,使用者在自己的設定檔寫同一筆沒有作用。守門 mod 讀不到受管理設定時會拒絕所有使用者 mod,是失敗即拒絕的設計。

想達到的政策 要設什麼
不准任何自裝 mod,hooks 不動 allowManagedModsOnly,不部署自己的 mod
只准組織自己的 mod allowManagedModsOnly,加上以目錄型 marketplace 部署 mod
准許核可 marketplace 上的 mod 保留 marketplace 限制,加 disableSideloadFlags: true
mod 和所有 hooks 全關,受管理 hooks 也停 disableAllHooks: true

四個會讓政策無聲失效的設定細節

allowManagedModsOnly 有沒有真的生效,取決於 Anthropic 管理文件裡的四條規則,設錯了不會有錯誤訊息:

  1. 鍵名只認 cc-plugin-sec-default@builtin。prependPlugins 接受 sec-default@builtin,pluginConfigs 不接受。
  2. 一旦在受管理設定寫了 prependPlugins,清單就取代預設值。沒把 sec-default@builtin 列進去,守門 mod 不會載入,兩個選項跟著失效。
  3. 從 GitHub、git、URL 或 npm 來源安裝的外掛,就算由受管理的 enabledPlugins 啟用,仍算使用者的 mod。它在 allowManagedModsOnly 底下不會載入。組織的 mod 必須放在每台機器同一個絕對路徑的目錄型 marketplace,且該目錄只有管理者能寫。
  4. disableSideloadFlags 除了擋 --plugin-dir 和 --plugin-url,也會擋 --agents 與 --mcp-config。開之前要確認沒有人在用。

驗證方法是在測試機用 claude --debug 啟動,然後讀 debug log。使用者 mod 被擋時,log 會多出這一行:

refused by cc-plugin-sec-default: mods are limited to your organization's by policy (allowManagedModsOnly)

想放行一部分 mod,可以寫自己的政策 mod。它在 plugin.register 事件讀 e.uses.calls,遇到 process.run 就回傳 { refuse }。它有兩個限制,文件都寫了:檢查函式丟出例外或逾時時預設放行,要自己接 .catch;使用者用 --safe-mode 啟動,或執行 mod 的 worker 連續當掉三次,組織的政策 mod 也會被卸載。所以政策 mod 適合當稽核與提醒,硬性的界線仍要靠 allowManagedModsOnly 和 deny 規則。

常見問題

Claude Code mods 安全嗎?

Claude Code mods 沒有沙箱,從 v2.1.287(2026 年 10 月 1 日)起預設開啟,以安裝者的權限執行。mod 載入後能讀寫檔案、啟動程式、連網、讀環境變數裡的 API key。在沒有受管理設定、也沒用 Team 或 Enterprise 方案登入的機器上,處理 tool.check 的 mod 還能核准 deny 規則已拒絕的呼叫。安裝前先執行 claude plugin validate,確認 hooks: 和 calls: 兩行沒有超出它宣稱的功能。

Claude Code mods 是什麼,跟 hooks 差在哪裡?

Claude Code mods 是外掛裡的 JavaScript 或 TypeScript 函式,由 Claude Code 在自己的行程內呼叫。設定檔 hook 則是寫在設定檔裡的 shell 指令、HTTP 請求或提示詞,從外部執行,能擋或放行事件,但畫不了介面。官方文件說明既有的設定檔 hook 沒有被淘汰,會跟 mods 並存。

個人使用者要怎麼完全關掉 Claude Code mods?

個人使用者在 ~/.claude/settings.json 設 "disableAllHooks": true,每個工作階段的自裝 Claude Code mods 就會全部停用。副作用是設定檔 hook 和自訂 status line 也會停。只想停一次可以用 claude --safe-mode;內建 mod 不受這兩個開關影響,要到 /plugin 個別停用。

Claude Code mods 可以覆寫 deny 規則嗎?

Claude Code mods 在沒有受管理設定、也沒用 Team 或 Enterprise 方案登入的機器上,可以核准 deny 規則已拒絕的工具呼叫。做法是處理 tool.check 事件,它在權限規則和 PreToolUse hook 之後才回答。守門 mod sec-default 有載入時,deny 規則預設守得住,除非組織開了 allowModsToOverrideDenyRules。mod 自己的 $.fs.read 和 $.process.run 在任何機器上都不受 deny 規則約束。

用 API key 或 Amazon Bedrock 的人有 sec-default 守門 mod 嗎?

用 API key 或 Amazon Bedrock 驗證的使用者,只有在機器上有受管理設定時才會載入 sec-default 守門 mod;Google Cloud 的 Agent Platform 與 Microsoft Foundry 也一樣。沒有受管理設定的機器上,deny 規則壓不住會核准工具呼叫的 mod。以檔案或 MDM 派送的 allowManagedModsOnly 在這幾個供應商上作用相同。

權威引用

Author Insight

沒有受管理設定的個人開發者,只要 validate 的 hooks: 那一行出現 tool.check,就別裝這個 mod,除非你讀完了它的原始碼。在守門 mod 不載入的機器上,這個事件等於一張能蓋過 deny 規則的通行證,而你寫 deny 規則的理由通常就是那幾個絕對不能碰的檔案和指令。組織的門檻是版本。機隊還沒全面升到 v2.1.289 之前,先開 allowManagedModsOnly,把 mods 當成尚未審核的軟體來源;升完、審完第一批再逐一放行。自己寫守門 mod 的團隊另有一條:每個會回傳 { deny } 的 hook 都接上 .catch,否則一次逾時就等於放行。

術語表

用語 本文指的是
mod 含 hooks module 的 Claude Code 外掛,函式在 Claude Code 行程內執行
設定檔 hook(settings hook) 寫在設定檔的 command、HTTP、prompt 或 agent hook
受管理設定(managed settings) 由組織以檔案、MDM 或管理主控台派送,使用者無法覆寫的設定
守門 mod 內建的 sec-default@builtin,在 /plugin 顯示為 cc-plugin-sec-default
deny 規則 權限設定中拒絕特定工具呼叫的規則
Share this post
Ewan Mak

I'm a Full Stack Developer with expertise in building modern web applications that fast, secure, and scalable. Crafting seamless user experiences with a passion for headless CMS, Vercel and Cloudflare

Loading...