Claude Mods 是 Claude Code 正在 early access 測試的擴充方式:它把 TypeScript Function Hook 放進 Plugin,讓程式以 middleware(中介層)方式參與 Claude Code 的事件流程。截至 2026 年 9 月 20 日,官方仍明確提醒 API 可能隨版本變動;因此這篇不把它當成「裝了就好」的新玩具,而是帶你用拋棄式專案完成一次低風險、可撤回的實驗。
你會先分清 Skill、Classic Hook、Function Hook/Mod 與 Plugin,再建立一個只呼叫 UI 狀態 API、精簡且可觀察的 status-only Mod;接著用 plugin validate 做 capability diff(能力差異盤點)、跑 middleware 順序測試,最後演練停用、卸載、版本釘選與驗收。本文的 validator 與 tests 已在 Claude Code 2.1.278 執行;若你的版本不同,請把輸出差異視為要重新審查的訊號。
Claude Mods 先說結論
Claude Mod = Plugin 容器 + Function Hook 的 typed middleware。官方提案作者說明目前實作與 Claude Code 位在同一個 Bun 行程,但 Worker/node:vm 邊界不是 API contract,也不該被稱為安全 sandbox。把 Claude Code 想成一條廚房出餐線:Skill 是食譜,Classic Hook 是出餐口旁的檢查站,Function Hook 是能包住前後工序的中介層,Plugin 則是把食譜、檢查站、工具與 Mod 一起裝箱的容器。
- 只想教 Claude 一套可重用做法:先用 Skill。
- 想在既有生命週期事件外接 command、HTTP、prompt、agent 或 MCP tool handler:先看 Classic Hook。
- 想在 runtime 事件前後包一層、改寫輸入或結果、組合多個中介層:才評估 Claude Mod。
- 想把多種擴充一起安裝與分發:Plugin 是容器,不是與前三者互斥的第四種執行機制。

Skills、Classic Hooks、Function Hooks 與 Plugin 差在哪?
Skill:把知識與流程交給 Agent
依照 Claude Code Skills 官方文件,Skill 的主體是 Markdown 指令與可選資源;Claude 會先看到描述,再按需要載入完整內容。它很適合教 review 清單、部署流程或某個領域方法,但不是用來攔截每次工具呼叫。若你第一次接觸這套格式,可先讀站內的 Agent Skill 與 SKILL.md 教學,再回來判斷是否真的需要寫程式。
Classic Hook:在既有事件接一個 handler
現行 Claude Code Hooks reference 列出 command、HTTP、prompt、agent(目前仍是 experimental;正式流程官方建議優先 command)與 MCP tool 等 handler。Classic Hook 收到結構化 JSON,也能在部分事件用 updatedInput 或 updatedToolOutput 改資料;所以「舊 Hook 只能擋或放、完全不能改輸入輸出」已不是正確對照。它與 Function Hook 的核心差異,是後者直接在 engine event chain 中以 typed function 組成 before/after/around middleware,不需把每一步都交給外部程序或 HTTP endpoint。
Function Hook/Mod:包住 runtime 事件鏈
官方目前把產品名稱定為 Claude Mods,工程原語仍叫 Function Hooks;截至 2026 年 9 月 20 日官方 repo 的 Mods README給出的定義很直接:Mod 是行為寫在 hooks module 裡的 Plugin。模組匯出一個 register(on, options),每個 Hook 的形狀是 ($, e, next)。
其中 e 是事件資料,next(e) 把流程交給內層,$ 是唯一的主機能力入口。依你訂閱的事件不同,Mod 可能位在 prompt、context、model stream、tool call 與結果的資料路徑上;也可能只畫 UI。這正是它有力量、也需要先做能力盤點的原因。
Plugin:載入與分發的外殼
Plugin 可以同時包 Skills、Classic Hooks、MCP、LSP、agents、commands、Function Hook 與受支援的 Plugin 設定;目前 settings.json 僅支援 agent、subagentStatusLine。官方 Plugin reference 的 user、project、local、managed scope 決定在哪裡載入與分享,不是作業系統權限邊界。官方安全說明也把 Plugin 與 Marketplace 視為高度信任元件,內容可能以目前使用者權限執行程式碼;安裝前仍要檢查整個 Plugin,而不只看 hooks/register.ts。站內的 Claude Code Plugin 安全檢查可補上 Marketplace 與一般 Plugin 的驗收流程。
Claude Mods 與 Function Hooks 怎麼運作?
Function Hooks 採用 Koa 式「洋蔥模型」。跨 Plugin 的現行 tier 由外到內是 prepend(managed)→ user → append(managed)→ builtin → core;同一 module/event 才依註冊順序,先註冊者在外。使用者 Mod 不能跳過更高權限的 managed prepend。外層先做 before,呼叫 await next(e) 後進入內層與 core;等內層完成,再倒序做 after。
outer before
inner before
Claude Code core
inner after
outer after
AlphaLab 在 2.1.278 建立兩個 session.start Hook,第一個先註冊;claude plugin test 的實際順序就是 outer:before → inner:before → inner:after → outer:after,1 個測試通過、0 個失敗。這不只是呼叫順序的小細節:外層能在事件進去前檢查,也能在結果回來後包裝;若不呼叫 next,就可能自行回答並停止內層。
但別把 typed event 誤解成「自動看懂 shell 語意」。例如目前 Bash 工具仍提供一段 e.command 字串,不是 shell AST;heredoc、轉義與間接執行仍可能讓單純 regex 政策失效。要做安全閘門,先理解事件 schema,再把高風險限制放到獨立 CI、OS 或網路控制。若你的需求只是既有 Hook,可先看 Claude Code Hooks 完整教學。
低風險試作 Claude Mods:建立精簡、可觀察的 status-only Mod
以下實驗只呼叫 $.ui.status,不要求檔案、HTTP、process、prompt、model 或 tool 能力。先在拋棄式 repository 建立 status-only,並記下版本。這一節的 shell 指令適用 macOS、Linux 與 WSL:
claude --version
mkdir -p status-only/.claude-plugin status-only/hooks status-only/tests
第一個檔案是 status-only/.claude-plugin/plugin.json:
{
"name": "status-only",
"version": "0.1.0",
"description": "Shows one status line in interactive sessions",
"author": { "name": "Your Name" }
}
第二個檔案是 status-only/hooks/hooks.json。這個精簡 Plugin 只列一個 Function Hook module:
{
"description": "One session.start hook that only calls the UI status API",
"modules": ["./register.ts"]
}
第三個檔案是 status-only/hooks/register.ts。用 isInteractive guard,避免在沒有可見介面的 headless session 設狀態:
import type { On } from 'claude-code'
export function register(on: On): void {
on('session.start', ($, e, next) => {
if (e.isInteractive) $.ui.status('status-only active')
return next(e)
})
}
先不要啟用 flag。從上層目錄做嚴格靜態驗證:
claude plugin validate ./status-only --strict --json
在 2.1.278 的實際輸出中,success 為 true,notes 只有 hooks: session.start 與 calls: $.ui.status。若你的清單多出 $.fs、$.http、$.process、$.env、$.prompt、$.model、$.tool 或 $.mcp,先停下來追到是哪一行、為什麼需要。
Validator 會檢查 manifest、source 與 capability footprint,不是 TypeScript type-checker。第一次開啟 Function Hook loader 前,先盤點目前已啟用的 Plugin:
claude plugin list --json
這個 early-access flag 開的是 Function Hook loader,官方沒有把它描述成只授權 --plugin-dir;enabled 清單也不是單一 Plugin clean room 的證明。嚴格驗證與盤點都符合預期後,才在拋棄式 repo 執行互動式 /plugin-types。這個 session 已是第一次 Function Hook loader activation,不只是 editor setup:
cd status-only
CLAUDE_CODE_ENABLE_FUNCTION_HOOKS=1 claude
# 在 Claude Code 裡輸入:/plugin-types
# 完成後離開 session,再回到上層目錄
它會寫入 .claude/types/;每次更新 Claude Code 都要重生,不要手改。讓 editor 或 TypeScript 5.4+ 讀到現行 contract,可加入精簡的 tsconfig.json:
{
"compilerOptions": {
"target": "es2023",
"lib": ["es2023"],
"types": [],
"module": "esnext",
"moduleResolution": "bundler",
"strict": true,
"noEmit": true,
"skipLibCheck": true
},
"include": [".claude/types", "hooks", "tests"]
}
用 generated types 跑測試,再以 --plugin-dir 載入示範 Mod
靜態清單符合預期後,再加入 status-only/tests/register.test.ts。這個測試不碰真實網路或主機程序,只記錄 ui.status event:
import { describe, expect, test } from 'claude-code/testing'
describe('register', () => {
test('sets one status line at interactive start', async ($, on) => {
const statuses: Array<string | undefined> = []
on('ui.status', ($, e) => {
statuses.push(e.text)
return { value: undefined }
})
on('session.start', ($, e) => ({ cwd: e.cwd }))
await $.session.start({
cwd: '/work', surface: 'terminal', isInteractive: true
})
expect(statuses).toEqual(['status-only active'])
})
})
執行下列測試時,本文環境得到 1 pass、0 fail:
CLAUDE_CODE_ENABLE_FUNCTION_HOOKS=1 \
claude plugin test ./status-only
完成型別生成與測試後,才在新 session 以 --plugin-dir 實際載入 status-only;只用 one-shot 環境變數,不先寫進 shell profile:
CLAUDE_CODE_ENABLE_FUNCTION_HOOKS=1 \
claude --plugin-dir ./status-only
看到 status-only active 後,便完成「只新增 $.ui.status」的 smoke test。官方 sec-default README 顯示它只保護部分 managed prompt、settings 與 tool policy 不被 user tier 改寫,而且明確不自行新增政策;它不是通用安全沙箱。官方 early-access 更新與啟用方式可在 Claude Code 官方 issue核對。
Native PowerShell 不支援前面的 mkdir -p、行首環境變數與反斜線續行;改用:
New-Item -ItemType Directory -Force -Path status-only\.claude-plugin,status-only\hooks,status-only\tests
claude plugin list --json
$previous = $env:CLAUDE_CODE_ENABLE_FUNCTION_HOOKS
try {
$env:CLAUDE_CODE_ENABLE_FUNCTION_HOOKS = "1"
Push-Location .\status-only
try {
claude
# 輸入 /plugin-types,完成後離開
} finally {
Pop-Location
}
claude plugin test .\status-only
claude --plugin-dir .\status-only
} finally {
if ($null -eq $previous) {
Remove-Item Env:CLAUDE_CODE_ENABLE_FUNCTION_HOOKS -ErrorAction SilentlyContinue
} else {
$env:CLAUDE_CODE_ENABLE_FUNCTION_HOOKS = $previous
}
}
Claude Mods 能力盤點:把 validate 當 capability diff
claude plugin validate 能靜態列出 Hook pattern 與呼叫的 $ 方法,適合回答「這次更新多了哪些能力」。它不是惡意程式掃描器,也不會替你判斷目的 URL、檔案路徑、指令、依賴套件或政策邏輯是否安全。
為了驗證這個界線,AlphaLab 另建一個只執行靜態 validation 的測例,宣告 $.process.run(['printf', 'probe']) 與 $.http.fetch('https://example.com')。嚴格驗證仍回傳 success: true,但 notes 清楚多出 $.http.fetch, $.process.run。這只證明靜態語法、結構與 capability 掃描通過;不保證實際載入成功,更不代表行為可信。
- 先存基準:把已審查版本的
--strict --json輸出,連同 source pin/識別一起保留:Git full SHA、archive SHA-256、npm exact version;若是commandsource,保存 accepted command digest 與 resolved output hash。 - 更新後再掃:對 hooks、calls 與 literal env names 做 diff;新增高權限能力就要求逐行說明。
- 讀完整 Plugin:Function Hook realm 沒有 ambient Node/DOM,但同一 Plugin 還可能帶 Classic command hook、MCP、LSP、monitor 或 executable。
- 測失敗路徑:現行 contract 下,Hook throw、逾時或回傳錯誤形狀時,預設會略過該 Hook、讓內層或 core 繼續。拒絕型檢查要在呼叫
next()前完成,並測試.catch;catch 的拒絕結果不能撤銷已執行的內層效果,而且目前另有 1 秒預算。 - 把高風險控制外移:合併政策、秘密隔離與 egress 限制仍要放在 CI、OS、container 或網路層。
最重要的安全句子是:沒有 ambient Node/DOM,不等於沒有主機能力。目前 $ 可以提供檔案、HTTP、process、prompt、model、tool 與 MCP 等介面;上游 managed Hook 可盤點或限制部分能力,但安裝 scope 本身不是權限沙箱。權限流程也不能一概而論:$.tool.call() 的契約明確會經過 permission check,必要時顯示 permission dialog;$.mcp.call() 則明確沒有 permission prompt。現行契約沒有承諾直接的 $.fs、$.http、$.process 會自動套用一般工具權限,因此這些能力要另設上游政策與主機層控制。需要把規則、測試與獨立 gate 串起來時,可參考 Agent CAPA 實作教學。
還要單獨盤點 Plugin monitor:它會以 unsandboxed shell command 執行。若 monitor 已在目前 session 啟動,disable 或 reload 都不會終止該程序,必須結束 session。
如何停用、卸載、版本釘選與準備回退?
版本回退方案要同時管「Claude Code 版本」與「Mod source」。對 copied、非 command source 的 Plugin,plugin.json.version 會影響 cache/更新判斷,但不是密碼學內容釘選;local-directory Marketplace 的 load-in-place Plugin 也是例外。個別 Git plugin source 應鎖完整 40 字元 commit SHA,archive 應鎖 SHA-256,npm source 應鎖 exact version。Marketplace source 本身只能固定 ref,不要把兩層 pin 混在一起。command source 預設會在每個 enabled session 背景重跑一次;設定 CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC 時會跳過背景重跑。Copy mode 以內容 hash 派生版本,link mode 則以 real path 與 top-level entries 派生;這套 cadence 不受 DISABLE_AUTOUPDATER 控制。它不能用 authored version 或 Git SHA 當成同一套回退保證;需要可重現回退時,先停用它,改用已釘選的 Git 或 archive source。官方的 Plugin source 文件列出可用的 source 與 pinning 方式。
- 先記 compatibility pair:保存 Claude Code 精確版本、Mod source pin/識別(Git full SHA、archive SHA-256、npm exact version;
commandsource 保存 accepted command digest 與 resolved output hash)、validation JSON、測試結果,以及/plugin-types生成檔第一行的版本。 - 本地測試立刻停用:結束 session;新 session 不帶
CLAUDE_CODE_ENABLE_FUNCTION_HOOKS=1與--plugin-dir。 - 先辨識來源與 scope:對自行從 Marketplace 安裝的 user/project/local Plugin,先確認實際 scope,再執行
claude plugin disable name@marketplace --scope <user|project|local>;若要卸載,也明確指定同一 scope。從最後一個 scope 卸載時,Claude Code CLI 預設也會刪除${CLAUDE_PLUGIN_DATA}。一般版本回退若需保留資料,先備份並使用claude plugin uninstall name@marketplace --scope SCOPE --keep-data;若是安全事故,則先隔離與檢查該目錄,不要直接讓 known-good 版本重用可能已受污染的 state。官方 Persistent data 說明列出這項卸載語意。Managed 或組織要求的 synced Plugin 需由管理員處理;一般 synced Plugin 從 claude.ai 移除;skills-dir來源則停用或刪除來源。 - 回到 known-good Mod:若你控制 Marketplace,先把個別 Plugin 的 Git source 鎖回已審查的完整 SHA,並確認它會解析成不同的 resolved version;若 authored version 未變,
plugin update會把它視為同一版本而跳過。這種情況先維持停用,將 known-good source 發布成新的 resolved version,再更新或重裝,不能只改 SHA 就宣稱已回退。不控制 Marketplace 時,先停用/卸載,再從受控且固定 SHA 的來源重裝;archive 則核對 SHA-256。官方 version resolution 說明是驗收依據。 - 回到 known-good CLI:依官方指定版本安裝方式,macOS/Linux 可用
curl -fsSL https://claude.ai/install.sh | bash -s 2.1.278安裝本文版本,再跑claude --version。DISABLE_AUTOUPDATER=1只停背景更新;需要凍結所有更新路徑時使用DISABLE_UPDATES=1。 - 重新驗證:重跑
/plugin-types、strict validation 與 tests。 - 停用驗收:新 session 的
claude plugin list --json顯示正確 scope 且已 disabled/未載入,原本行為消失。不要把 disabled Plugin 仍出現在清單或 cache 目錄仍存在,誤判成仍在執行。 - 版本回退驗收:新 session 顯示預期的 known-good resolved version,source pin/識別正確,而且 validation、tests 與 Hook trace 符合保存的 known-good 基準。
Disable/uninstall 在目前 session 何時生效取決於操作路徑:關閉互動式 /plugin menu 時,Claude Code 會自動執行 /reload-plugins;若變更來自另一個 terminal 的 claude plugin 指令,則可在目前 session 手動執行 /reload-plugins。互動式 terminal 可重新載入 hooks、skills、agents、plugin MCP 與 LSP;Desktop、Agent SDK 與 -p 雖可 reload,但不會重連 plugin MCP server,MCP 變更要等下一個 session。這些 reload 說明不適用於已啟動的 monitor:disable 或 reload 都不會停止它。只有確認 Plugin 不含 monitor 的一般變更才把 reload 當候選;Plugin 含 monitor 或正在做事故隔離時,直接結束並重開 session。若你把規則檔也納入遷移,Claude Code 原生 AGENTS.md 教學可幫你分清規則文件與 runtime 擴充,不要把兩者混成同一個退場單位。
截至 2026 年 9 月,Claude Mods 有哪些時效風險?
本文使用的最新公開 Claude Code release 是 2.1.278;官方 repo 內的 Function Hook declaration 則由 2.1.277 生成,檔頭直接標示 EARLY ACCESS,並要求更新後重新執行 /plugin-types。官方目前也有 sec-default、diff、telemetry、agents-md 四個 built-in Mod;早期文章若只列三個,代表它的快照已經不同。
因此不要照抄某篇教學宣稱的最低版本、事件欄位或「零 token」結論。不同 Mod 可以只畫 UI,也可以呼叫 model、agent 或 tool;是否用到模型與 token 取決於實作。每次升級都應把 generated type diff 視為 migration review,而不是例行按下更新。想理解這種 runtime 為何需要成套控制,可延伸閱讀 AI Agent Harness 是什麼與 Claude Token 節省教學。
Claude Mods 常見問題
Claude Mods 是什麼?
它是使用 Function Hooks 的 Claude Code Plugin。行為寫在 hooks module,透過 register(on, options) 訂閱 engine events,並以 ($, e, next) 參與事件鏈。
Function Hook 和 Mod 是同一件事嗎?
不完全相同。Function Hook 是技術原語;Claude Mod 是把這個原語裝進 Plugin 後的產品名稱。討論 API 時看 Function Hook,討論安裝與分發時看 Mod/Plugin。
Claude Mod 能看見 prompt 或改寫工具呼叫嗎?
取決於它訂閱的事件與取得的能力。現行生成型別包含 prompt.submit、prompt.context、tool.call 等事件;相應 Hook 可以讀取並在 contract 允許的範圍改寫輸入或結果。安裝時應把 prompt、instruction、transcript、tool arguments 與 results 都列入資料流盤點。
plugin validate 通過就代表安全嗎?
不是。它能找出部分會阻止載入的靜態/結構問題,並列出 Hook pattern 與 $ capability footprint;它不保證 runtime 可載入或安全。本文的 process+HTTP 測例也能通過 strict validation,所以你仍要讀 source、檢查 dependency、釘選內容並測試失敗路徑。
Claude Mods 一定不耗 token 嗎?
不能一概而論。只更新 UI 的範例不需呼叫模型;但現行 $ 也提供 model、agent、prompt 與 tool 相關能力,實際 token 與上下文影響取決於該 Mod 做了什麼。
怎麼先停用 Claude Mod?
本地 early-access 測試先關 session,再以不帶 flag 與 --plugin-dir 的新 session 啟動。已安裝 Plugin 則在正確 scope disable 或 uninstall;只有不含 monitor 的變更才把 reload 當候選。Plugin 含 monitor 或正在做事故隔離時,直接結束並重開 session。
已經有 Skill,還需要 Mod 嗎?
多數教學型需求先用 Skill 就夠。只有當你必須參與 engine event chain、在前後處理資料或提供新 runtime 行為時,才承擔 Mod 的版本與安全成本。
現在適合把 Claude Mods 用在正式政策嗎?
適合受控試驗,不適合單獨成為不可繞過的唯一防線。它仍是 early access,失敗語意與 API 都必須按精確版本驗證;高風險政策要另有 managed layer、CI 與 endpoint 控制。
給新手的 6 個重點
- 先用一句話選層:知識用 Skill、事件外接用 Classic Hook、runtime middleware 才用 Mod、分發用 Plugin。
- 只在拋棄式 repository 與 one-shot flag 測試 early-access 功能。
- 把
plugin validate --strict --json當 capability diff,不當安全證書。 - 每次更新都綁定 Claude Code 版本、Mod source pin/digest、generated types 與測試結果。
- 拒絕型 Hook 必須測 throw、timeout、錯誤形狀與
.catch,不能假設 fail-closed。 - 停用驗收要在新 session 確認未載入且行為消失;版本回退則要確認 known-good resolved version、source pin 與保存的驗證基準,不能只看資料夾是否還在。
接著閱讀
左右滑動查看更多推薦
結語:先證明單一能力,再談強大擴充
Claude Mods 最值得學的不是「能 Hook 更多事件」,而是它把 runtime 擴充變成可列出、可測試、可組合的能力面。新手的正確起點,是讓 validation 只列出 session.start 與 $.ui.status,並讓測試驗證預期的一次狀態列行為,再演練一次停用與驗收。等這條證據鏈穩定後,才逐項加入真正需要的能力;每多一項,都要能回答誰批准、如何限制、怎麼測、出了事如何撤回。






