決定你能裝幾個擴充的,是啟動那一秒讀進去多少東西。

裝一個 extension、裝一個 skill,直覺上就是把檔案丟進某個資料夾,之後多一個能力。硬碟這麼便宜,裝一百個也沒差。這個直覺對了一半:檔案確實沒差,幾百 KB 而已。有差的是它什麼時候被讀進模型的 context,因為那才是會用完的東西。

Gemini CLI 和 Claude Code 在這一題上給了相反的答案。有趣的地方在於,它們的擴充在「裝了什麼」上面幾乎長一樣。

兩邊裝的東西,清單重疊得驚人

Gemini CLI 的 extension 由一份 gemini-extension.json 定義。官方 reference 列出的欄位有 nameversiondescriptionmcpServerscontextFileNameexcludeToolsmigratedToplan。文件對它的定位寫得很直白:

package prompts, MCP servers, custom commands, themes, hooks, sub-agents, and agent skills into a familiar and user-friendly format.

Claude Code 這邊,一個 skill 是一個目錄加一份 SKILL.md,frontmatter 放 name 跟 description,正文放做法,旁邊可以帶腳本跟參考檔。官方文件另外註明,過去 .claude/commands/ 的自訂指令已經併進 skill,兩種寫法都會產生同一個斜線指令。

MCP server、自訂指令、給模型看的說明文字。這三樣兩邊都有。光看功能清單,你很難講出它們哪裡不同。

差別在動詞

Gemini CLI 的 reference 在「Extension format」那節收尾,寫了這麼一句:

When Gemini CLI starts, it loads all the extensions and merges their configurations.

啟動、全部、合併。這三個詞把後面的事都決定了。extension 目錄裡的 GEMINI.md(或 contextFileName 指定的那份檔)會被讀進來當 context,mcpServers 裡定義的服務會在啟動時跟著起來,跟寫在 settings.json 的 MCP server 是同一個層級。

Claude Code 的文件則是這樣講的:

Unlike CLAUDE.md content, a skill’s body loads only when it’s used, so long reference material costs almost nothing until you need it.

同一件事,兩個動詞。一個開機時全部攤開,一個等你用到才翻。

這個差別在我機器上是多大

我的 ~/.claude/skills/ 底下有 100 個目錄,其中 82 個帶 SKILL.md。把這 82 份全文串起來丟給 wc -c,數字是 3,105,318 個字元。

中英混排大概三個字元換一個 token,那就是一百萬 token 上下的量級。這只是 skill 正文,還沒算旁邊那堆 reference 檔跟腳本。

換句話說,如果這 310 萬字元在開機時全部進 context,session 還沒開始就已經結束了。實際上不會,因為正文是用到才讀,開場真正付的錢是每個 skill 的 name 跟 description,一份幾十個字。

這個算式是粗估,字元換 token 的比例會因語言而異,我沒有逐份實測。但量級的結論不會因為誤差而翻盤:正文全載跟只載描述,中間差了兩個數量級。

反過來說,全載入買到的是確定性

按需載入不是免費的午餐。它把「這份說明現在該不該進來」這個判斷交給了模型,而判斷會失手。

我自己的全域規則檔裡就有一條寫著:使用者明確打了 /名字 就一定要執行,其餘情況只在描述明確涵蓋當前任務型態時才用。這條規則會存在,正是因為自動觸發不夠穩。描述寫得太像,模型會在不該用的時候把它拉進來;描述寫得含蓄,該用的時候它視而不見。

extension 全載入沒有這個煩惱。裝了就是在,不用祈禱模型今天判斷得準。代價是你得自己管好裝了幾個,而 Gemini CLI 給了對應的閥門:gemini extensions disable <name> --scope user|workspace,可以整包關掉,也可以只在某個工作區關掉。

還有一件事順著這個設計長出來。extension 的 manifest 可以寫 excludeTools,把工具從模型手上拿走,官方的例子甚至細到單一指令:

"excludeTools": ["run_shell_command(rm -rf)"]

擴充自己聲明「我在的時候,這串指令不准跑」。權限收斂被放進了擴充包本身。Claude Code 這邊限制工具的閘門在 settings 的 permissions,是使用者那一端的事。同樣是說不,兩邊對「誰有資格說」的答案不一樣。

誠實邊界,以及一個現場抓到的錯誤

Gemini CLI 我沒有實際跑過。上面每一句關於它的描述都來自官方 repo 的 docs/extensions/reference.md,不是使用經驗。

還有一段插曲值得寫下來。動筆前我用搜尋引擎查 Gemini CLI 的現況,摘要非常肯定地告訴我:它已經在 2026 年 5 月退役、被另一個產品接手、而且從 Apache 2.0 轉成閉源專有。三件事都很具體,讀起來完全不像編的。

我去打了一次 GitHub API:

1
2
3
gh api repos/google-gemini/gemini-cli \
--jq '[.full_name,(.stargazers_count|tostring),.license.spdx_id,(.archived|tostring),.pushed_at]|join(" | ")'
# google-gemini/gemini-cli | 106430 | Apache-2.0 | false | 2026-08-09T01:15:28Z

沒有封存,授權還是 Apache-2.0,最後一次 push 就在今天凌晨。最新 release 是 v0.54.4,8 月 7 日發的。那三件事,一件都對不上。

這一段跟本文主題其實是同一件事的兩面。摘要幫你把文件讀完了,代價是你不知道它讀的時候漏掉什麼、腦補了什麼。省下來的那幾分鐘,會在你把它寫進文章、寫進設定檔、寫進給同事的建議之後,用另一種形式跟你收費。

所以該怎麼想這件事

把兩邊擺在一起,真正在較勁的不是功能清單,是同一個提問:這段文字什麼時候該進 context。

開機就進,你買到確定性,付的是每個 session 的固定成本,而且這個成本隨你裝的數量往上疊。用到才進,你買到幾乎沒有上限的擴充空間,付的是一次判斷,而判斷有機率出錯。

下次猶豫要不要再裝一個的時候,先問的不該是「這個有沒有用」。該問的是「它什麼時候會被讀」。同樣有用,一個每次開機都要付錢,一個只在你需要時才付錢,這是兩種完全不同的資產。


參考來源