Instruction manual

emilkowalski/skills instruction manual

A reusable Agent Skills collection for improving user-interface design and engineering, with opinionated guidance and workflows for web and Expo animation, animation review and audits, prototyping, Apple-style design, Swift, Sonner, and UI-library selection.

1. Purpose, classification, installation, and scope

Skills for Designers and Engineers

`emilkowalski/skills` is a public, MIT-licensed Markdown repository for helping designers and engineers build better user interfaces. Its documented strengths are animation judgment, design engineering, React Native/Expo motion, Sonner toasts, Apple-inspired interaction design, modern Swift, UI-library selection, prototyping, and motion review. The repository description is “Skills for Designers and Engineers,” and the README says the guidance reflects Emil Kowalski’s experience at Vercel and Linear.

**Claude Code relationship:** **context injection**, installed as a **Claude extension / Agent Skills package**, with **low setup effort**. Confidence is high because the repository is organized as named `SKILL.md` files with descriptions and invocation controls, and the documented installer is the Skills CLI. The skills primarily add specialized instructions and decision frameworks to the agent; they are not a standalone application or an external tool server.

Install the collection with the only repository-wide installation command documented in the supplied files:

npx skills@latest add emilkowalski/skills

Most skills are intended to activate when their description matches the task. Three are explicitly manual-only: `prototype`, `pick-ui-library`, and `review-animations` have `disable-model-invocation: true`. Invoke those deliberately by name. The README also catalogs `find-animation-opportunities`, which searches for useful motion opportunities and warns what not to animate, but its detailed `SKILL.md` was not supplied; no additional workflow or syntax can be documented reliably here.

2. Core design engineering and web animation construction

`emil-design-eng`

This is the broad UI-polish skill. It applies a taste-and-craft philosophy to component design, motion, responsiveness, performance, and accessibility. If invoked without a specific question, it gives a short readiness message; provide a concrete UI question to receive useful guidance. For reviews, its required output is one Markdown table with **Before**, **After**, and **Why** columns.

Its main rules are: do not animate keyboard-driven or extremely frequent actions; require a purpose such as feedback, spatial consistency, state indication, explanation, or preventing a jarring change; prefer strong `ease-out` for entrances and exits; keep ordinary UI motion below 300ms; use subtle press scaling; avoid `scale(0)`; anchor popovers to their trigger; use transitions for rapidly retargeted UI; animate `transform` and `opacity`; gate hover motion; and provide reduced-motion behavior.

Source-supported CSS defaults include:

--ease-out: cubic-bezier(0.23, 1, 0.32, 1);
--ease-in-out: cubic-bezier(0.77, 0, 0.175, 1);
--ease-drawer: cubic-bezier(0.32, 0.72, 0, 1);

`animate`

Use this when you want the agent to implement a web animation from scratch. It processes the decision in order: whether motion belongs, its purpose, the cheapest suitable tool, properties, timing or spring, interruption/exit behavior, and accessibility. It may correctly return no animation and suggest an instant state change instead.

The tool ladder is CSS transition → CSS `@starting-style` → CSS animation → WAAPI → Motion. If the request is really for a component such as a toast or dropdown, it redirects to `pick-ui-library`. Its deliverable is code followed by a brief gate result, ingredient summary, and any necessary feel-check.

3. React Native and Expo animation

`animate-expo`

Use this construction skill for motion in React Native or Expo: press feedback, gestures, sheets, navigation transitions, haptics, and performance problems on devices. It uses Reanimated 4, Gesture Handler, Expo Router, and `expo-haptics`, with an explicit requirement to keep per-frame work on the UI runtime rather than triggering React state or RN-runtime callbacks every frame.

The workflow first rejects unsuitable motion. High-frequency actions such as tab switches, settings toggles, scrolling, and keyboard transitions receive platform-default behavior or no animation; peer tabs specifically use `animation: 'none'`. It then names the purpose and picks the cheapest fitting mechanism: Reanimated CSS transitions or animations, layout animations, shared values plus gestures, native stack options, native sheets/tabs/menus, keyboard controller, Lottie, or Skia.

Install compatible dependencies through Expo, not a plain package-manager install. The supplied general form is:

npx expo install <package>

The documented Reanimated setup command is:

npx expo install react-native-reanimated react-native-worklets

Key implementation rules are `transform` and `opacity` by default, springs whenever a finger is involved, timing curves otherwise, `.get()`/`.set()` for shared values, no shared-value access during render, no `setState` in gesture or scroll callbacks, and no per-frame `scheduleOnRN`. Haptics fire once at the causal visual moment and never stand alone. Reduced motion keeps explanatory opacity/color changes but removes translation, scale, parallax, and overshoot. Verification must happen in a release build on the slowest supported physical device; Expo Go and simulators are not accepted as feel checks.

4. Animation review, auditing, plans, and execution modes

`review-animations`

This manual-only skill reviews motion code, not general code and not feature implementation. It checks ten standards: justified and frequency-appropriate motion, responsive easing, sub-300ms UI timing, correct origin and physicality, interruptibility, GPU-friendly properties, accessibility, asymmetric deliberate/response timing, and product cohesion. It aggressively flags `transition: all`, `scale(0)`, UI `ease-in`, high-frequency animation, unreasoned durations above 300ms, wrong popover origins, keyframes on rapidly triggered UI, layout-property animation, missing reduced-motion support, and ungated hover effects.

Its output always has a findings table with **Before / After / Why**, then impact-tier commentary and an explicit **Block** or **Approve** verdict. Findings should cite `file:line`. It does not fix unrelated code.

`improve-animations`

Use this for a codebase-wide, read-only motion audit and roadmap. It maps the stack, tokens, conventions, personality, and frequency; audits purpose, timing, physicality, interruption, performance, accessibility, cohesion, and missed opportunities; vets every cited finding; then waits for selection before writing self-contained plans under `plans/` or `animation-plans/`. It must not modify source, install packages, format, commit, or run mutating operations.

Documented invocation variants are `quick`, `deep`, a category such as `performance`, `plan <description>`, `execute <plan>`, and `reconcile`. Bare invocation performs the full recon/audit/confirmation/planning workflow. `execute <plan>` dispatches implementation in an isolated worktree and reviews the resulting diff; `reconcile` updates plan status against current code. Plans include exact paths, excerpts, values, boundaries, verification, and feel checks.

5. Variant prototyping and curated dependency selection

`prototype`

This manual-only divergence skill builds several genuinely different versions of one UI piece and puts them behind a visual picker. It does not review existing UI, plan animation fixes, or choose dependencies. The default is three variants, with a maximum of five when requested or justified. Each direction must differ on a named axis such as layout, density, personality, motion, or interaction model; color-only variations do not count.

The six phases are scope, project reconnaissance, direction selection, isolated picker construction, verification/hand-off, and promotion after the user chooses. Existing projects receive an isolated prototype route or page; a no-project context receives one self-contained HTML file. Production code remains untouched during exploration. The picker shows one full-size variant at a time, switches instantly, and uses the separately documented picker specification. On selection, the chosen variant is integrated and the prototype surface is deleted unless the user asks to retain it.

Supported invocation forms are `<description>`, `<description> x5`, `riff <variant>`, `keep <variant>`, and `keep <variant>, leave the picker`.

`pick-ui-library`

This manual-only lookup checks `package.json`, identifies the actual task, recommends one curated library, and can wire it up when requested. Picks include Base UI for accessible primitives, cmdk for command menus, Sonner for toasts, input-otp, Leva, Motion, NumberFlow, torph, Cobe, Satori, Shiki, Liveline for streaming charts, recharts for other charts, dnd kit, Virtuoso, zustand, clsx, cva, and next-themes. It preserves an existing competitor unless dependency churn is requested. If the task is uncovered, it says it is leaving the curated list before using general knowledge.

6. Sonner setup, toast operations, styling, and troubleshooting

`ask-sonner`

Use this guide whenever the project uses Sonner or a toast is missing, duplicated, unstyled, incorrectly themed, clipped, or behind an overlay. Setup has exactly two pieces: mount one `<Toaster />` near the application root and call `toast()` from client code. No provider or hook is required for dispatch. Server actions must return a result so client code can display the toast.

import { Toaster } from 'sonner'; // once, in layout
import { toast } from 'sonner';   // anywhere client-side

Available operations include plain, success, error, info, warning, loading, promise-driven, action/cancel, custom-shell, and headless custom toasts. Update by reusing an ID:

const id = toast.loading('Uploading…');
toast.success('Uploaded', { id });

Use `{ duration: Infinity }` to persist. Use `toast.dismiss(id)` for one or `toast.dismiss()` for all. `useSonner()` reads active toasts in React; `toast.getActiveToasts()` does so outside React. Multiple toasters require an `id` on each Toaster and `toasterId` on each targeted toast.

The styling ladder is defaults, inline styles, part classes, then `toast.custom()` for full headless control. Sonner’s injected styles can outrank classes, requiring `!important`; extensive overrides are a reason to go headless. Theme defaults to light, so use `theme="system"` or a resolved provider value. Duplicate toasts usually mean two Toasters or a StrictMode effect; missing styles can be repaired with the documented explicit import:

import 'sonner/dist/styles.css';

7. Apple-style interaction principles and animation terminology

`apple-design`

This reference translates Apple’s fluid-interface principles to the web. Use it for gesture-driven UI, springs, momentum, interruptibility, materials, depth, typography, accessibility, or design foundations. Its central model is immediate response, 1:1 pointer tracking, animation from the live presentation value, velocity handoff, projected momentum, symmetric spatial paths, and rubber-band resistance at boundaries.

A touched object should use an interruptible spring. Typical guidance is damping `1.0` and response `0.3–0.4` for no overshoot, or damping about `0.8` after a momentum-carrying gesture. Pointer input uses capture and preserves the grab offset. Release velocity determines both the projected destination and the spring’s initial movement. The skill also covers translucent materials, same-frame visual/audio/haptic causality, reduced motion/transparency/contrast, responsive typography, and eight design principles: purpose, agency, responsibility, familiarity, flexibility, simplicity, craft, and delight.

`animation-vocabulary`

Use this naming-only glossary when you know what an effect looks or feels like but not what it is called. It returns the best glossary term and its authoritative description; when needed, it adds one or two close alternatives and explains the distinction. It does not design or implement the effect.

Coverage includes entrances, timing, transforms, state transitions, scroll effects, gestures, easing, springs, ambient motion, visual polish, performance, and principles. For example, resistance beyond an edge is **Rubber-banding**; items entering sequentially use **Stagger**; a popover growing from its trigger is an **Origin-aware animation**. If no term matches, the skill identifies the closest approximation rather than inventing vocabulary.

8. Modern Swift writing, concurrency, performance, and testing

`write-swift`

Use this extensive reference when writing, reviewing, or migrating Swift, or when diagnosing concurrency errors, hangs, races, retain cycles, and performance problems. Its baseline is Swift 6.3, with Swift 6.4-only material explicitly marked unreleased. Projects on Swift 6.1 or earlier must not apply the 6.2 `async`/`@concurrent` model unchanged.

The default hierarchy is value types before classes, concrete types before abstractions, `some P` before `any P`, synchronous main-actor execution before concurrency, standard collections before specialized memory types, and safe APIs before pointers. It covers copy-on-write and noncopyable ownership; visible error paths; Swift 6.2 actor isolation; `Sendable`; structured tasks, cancellation, continuations, and `AsyncSequence`; SwiftUI isolation; protocol dispatch and generics; API design; measured optimization; ARC lifetime; macros; logging; unsafe interop; modern syntax; and staged Swift 6 migration.

Concurrency should progress from main-actor synchronous code to `async` for latency, then `@concurrent` for measured CPU work, and finally actors when state itself must move. Prefer `async let` for a fixed number of child jobs and bounded task groups for dynamic work. Never hold a blocking primitive across `await`, and re-check assumptions after suspension.

For new tests, use Swift Testing: `@Test`, `#expect`, and `try #require`. XCTest remains for UI automation, performance metrics, Objective-C tests, and Objective-C exception handling. Performance work begins with algorithmic complexity and Instruments, not intuition. The migration order is new compiler, complete concurrency checking per target, warning fixes, Swift 6 language mode, then separate refactoring.

9. Choosing the right skill and documented boundaries

Task-to-skill guide

Use `animate` to write one web animation, and `animate-expo` for React Native/Expo. Use `review-animations` for a specific motion diff; use `improve-animations` for a read-only codebase survey and implementation plans. Use `emil-design-eng` for broader UI craft or reviews. Use `prototype` when you explicitly want multiple working directions and a picker. Use `pick-ui-library` before hand-building a common frontend component. Use `ask-sonner` for Sonner implementation and troubleshooting, `apple-design` for physical interaction principles, `animation-vocabulary` to name an effect, and `write-swift` for modern Swift.

These boundaries prevent overlapping modes from producing the wrong deliverable. `animate` writes code but does not audit an entire repository. `review-animations` reviews but does not implement features. `improve-animations` plans and is source-read-only. `prototype` waits for the user’s selection before production integration. `animation-vocabulary` names but does not build. `pick-ui-library`, `prototype`, and `review-animations` do not self-trigger.

Several supplied files refer to companion documents such as `RECIPES.md`, `PICKER.md`, `API.md`, `STANDARDS.md`, `AUDIT.md`, and `PLAN-TEMPLATE.md`. Their contents were not supplied, so this manual does not invent their exact recipes, prop tables, picker implementation, or plan templates. Likewise, the README’s `find-animation-opportunities` entry supports only the high-level statement that it searches a UI for motion that would genuinely help and identifies what should remain static. For updates, the README links the project homepage at `https://emilkowal.ski/skill` and a newsletter at `https://animations.dev/skills`.