懶人包
- prototype 是 Emil Kowalski 收在
emilkowalski/skills(MIT)裡的 Claude Code skill:把你描述的一個 UI 元件做成幾個方向真的不同的版本,放進一個固定規格的切換器(PICKER.md),讓你一個一個切換比較,挑中再整合。- 它設了
disable-model-invocation: true,只有你打/prototype才會跑。我用同一句需求不點名跑一次,Claude 完全沒讀它,直接改了 3 支正式程式檔。- 點名那次(Sonnet、175 秒)做出 4 個卡片 hover 版本,全放在獨立的
prototype.html與src/prototypes/,正式程式一行沒動;切換器的數字鍵、方向鍵與?v=網址參數我用 Playwright 驗過都正常。- 坑:4 個版本裡有 1 個打開就是壞的,三張卡片的內文區整片黑底、字看不見。Claude 自己回報「沒有在瀏覽器裡實際看過」,skill 要求的逐一檢查被跳過了,切換器開起來要自己逐版看過。
- repo 在 2026-10-21 是 48,160 stars、2,785 forks,這是 15 支 skill 共用的數字。安裝指令
npx skills@latest add emilkowalski/skills --skill prototype我實際跑過,會裝進SKILL.md與PICKER.md兩個檔。
- prototype skill 是什麼?
- 它的流程怎麼走?
- PICKER.md 是什麼?
- 為什麼一定要打 /prototype?
- 怎麼安裝到 Claude Code?
- 實測:替部落格文章卡片做 hover 原型
- 不點名會怎樣?
- 適合誰、不適合誰?
- 限制與坑
- 延伸資源
🧪 prototype skill 是什麼?
prototype 是一份給 AI coding agent 讀的 SKILL.md,98 行,另外附一份 197 行的 PICKER.md。它在 2026-07-27 以 commit「Add /prototype skill」加進 emilkowalski/skills,2026-09-15 又小改過一次。
它自稱是一支「divergence skill」,只做一件事:你描述一塊 UI(例如「一個 toast」「價格卡片」「長按刪除的按鈕」),它做出幾個方向真的不同的版本,放到一個切換器後面,讓你在瀏覽器裡一個一個切換,選出要留下的那一個。
它刻意不做的事也寫得很清楚:審查既有 UI 是 review-animations 的工作,規劃修正是 improve-animations,挑選依賴套件是 pick-ui-library。prototype 只負責「發散」。
skill 對「發散」的要求很硬:三個只是換了顏色的同一個想法,等於浪費切換器,因為你來回切也學不到東西。每個版本都得是「單獨拿出來也能出貨」的方向,同時還要守住 Emil Kowalski 的工藝標準:進場用 ease-out、UI 動畫低於 300ms、只動 transform/opacity、處理 reduced-motion。
repo 本身在 2026-10-21 查是 48,160 stars、2,785 forks、MIT 授權。GitHub 只能對整個 repo 加星,所以這是 15 支 skill 共用的數字,不是 prototype 一支的熱度。作者背景與整個 repo 的來龍去脈,我在 apple-design skill 實測 那篇寫過,這裡不重複。
🔁 它的流程怎麼走?
skill 把一次執行拆成 6 個階段,每個階段都有完成條件:
| 階段 | 做什麼 | 關鍵規則 |
|---|---|---|
| 1 Scope | 把需求縮成一個元件,用一句話重述 | 一次只做一個;需求太大(「整個 dashboard」)就挑最有影響的那塊,其餘列為後續 |
| 2 Recon | 盤點技術棧、design token、產品個性、元件會出現的位置 | 每個版本都要用專案自己的 token,看起來明天就能上線 |
| 3 Choose directions | 先列出每個版本的名字與「軸」 | 預設 3 個,使用者要求或設計空間很寬時最多 5 個;名字要描述方向,不准叫 Option A/B/C |
| 4 Build harness | 蓋切換器與各版本 | 有 dev server 就開獨立路由(如 /prototypes/<slug>),一個版本一個檔;沒有專案就產單一自足 HTML |
| 5 Verify | 跑起來,逐版切過,console 要乾淨 | 有瀏覽器工具就逐版截圖;交出一張「版本/軸/何時選它/代價」的表,然後停下來等你選 |
| 6 Promote | 你選定後整合進正式程式 | 照專案慣例整合,接著刪掉原型區 |
選完之後的指令也有固定說法:
| 指令 | 效果 |
|---|---|
/prototype <描述> | 完整流程,預設 3 個版本 |
/prototype <描述> x5 | 指定版本數,上限 5 |
riff <版本名> | 保留切換器,以某個版本為中心再發散一輪 |
keep <版本名> | 把該版本整合進正式程式並刪掉原型區 |
keep <版本名>, leave the picker | 整合,但保留原型區 |
/prototype 不帶需求,skill 規定 Claude 只回一句準備好了的開場白,其他什麼都不說,等你開口。
🎛️ PICKER.md 是什麼?
PICKER.md 是切換器的完整規格,連 HTML 結構、CSS 與鍵盤行為都寫死,skill 要求「逐字照抄」。它不是把多個方案並排成縮圖比較,剛好相反:一次只顯示一個版本,全尺寸,放在真實的周邊情境裡。skill 的理由是縮圖會扭曲間距與比例,UI 不該在郵票大小下評判。
切換器長這樣:畫面底部正中央一顆深色半透明膠囊(rgba(10,10,10,0.82) 加 12px 模糊),裡面是各版本名稱,目前選中的那顆底下有一塊高亮會滑過去(250ms、cubic-bezier(0.23, 1, 0.32, 1))。下面那張實測截圖底部就是它。
規格裡幾個值得知道的設計:
- 它是外框,不是參賽者。外觀不跟專案主題走,不做亮暗模式,
z-index直接設2147483647。唯一允許的修改是版本本身佔用底部中央時,改成data-position="top"移到上方。 - 鍵盤:數字鍵
1–N直接跳版本,←/→循環切換,R重播動畫;焦點在輸入框或按著修飾鍵時不攔截。 - 網址記得狀態:目前版本寫進
?v=2這樣的參數,重新整理不會跑掉,也能直接把網址傳給別人。 - 切換是瞬間的:切換版本本身不做動畫,因為一次探索可能切上百次。每次切換會重新掛載該版本,讓進場動畫重新播放。
- 重播鈕只在需要時出現:版本有動畫才放「Replay」,純 hover 的元件不放。
🔒 為什麼一定要打 /prototype?
prototype 的 frontmatter 有一行 disable-model-invocation: true,description 也直說「Only runs when explicitly invoked; it does not trigger on its own」。
Claude Code 官方 skills 文件 對這個欄位的說明是:設了之後,你可以用 / 叫它,但 Claude 不會自己決定去用;它的 description 不會放進 Claude 的 context,只有你叫用時才載入完整內容。文件還提到它同時會阻止 skill 被預載到 subagent。
我在同一個 repo 裡數了一下,15 支 skill 中設了這個欄位的有 3 支:prototype、pick-ui-library、review-animations。這三支有個共同點,都是「一跑就會產出一大包東西或改變專案狀態」的流程型 skill,讓使用者自己決定何時開跑很合理。
實際影響是:你不打 /prototype,它就不存在。下面的對照實驗會看到,同一句需求不點名時,Claude 連這份 skill 都沒讀,走的是完全不同的做法。
⚙️ 怎麼安裝到 Claude Code?
在專案根目錄跑:
npx skills@latest add emilkowalski/skills --skill prototype
我在 2026-10-21 確認 skills CLI 的 latest 是 1.7.4,--skill 參數存在。想要非互動、直接複製檔案(不建 symlink)到 Claude Code,可以帶完整參數:
npx -y skills@1.7.4 add emilkowalski/skills --skill prototype --agent claude-code --copy -y
驗證安裝:
find .claude/skills/prototype -type f
.claude/skills/prototype/PICKER.md
.claude/skills/prototype/SKILL.md
兩個檔都要在。SKILL.md 在第 4 階段會叫 Claude 去讀 PICKER.md,少了它切換器就沒有規格可照抄。裝好後在 Claude Code 裡打 /prototype 加上你的需求就會開始。
🧪 實測:替部落格文章卡片做 hover 原型
我想知道兩件事:點名時它真的會照 6 個階段走、把正式程式擋在外面嗎?做出來的版本能不能直接拿來挑?
環境:Vite 8.3 + React 19.3 + TypeScript 的小專案,畫面是三張仿我部落格風格的文章卡片(粗黑框、黃色分類標籤)。Claude Code 2.1.306,模型 Sonnet,claude -p 非互動模式,沒有接任何 MCP,所以這次 Claude 手上沒有瀏覽器工具。
需求我寫得像真的在問:
/prototype 這是我部落格的文章列表(src/App.tsx、src/ArticleCard.tsx)。我想替文章卡片做滑鼠 hover 效果,但還沒決定風格,想先看幾種真的不一樣的做法、在瀏覽器裡切換比較再決定。不要裝新套件、不要用 CDN。做完就結束,最後告訴我在哪個網址看、怎麼切換。
結果:175 秒、18 輪、花費 0.35 美元。
| 項目 | 觀察 |
|---|---|
| 版本數 | 4 個。我沒要求數量,skill 預設是 3 個 |
| 正式程式 | App.tsx、ArticleCard.tsx 完全沒動,git status 只多出 prototype.html 與 src/prototypes/(共 367 行) |
| 切換器 | 照 PICKER.md 實作,只省略了用不到的分隔線、重播鈕與 data-position="top" 規則;hover 不需要重播,所以沒放 Replay 是對的 |
| 自我檢查 | 跑了 tsc、oxlint、curl 確認頁面回 200;沒有在瀏覽器裡看過任何一個版本 |
| 交付 | 一張「版本/做法/適合情況/代價」表,最後提示可以回 keep 2 或 riff 3,然後停下 |
| # | 版本 | 做法 | 它自己寫的代價 |
|---|---|---|---|
| 1 | Hard Shift | 卡片往左上浮起,黑色硬陰影變大,按下去沉回 | 陰影往右下延伸,24px 間距會擠 |
| 2 | In-place | 卡片不動,封面浮出斜線紋,「閱讀文章」被黃色條掃過 | 反應集中在下半部,整體較小 |
| 3 | Ink Fill | 整張卡片從底部填黑,文字反白,連結變黃 | 長列表一路掃過去會一直閃 |
| 4 | Pointer Tilt | 卡片跟著滑鼠做 3D 傾斜,黃色光暈跟著游標 | 和扁平粗框風格最不搭,只有滑鼠有效 |
3 跳到 Ink Fill、按 → 跳到 Pointer Tilt、重新整理後網址的 ?v=4 讓它停在原處。切換器本身的行為全部符合規格。
問題出在第 1 版。Hard Shift 一打開,三張卡片的內文區整片是黑的,標題和摘要都看不見,跟有沒有 hover 無關:
原因在 CSS:它用一個 ::before 黑色底層當硬陰影,同時在卡片上設了 isolation: isolate。
.p-shift .card { position: relative; isolation: isolate; height: 100%; }
.p-shift .card::before {
content: '';
position: absolute;
inset: -2px;
background: var(--color-ink);
z-index: -1;
}
卡片自己成了堆疊環境,z-index: -1 的子層就只會畫在卡片背景之上、內容之下,於是整片蓋住米白底。內文的字也是同一個墨黑色,黑底黑字就消失了。封面有自己的底色,所以只有封面看得到。
這種錯誤 tsc 和 lint 都抓不到,打開頁面看一眼就會發現。skill 第 5 階段寫的是「flip through all of them yourself before showing the user」,Claude 的回報也很誠實:「我沒有在瀏覽器裡實際看過各個版本,也沒看 console」。這次我沒給它瀏覽器工具,它沒辦法照做,這部分是我的實驗設定造成的;但結論對實際使用一樣成立:沒有瀏覽器工具的環境下,第 5 階段等於交給你做。
🆚 不點名會怎樣?
同一個專案、同一句需求,只拿掉開頭的 /prototype,其餘設定相同。
| 比較 | 點名 /prototype | 不點名 |
|---|---|---|
| 有沒有讀 skill | 有,並自己去讀了 PICKER.md | 沒有,完全沒碰 .claude/skills/prototype |
| 正式程式 | 一行沒動 | 改了 App.tsx、ArticleCard.css、ArticleCard.tsx,+104/-5 行 |
| 版本數 | 4 個 | 5 個加一個「無」對照組 |
| 切換方式 | 底部膠囊、數字鍵、?v= | 頁面上方一排按鈕、?hover=flood 參數 |
| 收尾 | 等你說 keep,再由它整合並刪原型區 | 叫你自己把不要的變體和按鈕刪掉 |
| 耗時與花費 | 175 秒、0.35 美元 | 115 秒、0.15 美元 |
有意思的是,不點名那次的「硬陰影浮起」反而畫對了。兩邊各只跑一次,這不代表哪一邊的視覺品質比較好。差別在流程:不點名的版本把切換按鈕直接寫進文章列表、把五種 hover 樣式塞進正式的 ArticleCard.css,選完之後要自己清;點名的版本整包隔離,選完一句 keep 就收乾淨。
👥 適合誰、不適合誰?
適合:
- 一個元件還沒定方向,想同時看到幾種完全不同解法的人。尤其是 hover、toast、卡片、按鈕這種「看了才知道」的東西。
- 專案已經有 design token 和 dev server,想讓 AI 的探索不汙染正式程式的人。
- 要拿原型去跟別人討論的人。
?v=網址可以直接傳給同事,對方打開就停在同一個版本。
- 已經知道要什麼樣子。這時直接請 Claude 實作就好,跑發散流程是浪費時間和 token。
- 要一次重做整頁或整個流程。skill 規定一次只做一個元件,需求太大它會先幫你縮。
- 要審查或修正既有動畫。那是同 repo 的 review-animations 與 improve-animations 的工作;要挑動畫或元件函式庫,看 pick-ui-library。
🚧 限制與坑
- 不打
/prototype就不會跑。這是設計,不是 bug。要用就點名,Claude 不會在你描述「想看幾種做法」時自己想起它。 - 版本數不一定照預設。我沒指定數量,它做了 4 個。想固定數量就在需求後面加
x3。 - 第 5 階段需要瀏覽器工具。skill 要求 Claude 自己逐版切過、console 乾淨才交付;沒有瀏覽器工具時,它只能做到型別檢查和 lint,畫面是不是壞的要你自己看。我這次 4 版壞 1 版,就是在這一步漏掉的。
- 它會自己開 dev server。這次 Claude 把 Vite 開在背景,任務結束後 process 還在跑,佔著 5173 埠。用完記得關。
- 切換器不跟主題走。深色膠囊在任何背景下都長一樣,這是規格刻意的;元件本身固定在底部中央時(例如 bottom sheet、toast),要確認它有改用
data-position="top",不然會互相擋住。 - 比直接做慢、貴一些。我這兩次是 175 秒對 115 秒、0.35 美元對 0.15 美元。多出來的成本換到的是隔離的原型區和有紀律的收尾。
🔗 延伸資源
- GitHub repo:emilkowalski/skills
- skill 原文:skills/prototype/SKILL.md、PICKER.md
- Claude Code 官方文件:Extend Claude with skills(
disable-model-invocation的行為說明) - 同作者的動效規範 skill:apple-design skill 實測
/prototype <它的描述> x3。切換器開起來後,先把每一版都切一遍、開著 DevTools console 看一輪,確認沒有壞掉的版本,再開始比較哪個方向對。