懶人包
- pick-ui-library 是 Emil Kowalski 收在
emilkowalski/skills(MIT)裡的一支 Claude Code skill,85 行,內容是一份 19 種前端任務對應 20 個函式庫的選型清單,2026-07-21 加入 repo。- 它設了
disable-model-invocation: true,要自己打/pick-ui-library才會載入。repo 在 2026-10-21 是 48.1k stars,這是 15 支 skill 共用的數字。- 我在 React 19 專案跑了 6 個情境:已裝 react-hot-toast 時,它照規則沿用、不硬換 Sonner;只打指令不帶問題時,只回一句固定開場白。
- 實測抓到 2 個坑:清單只放連結、沒寫 npm 套件名,模型一次給了已棄用的
@base-ui-components/react;沒點名時模型沒載入 skill,卻用 Bash 掃.claude/讀到清單照樣推薦。- 清單本身的時效還行:20 個套件裡多數最近半年內有發版,但
cva這個 npm 名稱是佔位套件,Liveline 還在 0.0.x,drawer 這類需求清單沒有列。
- pick-ui-library 是什麼、解決什麼問題?
- 清單推薦哪些函式庫?
- 清單過時了嗎?對照 npm 現況
- disable-model-invocation 是什麼意思?
- 怎麼安裝到 Claude Code?
- 實測:6 個情境的結果
- 實測抓到的 2 個坑
- 其他限制
- 適合誰、不適合誰
- 延伸資源
🧭 pick-ui-library 是什麼、解決什麼問題?
pick-ui-library 是一份給 AI coding agent 讀的 SKILL.md,全文 85 行,作者是 Emil Kowalski(toast 元件 Sonner 和 drawer 元件 vaul 的作者)。它的工作很單純:你說要做什麼,它從作者挑好的清單裡回你一個函式庫。
repo README 對它的描述是讓 agent 挑對函式庫,「instead of letting AI hand-roll a toast component or install an abandoned package」——不要讓 AI 手刻 toast,也不要裝一個沒人維護的套件。
它規定的流程有四步,原文在 How to use this 那一節:
- 辨識任務,不是辨識使用者講的函式庫名。「我要一個下拉選單」是 UI primitives 任務,答案是 base-ui。
- 先看
package.json。已經裝了清單裡的函式庫就用它;裝的是競品(例如用 react-window 而不是 Virtuoso),可以提出建議,但沒被要求就不要換依賴。 - 只推一個,用一句話說它是做什麼的。清單有明確答案時不要列選單。
- 任務不在清單內要明講,再用模型自己的知識推薦,並說清楚已經離開清單。
/pick-ui-library、沒帶問題時,只能回「I'm ready to pick the right library for your task, my picks come from Emil Kowalski's curated list.」,其他什麼都不說。
repo 歷史裡,這支 skill 在 2026-07-21 以 commit 049c92e 加入,同一天另一個 commit 修正了 dialkit、torph、Liveline 三條連結,之後只有全 repo 共用的修改。
📋 清單推薦哪些函式庫?
清單分五組,共 19 種任務、20 個函式庫(Leva 那列附了一個替代品 dialkit)。我把它整理成「遇到什麼需求 → 用什麼」:
| 分組 | 需求 | 推薦 |
|---|---|---|
| UI 元件 | 無樣式、可及性完整的 dialog、popover、menu、select | base-ui |
| UI 元件 | ⌘K 指令面板 | cmdk |
| UI 元件 | toast 通知 | Sonner |
| UI 元件 | 一次性密碼/驗證碼輸入框 | input-otp |
| UI 元件 | 可調參數的控制面板 | Leva(替代:dialkit) |
| 動態與視覺 | 通用動畫:spring、layout、進出場 | motion(Framer Motion) |
| 動態與視覺 | 數字動畫:計數器、價格 | NumberFlow |
| 動態與視覺 | 文字動畫元件 | torph |
| 動態與視覺 | 3D 地球 | Cobe |
| 動態與視覺 | 動態 OG 圖(HTML/CSS 轉 SVG/PNG) | Satori |
| 動態與視覺 | 語法高亮 | shiki |
| 圖表 | 即時串流圖表 | Liveline |
| 圖表 | 一般圖表與儀表板 | recharts |
| 互動與效能 | 拖放 | dnd kit |
| 互動與效能 | 長列表、大表格虛擬化 | Virtuoso |
| 狀態與樣式 | 狀態管理 | zustand |
| 狀態與樣式 | 條件組 className | clsx |
| 狀態與樣式 | Tailwind 的型別安全變體樣式 | cva |
| 狀態與樣式 | 主題切換、暗色模式(載入不閃) | next-themes |
- motion 什麼時候才用:要 spring、layout 動畫、退場動畫或手勢驅動的值才用。單純 hover 或淡入淡出,原文說 CSS transition 就是對的工具。
- Liveline 和 recharts 怎麼分:資料是即時進來、圖會隨時間捲動的用 Liveline,其他全部 recharts。
- clsx 和 cva 怎麼分:臨時的條件 class 用 clsx;元件有真正的變體(尺寸、意圖、狀態)值得一個有型別的 API 時用 cva。
<div> 自己做下拉選單和焦點管理、靠重新 render 文字做數字動畫、直接 render 上千列、用一堆 useState 層層傳 props 共享狀態、三層深的 className 三元運算式。
📅 清單過時了嗎?對照 npm 現況
清單只放了官網連結,沒寫版本。我在 2026-10-21 用 npm registry API 抓了每個套件的最新版與 2026-10-12~10-18 這一週的下載量:
| 套件(npm 名稱) | 最新版 | 發布日 | 週下載量 |
|---|---|---|---|
@base-ui/react | 1.9.0 | 2026-10-09 | 10,846,815 |
cmdk | 1.1.1 | 2025-03-14 | 25,375,948 |
sonner | 2.0.8 | 2026-08-09 | 30,030,645 |
input-otp | 1.5.0 | 2026-08-18 | 17,414,835 |
leva | 0.10.1 | 2025-10-31 | 841,639 |
dialkit | 2.0.2 | 2026-09-09 | 117,652 |
motion | 14.5.0 | 2026-10-21 | 15,750,774 |
@number-flow/react | 0.6.2 | 2026-07-18 | 1,211,474 |
torph | 0.1.3 | 2026-09-07 | 105,811 |
cobe | 2.0.1 | 2026-03-19 | 344,071 |
satori | 0.63.2 | 2026-10-20 | 2,842,555 |
shiki | 4.5.0 | 2026-10-01 | 16,095,079 |
liveline | 0.0.7 | 2026-03-12 | 179,434 |
recharts | 3.10.1 | 2026-07-25 | 33,269,434 |
@dnd-kit/core | 6.3.1 | 2024-12-05 | 17,050,828 |
@dnd-kit/react | 0.5.1 | 2026-10-15 | 1,053,647 |
react-virtuoso | 4.18.19 | 2026-10-13 | 1,828,413 |
zustand | 5.0.15 | 2026-08-13 | 37,735,389 |
clsx | 2.1.1 | 2024-04-23 | 75,784,845 |
class-variance-authority | 0.7.1 | 2024-11-26 | 40,481,384 |
next-themes | 0.4.6 | 2025-03-11 | 16,568,729 |
- 沒有一個是棄坑的套件。20 個裡多數在最近半年內有發版,clsx、
class-variance-authority、@dnd-kit/core很久沒發版,但週下載量都在千萬級,屬於功能定型。 - 成熟度落差很大。Liveline 是 0.0.7、torph 是 0.1.3、dialkit 週下載量 11.7 萬,跟 recharts 的 3,300 萬不是同一個量級。清單是作者的品味選擇,不是市佔排行,用在正式專案前要自己評估。
- dnd kit 有兩條線。官網 dndkit.com 對應的套件有舊的
@dnd-kit/core(6.3.1)和新的@dnd-kit/react(0.5.1,上週剛發版),清單沒說要用哪一個。 - base-ui 已經涵蓋了清單其他列的需求。我查了
@base-ui/react的版本紀錄:toast 和 combobox 在 1.0.0-rc.1(2025-12-11)出現,drawer 在 1.2.0(2026-02-12),OTP 欄位在 1.4.0(2026-04-13)。也就是 skill 加入時,base-ui 本身已經有 toast 和 OTP,清單仍把這兩項分給 Sonner 和 input-otp。照清單選不會錯,只是同一個專案可能同時裝兩套做同一件事。
🔒 disable-model-invocation 是什麼意思?
pick-ui-library 的 frontmatter 有一行 disable-model-invocation: true,description 最後也寫明「Only runs when explicitly invoked; it does not trigger on its own.」
Claude Code 官方文件(code.claude.com/docs/en/skills)對這個欄位的說明是:設成 true 之後,Claude 不能自己載入這支 skill,它的 description 不會放進 context,只有使用者打 /名稱 時才會把全文載入;它也不會被預先載入到 subagent。跟它相反的是 user-invocable: false,那是只讓 Claude 呼叫、使用者不能用 / 叫用。
所以這支 skill 的用法是:要它出手,就在需求前面打 /pick-ui-library。同 repo 另外兩支 prototype 和 review-animations 也是同樣設定。
⚙️ 怎麼安裝到 Claude Code?
repo README 給的是整包安裝。只要這一支,加上 --skill:
npx skills@latest add emilkowalski/skills --skill pick-ui-library
我在 2026-10-21 用 skills CLI 1.7.4 實際裝過一次,用的是非互動參數:
npx -y skills@1.7.4 add emilkowalski/skills --skill pick-ui-library --agent claude-code --copy -y
結果:
- 在專案下產生
.claude/skills/pick-ui-library/SKILL.md,內容和 repo commit2d22863的版本逐字相同。 - 另外產生一個
skills-lock.json,記錄來源和雜湊值。 - 安裝畫面附了三家的安全評估:Gen 標 Safe、Socket 0 alerts、Snyk 標 Low Risk。
/pick-ui-library 加上你的需求就能用。
🧪 實測:6 個情境的結果
測試環境:
- Claude Code 2.1.306,用
claude -p非互動模式跑,模型是 claude-fable-5-1。 - 專案是一份最小的
package.json:React 19.2、Tailwind 3.4、Vite 7、TypeScript 5.9,src/是空的。s3、s4 另外加了react-hot-toast。 - skill 放在專案的
.claude/skills/pick-ui-library/。 - 我用
--setting-sources project,local排除自己裝的使用者層級 skill,但我的使用者層級CLAUDE.md仍會載入,所以有兩個回覆提到我個人規則裡的東西,跟 skill 無關。 - 每個 prompt 都附上「先給建議就好,不要安裝或改檔案」。
逐項看:
| 情境 | 輸入 | 結果 |
|---|---|---|
| s1 | /pick-ui-library + 可搜尋、可鍵盤操作的下拉選單 | 推薦 base-ui 的 Combobox,順便排除 cmdk(那是 ⌘K 面板,語意不對)和手刻。安裝指令寫成 npm install @base-ui-components/react |
| s2 | /pick-ui-library + 手機底部滑出、可往下拖關閉的 drawer | 先上網查官方文件,推薦 Base UI 的 Drawer(@base-ui/react 1.9.0),理由是清單外的 vaul 最新版停在 2024 年的 1.1.2 |
| s3 | /pick-ui-library + toast,專案已裝 react-hot-toast | 建議沿用 react-hot-toast,說明清單首選是 Sonner,但規則是已有同類套件就不換;最後補一段「什麼時候才值得換 Sonner」 |
| s4 | 同 s3 的需求,不打指令 | 同樣建議沿用 react-hot-toast,沒呼叫 Skill 工具 |
| s5 | 只打 /pick-ui-library | 2.4 秒、1 個 turn,只回那句固定開場白,一個字都沒多 |
| s6 | 同 s1 的需求,不打指令 | 沒呼叫 Skill 工具,但推薦一樣是 Base UI Combobox,套件名給的是正確的 @base-ui/react |
package.json、已有競品就不動」這條規則被照做了,而且它把換套件的條件講清楚,沒有為了推自己清單上的 Sonner 而叫我改依賴。
s5 證明 slash command 有正確展開:如果 skill 沒被載入,模型不會知道那句固定開場白。
🕳️ 實測抓到的 2 個坑
坑一:清單沒寫 npm 套件名,模型會憑記憶補
清單的寫法是「任務 → 函式庫名稱加官網連結」,沒有 npm 套件名。s1 的回覆因此用了模型記憶裡的舊名 @base-ui-components/react。我查 npm registry,這個名稱最新版停在 1.0.0-rc.0,標記為 deprecated,訊息是「Package was renamed to @base-ui/react」。
同樣的需求,s6 的模型有上 npm 查,就給出正確的 @base-ui/react,還提醒舊名已棄用。差別在模型有沒有自己去查,不在 skill。
清單裡會遇到同樣問題的還有 cva:連結是 cva.style,但實際要裝的套件是 class-variance-authority。直接打 npm install cva 裝到的是 latest 標籤指向的 0.0.0,套件描述是「Awesome node module」,同作者的 cva 1.0 目前還在 beta 標籤。
我的做法:用這支 skill 拿到推薦之後,安裝前看一眼 npm 上的套件名稱和最新版,或直接在需求裡加一句「給 npm 套件名並確認未棄用」。
坑二:沒點名不會載入 skill,但檔案還是讀得到
s4 和 s6 都沒打指令,模型也確實沒有透過 Skill 工具載入它。但兩次模型都用 Bash 列出專案檔案,順手把 .claude/skills/pick-ui-library/SKILL.md 的內容讀出來:
- s4 的回覆寫明「該 skill 設定為只在明確呼叫時才啟用,這次沒呼叫,所以我沒套用它」,然後引用 skill 的規則 2 支持「不換依賴」的結論。
- s6 則是直接說「專案自己的選庫清單指向它」,照清單推薦 base-ui。
disable-model-invocation 管的是「Claude 能不能透過 Skill 機制自己載入」,它不會把檔案藏起來。skill 放在專案目錄裡,模型探索專案時就可能讀到。如果你想讓這份清單只在點名時影響建議,可以考慮把 skill 裝在使用者層級(~/.claude/skills/),不放進專案的 .claude/,這個做法我沒有實測;反過來,如果你希望團隊不打指令也大致照這份清單走,放在專案裡的效果我只觀察到這兩次,不能當成穩定行為。
🚧 其他限制
- 清單沒涵蓋的需求,模型會往清單裡擠。drawer 不在 19 種任務裡,skill 的第 4 條規則要模型明講「已離開清單」。s2 的模型沒這樣說,而是把 Drawer 歸到 base-ui 那一列。結論本身合理(base-ui 確實有 Drawer),但讀的人會以為那是清單上的推薦。
- 清單以 React 生態為主。base-ui、Sonner、cmdk、input-otp、Virtuoso 都是 React 元件,Vue、Svelte 或原生 iOS 大多用不上(shiki、Satori、clsx 不綁框架);同 repo 寫原生的話可以看 write-swift 和 mobile-native。
- 它只負責選,不負責寫好。toast 選了 Sonner 之後,動畫、手勢、樣式寫得好不好是另一回事。同 repo 的 ask-sonner 是專門處理 Sonner 用法的 skill。
- Windows 的 Git Bash 用
claude -p跑會失效。我第一輪在 Git Bash 執行claude -p "/pick-ui-library ...",MSYS 把開頭的/pick-ui-library當成路徑,改寫成C:/Program Files/Git/pick-ui-library,指令完全沒展開。加上export MSYS_NO_PATHCONV=1之後才正常。在 Claude Code 互動畫面裡直接打指令不受影響。
👥 適合誰、不適合誰
適合:
- 用 React 寫前端、常讓 Claude Code 決定「這個功能要裝什麼套件」的人。打一次指令換來一個有理由的單一答案,比讓模型列三個選項省事。
- 想讓 AI 先看
package.json再推薦的人。s3 那種「已有就不換」的判斷,是這份 skill 明文寫下的規則。
- 需要多方比較的選型。skill 第 3 條規定只推一個,你要的是比較表,就直接問模型、不要點名它。
- 非 React 專案,或公司已經有自己的元件庫與套件白名單。這時候清單和你的規範會互相打架。
- 希望 AI 不打指令也自動照清單選的人。這支 skill 刻意關掉了自動觸發,想要那種行為要另外寫一支沒設
disable-model-invocation的 skill,或把清單放進專案的CLAUDE.md。
🔗 延伸資源
- skill 原文:skills/pick-ui-library/SKILL.md
- GitHub repo:emilkowalski/skills
disable-model-invocation官方說明:Claude Code skills 文件- 同 repo 的動效 skill:apple-design skill 實測:17 節 Apple 動效規範,點名最保險
- 選了 Sonner 之後:ask-sonner skill
/pick-ui-library,丟一個你最近剛好要做的需求(下拉選單、通知、長列表都行),看它有沒有先讀 package.json,再到 npm 上核對它給的套件名稱和最新版。