剛剛,Claude Code 推出了 Mods 功能。
用幾行 TypeScript,就能改掉 Claude Code 的行為、重畫它的介面,甚至把它的內建功能換成你自己寫的版本。
不會寫也沒關係,直接跟 Claude 說你想要什麼,它會自己寫好、裝上、熱多載,當前會話裡馬上生效。
Mods 隨外掛(plugin)一起分發,在 CLI 或桌面端裡用 /plugin 就能安裝,從 Claude Code 2.1.287 開始默認開啟。
2.1.287 版本
Claude Code 負責人 Boris Cherny 表示:
Mods 簡直瘋狂。你現在只需要提示一下,就能把 Claude 定製成你想要的工作方式和樣子。每個人的工作方式都不一樣,沒有理由讓所有人都用一模一樣的 Claude。
01. Mods 是什麼
Claude Code 每做一件事,都會發出一個事件:呼叫工具、申請權限、提交 prompt、開始和結束一輪對話,甚至是畫螢幕上的某一塊。
一個 Mod,就是掛在某個事件上的一個函數。它可以在事件之前跑、之後跑,或者乾脆取而代之,也可以把事件包起來前後各跑一段。
Anthropic 工程師 Lydia Hallie 稱,Mods 基本上就是 Claude Code 的中介軟體。
寫過 Express 或 Koa 的同學應該會很熟悉,每個 hook 永遠是三個參數:
一個 hook 能做的動作只有三種:觀察、改寫、接管。觀察是先調 next 再看結果,改寫是改了 e 再交給 next,接管則是不調 next、自己返回結果。
接管最典型的用法,就是說「不」。
Anthropic 在 GitHub 上公開徵求意見時錄過一組演示,那會兒它還叫 Function Hooks。其中一個給 tool.call 加了 matcher,只匹配命令裡帶 curl 的 Bash 呼叫,然後不呼叫 next,直接返回 deny 和理由:
讓 Claude 去 curl 一個網址,模型呼叫 Bash,被 hook 拒絕,工具根本沒跑,拒絕理由作為工具報錯回到了模型那裡。
整個過程既沒有彈權限窗口,也不用去改配置檔案。
這樣一個函數能做的事,官方列了這幾類:在 prompt 發給模型之前改寫它;攔下、改寫或重試一次工具呼叫;替你批准或拒絕一次權限請求;在 Claude 讀到工具輸出之前,把裡面的金鑰抹掉。
Mod 還能改你看到的東西。Claude Code 給每次工具呼叫都畫一行,另一個演示掛在 ui.render 上、匹配 ToolUse 元件,換成自己返回一段黃色文字:
黃色那行就是外掛畫的,Claude Code 自己的那行沒有再畫。同一個會話切到桌面端,這一行也在。
工具結果、Claude 向你提問的對話方塊,這些官方介面都能改寫或替換。Mod 還能加按鈕和輸入框,其他 Mod 也能響應這些按鈕。目前 Mod 可以畫在終端、桌面端,或者兩邊都畫。
多個 Mod 掛在同一個事件上時,按載入順序執行,先載入的最先看到事件、最後拿到結果。
演示裡 hook A 和 B 都在 next 前後各打一行日誌,A 先註冊時是 A 包著 B,把 B 剪下貼到 A 上面再跑一遍,日誌就變成了 B before、A before、A after、B after:
像洋蔥一樣一層套一層,所以管理員想管控就往前插,想設預設值就往後加,不同作者寫的 Mod 也能這樣疊著用。
注意:上面這幾段演示都錄於上線前的早期版本,有些 API 和正式版已經不太一樣了。
那它和之前的 hooks 有什麼區別呢?
hooks 已經能攔截一部分事件,但沒法改寫事件、畫新介面、替換功能,這些 Mods 都可以。
而且 Settings hook 每個事件都要跑一次 shell 命令,靠 stdin/stdout 傳 JSON;Mod 則只載入一次、常駐在會話裡,能保存狀態,能畫隨事件即時更新的介面,還能反過來呼叫 Claude Code 開面板、跑處理程序、註冊斜槓命令,甚至註冊一個給模型用的工具。
02. 三個官方示例
Addy Osmani 寫的官方入門指南,用了三個 Mod 來展示它能幹什麼。
第一個叫 Token Weather,在輸入框上方畫一行上下文「天氣預報」:
上下文用量不到 25% 是晴 ☀,25-49% 多雲,50-74% 陣雨,75-89% 雷暴,90% 以上則是「快要 compact 了」↯。
後面跟著百分比、已用 token / 窗口大小、最近 12 輪的迷你柱狀圖,以及上一輪漲了多少。
在桌面端的真實會話裡,每一輪讓 Claude 多讀幾個檔案,天氣便從晴一路變成了雷暴:
整個 Mod 大約 80 行,而你其實可以一行都不寫。官方給了個捷徑,在 Claude Code 裡直接貼上這段描述就行:
幫我做一個叫 token-weather 的 Claude Code mod:在輸入框上方的那一欄裡,即時顯示我的上下文窗口「天氣預報」。
一行裡要顯示:
- 一個天氣圖示和詞,表示上下文窗口有多滿:25% 以下 ☀ Clear(黃色),25–49% ☁ Cloudy(青色),50–74% ☂ Showers(藍色),75–89% ☇ Storm(品紅),90% 及以上 ↯ Compact soon(紅色)。
- 已用百分比,然後是已用 token / 窗口大小,比如「134.4k / 200k」。
- 最近 12 輪的小圖表,用 ▁▂▃▄▅▆▇█ 畫。
- 上一輪增加了多少,比如「▲ +98.3k last turn」。
每一輪結束後都要更新。
Claude 會問一次要不要為當前會話開啟熱多載,同意之後,這一輪結束時那一欄就出現了。
之後你還可以接著提要求(「讓 Storm 從 70% 開始」「在最後加上花了多少美元」),一邊說一邊看它變。
這段 prompt 從頭到尾只描述了想看到什麼,一個 API 都沒提。
第二個 Blast Radius,管的是危險命令。
當 Claude 要用 Bash 跑 rm -rf、git reset --hard、git clean、強推或者資料庫遷移時,Blast Radius 會先把這次呼叫扣下來,算出這條命令會影響那些東西,再彈出一個帶 Proceed 和 Cancel 的面板:
演示裡它扣下了 rm -rf build,列出會刪掉的 9 個檔案。按 2 取消,Claude 會收到一條帶原因的拒絕,等你說「刪吧,我確定」再來一次,按 1 才真正執行。
終端裡也是一樣:
窗口不夠寬、放不下側邊面板時,它會退回到輸入框上方顯示:
它用的正是「接管」:不呼叫 next,直接返回 { deny: "…" }。dry run 的資料則來自 git status --porcelain、git clean -n 這些工具自帶的命令。
不過官方也提醒了,它只是安全網,不是權限系統。它看的是命令文字,$(…)、別名、呼叫了 rm 的指令碼都能繞過去,真要硬攔截還得靠權限規則。
Replay Theater 則用來回放 Claude 剛改了什麼。
一輪對話進行時,它會記下每一次 Edit 和 Write 改了那個檔案、改前改後是什麼。
演示裡讓 Claude 把 greet 全域改名為 welcome,它在四個檔案裡改了六處,這一輪結束後輸入框上方出現一個回放提示:
按 r(或輸入 /replay),就會打開一個面板,一步一個 diff 地回放,帶編號步驟條和 Prev、Next、Close 按鈕:
它全程只觀察,不攔也不改任何一次編輯。全螢幕時面板停靠在右邊,80 列寬時則直接內嵌在輸入框上方,Mod 畫的是同一棵樹,擺在那由介面決定:
03. 讓 Claude 幫你寫
最省事的,還是在互動式會話裡直接跟 Claude 描述你想要的 Mod,比如「做一個 mod,在輸入框上方顯示當前 git 分支」。
Claude 靠的是一個內建的 plugin-authoring skill,裡面寫清楚了 Mod 該寫在那、當前版本有那些事件和方法、怎麼載入。你也可以手動輸入 /plugin-authoring 載入它。
設計帖裡有一個完整演示,人只打了一句話:「把工具輸出裡的高熵金鑰抹掉,並告訴模型抹了幾個」。
Claude 先載入寫外掛的 skill,寫好兩個清單檔案,再寫一個掛在 tool.call 上的函數,掃描像金鑰的長串、按熵打分、把分高的換成標記,最後自己跑完校驗。
帶上外掛重新啟動後讓它讀 .env,兩個 key 都變成了 [REDACTED_SECRET],普通的那行原樣保留,模型還被告知了具體發生了什麼:
另一個演示在桌面端,需求同樣只有一句:做個外掛,把螢幕上的數字和信箱都藏起來,滑鼠懸停時再顯示。Claude 寫好、兩條命令裝上,不用重啟,當前會話就生效了。
它寫的 hook 掛在 ui.render 上,所以 Claude 讀到的仍然是真實文字,變的只是顯示:
讓它出本季度報表,表格里所有數字和信箱都被藏了起來,指到那個才顯示那個,問 EMEA 的增長率,它照樣能按真實資料答出來。
正式版裡,讓 Claude 寫 Mod 的流程是這樣的:
1. Claude 把 Mod 寫進當前會話專屬的目錄 ~/.claude/dev-mods/<會話 ID>/。因為 ~/.claude 是受保護路徑,default 和 acceptEdits 模式下每個檔案都要你批准一次
2. 保存第一個檔案時,Claude Code 會問是否為本會話開啟熱多載。選 Enable for this session,Mod 會在這一輪結束時載入,之後每次修改都在輪次結束時多載;選 Not now 則暫不載入,下次啟動這個會話時再載入
3. 運行 /plugin,按 Tab 切到 Installed 標籤頁,就能看到這個 Mod,也可以在這裡關掉它
4. 不滿意就繼續跟 Claude 說要改什麼
這個 Mod 只在寫它的那個會話裡生效,會話目錄超過 cleanupPeriodDays 後還會被清理。
想留著用,就把目錄拷到比如 ~/mods/git-branch,之後用 claude --plugin-dir ~/mods/git-branch 啟動,或者放進 marketplace 分享給別人。
另外,在 claude -p、dontAsk 模式這類沒人能點批准的會話裡,或者在沒信任過的目錄、開了 --safe-mode / --bare / disableAllHooks 的情況下,Claude 寫的 Mod 都不會載入。
04. 自己寫一個
想看懂 Mod 的程式碼長什麼樣,官方文件給了一個 first-mod 教學:統計 Claude 呼叫了多少次工具,把次數顯示在 spinner 旁邊,再加一個 /tally 命令。
前提是 Claude Code 版本在 2.1.287 及以上(claude --version 查看)。不需要 Node.js,也不需要打包和建構,.js 和 .ts 檔案 Claude Code 直接就能載入。
目錄結構只有三個檔案:
plugin.json 是普通的外掛清單:
hooks/hooks.json 裡的 modules 指向你的程式碼,有了它,這個外掛才算一個 Mod:
register.js 是 Mod 的本體,官方叫它 hooks module:
四個 hook 正好把三種動作都用上了:session.start 和 tool.call 是觀察,command.run 是接管,ui.render 是改寫。
然後用 --plugin-dir 載入,這個參數隻在本次會話裡載入外掛,不會安裝:
讓 Claude 做點需要好幾次工具呼叫的事,spinner 後面就會出現不斷上漲的計數,比如 Thinking · tool calls: 2…;結束後輸入 /tally,會列印出總次數。
會話別關,直接改程式碼保存,Claude Code 會熱多載這個模組,下一個 spinner 就用上了新文字。官方說,這個快速反饋的循環,正是寫 Mod 好玩的大部分原因。
只是熱多載會重新跑 register,模組裡的變數會清零,想跨多載保存資料,要放進 $.state。
寫完之後,有兩個命令可以檢查:
validate 會用和 Claude Code 載入時相同的靜態分析,列出這個 Mod 掛了那些事件、呼叫了那些 API,事件名拼錯它會直接報出來,比如 "tool.calls" is not an event。
test 則跑 tests/ 下的測試,不需要會話、登錄和網路。
靜態分析也帶來了幾條寫法上的規矩:$ 的呼叫要寫全($.store.get(...),不能把 $.ui 賦給變數或解構),on 的事件名必須是字串字面量,只能用 ES module 的 import,也只能引用外掛目錄裡的檔案……
每次載入 Mod 時,Claude Code 還會把當前版本的類型聲明寫進 .claude-plugin/types/,編輯器能直接補全和類型檢查。
官方特別說明,事件和方法在版本之間可能會變,兩者衝突時以這些類型檔案為準,文件也不例外。
完整的 API,可以看 GitHub 設計帖裡 9 月 9 日放出的這張官方速查表,只是它對應的還是上線前的版本:
05. 安裝與分享
Mod 就是外掛,所以分享方式跟外掛完全一樣:把它放進一個帶 .claude-plugin/marketplace.json 的 GitHub 倉庫,這個倉庫便成了你的 marketplace。
別人安裝只需三條命令:
也可以在 shell 裡用 claude plugin install <名字>@<marketplace>。想讓更多人找到,可以提交到 Claude 目錄 claude.ai/directory/manage。
發佈前還要注意,外掛名不能像 Anthropic 官方的(比如以 claude- 開頭),validate 會直接攔下;而事件和方法又會隨版本變化,最好在 README 裡寫明你測試時用的 Claude Code 版本。
官方還會在 Claude Code Playground 倉庫裡陸續放入預置的示例 Mod,可以直接拿來改。
Anthropic 的 Thariq 推薦了一個他自己用得很多的 Mod,叫 next-steps,每輪結束後會給出下一步建議,包括該用那個 skill 或命令:
安裝方式:
06. 內建 Mods
Claude Code 已經把自己的一部分功能改成了 Mod。
比如 /diff 現在就是一個 Mod,你可以在 /plugin 裡關掉它,或者換成自己寫的版本,AGENTS.md 支援也是。
而官方的計畫是把更多內建功能陸續遷成 Mod,最後讓你可以把 Claude Code 削減到一個很小的核心,只把自己想要的加回來。
目前內建的 Mods 有這些:
/plugin | |
|---|---|
/diff 並畫出它的面板 | |
其中 You should know 默認關閉,用 /plugin enable cc-plugin-you-should-know@builtin 開啟(限直連 Anthropic 的會話,且要開著遙測)。
這些內建 Mod 的原始碼和測試都公開在 anthropics/claude-code 倉庫的 mods/ 目錄下,官方團隊怎麼寫的,可以直接翻。
同一個 2.1.287 版本裡,追蹤帳號 ClaudeCodeLog 統計到提示詞檔案少了 13 個,提示詞 token 少了 8328 個(-26.6%)。我大膽猜測一下……這或許跟一部分功能被挪進了 Mod 有關?
07. 能在那跑
claude(含編輯器內建終端、JetBrains 外掛) | ||
claude -p | ||
08. 安全
Mod 的權限和 Claude Code 本身一樣大,沒有沙箱。
按官方文件的說法,一個 Mod 可以以你的身份讀寫你帳號能碰到的任何檔案、啟動程序、發網路請求;讀到環境變數和配置檔案裡的 API key;看到你發的每條 prompt 和 Claude 的每次工具呼叫,並改寫它們,甚至冒充你提交一條 prompt;不問你就批准一次工具呼叫;還能用你的套餐或 API key 調模型花錢。
所以官方反覆強調,只裝你信得過的來源,就像在電腦上裝任何程式碼一樣,裝之前先看看倉庫。
安裝前,可以先用 claude plugin validate ./some-mod 列出這個 Mod 會做什麼。
想關掉 Mod,有三種粒度:
- 關掉單個 Mod:在
/plugin的 Installed 標籤頁停用或解除安裝 - 本次會話關掉所有已安裝的 Mod:用
--safe-mode啟動(其他自訂也會一起關掉) - 所有會話都關掉自己裝的 Mod:在
~/.claude/settings.json裡設定"disableAllHooks": true(settings hooks 和自訂狀態列也會停,組織管理的照常運行)
09. 企業管控
對於團隊和企業,Mod 沿用外掛的那一套管控,管理員可以允許或遮蔽 plugin marketplace。
Team 和 Enterprise 套餐由 owner 在管理後台設定,Claude API 和第三方 API 套餐則由管理員把 managed settings 推到使用者機器上。
在 Team / Enterprise 套餐,以及任何有 managed settings 的機器上,會有一個叫 sec-default(security default)的內建 Mod 最先載入,使用者關不掉。
它保護的是組織管理的那部分,使用者裝的 Mod 不能改託管 hooks 的輸入和決定、系統提示詞、託管的 CLAUDE.md 和指令、託管 MCP server 的工具,也不能批準被 deny 規則拒絕的呼叫。
除此之外它不加其他限制,使用者的 Mod 依然能以使用者權限讀寫檔案、跑處理程序、聯網、改寫 prompt 和工具呼叫。管理員想更嚴,可以開 allowManagedModsOnly,只讓組織自己的 Mod 載入:
團隊也可以用 Mod 做自己的管控和功能,官方舉了三個例子:在對話旁邊放一個面板顯示 CI/CD 流水線狀態;任何命令碰到生產配置前都要求確認;寫一個最先載入的 Mod,記錄其他所有 Mod 的每一次呼叫,當作審計日誌。
10. 和 hooks、skills、MCP 怎麼選
原來的 hooks 也沒有被廢棄,settings 裡和外掛 hooks/hooks.json 裡的 hooks 都照常運行,和 Mod 並存。
11. 從一個 issue 開始
Mods 的設計,最早是 9 月 3 日在 GitHub 上公開徵求意見的,issue 標題叫「Mods - make Claude 10x more extensible」。
提案作者把它描述成 Express / Koa 那樣的函數式 hook,按註冊順序用 next 串起來,副作用都走一個參數化的 $ 對象。他還專門留了一句:
$ 這個符號沒得商量,我信奉的是一位更古老的神。後面連結的,正是 jQuery 官網……
這個帖子下面有兩百多條討論。
9 月 9 日官方宣佈幾周內上線,正式改名叫 Claude Mods,function hook 則保留為底層的技術名詞,想嘗鮮的可以用 CLAUDE_CODE_ENABLE_FUNCTION_HOOKS=1 claude 提前開啟(2.1.287 起這個變數已被忽略)。
到 10 月 1 日,它就上線了。
Thariq 表示:
所有軟體都在變得可塑,所以把它作為 Claude Code 的一等公民來支援很重要,我希望越來越多的軟體能像這樣可擴展!
他還提到,Mod 可以分叉出子 Agent 去做額外的活,比如自己做一套記憶系統:每輪跑一個自訂分類器,命中了就寫入記憶。他自己正在把 plan mode 也改成一個 Mod。
TestingCatalog 則認為,這其實意味著大部分客戶端軟體,只要花點功夫和 token 都能被「mod」,算是邁向個性化 UI 的第一步。
入門指南的結尾,官方也給了一些可以動手的點子:用 $.session.usage() 做一個花費或限額的狀態列,用 prompt.submit 給每條 prompt 自動加上團隊規範,做一個面板列出這次會話 Claude 讀過的所有檔案,長任務結束時用 $.ui.toast 彈個提醒,或者針對自己的技術堆疊加一道 tool.call 守衛,比如生產環境的 kubectl 和 terraform apply。
建議先從 Token Weather 那段 prompt 開始,改改「一行裡要顯示」下面那幾條,就是你自己的 Mod 了。
◇ ◆ ◇
官方部落格:https://claude.com/blog/claude-code-mods (AGI Hunt)
