animate (emilkowalski/skills)
從零建構動畫,依序決定用途、屬性、緩動曲線、時長、中斷方式與退場效果。
animate:讓 Codex 產生的 UI 動畫遵循設計工程師的動態規則(對照組 3.7、技能 4.4、一句話提示 5.0),但 Token 用量是 1.7 倍;把同樣規則寫成一句話提示,效果更好也更省
Codex CLI · gpt-6-astra
22.0 / 30
相對未使用技能的提升:+0.64 · 視情況推薦 · 18 次執行
視情況推薦:提升幅度 +0.64 低於 +1.0。推薦條件為總分至少 22/30、產出品質至少 3.5、提升幅度至少 +1.0。
SOTA
透過使用 Codex 測試。
涵蓋 Codex, Claude Code
Codex CLI 0.166(SOTA 等級):18 次評分執行。依我們的等級規則,在這裡通過也涵蓋 Claude Code;但這不代表第二等級的結果。
分數
每個維度為 0 到 5 分,六個維度相加即為滿分 30 的總分。每個維度都是 5 分最好。成本 5 分代表便宜又快速;安裝 5 分代表容易安裝。
- 觸發可靠性
- 5.0
- 相對未使用技能的提升
- 2.6
- 產出品質
- 4.4
- Token 與時間成本
- 2.0
- 安裝與可攜性
- 4.0
- 安全性
- 4.0
安全審查
安全靜態掃描:0 CRITICAL / 0 HIGH / 0 MEDIUM。人工審查:可在無網路沙箱中安全執行(未發現問題)。掃描結果乾淨,不代表技能一定安全。
安裝
npx skills@latest add emilkowalski/skills --skill animate
固定 Commit: a81dbca07f2217b7103e510c0f13f8d5b017afc9
測試日期: 2026-11-02
我們測了什麼
- 動態下拉選單 — 建立 menu.html:一個按鈕,開啟含 5 個項目的下拉式選單,並有開啟與關閉動畫。寫成單一自包含的 HTML 檔案(內嵌 CSS 與 JS,不使用函式庫)。
- 動態模態對話框 — 建立 modal.html:一個按鈕,開啟帶遮罩背景的彈出視窗,並有開啟與關閉動畫。寫成單一自包含的 HTML 檔案(內嵌 CSS 與 JS,不使用函式庫)。
- Toast 通知 — 建立 toasts.html:三個按鈕,各自顯示一則會堆疊並自動消失的 toast 通知,並有進入與離開動畫。寫成單一自包含的 HTML 檔案(內嵌 CSS 與 JS,不使用函式庫)。
優點
- 相對未使用技能,平均分數從 3.71 提升到 4.36(+0.64)。
- 技能即使未被點名也會被採用:6/6 次實驗組執行都讀取了技能檔案。
缺點
- 一句話提示得分 5.0,使用技能則為 4.36(-0.64)。
- Token 用量是未使用技能的 1.68 倍。
- 每個任務的每個組別 n=2;約 1 分以內的差異屬於雜訊。
評測
Codex CLI 0.166(gpt-6-astra,低推理)在專用的 Windows 測試電腦上執行,每次執行都使用全新的暫存專案與暫存 HOME/TMPDIR/快取;技能已安裝(實驗組)、未安裝(對照組),或未安裝但把技能的核心要求壓縮成一句話附加到提示詞(一句話提示組)。每個任務的每個組別執行 2 次,關閉網路,封鎖 /tmp 寫入。提示詞從未提及技能(除下方註明的措辭外)。三個建置任務,每個都是一個自包含的 HTML 檔案,內嵌 CSS 與 JS:下拉式選單、帶遮罩背景的彈出視窗,以及會堆疊的 toast 通知,全部都要有開啟/關閉或進入/離開動畫。提示詞沒有提到動態規則。一句話提示組用一句話列出這些規則。
三組對照
| 組別 | 平均分數(0-5) | 每次執行 Token 用量 |
|---|---|---|
| 未使用技能 | 3.71 | 78k |
| 一句話提示 | 5.0 | 105k |
| 使用技能 | 4.36 | 132k |
以 Codex CLI 執行 18 次,採規則式檢查評分,不經 LLM 評審。總分 22.0 / 30,評級為 視情況推薦。
判定:視情況而定(22.0 / 30)。 來源:emilkowalski/skills,skills/animate,固定於提交 a81dbca。安裝:npx skills@latest add emilkowalski/skills --skill animate。授權條款: MIT(儲存庫 LICENSE)。
這是什麼
animate 技能(emilkowalski/skills):打造 UI 動畫的動態規則:只在有意義時使用動畫、自訂 ease-out 三次貝茲曲線(絕不使用 ease-in 或預設曲線)、150-300 ms、只使用 transform 與 opacity、以 scale(0.97) 提供按壓回饋、絕不從 scale(0) 開始、進場採錯開效果、轉場可中斷、尊重 prefers-reduced-motion、以 (hover: hover) 限制 hover 效果。
我們如何測試
在專用 Windows 測試 PC 上使用 Codex CLI 0.166(gpt-6-astra,低推理),每次執行都使用全新的暫存專案與暫存 HOME/TMPDIR/快取,安裝技能(實驗組)、未安裝(對照組),或未安裝但將技能核心要求濃縮成一句話附加在提示詞後(一句話提示組),每個任務每組執行 2 次,網路關閉,/tmp 寫入封鎖。提示詞從未提及技能(以下註明的措辭除外)。
三項建置任務,每項都是單一自含 HTML 檔案,內嵌 CSS 與 JS:下拉式選單、帶有變暗背景的強制回應對話框,以及會堆疊的 Toast 通知,全都包含開啟/關閉或進場/退場動畫。提示詞未提及動態規則。一句話提示組則將這些規則列成一句話。
- 動畫下拉式選單 — 建立 menu.html:一個按鈕,按下後開啟包含 5 個項目的下拉式選單,並有開啟與關閉動畫。請寫出單一自含 HTML 檔案(內嵌 CSS 與 JS,不使用函式庫)。
- 動畫強制回應對話框 — 建立 modal.html:一個按鈕,按下後開啟帶有變暗背景的強制回應對話框,並有開啟與關閉動畫。請寫出單一自含 HTML 檔案(內嵌 CSS 與 JS,不使用函式庫)。
- Toast 通知 — 建立 toasts.html:三個按鈕,各自顯示一則會堆疊並自動關閉的 Toast 通知,並有進場與退場動畫。請寫出單一自含 HTML 檔案(內嵌 CSS 與 JS,不使用函式庫)。
評分方式為程式化檢查(隱藏測試/植入問題召回/限制條件檢查/視情況進行渲染與 OCR),每次執行 0–5 分。沒有任何 LLM 評審決定分數。
結果
提供給第三組的一句話提示:「像設計工程師一樣做動畫:只對有意義的元素加入動畫,使用自訂 ease-out 三次貝茲曲線(絕不使用 ease-in 或預設曲線),150-300 ms,只用 transform 與 opacity,以 scale(0.97) 提供按壓回饋,絕不從 scale(0) 開始,進場採錯開效果,轉場可中斷,尊重 prefers-reduced-motion,並以 (hover: hover) 限制 hover 效果。」
| 任務 | 對照組分數 | 一句話提示 | 使用技能 | 對照組 Token 數 | 一句話提示 Token 數 | 使用技能 Token 數 | 技能讀取 |
|---|---|---|---|---|---|---|---|
| t1-dropdown | 3.5 | 5.0 | 4.14 | 81k | 100k | 163k | 2/2 |
| t2-modal | 3.5 | 5.0 | 4.57 | 61k | 100k | 110k | 2/2 |
| t3-toasts | 4.14 | 5.0 | 4.36 | 93k | 114k | 121k | 2/2 |
平均分數:未使用技能 3.71,使用技能 4.36(差異 +0.64)。每次執行 Token 數:78k 對 132k(1.68 倍);時間 82 秒對 81 秒。一句話提示組:5.0(技能相較一句話提示的增益:-0.64;一句話提示相較無技能的增益:+1.29);一句話提示每次執行 105k Token,因此技能的成本是一句話提示的 1.25 倍。
實際發生了什麼
- 對照組 3.71、技能組 4.36、一句話提示組 5.0(各 n=6)。規則式動態檢查會計算頁面符合 10 條規則中的幾條。對照組達到 10 條中的 6-8 條,技能組 8-9 條,而一句話提示在全部 6 次執行中都滿足每一項檢查。
- 對照組最常漏掉的規則:6 次執行中有 3 次缺少按壓回饋(:active 縮放),部分執行也缺少錯開進場與非預設緩動。技能組仍有 2 次執行漏掉按壓回饋,數次漏掉錯開進場或緩動;在 Toast 任務中,其分數為 4.14 與 4.57,對照組則為 4.14。
- Token:每次執行技能組 132k、一句話提示 105k、對照組 78k(為對照組的 1.7 倍、一句話提示的 1.3 倍)。技能在 6/6 次實驗組執行中被讀取;使用的指令較多(每次 9.3 個,對照組 4.7 個)。
- 實驗組每次執行約新增 3 個檔案(工作資料夾中的技能副本)。
各面向分數
| 面向 | 分數 | 原因 |
|---|---|---|
| 1_輸出品質 | 4.36 | 使用技能時平均分數 4.36/5(程式化檢查,見各任務 表格)。 |
| 2_相較無技能的提升 | 2.64 | 相較未使用技能的 3.71,+0.64 分(每項任務 n=2;約 1 分以下 屬於雜訊)。 |
| 3_觸發 | 5.0 | 技能檔案在 6/6 次實驗組執行中被讀取。 |
| 4_指令可攜性 | 4 | SKILL.md 規則加上參考文字。 |
| 5_效率 | 2 | 1.68 倍 Token(每次執行 132k 對 78k)與 0.99 倍時間(81 秒對 82 秒)。 |
| 6_安全性與衛生 | 4 | 僅有文字;見 security.md。 |
這項測試的限制
- 對單一 HTML 檔案的程式碼文字進行規則式檢查;動畫未在瀏覽器中渲染或計時,因此不評判流暢度與視覺品質。
- 一句話提示是技能自身檢查清單的貼近改寫,而檢查項目也反映同一份規則清單。
- 每個儲存格 n=2。
- 每項任務每組 n = 2:約 1 分以下的差異屬於雜訊。
- 規則式評分只能衡量檢查看得到的部分;無法評判品味,也無法判斷結果是否為最佳可能。
安全性
見 security.md。掃描:CRITICAL 0 / HIGH 0 / MEDIUM 0。判定:可安全執行(網路關閉的沙箱)。乾淨的掃描結果不能證明技能安全。
總結
相較於完全沒有指引,這項技能能提升遵循的動態規則,但把同一套規則寫成一句話,就能以更少 Token 達到滿分,因此其效益僅止於勝過單純的提示詞。
完整紀錄
執行日誌:animate (Codex CLI, network off, per-run temp HOME/TMPDIR, one row per graded run.) 欄位:任務、組-輪次、得分(0-5)、token、秒、通過的檢查、代理開啟的 skill 檔案。 t1-dropdown control-1: 得分 3.71, token 52757, 秒 64.6, 檢查 1/2, 未開啟 t1-dropdown control-2: 得分 3.29, token 109744, 秒 78.3, 檢查 1/2, 未開啟 t1-dropdown oneliner-1: 得分 5.0, token 90139, 秒 90.1, 檢查 2/2, 未開啟 t1-dropdown oneliner-2: 得分 5.0, token 110798, 秒 84.6, 檢查 2/2, 未開啟 t1-dropdown treatment-1: 得分 4.14, token 162460, 秒 70.2, 檢查 2/2, 開啟 animate t1-dropdown treatment-2: 得分 4.14, token 165193, 秒 85.1, 檢查 2/2, 開啟 animate t2-modal control-1: 得分 3.71, token 69259, 秒 69.5, 檢查 1/2, 未開啟 t2-modal control-2: 得分 3.29, token 52805, 秒 73.9, 檢查 1/2, 未開啟 t2-modal oneliner-1: 得分 5.0, token 110675, 秒 103.1, 檢查 2/2, 未開啟
18 次執行、3 個產出檔案
範例產出
SOTA · 装了 skill:menu.html(t1-dropdown,第 1 次,Codex)
<!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Workspace menu</title> <style> :root { font-family: system-ui, sans-serif; color: #252c39; background: #f4f5f7; --ease-out: cubic-bezier(0.23, 1, 0.32, 1); } * { box-sizing: border-box; } body { margin: 0; min-height: 100svh; display: grid; place-items: center; padding: 24px; } main { width: min(100%, 400px); min-height: 440px; } .eyebrow { color: #687183; font-size: 11px; font-weight: 700; letter-spacing: .16em; text-transform: uppercase; } h1 { margin: 12px 0 8px; font-size: 30px; letter-spacing: -.04em; } .description { margin: 0 0 28px; color: #687183; font-size: 14px; line-height: 1.6; } .dropdown { position: relative; width: min(100%, 280px); } button { font: inherit; cursor: pointer; } .trigger { display: flex; align-items: center; justify-content: space-between; gap: 32px; border: 1px solid #303a4e; border-radius: 12px; background: #293448; color: white; padding: 14px 18px; font-size: 14px; font-weight: 600; box-shadow: 0 3px 5px #20293b15; } .chevron { width: 16px; height: 16px; transition: transform 200ms var(--ease-out); } [aria-expanded="true"] .chevron { transform: rotate(180deg); } .menu { position: absolute; top: calc(100% + 10px); left: 0; width: 100%; padding: 6px; border: 1px solid #e1e4eb; border-radius: 14px; background: white; box-shadow: 0 16px 36px -12px #27324a30, 0 3px 8px #27324a08; opacity: 0; transform: scale(.95); transform-origin: top left; pointer-events: none; transition: opacity 200ms var(--ease-out), transform 200ms var(--ease-out); } .dropdown.open .menu { opacity: 1; transform: scale(1); pointer-events: auto; } .item { width: 100%; display: flex; align-items: center; gap: 12px; border: 0; border-radius: 8px; background: transparent; color: #394256; padding: 12px; text-align: left; font-size: 14px; } .icon { width: 20px; text-align: center; color: #738098; font-size: 18px; line-height: 1; } .item:last-child { margin-top: 5px; border-top: 1px solid #edf0f5; border-radius: 0 0 8px 8px; } button:focus-visible { outline: 2px solid #657cf0; outline-offset: 3px; } .item:focus-visible { outline-offset: -2px; background: #f0f3fa; } @media (hover: hover) and (pointer: fine) { .trigger:hover { background: #36435b; } .item:hover { background: #f0f3fa; } } .dropdown.instant .menu, .dropdown.instant .chevron { transition: none; } @media (prefers-reduced-motion: reduce) { .menu, .dropdown.open .menu { transform: none; } .chevron { transition: none; } } .status { margin-top: 300px; font-size: 13px; color: #687183; min-height: 20px; } </style> </head> <body> <main> <div class="eyebrow">Your workspace</div> <h1>A little room for everything.</h1> <p class="description">Your everyday essentials, one click away.</p> <div class="dropdown" id="dropdown"> <button class="trigger" id="trigger" type="button" aria-haspopup="menu" aria-expanded="false" aria-controls="menu"> Workspace <svg class="chevron" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-wid [... excerpt: first 3200 of 7249 characters]