# UI Craft
**Ship designer-grade UI by default.** A design engineering system for AI coding agents — install it as a skill or as the `ui-craft` CLI, and your agent starts designing like it has taste. Ask for a dashboard, get one you'd put in production. Not gradient cards and bounce animations.
**Website:** [skills.smoothui.dev](https://skills.smoothui.dev)

## Ask for a surface. Ship it.
```
/craft dashboard
```
Three questions (or none — the defaults are strong), a named composition, a production theme preset, and a build that must pass a **10-item acceptance bar** before it reports done: *"would a designer retouch this?"* If a box fails, it isn't done.
For everything else — reviews, animations, forms, polish — the skill routes by intent: just describe what you're building.
**New here?** Run `/start` — it reads your project (framework, tokens, brief, existing UI) and tells you what ui-craft can do right now, then points you at the right next step.
## What it does
UI Craft gives AI coding agents the design knowledge they're missing. Not templates. Not component libraries. Actual craft knowledge — opinionated rules about how interfaces should look, move, and feel — plus the tooling to verify the result. Stack-agnostic by design.
Every UI gets tested against a single question: *"Would someone believe AI made this?"* If yes, it starts over.
### The ladder — four rungs
There is one thing to learn, and it's a ladder. Each rung is a real jump in what you get, and each costs a little more than the one below. **You only climb when you want the next thing.**
| Rung | You want | You do | You get | Effort |
|------|----------|--------|---------|--------|
| **0 · Ask** | Better UI with zero effort | Install, then ask for UI the way you always do | Real hierarchy, your own tokens, no AI slop — same prompt, shippable result | none |
| **1 · Direct** | Control over one pass | `/craft`, `/critique`, `/polish`, `/animate`, … | A focused pass on one surface, aimed by you | one command |
| **2 · Persist** | Consistency across sessions | `/brief`, `/tokens`, `/remember` | Durable design context every future session reads | write once |
| **3 · Enforce** | Proof it cannot regress | `/finalize`, review agents, MCP gates, `ui-craft-detect` | Gates in review and CI, plus a deterministic 0-100 score | wire once |
**Start at rung 0.** Most people never leave it — that's the point. Rungs 1 to 3 are there the day you want them, and `/start` will tell you which rung your project is on right now.
`/sddesign` is **not** a fifth rung. It's the express lane that walks rungs 1 to 3 in one guided run, for a single big surface.
**What makes this different:** the only AI design system that produces a **scoreable, defensible critique** — Nielsen's 10 usability heuristics × 6 classic design laws (Fitts, Hick, Doherty, Cleveland-McGill, Miller, Tesler) × 5 persona walkthroughs, with every finding tagged by business impact (`blocks-conversion` / `adds-friction` / `reduces-trust` / `minor-polish`). Paste the scorecard straight into any issue tracker.
## Same prompt, different result
<table>
<tr>
<td><strong>Without UI Craft</strong><br/><img src="assets/screenshots/hero-without.png" alt="Hero built without UI Craft" width="100%" /></td>
<td><strong>With UI Craft</strong><br/><img src="assets/screenshots/hero-with.png" alt="Hero built with UI Craft" width="100%" /></td>
</tr>
<tr>
<td><img src="assets/screenshots/dashboard-without.png" alt="Dashboard built without UI Craft" width="100%" /></td>
<td><img src="assets/screenshots/dashboard-with.png" alt="Dashboard built with UI Craft" width="100%" /></td>
</tr>
</table>
More before/after comparisons on the [landing page](https://skills.smoothui.dev).
## Install
### CLI — recommended (cross-harness, installs the whole system)
A single static Go binary that detects your AI coding harness and wires skill+commands, MCP gates, review agents, and design-memory into its native config in one interactive pass. No Node required at install time.
**macOS / Linux:**
```bash
curl -fsSL https://skills.smoothui.dev/install | bash
```
**Windows:**
```powershell
irm https://skills.smoothui.dev/install.ps1 | iex
```
The script detects your OS/arch, downloads the latest release, verifies its checksum, and installs the `ui-craft` binary — no brew/scoop required.
**Then run:**
```bash
ui-craft install
```
<details>
<summary>Alternative installs (Homebrew, Scoop)</summary>
**macOS (Homebrew):**
```bash
brew install --cask educlopez/tap/ui-craft
```
**Windows (Scoop):**
```powershell
scoop bucket add educlopez https://github.com/educlopez/scoop-bucket
scoop install educlopez/ui-craft
```
</details>
`ui-craft install` detects Claude Code / Cursor / Codex / Gemini / OpenCode, walks you through à-la-carte component selection (interactive TUI or `--yes` for CI), and writes each chosen component into that harness's native config. All writes are idempotent, backed up before they happen, and rolled back automatically on any failure.
**What rides which install?**
| Component | CLI | Claude Code plugin | `npx skills add` |
|-----------|:---:|:------------------:|:----------------:|
| Skill + commands | All harnesses | ✅ | All harnesses |
| MCP gates (`check_anti_slop`, `tokens_lint`, `acceptance_bar`, `score_ui`) | All MCP-capable harnesses | ✅ auto-wired | Manual `.mcp.json` |
| Review agents (`design-reviewer`, `a11y-auditor`) | Claude Code + OpenCode | ✅ | — |
| Design memory (`.ui-craft/`) | ✅ (component opt-in) | — | — |
### Platform support
Six binaries ship on every release. They are not equally exercised, and the difference is worth knowing before you rely on one.
| Platform | Binary | Go suite in CI | Installer end-to-end | Gatekeeper / fresh install |
|---|:--:|:--:|:--:|:--:|
| macOS Apple Silicon · `darwin/arm64` | ✅ | ✅ | ✅ | ✅ by hand, every release |
| macOS Intel · `darwin/amd64` | ✅ | — | — | — |
| Linux x86-64 · `linux/amd64` | ✅ | ✅ | ✅ Ubuntu · Fedora · Arch | n/a |
| Linux arm64 · `linux/arm64` | ✅ | — | — | n/a |
| Windows x86-64 · `windows/amd64` | ✅ | ✅ | ✅ | n/a |
| Windows arm64 · `windows/arm64` | ✅ | — | — | n/a |
A dash means the binary is built and published but nothing runs on it. Those rows are honest gaps, not oversights we have quietly closed.
**Windows** has only been covered since v1.0.16. Before that the suite had never been green there, and five Windows-only bugs shipped as a result — one of them deleting files during rollback that it existed to protect. The suite now gates every pull request that touches the CLI.
**macOS on Intel** is the largest remaining gap: built and shipped, never tested, and not covered by the manual Gatekeeper check either — that one is Apple-Silicon-only.
Two conditions are untested on every platform: installing with the disk nearly full, and two `ui-craft install` runs racing against the same machine. See [`RELEASE_CHECKLIST.md`](RELEASE_CHECKLIST.md) for what each release actually verifies, and what a completed checklist does not promise.
**Full reference docs:** [skills.smoothui.dev/docs](https://skills.smoothui.dev/docs).
### Claude Code plugin — alternative (skill + commands + agents + MCP, no CLI needed)
One command installs the skill, all 25 slash commands, the 2 review agents, and the MCP quality-gate server — auto-wired, no `.mcp.json` editing:
```
/plugin marketplace add educlopez/ui-craft
/plugin install ui-craft
```
The plugin bundles a `.mcp.json` (`npx -y ui-craft-mcp@0.9.0`), so the deterministic gates register automatically on install. The exact package version is declared in [`distribution-manifest.json`](distribution-manifest.json), avoiding an implicit upgrade on first launch. This uses Claude Code's own plugin system, so it's not affected by the global-path issue noted below.
### Cursor plugin — alternative (skill + commands + agents + MCP + rules + hook)
Clone this repository into Cursor's local plugin folder, then reload the window:
```bash
git clone https://github.com/educlopez/ui-craft.git ~/.cursor/plugins/local/ui-craft
```
The plugin is the repo itself (`.cursor-plugin/plugin.json`). It registers the `ui-craft` skill and its variants, the slash commands, the `design-reviewer` and `a11y-auditor` agents, the `.mdc` rules, the `ui-craft-mcp` quality-gate server, and a `preToolUse` hook that runs `ui-craft-detect` before every file write.
Open **Customize** and confirm those components loaded. On Teams and Enterprise, local plugin imports must be allowed under Dashboard → Settings → Security & Identity → Marketplace and Plugins.
### Agent Skills — alternative (skill + commands only, any harness)
```bash
npx skills add educlopez/ui-craft
```
> [!warning]
> This installs the **skill only** — no slash commands beyond the ones mirrored as sub-skills, no review agents, no MCP gates, no hooks. For the full system (MCP quality gates, review agents, design memory), use the [installer above](#cli--recommended-cross-harness-installs-the-whole-system).
Works with any agent that supports the [Agent Skills](https://skills.sh) spec. Each agent gets a pre-built mirror under a dedicated folder (`.codex/`, `.cursor/`, `.gemini/`, `.opencode/`, `.agents/`). The main `ui-craft` skill lands as a peer skill; each slash command is materialized as its own sub-skill in non-Claude harnesses (other agents trigger them by intent: "audit my UI", "polish this page").
> [!note]
> **Using `npx skills add -g` with Claude Code?** The skills CLI installs global skills to `~/.agents/skills`, but Claude Code reads `~/.claude/skills` ([vercel-labs/skills#693](https://github.com/vercel-labs/skills/issues/693)). If the skill isn't picked up, use the CLI or plugin install above, install per-project (drop `-g`), or symlink it:
> ```bash
> ln -s ~/.agents/skills/ui-craft ~/.claude/skills/ui-craft
> ```
### Other ways
```bash
# Clone
git clone https://github.com/educlopez/ui-craft.git ~/.skills/ui-craft
# Git submodule
git submodule add https://github.com/educlopez/ui-craft.git .skills/ui-craft
```
## CLI
The `ui-craft` binary is a single static Go binary (see [Install](#install) above for the recommended install script, plus Homebrew/Scoop alternatives). It is the lifecycle and cross-harness wiring core for the system.
Run `ui-craft` with no arguments to open the **interactive hub** — a full-screen menu with an async update check that routes into install, upgrade, backups, and uninstall. Every subcommand below also works directly for scripting/CI.
### Commands
| Command | Does |
|---------|------|
| `ui-craft` *(no subcommand)* | Open the interactive TUI hub: welcome menu + update check → Start installation · Upgrade · Manage backups · Managed uninstall. |
| `ui-craft install` | Detect harnesses, à-la-carte component selection, write configs. |
| `ui-craft update [harness]` | Re-apply all installed components at the new embedded version. |
| `ui-craft update [harness] --component <name>` | Re-apply one component only. |
| `ui-craft uninstall [harness]` | Remove managed blocks and wired components. |
| `ui-craft doctor` | Health check — verifies each harness install is coherent. |
| `ui-craft backup` | Snapshot all harness configs without installing. |
| `ui-craft backup list` | List existing snapshots. |
| `ui-craft backup pin <id>` / `unpin <id>` | Protect or unprotect a snapshot from retention cleanup. |
| `ui-craft rollback [harness]` | Restore latest backup for a harness. |
| `ui-craft self-update` | Upgrade binary to latest GitHub release (or prints the correct package-manager command when installed via Homebrew/Scoop). |
| `ui-craft version` | Print the binary version. |
| `ui-craft version --json` | Print `{ "version": "…" }`; there is no separate mirror-version field. |
| `ui-craft version --check-parity` | Verify the Claude Code install matches the expected surface. |
### Key flags for `install`
| Flag | Effect |
|------|--------|
| `--harness <name>` | Target a specific harness (`cursor`, `codex`, `gemini`, `opencode`) instead of auto-detecting. |
| `--components <list>` | Comma-separated components to install (`skill-commands`, `mcp-gates`, `review-agents`, `design-memory`). |
| `--dry-run` | Preview all planned writes without touching any file. |
| `--yes` | Non-interactive — skip TUI prompts and apply defaults. |
### Scripting flags (global)
| Flag | Effect |
|------|--------|
| `--json` | Machine-readable JSON output. Implies non-interactive. |
| `--quiet` | Suppress non-essential output; print only errors and a final one-line outcome. |
### Safety
Every install snapshots existing configs to `~/.ui-craft/backups/` (tar.gz, SHA-256 deduped) before writing. Any mid-plan failure rolls back the whole plan. `rollback [harness]` restores from the latest snapshot at any time. State is persisted to `~/.ui-craft/state.json` so `update` can replay your choices at the new version without re-prompting.
## Discovery phase
Before building anything, the skill analyzes your project for existing design decisions — CSS variables, Tailwind config, font imports, component themes. If your project already has a design system, it respects it. If not, it asks 4 quick questions (style, accent color, font, optional animation stack) so it never defaults to generic blue/Inter.
## Knobs
Three numeric knobs (1-10) that the skill asks about during Discovery. They change behavior, not just tone.
| Knob | 1 | 10 |
|------|---|----|
| **CRAFT_LEVEL** (default 7) | ships fast, skips Polish Pass | pixel-perfect, compound details applied |
| **MOTION_INTENSITY** (default 5) | hover states only | scroll-linked, page transitions, magnetic cursor |
| **VISUAL_DENSITY** (default 5) | whitespace-heavy editorial | dashboard-dense |
At `MOTION_INTENSITY 8+` the skill loads [`references/stack.md`](skills/ui-craft/references/stack.md) only if the user opts into Motion / GSAP / Three.js during Discovery.
## Style variants
Three opt-in sibling skills that pre-commit to a style and lock the knobs to matching values. Agents pick them when the user mentions a specific aesthetic or product reference.
| Variant | Triggers on | Knobs locked | Style anchors |
|---------|-------------|--------------|---------------|
| `ui-craft-minimal` | "minimal", "Linear-like", "Notion-like", "whitespace-heavy" | CRAFT=8 / MOTION=3 / DENSITY=2 | Monochrome + one accent, Inter/Geist, hairline borders |
| `ui-craft-editorial` | "editorial", "magazine", "Medium-like", "Substack-like", "long-form" | CRAFT=9 / MOTION=4 / DENSITY=3 | Serif display + humanist body, wide reading column, OpenType |
| `ui-craft-dense-dashboard` | "dashboard", "admin panel", "Bloomberg-like", "Retool-like" | CRAFT=7 / MOTION=3 / DENSITY=9 | IBM Plex + mono numbers, semantic palette, 4/8px grid |
Each variant defers to the main `ui-craft` skill for base rules and references — it only overrides knob defaults and adds style-specific guidance.
### Style presets
For playful and brutalist aesthetics (Clay / Gumroad / Duolingo / Arc-playful, Nothing-phone / Swiss-print / brutalist), see `examples/presets/playful.md` and `examples/presets/brutalist.md`. The main `ui-craft` skill applies these preset knob values + style overrides on top of the base rules when the user asks for those aesthetics.
## Slash commands
25 commands. They are **not a flat list** — every one belongs to a rung, and the rung tells you what it costs you before you read what it does.
**Front door — unsure where you are:**
| Command | Does |
|---------|------|
| `/ui-craft:start` | **Run this first.** Reads the project (framework, tokens, brief, spec, existing UI), reports which rung you are on, and names the one command worth running next. Read-only — no code changes. |
### Rung 1 · Direct — one focused pass, session-local
**Build a surface:**
| Command | Does | Next step |
|---------|------|-----------|
| `/ui-craft:craft` | **One-shot surface build.** Outcome recipe pipeline — Craft Read + variance + signature bet → named composition → theme → build order → acceptance bar. Surfaces: `dashboard`, `landing`, `auth`; portfolios use the landing recipe at variance 8. | `/finalize` |
| `/ui-craft:shape` | **Wireframe-first.** ASCII layout + content inventory + state list + open questions before any JSX. Run when starting a new screen. | `/craft` |
| `/ui-craft:redesign` | **Redesign without regression.** Audits the existing surface first, classifies what to preserve (brand, IA/SEO, content, conversion paths), picks refresh/reskin/rebuild scope, then modernizes. | `/critique` |
**Adjust one dimension:**
| Command | Does | Next step |
|---------|------|-----------|
| `/ui-craft:animate` | Add / fix motion. Honors `MOTION_INTENSITY` + chosen stack. | `/polish` |
| `/ui-craft:adapt` | Responsive pass — mobile, tablet, desktop, touch, safe areas. | `/audit` |
| `/ui-craft:typeset` | Typography pass — fonts, scale, tracking, micro-typography. | `/polish` |
| `/ui-craft:colorize` | Introduce color strategically — one accent, 3–5 placements, no decoration. | `/tokens` |
| `/ui-craft:clarify` | UX copy — button labels, error messages, empty states, CTAs. | `/critique` |
| `/ui-craft:extract` | Pull repeated patterns into shared components and tokens. | `/tokens` |
| `/ui-craft:distill` | Strip to essence. Cut every section that doesn't earn its space. Absorbs visual-weight reduction (softer type, less motion). | `/polish` |
| `/ui-craft:delight` | Add purposeful micro-interactions — copy first, animation last. | `/finalize` |
| `/ui-craft:polish` | Final pass — the compound details that turn "done" into "crafted". | `/finalize` |
| `/ui-craft:bolder` | Raise DESIGN_VARIANCE and motion amplitude — stronger composition, type, and signature without a full rebuild. | `/critique` |
| `/ui-craft:quieter` | Lower variance and motion — more restrained grids, type, and color. Honors `prefers-reduced-motion`. | `/critique` |
**Review a surface:**
| Command | Does | Next step |
|---------|------|-----------|
| `/ui-craft:heuristic` | **Signature move.** Scored critique — Nielsen 10 + 6 design laws + persona walkthroughs. Markdown scorecard with impact tags. No code changes. | fix, then `/finalize` |
| `/ui-craft:critique` | UX — hierarchy, clarity, anti-slop. No code changes. | `/polish` |
| `/ui-craft:audit` | Technical — a11y, performance, responsive. Prioritized findings table. | `/harden` |
| `/ui-craft:unhappy` | State-first pass — design every non-happy state (idle/loading/empty/error/partial/conflict/offline) before the happy path. | `/harden` |
| `/ui-craft:harden` | Production readiness — loading/empty/error states, i18n, offline, edge cases. | `/finalize` |
### Rung 2 · Persist — written once, read by every future session
| Command | Does | Next step |
|---------|------|-----------|
| `/ui-craft:brief` | Write or update the project's durable design brief at `.ui-craft/brief.md` — 5 required sections + principles workshop. Run before any net-new project. | `/tokens` |
| `/ui-craft:tokens` | Audit or establish the 3-layer token spine (primitive → semantic → component). Light and dark both intentionally crafted, not just inverted. | `/craft` |
| `/ui-craft:remember` | Record a learned design constraint into `.ui-craft/brief.md` — corrections that should persist across sessions. | keep working |
### Rung 3 · Enforce — wired once into review or CI
| Command | Does | Next step |
|---------|------|-----------|
| `/ui-craft:finalize` | Pre-ship gate. Runs the detector + brief/token check + the 10-pass finish bar + feedback hierarchy filter. Output only — no auto-fix. | ship |
The rest of rung 3 is not commands: the two review [agents](#agents), the MCP quality gates, the composite score, and `ui-craft-detect` in CI.
### Express lane
| Command | Does | Next step |
|---------|------|-----------|
| `/ui-craft:sddesign` | **Full spec-driven pipeline.** brief → tokens → shape → craft → converge → ship. Writes `.ui-craft/spec.md`. Walks rungs 1 to 3 in one run — reach for it when a surface is big enough to deserve a spec. | ship |
## Rung 0 in practice — you ask, it routes
There is no mode enum to learn. At rung 0 you describe the task and the skill's routing table decides which references to load and which pass to run.
| You say | It runs |
|---------|---------|
| "Build a pricing page" | A build pass — layout, typography, color, spacing, a11y and responsive decided together, not one at a time |
| "Add an entrance to this modal" | A motion pass — the right easing, duration and origin point |
| "Review this component" | A review pass — generic AI patterns, a11y gaps, missed details |
| "Polish this dashboard" | A polish pass — the twenty small things that turn "done" into "crafted" |
Climb to rung 1 when you would rather name the pass yourself.
## 32 domain references
| Domain | Covers |
|--------|--------|
| Craft intent | Craft Read, DESIGN_VARIANCE knob, signature bets, product + marketing build patterns, accent rotation when no brand. **Load before `/craft` or any full-surface build** |
| Dashboard recipe | Outcome blueprint: 3 named compositions (Overview / Command / Analytics), exact shell spec, build order, shippable acceptance bar. Run via `/craft dashboard` |
| Landing recipe | Marketing page compositions (product-forward / message-forward / proof-forward), section grammar, CTA hierarchy, acceptance bar. Run via `/craft landing` |
| Auth recipe | Sign-in/sign-up compositions (split panel / centered card), form contract, trust signals, acceptance bar. Run via `/craft auth` |
| Theme presets | 4 named production token stacks (Graphite, Porcelain, Carbon, Signal) — full OKLCH color, type, radius, shadow, motion; light + dark both intentional |
| Motion | Decision ladder, duration + easing token scales, interaction rules, choreography, motion budget, reduced-motion contract. Rendering performance (compositor, FLIP, scroll timelines, will-change lifecycle) |
| Layout | Spacing systems, optical alignment, layered shadows, visual hierarchy |
| Typography | `text-wrap: balance`, tabular-nums, font scale, curly quotes |
| Color | OKLCH, design tokens, dark mode, APCA contrast |
| Accessibility | WAI-ARIA, keyboard nav, focus management, touch targets |
| Modern CSS | View Transitions, Anchor Positioning, Popover, `<dialog>`, `interpolate-size`, `color-mix()`, scroll-driven, container queries |
| Responsive | Fluid sizing, mobile-first, touch zones, safe areas |
| Sound | Web Audio API, feedback sounds, appropriateness matrix |
| UX Copy | Voice / tone matrix, reading level, terminology, locale-aware strings, inclusive language, error/empty/CTA tactics |
| UI Review | Systematic critique methodology, anti-slop detection, Polish Pass |
| Dashboard | Signal-to-noise hierarchy (hero / supporting / context / deep-dive), sidebar, metric cards, data tables |
| Inspiration | Pattern archetypes from observed mature SaaS — hero archetypes, signature details by pattern type, what mature interfaces never do, reference token values |
| Brief | Durable design brief format — product purpose, primary user, 3-5 ranked principles, success metric, out of scope. Persists across sessions at `.ui-craft/brief.md` |
| Tokens | 3-layer token spine (primitive → semantic → component). Both modes intentional. 7 required categories with cross-refs |
| Finish bar | 10-pass finishing protocol with measurable criteria. Hierarchy / type system / surface stack / spacing rhythm / iconography / states / motion / microcopy / pixel honesty / data formatting |
| Principles catalog | 42 example principles across 8 product categories, seed material for the `/brief` workshop |
| Stack | Motion, GSAP, Three.js — decision tree, patterns, perf gotchas, anti-patterns (opt-in) |
| Heuristics | Nielsen's 10 + Fitts / Hick / Doherty / Cleveland-McGill / Miller / Tesler with 1-5 scoring rubric and impact framing |
| Personas | 5 archetypes (first-timer, power user, low-bandwidth, screen-reader, one-thumb) with walkthrough checklists |
| State design | Idle / loading / empty / error / partial / conflict / offline — design the unhappy path first |
| Data viz | Cleveland-McGill perceptual hierarchy, chart selection matrix, ColorBrewer + Okabe-Ito palettes, direct labeling, Tufte |
| AI / chat surfaces | Streaming contract, 7-state model, tool traces, citations, feedback affordances, generative UI, conversation layout |
| Forms | Validation timing, progressive disclosure, multi-step wizards, autosave, optimistic submit, field-specific patterns |
| Composition spec | `.ui-craft/spec.md` format — per-surface composition choice, layout skeleton, component inventory, state lattice, acceptance bar. Written by `/shape` Step 6, consumed by `/sddesign` and `/craft`. |
## Agents
Two read-only Claude Code plugin agents form the ui-craft **parallel verify team**. They complement the slash commands — they do not replace them.
| Agent | Invocation | Does |
|-------|-----------|------|
| **design-reviewer** | `ui-craft:design-reviewer` | Adversarial design critique — loads review rules, anti-slop signals, and Nielsen/design-law heuristics. Returns severity-tagged findings (Critical / Warning / Suggestion, `file:line`). No edits. |
| **a11y-auditor** | `ui-craft:a11y-auditor` | Accessibility audit — keyboard, focus-visible, APCA contrast, ARIA, touch targets, reduced-motion. Returns severity-tagged findings. No edits. |
Both agents are **read-only** (tools: Read, Grep, Glob) and run in a **fresh context**, making them suitable for dedicated review passes and PR audits where you want independent judgment uncontaminated by the build session.
### Parallel verify team
Delegate both agents simultaneously on the same diff or file for a full design + a11y sweep in one pass:
> Delegate `ui-craft:design-reviewer` and `ui-craft:a11y-auditor` together on [target]. Run both simultaneously. Each returns an independent severity-tagged findings table.
**When to use agents vs. commands:**
- **Agents** — fresh context, parallel, read-only. Best for final review passes, PR audits, and CI-style verification. Invoke as `ui-craft:design-reviewer` / `ui-craft:a11y-auditor`.
- **Commands** (`/critique`, `/audit`) — inline in the caller's context, sequential. Best for interactive build sessions where you want a quick lens mid-work.
## When to use what
UI Craft surfaces the same craft knowledge five ways. They don't compete — each fits a different moment. The two axes that decide: **does it write code?** and **is it judgment or a deterministic check?**
| Surface | What it is | Reach for it when | Writes code? | Judgment / deterministic | Runs |
|---------|------------|-------------------|:------------:|--------------------------|------|
| **The skill** (passive) | Always-on design knowledge + anti-slop, triggered by intent | You're building or editing any UI — the default | ✅ | Judgment | Inline, every harness |
| **Slash commands** | Focused single-lens passes (`/craft`, `/shape`, `/polish`, `/heuristic`, `/finalize`, …) | You want one specific pass, mid-work | Build/transform ✅ · review passes ❌ | Judgment | Inline, your session |
| **Agents** (`design-reviewer`, `a11y-auditor`) | Read-only verify team, fresh context, parallel | Final review / PR audit — you want independent judgment uncontaminated by the build session | ❌ | Judgment | Claude Code |
| **MCP tools** (`check_anti_slop`, `tokens_lint`, `acceptance_bar`, `score_ui`) | Deterministic checks an agent calls | A programmatic gate inside any MCP client, or a reproducible score | ❌ | Deterministic | MCP client / CI |
| **CLI** (`ui-craft` binary, `ui-craft-detect`, `scripts/eval.mjs`) | Installer + zero-dep scanners + UICraftScore | Install/update the system across harnesses; run quality gates in CI or git hooks | ❌ | Deterministic | Terminal / CI |
**The short version:** *taste that writes code* → the skill + commands. *Independent review, no edits* → the agents. *A check that must be identical every run* → MCP or the CLI. New to it or unsure? Run `/start` and it picks for you.
## Framework agnostic
The skill detects your project's styling approach and adapts:
- **Tailwind CSS** — uses utility classes, maps design rules to Tailwind equivalents
- **CSS Modules** — writes scoped `.module.css` files
- **styled-components / Emotion** — uses tagged templates
- **Vanilla CSS** — uses custom properties and modern features
- **SFC styles** (Vue, Svelte, Astro) — writes in `<style>` blocks
## Anti-slop
The skill actively rejects patterns that scream "AI made this":
- ~~Purple-cyan gradients~~
- ~~Glassmorphism with neon accents~~
- ~~Identical card grids~~
- ~~Bounce and elastic easing~~
- ~~Glow effects as affordances~~
- ~~Colored accent borders on cards~~
- ~~ALL CAPS headings~~
- ~~Uniform border-radius everywhere~~
- ~~Emoji as icons~~
- ~~Background gradient blobs~~
- ~~Bento grid abuse~~
- ~~Stagger-animate everything on load~~
- ~~Star ratings on testimonials~~
- ~~Generic CTAs ("Learn more", "Click here")~~
- ~~Walls of text on landing pages~~
- ~~Pure black (#000) text~~
## Canonical pipeline
Once the spine is in place, the workflow is:
```
Discovery → /brief → /tokens → build → /finalize → ship
```
The brief and tokens land as durable artifacts at `.ui-craft/brief.md` and the project's preferred token destination — they survive across sessions and anchor every subsequent design decision. Build proceeds with full reference loading via the routing table. `/finalize` runs the 10-pass finish bar before merge, gated on the brief existing.
## Project structure
```
ui-craft/
├── agents/ # 2 Claude Code plugin agents (auto-discovered)
│ ├── design-reviewer.md # Adversarial design critic — read-only, severity-tagged output
│ └── a11y-auditor.md # Accessibility auditor — read-only, severity-tagged output
├── skills/
│ ├── ui-craft/ # Main skill
│ │ ├── SKILL.md # Slim entry — knobs, discovery, anti-slop, routing
│ │ └── references/ # 32 domain references (accessibility, motion, layout,
│ │ # typography, color, modern-css, responsive,
│ │ # sound, copy, review, dashboard, inspiration, stack,
│ │ # heuristics, personas, state-design, dataviz,
│ │ # ai-chat, forms, brief, tokens,
│ │ # finish-bar, principles-catalog, spec, agents)
│ ├── ui-craft-minimal/ # Variant — Linear/Notion aesthetic
│ ├── ui-craft-editorial/ # Variant — Medium/Substack aesthetic
│ └── ui-craft-dense-dashboard/ # Variant — Bloomberg/Retool aesthetic
├── commands/ # 25 Claude Code slash commands (source of truth)
├── examples/
│ ├── animation-storyboard.md # Multi-stage animation pattern template
│ └── presets/
│ ├── playful.md # Clay / Gumroad / Duolingo / Arc aesthetic preset
│ └── brutalist.md # Swiss print / Nothing / terminal aesthetic preset
├── evals/ # Eval query sets for description optimizer
│ └── presets/ # Playful + brutalist eval JSONs (reference material)
├── scripts/
│ ├── detect.mjs # ui-craft-detect CLI (also shipped on npm)
│ └── validate.mjs # Manifest + link checker
├── .codex/skills/ # harness mirror for `npx skills add` / submodule installs
├── .cursor/skills/ # harness mirror
├── .gemini/skills/ # harness mirror
├── .opencode/skills/ # harness mirror
├── .agents/skills/ # harness mirror (generic agent-skills spec)
├── cli/assets/<harness>/ # hand-authored per-harness assets the CLI embeds + installs
├── .github/workflows/
│ └── validate.yml # Runs validator on PR + push
├── README.md
├── CONTRIBUTING.md
├── LICENSE
└── VERSIONS.md
```
## Anti-slop detection
[](https://www.npmjs.com/package/ui-craft-detect)
Scan a codebase for common AI-generated UI anti-patterns — 43 rules covering AI slop (`transition: all`, bounce easing, purple gradients, ALL CAPS headings), dark patterns (confirmshaming, destructive actions without confirmation), a11y (icon-only buttons without labels, modal-without-`<dialog>`, `outline: none` without `:focus-visible` replacement, streaming without `aria-live`, heading-level skips), forms (placeholder-as-label, missing `autocomplete`), auth tells (caps "OR" dividers, full-bleed saturated brand panels), marketing copy tells (eyebrow floods, scroll cues, numbered section eyebrows, duplicate CTA intent, em-dash floods), perf (images without dimensions → CLS), tables (no overflow handling on mobile), dataviz (categorical rainbow palettes), state design (data fetching without empty/error branches), and placeholder copy shipped to prod (`Lorem ipsum`, `TODO`, `John Doe`). Zero dependencies, works out of the box.
Published as a standalone CLI on npm — use it anywhere without cloning:
```bash
npx ui-craft-detect ./src
# or with JSON output:
npx ui-craft-detect ./src --json
```
Or from a clone of this repo:
```bash
node scripts/detect.mjs ./src
```
Exit code 0 when clean, 1 when findings — usable as a CI gate. Rules mirror the Anti-Slop Test in `skills/ui-craft/SKILL.md`.
### Diff-scoped scanning — `--scope`, `--base`, `--fail-on`
Scope findings to what a branch actually changed, so CI only flags new anti-patterns instead of the entire pre-existing codebase.
| Flag | Values | Default | What it does |
|------|--------|---------|--------------|
| `--scope` | `full` \| `files` \| `changed` | `full` | `full` scans everything (unchanged behavior). `files` reports all findings in any file touched vs the base ref. `changed` reports only findings whose line falls inside an actual diff hunk. |
| `--base <ref>` | any git ref | merge-base of `HEAD` with the default branch | Overrides the comparison ref used for `--scope files`/`changed`. |
| `--fail-on` | `none` \| `warning` \| `error` | `error` | Exit-code gate, evaluated on the scope-filtered findings only. `none` is always advisory (exit 0). `warning` fails on any surviving finding. `error` fails only on critical findings (matches pre-existing default behavior). |
```bash
# Local pre-commit-style gate: only fail on new critical issues in changed lines
npx ui-craft-detect --scope changed --fail-on error
# Compare against a specific ref instead of the default branch
npx ui-craft-detect --scope changed --base origin/develop
# Advisory mode — see scoped findings without affecting the exit code
npx ui-craft-detect --scope files --fail-on none --json
```
If git is unavailable, the directory isn't a git repository, or the base ref can't be resolved (e.g. shallow clone), the tool falls back to `--scope full` automatically and prints a note on stderr — it never crashes or silently drops findings.
### Live URL scanning
Point the detector at a deployed page instead of source files:
```bash
npx ui-craft-detect https://your-site.com
npx ui-craft-detect https://your-site.com --json --fail-on none
```
Two engines, picked automatically:
- **puppeteer** (optional — `npm install puppeteer`) loads the page in headless Chromium and scans the JS-rendered DOM, so SPA/client-rendered markup is covered.
- **fetch** (zero-dep fallback) scans the server-rendered HTML as delivered. No JS execution.
Force one with `--engine puppeteer` or `--engine fetch`. Findings report the URL as the file and line numbers within the fetched HTML document. The core detector stays zero-dependency — puppeteer is resolved via dynamic import only when present.
### Agent edit-time hooks — `hooks` subcommand
Pre-commit and CI catch problems after the fact. Agent hooks catch them **while the agent is still working** — the detector runs after every agent file edit and feeds findings straight back into the loop:
```bash
npx ui-craft-detect hooks install # both harnesses
npx ui-craft-detect hooks install --harness claude # just one
npx ui-craft-detect hooks status
npx ui-craft-detect hooks uninstall
```
| Harness | Manifest | Mechanism |
|---------|----------|-----------|
| **Claude Code** | `.claude/settings.json` | `PostToolUse` hook (matcher `Edit\|Write\|MultiEdit`). On critical/major findings the hook exits 2, so the findings summary is fed back to the model as actionable feedback — the agent fixes the slop before finishing. |
| **Cursor** | `.cursor/hooks.json` | `afterFileEdit` hook (schema version 1). Findings appear in Cursor's Hooks output channel. Committed to the repo, project hooks load for the whole team — including Cloud Agents. |
Install is merge-safe and idempotent: existing manifest entries are always preserved, re-running is a no-op, and `uninstall` removes only the detector's own entries. The hook runner scans just the edited file, stays silent on clean edits and warn-level findings, and fails open on internal errors so a broken hook can never stall an agent.
### Pre-commit hooks — `init-hook` subcommand
`ui-craft-detect` can install its own pre-commit hook with zero config.
```bash
# Auto-detect (uses husky if present, else native .githooks)
npx ui-craft-detect init-hook
# Pick explicitly
npx ui-craft-detect init-hook --native # .githooks/pre-commit (no deps)
npx ui-craft-detect init-hook --husky # .husky/pre-commit (assumes husky)
npx ui-craft-detect init-hook --github-action # .github/workflows/ui-craft-detect.yml (deprecated; use `ci install`)
npx ui-craft-detect init-hook --all # all three
npx ui-craft-detect init-hook --dry-run # preview without writing
```
The native hook scans only staged file content (via `git show :path`), so working-tree noise is ignored. Skip ad-hoc with `git commit --no-verify`. This repo's own `.githooks/pre-commit` also auto-bumps `marketplace.json` CalVer on every commit.
### CI integration — `ci install` / `ci config` / `ci upgrade`
One command sets up a full PR-feedback loop as a GitHub Action — no YAML to hand-write, no octokit dependency (it's all `gh api` under the hood):
```bash
npx ui-craft-detect@latest ci install
```
This writes `.github/workflows/ui-craft-detect.yml`, wired to:
- **Sticky PR summary comment** — one comment per PR, created on first push and edited (not duplicated) on every subsequent push, matched via a hidden marker.
- **Inline review comments** — findings are posted directly on the diff-visible lines that introduced them, scoped to `--scope changed` so pre-existing issues elsewhere in the file don't get flagged.
- **Commit status** — on pushes to the default branch (no PR context), posts a `ui-craft-detect` status with error/warning counts.
- **Minimal permissions** — `pull-requests: write` and `statuses: write` are each granted only for the steps that need them, with a one-line comment explaining why (same convention as this repo's own CodeQL workflow).
By default the workflow scans `--scope changed --fail-on error` on pull requests (`--scope full` on default-branch pushes, since a push has no PR diff to scope against).
Change settings anytime without reinstalling:
```bash
npx ui-craft-detect ci config --scope files # widen scope to whole changed files
npx ui-craft-detect ci config --fail-on warning # stricter gate
npx ui-craft-detect ci config --comment false # disable the sticky PR comment
npx ui-craft-detect ci config --inline-comments false # disable inline review comments
npx ui-craft-detect ci config --status false # disable the commit status
```
`ci config` reads and rewrites a small config marker embedded in the workflow file, so only the settings you pass change — the rest of the file (steps, permissions) is left untouched.
Bump the workflow to the latest template version while keeping your settings:
```bash
npx ui-craft-detect ci upgrade
```
`ci upgrade` compares the embedded version marker against the installed CLI version; if there's drift, it regenerates the template body and preserves your `ci config` settings exactly. If you're already current, it's a no-op.
`init-hook --github-action` still works (it's the same code path `ci install` wraps) but is deprecated in favor of `ci install`.
The `--scope`/`--fail-on` flags used above aren't CI-only — they work as plain CLI flags for local pre-commit-style gating too (see [Diff-scoped scanning](#diff-scoped-scanning---scope---base---fail-on) above).
## Design-quality score
**UICraftScore** is a deterministic 0-100 composite that turns three static-analysis signals into a single defensible grade. It gives you objective, reproducible design-quality evidence — not vibes.
**Formula:**
```
score = 100
− (antiSlop_critical × 8) − (antiSlop_major × 4) − (antiSlop_warn × 1)
− (token_findings × 2)
− (a11y_critical × 8) − (a11y_major × 4)
clamped [0, 100] · A ≥ 90 · B ≥ 80 · C ≥ 70 · D ≥ 60 · F < 60
```
Three dimensions, each with its own subscore:
| Dimension | Source | Penalty |
|-----------|--------|---------|
| **anti_slop** | 43 rules from `ui-craft-detect` | critical −8 · major −4 · warn −1 |
| **token_discipline** | Raw hex / off-scale radius / spacing / z-index | −2 per finding (flat) |
| **a11y** | 5 new static checks (no overlap with detect.mjs): `img-no-alt`, `non-semantic-interactive`, `positive-tabindex`, `aria-invalid-no-describedby`, `no-reduced-motion` | critical −8 · major −4 |
The formula, weights, and grade bands are published in `evals/quality/score.mjs` (`WEIGHTS`, `GRADE_BANDS`). Hand-authored fixtures in `evals/quality/fixtures/` and bands in `evals/quality/baselines.json` form the regression gate.
**Run the CLI benchmark:**
```bash
# Score a single file
node scripts/eval.mjs src/components/Hero.tsx
# Score a directory
node scripts/eval.mjs src/components/
# Run the full regression gate (8 fixtures — slop vs. designer separation)
node scripts/eval.mjs --baseline
# JSON output (CI-friendly)
node scripts/eval.mjs src/components/Hero.tsx --json
# Fail if score below threshold (default 70)
node scripts/eval.mjs src/components/Hero.tsx --threshold 80
```
Exit codes: `0` clean / in-band · `1` below threshold or out of band · `2` arg error.
**Score via MCP tool (`score_ui`):**
The `score_ui` tool in the MCP server exposes the same scorer to any MCP-compatible client:
```json
// Call score_ui with inline code:
{ "code": "<your tsx source>" }
// Or with a file path:
{ "path": "src/components/Hero.tsx" }
```
Returns `{ overall: { score, grade }, dimensions: { anti_slop, token_discipline, a11y }, version }` — the same envelope as the CLI `--json` output.
See [`evals/README.md`](evals/README.md) for how to run the regression gate, add fixtures, and regen baselines after rule changes.
### UsabilityScore — the judged companion
UICraftScore is deterministic, which also bounds it: static analysis can't see *experience* friction (a confusing flow, a missing undo, a 2-second save with no feedback). **UsabilityScore** covers that axis — a 0-100 score + grade rolled up from the `/heuristic` scorecard (Nielsen's 10 + 6 design laws):
```
heuristic_base = round( ((mean(nielsen_scores) − 1) / 4) × 100 ) # 10 scores, each 1–5
UsabilityScore = clamp( heuristic_base − 5 × (failed design laws) , 0 , 100 )
Same bands as UICraftScore: A ≥ 90 · B ≥ 80 · C ≥ 70 · D ≥ 60 · F < 60
```
It is **judged, not deterministic** — computed by the host agent from the rubric (zero deps, no API key, works in any harness), so it may vary run to run. **Gate CI on UICraftScore; use UsabilityScore for review depth.** The two render side by side in an *extended report* and are deliberately **never averaged** — that would hide which number is reproducible. Run it with `/heuristic <path>`; rubric + formula live in [`heuristics.md`](skills/ui-craft/references/heuristics.md).
## MCP Server
[](https://www.npmjs.com/package/ui-craft-mcp)
The `ui-craft-mcp` package exposes seven deterministic tools over the [Model Context Protocol](https://modelcontextprotocol.io/) (stdio transport). Works with Claude Desktop, Cursor, and any MCP-compatible client.
**Boundary:** the MCP server is the **checks layer** — deterministic, rule-based, identical output for identical input. The `SKILL.md` is the **taste layer** — judgment, aesthetics, architectural decisions. These never overlap.
| Tool | What it does |
|------|-------------|
| `route_task` | Routes a natural-language prompt to the references, commands and tools that cover it, plus the first move — pointers only, never rules |
| `check_anti_slop` | 43-rule anti-slop scanner via `scan()` from `ui-craft-detect` — in-process, no subprocess |
| `tokens_lint` | Off-system token detector: raw hex colors, non-scale radius/spacing px, magic z-index |
| `acceptance_bar` | Acceptance checklist for a UI surface (`dashboard`, `landing`, `auth`, `generic`) — data only, no scoring |
| `score_ui` | Composite UICraftScore (0-100 + grade + per-dim subscores) via `evals/quality/score.mjs` — all three dimensions in one call |
| `fold_candidates` | Draws landing-fold composition classes, preferring ones the project has not spent |
| `check_fold` | Renders a URL and reports what its fold actually is — screenshot, class, drift, invariants |
**Why `route_task` exists:** the routing table in `SKILL.md` only fires when your words match our filenames. Ask for "an analytics panel" and nothing points at `recipe-dashboard.md`, because that file never says analytics. A synonym map fixes a vocabulary mismatch a table cannot, and recipes are indexed by what they *contain*, so "pricing block" reaches the landing recipe.
**Quick start:**
```bash
# Wire the manifest-pinned release into your project's .mcp.json:
{ "mcpServers": { "ui-craft": { "command": "npx", "args": ["-y", "ui-craft-mcp@0.9.0"] } } }
```
See [`mcp/README.md`](mcp/README.md) for full install, tool docs, and the `acceptance-data.json` regen note.
## Maintaining harness assets
The canonical skill content lives in `skills/` (main skill + variants) and `commands/` (the slash-command lenses). Two consumers ship that content:
- **CLI (`ui-craft install`)** — per-harness assets are hand-authored under `cli/assets/<harness>/` (claude, cursor, codex, gemini, opencode) and compiled into the binary via `go:embed`. Command-capable harnesses (Claude Code, OpenCode) receive real `commands/*.md`; skills-only harnesses (Cursor, Codex, Gemini) receive each lens as a flat depth-1 peer skill. The embedded tree is also the uninstall manifest — cleanup removes exactly what it installed.
- **`npx skills add` / git submodule** — the repo-root mirror dirs (`.codex/`, `.cursor/`, `.gemini/`, `.opencode/`, `.agents/`) serve those install paths.
### Canonical quality gate
Before publishing or opening a PR, install the MCP development dependencies once with `npm ci --prefix mcp`, then run:
```bash
pnpm verify
```
This non-fail-fast gate runs distribution-contract checks, plugin/link validation, every mirror drift guard, detector and quality suites, MCP source and bundled smoke tests, plus Go tests, vet, and formatting. `pnpm verify:list` prints the suite IDs; a focused rerun can use `pnpm verify -- --suite=<id>`. Component versions and immutable launch specs live in the machine-readable [`distribution-manifest.json`](distribution-manifest.json).
When you change a skill or command, edit the canonical source under `skills/` + `commands/` and then regenerate every copy:
```bash
npm run sync # skills/ + commands/ → cli/assets/ + repo-root mirrors
npm run check:mirrors # the drift guard CI runs (fails on any stale mirror)
```
CI does not regenerate mirrors — `scripts/check-mirror-copies.mjs` only fails the build when one drifts, so run the sync before you push.
## Tuning skill descriptions
Every skill's `description` field is the primary trigger mechanism. The `evals/` folder holds query sets for `skill-creator`'s description optimizer (`run_loop.py`), which evaluates and iterates descriptions against realistic should-trigger / should-not-trigger prompts. See `evals/README.md` for the commands and how to add new eval sets.
## Roadmap
Where ui-craft is heading. Not commitments with dates — a public list of the directions we consider worth building, roughly ordered by how much they'd raise output quality. Feedback and PRs on any of these welcome.
**Design-tool integration**
- **Figma spec compliance** — read component specs (spacing, type, color, variants) via Figma's Dev Mode / REST API and score an implementation against them, the same way the detector scores anti-slop today. "Does the built component match the design?" becomes a deterministic gate instead of eyeball review.
- **Design-token import** — pull a token set from Figma variables / Tokens Studio / a `design-tokens.json` and emit the project's 3-layer spine (`/tokens`) from it, instead of hand-transcribing values.
**Detector**
- **Computed-style checks for URL scans** — the URL engine currently scans rendered markup; the next layer is computed styles via the browser engine: real contrast ratios (not class-name heuristics), effective tap-target sizes, actual font fallback chains.
- **Screenshot-diff regression (exploratory)** — likely as a thin integration over existing visual-regression tooling (Playwright snapshots / Chromatic-style diffs) rather than a bespoke engine.
- **More harnesses for edit-time hooks** — `hooks install` covers Claude Code and Cursor today; extend to other agents as their hook mechanisms stabilize.
**Skill & pipeline**
- **Reference-board step** — optional pre-build step that generates or collects visual references (mood board, type specimens, palette candidates) before the Craft Read, for briefs where the direction is genuinely open.
- **Multi-page consistency** — today's recipes reason about one surface at a time; a site-level pass would enforce shared rhythm, type scale, and CTA vocabulary across pages.
- **UsabilityScore trend tracking** — persist `/heuristic` and UICraftScore results per commit so quality is a curve you watch, not a snapshot.
**Evals**
- **Automated blind-build harness** — run the `evals/craft-quality/PROMPTS.md` tracks through an agent automatically and score the output, turning today's manual auditor pass into a repeatable regression suite.
Have a strong opinion on priority, or something missing? [Open an issue](https://github.com/educlopez/ui-craft/issues).
## Contributing
Spotted a new AI-generated pattern that should be in the anti-slop list? Have a craft rule from a product you admire? Want to add a new reference domain? PRs and issues welcome.
See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines on adding rules, improving references, or proposing new domains.
## Author
[Eduardo Calvo](https://x.com/educalvolpz)
## License
[MIT](LICENSE) — use it however you want.