animate (emilkowalski/skills)
animate: makes Codex's generated UI animations follow a design engineer's motion rules (control 3.7, skill 4.4, one-liner 5.0) at 1.7x the tokens; a one-sentence prompt of the same rules does better and cheaper
22.0 / 30
Lift over no skill: +0.64
Situational: the lift +0.64 is under +1.0. Recommended needs a total of 22/30, output quality of 3.5, and a lift of +1.0.
SOTA
PassTested with Codex.
Covers Codex, Claude Code
Codex CLI 0.166 (SOTA tier): 18 graded runs. A pass here also covers Claude Code under our tier rule; it says nothing about the second tier.
Scores
Each dimension is 0 to 5 and the six add up to the total out of 30. 5 is better on every dimension. Cost 5 means cheap and fast. Install 5 means easy.
- Trigger reliability
- 5.0
- Lift over no skill
- 2.6
- Output quality
- 4.4
- Token and time cost
- 2.0
- Install and portability
- 4.0
- Safety
- 4.0
Security review
SafeStatic scan: 0 CRITICAL / 0 HIGH / 0 MEDIUM. Manual review: Safe to run in a no-network sandbox (no findings). A clean scan does not prove a skill safe.
Install
npx skills@latest add emilkowalski/skills --skill animate
Pinned commit: a81dbca07f2217b7103e510c0f13f8d5b017afc9
Tested: 2026-11-02
What we tested
- Animated dropdown menu — Build menu.html: a button that opens a dropdown menu with 5 items, with open and close animations. Write one self-contained HTML file (inline CSS and JS, no libraries).
- Animated modal dialog — Build modal.html: a button that opens a modal dialog with a dimmed backdrop, with open and close animations. Write one self-contained HTML file (inline CSS and JS, no libraries).
- Toast notifications — Build toasts.html: three buttons that each show a toast notification which stacks and dismisses itself, with enter and exit animations. Write one self-contained HTML file (inline CSS and JS, no libraries).
Pros
- Lifts the mean score from 3.71 to 4.36 over no skill (+0.64).
- The skill was picked up without being named: Skill file read in 6/6 treatment runs.
Cons
- A one-sentence prompt scored 5.0, against 4.36 with the skill (-0.64).
- Uses 1.68x the tokens of no skill.
- n=2 per task per arm; differences under about 1 point are noise.
Review
Codex CLI 0.166 (gpt-6-astra, low reasoning) on a dedicated Windows test PC, a fresh temporary project and temporary HOME/TMPDIR/caches per run, skill installed (treatment) or absent (control) or absent with the skill's core requirement squeezed into one sentence appended to the prompt (one-liner group), 2 runs per group per task, network off, /tmp writes blocked. The prompts never mention the skill (except the wording noted below). Three build tasks, each one self-contained HTML file with inline CSS and JS: a dropdown menu, a modal with a dimmed backdrop, and stacking toasts, all with open/close or enter/exit animations. Prompts do not mention motion rules. The one-liner lists the rules in one sentence.
Three-arm comparison
| Arm | Mean score (0-5) | Tokens per run |
|---|---|---|
| Without the skill | 3.71 | 78k |
| One-sentence prompt | 5.0 | 105k |
| With the skill | 4.36 | 132k |
Measured with Codex CLI over 18 runs, scored by rule-based checks with no LLM judge. Total 22.0 / 30, verdict Situational.
Verdict: Situational (22.0 / 30). Source: emilkowalski/skills, skills/animate, pinned at commit a81dbca. Install: npx skills@latest add emilkowalski/skills --skill animate. Licence: MIT (repo LICENSE).
What it is
The animate skill (emilkowalski/skills): motion rules for building UI animations: animate only with purpose, custom ease-out cubic-bezier (never ease-in or the default), 150-300 ms, transform and opacity only, press feedback with scale(0.97), never start from scale(0), stagger entrances, interruptible transitions, prefers-reduced-motion, hover gated with (hover: hover).
How we tested
Codex CLI 0.166 (gpt-6-astra, low reasoning) on a dedicated Windows test PC, a fresh temporary project and temporary HOME/TMPDIR/caches per run, skill installed (treatment) or absent (control) or absent with the skill's core requirement squeezed into one sentence appended to the prompt (one-liner group), 2 runs per group per task, network off, /tmp writes blocked. The prompts never mention the skill (except the wording noted below).
Three build tasks, each one self-contained HTML file with inline CSS and JS: a dropdown menu, a modal with a dimmed backdrop, and stacking toasts, all with open/close or enter/exit animations. Prompts do not mention motion rules. The one-liner lists the rules in one sentence.
- Animated dropdown menu — Build menu.html: a button that opens a dropdown menu with 5 items, with open and close animations. Write one self-contained HTML file (inline CSS and JS, no libraries).
- Animated modal dialog — Build modal.html: a button that opens a modal dialog with a dimmed backdrop, with open and close animations. Write one self-contained HTML file (inline CSS and JS, no libraries).
- Toast notifications — Build toasts.html: three buttons that each show a toast notification which stacks and dismisses itself, with enter and exit animations. Write one self-contained HTML file (inline CSS and JS, no libraries).
Scoring is programmatic (hidden tests / planted-issue recall / constraint checks / render+OCR where relevant), 0–5 per run. No LLM judge decided any score.
Results
The one-liner given to the third group: "Animate like a design engineer: only animate what has a purpose, use a custom ease-out cubic-bezier (never ease-in or the default), 150-300 ms, only transform and opacity, press feedback with scale(0.97), never start from scale(0), stagger entrances, interruptible transitions, honour prefers-reduced-motion and gate hover with (hover: hover)."
| Task | Control score | One-liner | With skill | Control tokens | One-liner tokens | With-skill tokens | Skill read |
|---|---|---|---|---|---|---|---|
| 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 |
Mean score: 3.71 without vs 4.36 with the skill (delta +0.64). Tokens per run: 78k vs 132k (1.68x); time 82s vs 81s. One-liner group: 5.0 (the skill's gain over the one-liner: -0.64; one-liner's own gain over no skill: +1.29); one-liner tokens 105k per run, so the skill costs 1.25x the one-liner.
What happened
- Control 3.71, skill 4.36, one-liner 5.0 (n=6 each). A rule-based motion check counts how many of 10 rules the page follows. Control reached 6-8 of 10, the skill 8-9, and the one-liner satisfied every check in all 6 runs.
- The rules control most often missed: press feedback (an :active scale) in 3 of 6 runs, plus staggered entrances and non-default easing in some runs. The skill still missed press feedback in 2 runs and staggered entrance or easing in several; on the toast task its score was 4.14 and 4.57 against 4.14 for control.
- Tokens: skill 132k, one-liner 105k, control 78k per run (1.7x control, 1.3x one-liner). The skill was read in 6/6 treatment runs; it uses more commands (9.3 per run against 4.7).
- Treatment runs add about 3 new files (the skill copy in the working folder) per run.
Dimension scores
| Dimension | Score | Why |
|---|---|---|
| 1_output_quality | 4.36 | Mean score 4.36/5 with the skill (programmatic checks, see per-task table). |
| 2_lift_vs_no_skill | 2.64 | +0.64 points vs 3.71 without the skill (n=2 per task; under ~1 point is noise). |
| 3_trigger | 5.0 | Skill file read in 6/6 treatment runs. |
| 4_instructions_portability | 4 | SKILL.md rules plus reference text. |
| 5_efficiency | 2 | 1.68x tokens (132k vs 78k per run) and 0.99x time (81s vs 82s). |
| 6_safety_hygiene | 4 | Prose only; see security.md. |
Limits of this test
- Rule-based checks on the code text of one HTML file; the animations were not rendered or timed in a browser, so smoothness and visual quality are not judged.
- The one-liner is a close paraphrase of the skill's own checklist, and the checks mirror the same rule list.
- n=2 per cell.
- n = 2 per group per task: differences under about 1 point are noise.
- Rule-based scoring measures what the checks can see; it cannot judge taste or whether a result is the best possible.
Security
See security.md. Scan: 0 CRITICAL / 0 HIGH / 0 MEDIUM. Verdict: safe to run (no-network sandbox). A clean scan does not prove a skill safe.
Bottom line
The skill improves the motion rules followed over no guidance, but the same rules as one sentence achieve a perfect score for fewer tokens, so the benefit is over a bare prompt only.
Transcript
Run log for animate: Codex CLI, network off, per-run temp HOME/TMPDIR, one row per graded run. Columns: task, arm-run, score (0-5), tokens, seconds, checks passed, skill files the agent opened. t1-dropdown control-1: score 3.71, tokens 52757, secs 64.6, checks 1/2, opened nothing t1-dropdown control-2: score 3.29, tokens 109744, secs 78.3, checks 1/2, opened nothing t1-dropdown oneliner-1: score 5.0, tokens 90139, secs 90.1, checks 2/2, opened nothing t1-dropdown oneliner-2: score 5.0, tokens 110798, secs 84.6, checks 2/2, opened nothing t1-dropdown treatment-1: score 4.14, tokens 162460, secs 70.2, checks 2/2, opened animate t1-dropdown treatment-2: score 4.14, tokens 165193, secs 85.1, checks 2/2, opened animate t2-modal control-1: score 3.71, tokens 69259, secs 69.5, checks 1/2, opened nothing t2-modal control-2: score 3.29, tokens 52805, secs 73.9, checks 1/2, opened nothing t2-modal oneliner-1: score 5.0, tokens 110675, secs 103.1, checks 2/2, opened nothing
18 runs, 3 artifacts
Sample output
SOTA · With the skill: menu.html (t1-dropdown, run 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]