Design intelligence engine for AI coding tools (Claude Code, Cursor, Windsurf). Deterministic anti-AI-slop linter with 152 rules, 160 brand specs, a 7-axis synthesizer, an MCP server (18 tools), 25 commands, 17 IDEs. Offline, never calls an LLM. MIT.
翻译准备中
取自仓库 README
正在加载完整 README。 以下为已保存的摘录。
ux-skill: the design intelligence engine for Claude Code, Cursor, and every other AI coding tool
A design-intelligence engine that makes AI-generated UI distinctive instead of generic. Drop it into any of 17 AI coding tools and your output stops reading as AI-built. Free, MIT, offline, no LLM.
Star ux-skill on GitHub if this is useful, it is the single cheapest way to help the project. New here? Start with the 60-second tour or see it live at uxskill.laithjunaidy.com.查看完整 README ↗English · العربية · 简体中文 · 繁體中文 · 日本語 · 한국어 · हिन्दी · Bahasa Indonesia · Tiếng Việt · ไทย · Français · Deutsch · Español · Português · Italiano · Русский · Türkçe
A design-intelligence engine that makes AI-generated UI distinctive instead of generic. Drop it into any of 17 AI coding tools and your output stops reading as AI-built. Free, MIT, offline, no LLM.
pip install uxskill
Star ux-skill on GitHub if this is useful, it is the single cheapest way to help the project. New here? Start with the 60-second tour or see it live at uxskill.laithjunaidy.com.
Before: generic stock-photo SEO slop. After: real construction-photo hero under a dark scrim, editorial headline with an amber accent, quote form in the hero. Same AI coding tool, same prompt, different result when ux-skill supplies the constraints.
v4.0, FOUNDATIONS: one command builds a complete, WCAG-gated design system, with Arabic and right to left built in. The strongest UX plugin for AI coding. A Python reasoning core with a deterministic 7-axis synthesizer, 12 queryable JSON manifests (84 styles, 176 palettes, 70 type pairings, 148 components, 184 industries, 35 chart types, 57 motion presets, 112 UX laws, 171 anti-pattern rules, 25 tech stacks, 160 brand specs), 18 slash commands, 5 sub-agents, 25 MCP tools, and a deterministic anti-AI-slop linter. Cross-IDE: ships into Claude Code, Cursor, Windsurf, GitHub Copilot, Gemini CLI, Codex, Kiro, Cline, Continue, Aider, Zed, JetBrains AI, Pieces, Tabby, Tabnine, CodeWhisperer, and Roo Cline.
The brand name is
ux-skill. The PyPI / npm package name staysuxskill. The GitHub repo lives atLaith0003/ux-skill.
Author: Laith Aljunaidy, designer and CTO in Amman · Site: uxskill.laithjunaidy.com · Compare vs every Claude UX plugin: compare.html · GitHub: Laith0003/ux-skill · PyPI: uxskill · npm: uxskill
One brand color in, a design system out, with its contrast checked before you get it.
pip install --upgrade uxskill
uxskill system build --brand '#3366FF' --brief .ux/last-discovery.json --out design-system
Python 3.10 or newer. For the MCP server, pip install --upgrade 'uxskill[mcp]'. With pipx, pipx install uxskill (over an installed 3.x, pipx upgrade uxskill). With npm, npx uxskill@latest. Coming from 3.x? The migration guide maps every 3.x token to its 4.0 role.
Building a product or a landing page? You get tokens.css to link from your page, fonts.css with metric-matched fallbacks for the chosen faces, fonts-self-host.css that loads the faces from your own files, tokens.json for tools, decorative brand art in art/, and system-report.md, which says in plain words what was built, why, and which page composition to start from. Style with the roles (var(--color-action-primary), var(--color-text-default), var(--color-surface-page)), and switch dark mode, high contrast, compact spacing, right to left or reduced motion with one attribute on <html>. Load the faces with the Google Fonts link the report gives, or with fonts-self-host.css and a fonts/ folder, and link fonts.css with either one, before tokens.css; edit neither file. With --brief, the look follows the industry and tone when the brief names them, and structured fields (age, languages, default scheme, reading context) set text size, targets, scripts and which scheme opens; discovery does not ask for an industry, so /ux-system create asks for one. In Claude Code, /ux-system create checks the installed version, runs the build and explains the report.
Designing a design system? Nine foundations (color, type, space, layout, radius, border, elevation, motion, imagery), each varying continuously with the seven axes, with primitives and semantic roles, in the W3C design tokens format (DTCG 2025.10) with every mode's values. Same inputs, same bytes. Over MCP, ux_system_build returns the report, the gate result and each file's size, and writes the same files as the command when given out.
--force replaces files only when you ask.dir="rtl" text switches to an Arabic face with its own sizes and line height; spacing uses logical properties and motion mirrors. --latin-only leaves it out.A system you already have. /ux-system enhance --from reads it in its own names (DTCG tokens, CSS custom properties, a Tailwind theme, markdown rule files or a Figma variables export), checks it through the same gate and measures what your code actually does with it; nothing is rewritten. /ux-system extend --from adds foundations, roles or contracts without changing a token it has, in an extension file beside it, and uxskill system export writes it as tokens.css, a Tailwind 4 theme or Figma variables. 4.2 adds the trust layer (lint on every write, a finish reviewer) and the launch. See the changelog.
Components and sections. 23 component contracts say which tokens each part of a control binds in every state and how each state moves: a change of state transitions on motion.state, a press scales on motion.press.scale (and holds still under reduced motion), and tabs, menus and segmented controls slide one indicator. 14 section contracts (hero, pricing, FAQ, footer and the rest) name each section's job, the components its slots take, the proof it needs and how it stacks on a phone. Pages built from them use photographs; interface fragments are extra imagery, never a replacement.
A linter that reads the page. 171 rules, many with a check on the parsed CSS and markup, read the page's own system: motion is timed from its curve, display line height is held to the engine's floor, and a hidden control must leave the tab order. uxskill lint --render opens each page in headless Chromium at desktop and phone width and drives it: focus rings that do not show or are clipped, hover and press that answer late, focus lost after Escape, and a press that still moves under reduced motion.
Fewer commands. 25 slash commands become 18. /ux-discover takes --frame and --recommend, /ux-design takes --component, --dashboard and --from-image, /ux-polish loops lint, fix, re-lint until the score reaches 90 or three rounds pass, and /ux-init takes --stats. The seven old names still work as aliases and go away in 4.1; see the aliases.
Surface playbooks. Landing, dashboard and component rules live in references/surfaces/, one playbook each. /ux-design loads exactly one, picked by its mode, so a dashboard build never reads hero rules.
Tests 13101 passing. Offline. Deterministic. No LLM ever called.
recommend -> synthesize, and a hard floor in evaluate FAILS any output that drops the brand color/logo or ships no real imagery. Two-way interop with the open brand.md convention (render + ingest).responsive.md, component-behaviors.md) plus a wrap-aware gate that fails on horizontal scroll, a wrapping nav/wordmark/button label, or an over-tall sticky header.100vw rules; seeded picsum kept, random stripped.Full notes in CHANGELOG.md.
strict_brand (100% of one brand), brand_anchor (70% one brand + 30% axis-adapted siblings), pure_synthesis (no brand named, distill from 8 axis-matching exemplars)..ux/decisions.jsonl re-ranks candidates by past wins in the same (industry, ui_type) bucket. Cold-start safe. Counts only lint_score >= 80 + user_accepted = true decisions./ux-evolve auto-loop (in 4.0, the default loop of /ux-polish): lint → polish → re-lint until score ≥ 90 or plateau or 3 rounds in 4.0 (5 in v3). Quality gate at 65.ux_synthesize, ux_decisions_query, ux_decisions_stats.uxskill stats --html writes .ux/stats.html showing what YOUR install has learned. No telemetry, no global aggregate.Full details in CHANGELOG.md.
ux-skill is a design intelligence engine for AI coding tools. It runs as a Python package (pip install uxskill), as a Claude Code plugin, and as a 17-IDE multi-installer. The engine ingests a project brief (industry, audience, tone, must-haves, forbidden moves, stack, region) and returns a complete recommended design system: style, palette, type pair, motion presets, components, brand exemplars to study, and the anti-pattern guardrails that must hold. The recommendation is deterministic, same input always produces the same output.
The plugin sits between you and the AI coding tool. When you ask Claude Code, Cursor, or any other AI assistant to "build a fintech landing page," the assistant typically improvises, and the result reads as AI-generated within five seconds (purple-to-blue gradients, three equal cards, Inter at display size, "John Doe" in testimonials, 300ms default transitions, centered hero, bouncing arrow CTAs). ux-skill replaces improvisation with structured constraints: you run /ux-discover to capture the brief and pick the system, /ux-design to generate the code, and /ux-lint to verify it passes the 171 deterministic anti-AI-slop rules before commit.
This README is the canonical reference. Every command, every sub-agent, every data manifest, every install path, every brand spec, every anti-pattern category, it's all documented here. If you're shopping for a Claude Code design plugin or comparing AI design tools for Cursor, Windsurf, or Codex, read this top to bottom and the compare.html side by side.
v3.0.0 is the biggest architectural shift in ux-skill's history. The recommender no longer picks templates from a catalogue, the engine synthesizes a fresh design language per brief. Same brief always yields the same output (fully deterministic), but every distinct brief gets its own novel system. Brand specs aren't templates anymore; they're training data the engine learns the vocabulary from. The system has eyes on its own history, closes the feedback loop locally, and never calls an LLM.
The compiler is a deterministic 7-axis synthesizer, warmth, contrast, density, geometry, formality, motion, type_personality. Every brief maps to axis values; axis values compile to fresh palette + type + spacing + radius + motion tokens. Modular type scales pick their ratio from contrast (1.200 quiet / 1.250 balanced / 1.333 loud). Layout primitives are responsive by construction (auto-fit minmax(min(N, 100%), 1fr) + container queries). Broken layouts can't be emitted because they aren't representable.
There are three auto-dispatched modes: strict_brand (reference_brands=[stripe] strict=True → 100% Stripe tokens, fastest path); brand_anchor (reference_brands=[stripe] → 70% Stripe + 30% axis-adapted from 4 sibling brands); and pure_synthesis (no brand named → infinity space, 8 axis-matching exemplars distilled into a novel design language). Conflicting axes are resolved by a documented axis interaction matrix, dense + corporate compiles to 4px (density wins, Bloomberg-school), airy + corporate to 12px (formality wins, luxury), soft + playful to 18px radius, sharp + corporate to 2px. No silent ad-hoc rules in the implementation.
The decisions ledger (.ux/decisions.jsonl, schema _v: 1 locked) closes the feedback loop. The recommender now re-ranks candidates by past wins in the same (industry, ui_type) bucket. Cold-start safe, it skips below 3 priors. It only counts decisions with lint_score >= 80 AND user_accepted = true. Plus /ux-polish runs lint → polish → re-lint until score ≥ 90 or plateau or 3 rounds, with a 65-score quality gate below which output is refused unless --force. The result: every install gets smarter on its own corpus, every run is reproducible across machines, and the engine stays fully offline.
Three install paths. Pick the one that matches your environment.
If you live in Claude Code, install via the plugin marketplace:
/plugin marketplace add Laith0003/ux-skill
/plugin install ux@ux-skill
That wires all 18 slash commands (plus 7 old names kept as aliases until 4.1) and 5 sub-agents into your Claude Code session. After install, run /ux-init to set up the per-project .ux/ state directory and verify the Python engine is reachable.
If you live outside Claude Code (Cursor, Windsurf, CLI, CI), install the Python package:
pip install uxskill
uxskill init # auto-detects your IDE, installs the right artifact
uxskill stats # print manifest counts to verify install
uxskill lint . # run the linter against the current directory
The package exposes both ux and uxskill as CLI entry points, they're the same binary.
If you don't want to manage Python directly, the npx wrapper bootstraps everything via pipx:
npx uxskill init # downloads pipx + uxskill on first run
npx uxskill recommend --industry=fintech-neobank --tone=warm --stack=nextjs-15-app-router
ux stats
# {
# "version": "4.0.0",
# "counts": {
# "styles": 84,
# "palettes": 176,
# "type-pairs": 70,
# "components": 148,
# "industries": 184,
# "chart-types": 35,
# "tech-stacks": 25,
# "ux-guidelines": 112,
# "motion-presets": 57,
# "anti-patterns": 171,
# "landing-patterns": 40,
# "brands": 160
# }
# }
The twelve counts add up to 1,262 entries. If any count returns 0, the JSON file is missing, open an issue at github.com/Laith0003/ux-skill/issues.
Star counts last verified via gh api on 2026-05-28. ux-skill (Laith0003/ux-skill) is the newest entrant, we're tiny on awareness, deep on architecture. The comparison below is honest: where we lose, where we win.
| Plugin | Stars | Architecture | Slash commands | Linter (CI-safe) | Brand specs | Components | Motion presets | IDEs supported |
|---|---|---|---|---|---|---|---|---|
| nextlevelbuilder/ui-ux-pro-max-skill | 83,958 | Python BM25 + CSV, single skill | 1 | - | , | 0 | 0 | 18 |
| nexu-io/open-design | 54,406 | Node.js + 19 skills + preview | 19 | - | , | 0 | 0 | 1 |
| Leonxlnx/taste-skill | 25,202 | Bash + research-backed taste | 1 | - | , | 0 | 0 | 1 |
| alchaincyf/huashu-design | 15,455 | Single 62 KB SKILL.md + scripts | 1 | - | , | 0 | 0 | 1 |
| google-labs-code/stitch-skills | 5,762 | MCP-wired skill library | multi | - | , | 0 | 0 | 1 |
| dominikmartn/nothing-design-skill | 2,391 | Single-aesthetic skill | 1 | - | , | 0 | 0 | 1 |
| Nutlope/hallmark | 2,164 | Anti-slop design skill | 1 | - | , | 0 | 0 |
Full table-by-table side-by-side at uxskill.laithjunaidy.com/compare.html.
ux-skill (package name: uxskill)
│
├── data/ The brain, queryable JSON manifests
│ ├── styles.json 84 design styles + when/skip + tokens
│ ├── palettes.json 176 palettes (light/dark, contrast verified)
│ ├── type-pairs.json 70 display × body × mono triplets
│ ├── components.json 148 components (anatomy, states, motion)
│ ├── industries.json 184 industry rules + audience signals
│ ├── chart-types.json 35 chart types (when/skip, encoding)
│ ├── tech-stacks.json 25 stacks (Next, Astro, SvelteKit, Blade...)
│ ├── ux-guidelines.json 112 named UX laws (Hick, Fitts, Miller...)
│ ├── motion-presets.json 57 motion presets (entry, exit, hover...)
│ ├── anti-patterns.json 171 rules (CI-safe linter source)
│ └── brands/*.json 160 brand DESIGN specs + _index.json
│
├── engine/ Python, the reasoning
│ ├── synthesizer/ v3-7-axis deterministic compiler
│ ├── decisions/ v3, .ux/decisions.jsonl ledger + recommender re-rank
│ ├── recommender/ 5-parallel-search merge engine (re-ranked by decisions)
│ ├── linter/ Deterministic anti-slop scanner
│ ├── discovery/ 10-field forcing protocol
│ ├── generator/ Token + manifest emitter
│ ├── installer/ 17-IDE multi-installer
│ └── cli/ `ux` / `uxskill` entry point
│
├── commands/ 18 Claude Code slash commands (.md) + 7 aliases
│ ├── ux-init.md bootstrap + inventory snapshot (--stats)
│ ├── ux-discover.md 10-field intake (gate), --frame, --recommend
│ ├── ux-lint.md deterministic linter
│ ├── ux-design.md generate a page, --component, --dashboard, --from-image
│ ├── ux-system.md generate full design system
│ ├── ux-motion.md motion treatment + audit
│ ├── ux-audit.md 6-lens design audit
│ ├── ux-a11y.md WCAG 2.1 AA audit
│ ├── ux-critique.md taste critique (3 wins, 3 misses, 1 move)
│ ├── ux-copy.md microcopy review + rewrite
│ ├── ux-fix.md apply findings as atomic commits
│ ├── ux-polish.md lint, fix, re-lint loop + taste pass
│ ├── ux-research.md research planning + synthesis
│ ├── ux-workshop.md 5-phase design thinking workshop
│ ├── ux-case-study.md publishable monochrome editorial case study
│ ├── ux-next.md workflow conductor (read-only)
│ ├── ux-expert.md consulting hook
│ ├── ux-mcp.md MCP server
│ └── ux-frame.md, ux-recommend.md, ux-stats.md, ux-evolve.md,
│ ux-component.md, ux-dashboard.md, ux-image-to-code.md
│ aliases, removed in 4.1
│
├── agents/ 5 sub-agents (.md)
│ ├── frontend-engineer.md React/Next/Vue/Blade/Astro
│ ├── motion-engineer.md Framer Motion / GSAP / CSS
│ ├── copy-writer.md microcopy in brand voice
│ ├── research-synthesizer.md interviews + analytics + competitors
│ └── design-system-architect.md tokens / components / foundations
│
├── references/ Prose source for the data + demo pages
│ ├── foundations/ anti-patterns.md, principles, taste
│ ├── laws/ UX laws long-form
│ ├── process/ discovery-protocol.md (load-bearing)
│ ├── styles/ per-style prose (anti-slop.md, etc.)
│ ├── components/ component long-form
│ ├── output/ output rubrics
│ └── conditional/ stack-specific guidance
│
├── bin/
│ ├── uxskill.mjs npx wrapper -> Python engine
│ ├── ux-lint.py v2 linter (preferred)
│ └── ux-lint.sh v1 fallback (bash + perl-PCRE)
│
└── .ux/ (created per project)
├── last-discovery.json brief snapshot
├── last-recommendation.json picked system
├── last-frame.json framing block
├── last-audit.json / last-a11y.json / last-copy.json / last-motion.json
├── last-design.json / last-component.json / last-dashboard.json
└── last-critique.json / last-polish.json / last-research.json / last-workshop.json / last-case-study.json
/ux-discover (10 fields) or non-interactively via flags to ux recommend./ux-design in its page, component, dashboard and image modes, and /ux-system) consume the recommendation to generate actual code via the sub-agents./ux-lint re-scans the generated code against the 171 rules. Exits non-zero on Critical/High in CI.v3 additions. The recommender now re-ranks candidates from engine/decisions/ using .ux/decisions.jsonl (only counts decisions with lint_score >= 80 AND user_accepted = true; cold-start safe below 3 priors). The generator path can dispatch into engine/synthesizer/, a deterministic 7-axis compiler that produces fresh palette + type + spacing + radius + motion tokens per brief instead of picking templates from a catalogue. See The Brain, what v3.0 is for details.
Python thinks. HTML shows. Markdown chains.
Every command is shipped as a .md file under commands/ with description, allowed-tools, triggers, when to use, when to skip, input, process, and output state file. The descriptions below are condensed; the full source is the canonical spec.
Commands are grouped into seven buckets: bootstrap & inventory, discovery & recommendation, generation, audit & verify, fix & polish, discovery & narrative, and conductor. Seven 3.x names still work as aliases until 4.1.
/ux-init: bootstrap the project.claude/, .cursor/, .windsurf/, etc.), installs the right artifact, verifies the Python engine is reachable, prints a stats snapshot. --stats prints only the snapshot: version + entry counts for the data manifests.pip install --upgrade uxskill. --stats after install, after upgrade, or when a recommendation returns surprising picks and you suspect the manifests are incomplete.--stats never needs skipping: it's a 50ms read./ux-init (no args), /ux-init --stats, or uxskill init / uxskill stats from the CLI. --decisions adds the decisions ledger summary; --html writes .ux/stats.html..ux/ directory + stdout summary. --stats: JSON to stdout (see Verify install above)./ux-discover next. --stats is diagnostic only./ux-mcp: run the engine as an MCP serveruxskill recommend or uxskill lint is simpler./ux-mcp, or ux-mcp from the shell after pip install 'uxskill[mcp]'.commands/ux-mcp.md for per-client config./ux-discover: the forcing function (10-field intake, framing, recommendation)--frame captures who-it's-for, outcome, hypothesis, and success signal in a four-field framing block, lighter than the full intake. --recommend runs only the recommender, from a saved brief or one-shot flags./ux-design or /ux-system. Whenever a previous brief has gone stale. --frame at the start of a project, sprint, or one-off engagement, or mid-stream when a conversation has drifted. --recommend when pivoting a tired-looking product./ux-fix). You're only running a linter pass (/ux-lint). The brief is unchanged from the last session./ux-discover, /ux-discover --frame "loyalty wallet for a MENA retail pilot", or /ux-discover --recommend.
Invocation (CLI):
ux recommend \
--project-type=landing \
--industry=fintech-neobank \
--tone=warm --tone=editorial \
--must-have=dark-mode --must-have=a11y-AA \
--forbidden=brutalism --forbidden=purple-gradients \
--stack=nextjs-15-app-router \
--region=mena
.ux/last-discovery.json (the 10-field brief), .ux/last-recommendation.json (picked style, palette, type pair, top 5 motion presets, top 12 components, top 5 brand exemplars, all 171 anti-pattern guardrails active, plus rationale), and with --frame, .ux/last-frame.json ({audience, outcome, hypothesis, success_signal})./ux-design [extra brief] → frontend code grounded in the recommendation. /ux-design --component <name> → one component aligned to the discovered constraints. /ux-system → full design system from the recommendation. /ux-lint → verify the generated code./ux-design: generate a beautiful, anti-slop surface from a brieffrontend-engineer with creative direction from anti-slop and arsenal references. The brief, or a flag, picks one of four modes:
.ux/last-design.json.--component [name]: a single, production-grade component (button, modal, navbar, sidebar, card, table, form, chart). All four interaction states, accessible, on-brand. Looks up the component in .ux/last-recommendation.json first, falls back to direct manifest query. Writes .ux/last-component.json.--dashboard: data density discipline, bento layout, tabular monospace numerals, sparkline patterns, anti-card-overuse, semantic state colors, sparing motion. Not a marketing site with charts pasted on. Writes .ux/last-dashboard.json.--from-image <path>: reads a design reference image (PNG/JPG/WebP) with pure Pillow CV (dominant palette, canvas polarity, type signal), matches it against the palettes and styles manifests, and builds from the resulting recommendation. --extract-only stops after the extraction. Writes .ux/last-image-extract.json./ux-audit or /ux-critique). Backend or infrastructure work./ux-design generate a fintech landing for a MENA neobank, warm editorial tone, dark-mode AA, no purple gradients, /ux-design --component pricing-card-trio --brief="fintech, dark, monospace numbers", /ux-design --dashboard, /ux-design --from-image ref.png./ux-lint → verify against guardrails. /ux-polish → cosmetic pass. /ux-a11y → accessibility audit. /ux-copy → microcopy review. /ux-fix → apply findings as atomic commits./ux-system: generate a complete starter design systemdesign-system-architect./ux-design --component against the existing system instead. Backend or infrastructure./ux-system create (the foundations engine), /ux-system enhance --from <file> (measure a system you already have), /ux-system extend --from <file> --add <foundation> (add to it without changing it), or /ux-system (the 3.x flow; runs discovery first if not already on file).tokens.json, foundations.md, components/*.md contracts, optional Tailwind / vanilla / SCSS emit. Writes .ux/last-system.json for chain context./ux-design --component → build against the new system. /ux-design → generate a surface using the new tokens./ux-motion: motion treatment/ux-audit or /ux-polish). Backend or infrastructure./ux-motion path/to/component.tsx (audit mode) or /ux-motion --generate hero-entry (generation)..ux/last-motion.json report (in audit mode)./ux-fix → apply motion findings. /ux-polish → tighten./ux-lint: deterministic regex-based linter (no LLM, CI-safe)data/anti-patterns.json. Rules cover A11y (45), Content (35), Layout (18), Typography (16), Motion (14), Visual (14), Quality (12), Color (10), Performance (5), Depth (2)./ux-audit. After /ux-design in any mode to verify generation./ux-polish --fix or /ux-fix). You want taste judgment (use /ux-critique)./ux-lint src/.uxskill lint . or python3 bin/ux-lint.py . or bash bin/ux-lint.sh --ci --fail-on high.- name: ux-lint
run: bash bin/ux-lint.sh --ci --fail-on high
--fail-on high is set./ux-polish --fix → LLM-driven counterpart on the same patterns. /ux-fix → apply findings as commits, severity-sorted. /ux-audit → full 6-lens reasoning pass. /ux-next → let the conductor decide./ux-audit: 6-lens design audit.ux/last-frame.json first, audience and outcome anchor every finding's severity./ux-design). User wants one lens (use the targeted command: /ux-a11y, /ux-copy, /ux-motion, /ux-polish). User wants taste opinion (use /ux-critique). Backend or infrastructure./ux-audit https://example.com/pricing or /ux-audit src/components/Pricing.tsx..ux/last-audit.json, findings array of {lens, severity, title, principle, evidence, fix}, severity_counts, dominant_lens, strategic_moves./ux-fix → apply findings. /ux-polish → cosmetic pass. /ux-design → if structural redesign needed./ux-a11y: WCAG 2.1 AA audit + common-courtesy checks/ux-a11y https://example.com (live URL preferred, automated tools and keyboard testing only work live)..ux/last-a11y.json, findings array of {wcag_sc, sc_name, severity, title, evidence, fix, category}, beyond_wcag array, severity_counts./ux-fix → apply findings as commits. /ux-copy → fix alt text and form-error wiring as part of a copy pass./ux-critique: taste call (3 wins, 3 misses, 1 strategic move)/ux-audit). Backend or infrastructure./ux-critique https://example.com..ux/last-critique.json, 3 wins, 3 misses, 1 strategic move, plus prose./ux-design if the take recommends redesign. /ux-polish if the take recommends tightening./ux-copy: microcopy review + rewrite/ux-audit or /ux-polish). Accessibility-driven copy issues like alt text (use /ux-a11y). Backend or infrastructure./ux-copy src/views/checkout.blade.php..ux/last-copy.json, strings array of {location, severity, before, after, notes}, plus rubric + locales needing translation./ux-fix → apply rewrites. /ux-a11y → re-check after copy fixes./ux-fix: apply findings as atomic commits.ux/ (audit, copy, a11y, motion, or polish), validates the working tree, and applies findings as atomic commits via the right sub-agents. Re-verifies by re-running the originating command..ux/. Working tree is dirty and the user hasn't agreed to stash/commit. Fixes need design judgment, not mechanical application (use /ux-design for a redesign)./ux-fix (auto-detects which report to fix) or /ux-fix --from=last-a11y.json..ux/last-*.json file. Prints a summary./ux-next → conductor picks the next move./ux-polish: lint, fix, re-lint loop + AI-slop kill--rounds changes the cap). By default the loop output stays at <file>.evolved.html and the original is never touched. Only --loop-only or --fix replace the original, after a clean-tree check, and a quality gate at 65 keeps a failing result from replacing it unless --force; with --brand-file the brand-fidelity floor holds at every exit. Then the taste pass: spacing rhythm, hierarchy sharpening, AI-slop detection, token consistency. The LLM-driven counterpart to /ux-lint, uses your judgment on taste calls. --loop-only runs just the loop; --no-loop just the taste pass; --fix applies the taste findings./ux-design). Copy issues (use /ux-copy). Motion issues (use /ux-motion). A11y issues (use /ux-a11y)./ux-polish src/components/Hero.tsx, /ux-polish out/landing.html --css out/landing.css, /ux-polish out/landing.html --loop-only --rounds 5.<file>.evolved.html from the loop (promoted over the original only under --loop-only or --fix), updated code under --fix, .ux/last-evolve.json, one line in .ux/decisions.jsonl, and .ux/last-polish.json describing the taste findings./ux-lint → verify the polish held. /ux-a11y → re-check accessibility./ux-research: research planning + synthesis--synthesize): digests interviews, analytics, competitor sites, A/B results, support tickets into recommendations. Dispatches research-synthesizer./ux-research --plan "loyalty wallet adoption in MENA" or /ux-research --synthesize interviews/*.md..ux/last-research.json, research plan or synthesized themes + evidence + recommendations./ux-discover --frame → integrate findings into a frame. /ux-design → generate from findings. /ux-workshop → run a workshop using the research as input./ux-workshop: 5-phase design thinking workshop/ux-design or /ux-discover --frame). Team is mid-execution, not in discovery./ux-workshop "loyalty wallet pivot" --participants="2 PMs, 1 designer, 1 eng lead, 1 customer rep" --minutes=90..ux/last-workshop.json, game plan + per-phase artifacts./ux-design → execute the game plan. /ux-research → fill gaps the workshop surfaced. /ux-case-study → publish the journey./ux-case-study: publishable case study (monochrome editorial format).ux/last-frame.json, .ux/last-workshop.json, .ux/last-research.json, .ux/last-design.json, .ux/last-a11y.json, .ux/last-polish.json, .ux/last-recommendation.json, .ux/last-discovery.json./ux-design)./ux-case-study --format=html --slug=northwind-loyalty.case-studies/<slug>.<ext> + .ux/last-case-study.json./ux-next: workflow conductor (read-only).ux/last-*.json and names the highest-leverage next command. A conductor, not a builder. Read-only..ux/. You have a specific next command in mind./ux-next (no args) or /ux-next --focus=a11y./ux-expert: consulting hook/ux-expert.Seven 3.x commands merged into the 18 above. Their names still work for one release: each alias says where it moved, then runs the new command with the same arguments.
| Old command | Now | Notes |
|---|---|---|
/ux-frame | /ux-discover --frame | Same framing block, same .ux/last-frame.json |
/ux-recommend | /ux-discover --recommend | The ux_recommend MCP tool is unchanged |
/ux-stats | /ux-init --stats | Read-only snapshot |
/ux-evolve | /ux-polish --loop-only --rounds 5 | The alias keeps the old five-round cap; /ux-polish alone stops at three |
/ux-component | /ux-design --component | Same .ux/last-component.json |
/ux-dashboard | /ux-design --dashboard | Same .ux/last-dashboard.json |
/ux-image-to-code | /ux-design --extract-only --from-image | Drop --extract-only to build from the image |
┌──────────────────────┐
│ /ux-init │ --stats: inventory
└────────────┬─────────┘
│
┌────────────▼─────────┐
│ /ux-discover │ 10-field intake (FORCING GATE)
│ │ --frame: 4-field framing block
│ │ then 5 parallel searches -> merged system
└────────────┬─────────┘
│ writes .ux/last-discovery.json
│ writes .ux/last-recommendation.json
┌──────────────────┼──────────────────┐
│ │ │
┌────────▼───────┐ ┌────────▼────────┐ ┌──────▼──────┐
│ /ux-design │ │ /ux-motion │ │ /ux-system │
│ --component │ │ │ │ │
│ --dashboard │ │ │ │ │
│ --from-image │ │ │ │ │
└────────┬───────┘ └────────┬────────┘ └──────┬──────┘
│ │ │
└──────────────────┼──────────────────┘
│ writes .ux/last-<surface>.json
┌──────────────────┼──────────────────┐
│ │ │
┌────────▼───────┐ ┌────────▼────────┐ ┌──────▼──────┐
│ /ux-lint │ │ /ux-audit │ │ /ux-a11y │
│ /ux-critique │ │ /ux-copy │ │ /ux-motion │
└────────┬───────┘ └────────┬────────┘ └──────┬──────┘
│ │ │
└──────────────────┼──────────────────┘
│ writes .ux/last-<lens>.json
┌────────────▼─────────┐
│ /ux-fix │ apply findings as commits
│ /ux-polish │
└────────────┬─────────┘
│
┌────────────▼─────────┐
│ /ux-case-study │ publishable artifact
└──────────────────────┘
┌──────────────────────┐
│ /ux-next │ conductor, read-only
│ /ux-expert │ consulting hook
└──────────────────────┘
Sub-agents are role-specific generators dispatched by commands. They never run independently, they're called by /ux-design, /ux-system, /ux-fix, /ux-research, etc. Each agent has a defined ownership boundary: they do NOT decide the brief; they execute against it.
frontend-engineer/ux-design (page, component, dashboard and image modes), /ux-fix..ux/last-recommendation.json).Read, Write, Edit, Bash, Glob, Grep.motion-engineer/ux-design (every mode), /ux-motion --fix.data/motion-presets.json.prefers-reduced-motion fallbacks. Always tested against Core Web Vitals.Read, Write, Edit, Bash, Glob, Grep.copy-writer/ux-copy --fix, /ux-design (every mode), /ux-discover --frame.Read, Write, Edit, Bash, Glob, Grep.research-synthesizer/ux-research, /ux-workshop, /ux-discover --frame.Read, Write, WebFetch, Bash, Glob, Grep.design-system-architect/ux-system, /ux-design --component when no system exists..ux/last-recommendation.json (style + palette + type pair + motion presets).Read, Write, Edit, Bash, Glob, Grep.When a command dispatches a sub-agent, it passes:
.ux/).frontend-engineer gets the picked style + palette + components; motion-engineer gets the picked motion presets).Sub-agents return:
The calling command then runs /ux-lint automatically before declaring done.
The data layer is the brain. Every command reads from it; the engine merges across it; the linter scans against it. All files live under data/ and wrap their entries in {_meta, entries} for schema versioning.
styles.json: 84 design styles| Field | Description |
|---|---|
entries | 84 |
keys per entry | id, name, category, philosophy, when_to_use, when_to_skip, tokens, references, compatible_palettes, compatible_type_pairs, compatible_motion, compatible_industries, taste_score |
categories | Minimalist / Swiss, Brutalist, Editorial, Glassmorphism, Neumorphism, Bento, Skeuomorphic, Industrial, Maximalist, AI-Futurist, MENA-modern, Vaporwave, etc. |
sample entry | swiss-international, "Grid is law. Type does the heavy lifting. Decoration is failure." |
Used by: /ux-discover, /ux-system, /ux-design. Schema: data/SCHEMAS.md.
palettes.json: 176 color palettes| Field | Description |
|---|---|
entries | 176 |
keys per entry | id, name, mode (light/dark), tone, colors (canvas, surface, ink, body, muted, primary, primary_active, hairline, success, warning, danger, accent), wcag_contrast_audit, compatible_industries |
tones | warm, editorial, magazine, clinical, playful, brutalist, monochrome, jewel-tone, MENA-warm, dev-tools-dark, etc. |
sample entry | claude-warm-editorial, light, warm/editorial/magazine, canvas #faf9f5, primary #cc785c |
Used by: /ux-discover, /ux-system. Contrast verified at AA / AAA. Schema: data/SCHEMAS.md.
type-pairs.json: 70 type pairings| Field | Description |
|---|---|
entries | 70 |
keys per entry | id, name, display (family + weights + source + license + URL), body, mono, compatible_styles, taste_score |
sample entry | cormorant-inter-jetbrains, Cormorant Garamond × Inter × JetBrains Mono |
All families have license + source URL. Used by /ux-discover, /ux-system.
components.json: 148 components| Field | Description |
|---|---|
entries | 148 |
keys per entry | id, name, category, purpose, anatomy, states, tokens_used, motion, accessibility, compatible_styles, compatible_industries, code_skeleton |
categories | Navigation, Forms, Data Display, Feedback, Overlays, Layout, Content, Marketing, E-commerce, Auth, Dashboard, Charts, Empty States, Loading States, Error States |
sample entry | mega-nav-product-grid, Mega Navigation, Product Grid, 6-part anatomy, 4 states |
This is our biggest moat. No other Claude UX plugin ships a structured component manifest.
industries.json: 184 industry rules| Field | Description |
|---|---|
entries | 184 |
keys per entry | id, name, category, characteristics, audience_signals, recommended_styles, recommended_palettes, recommended_type_pairs, recommended_motion, regulatory_notes, regional_notes |
categories | Financial Services, Healthcare, Education, E-commerce, SaaS B2B, SaaS B2C, Developer Tools, Media, Gaming, Travel, Real Estate, MENA-specific, etc. |
sample entry | fintech-neobank, high trust, regulatory disclosures, balance/transaction primary UI, mobile-first daily-use |
Used by the recommender (/ux-discover) as the first parallel search axis.
chart-types.json: 35 chart types| Field | Description |
|---|---|
entries | 35 |
keys per entry | id, name, category, when_to_use, when_to_skip, encoding, accessibility, data_shape, compatible_styles |
categories | Comparison, Time Series, Distribution, Composition, Relationship, Flow, Geographic |
sample entry | bar-vertical, Compare 4 to 15 discrete categories. Position along x-axis maps category; height maps value. |
Used by /ux-design --dashboard and /ux-design --component (chart instances).
tech-stacks.json: 25 stacks| Field | Description |
|---|---|
entries | 25 |
keys per entry | id, name, category, tier, languages, ssr, rsc, compatible_styling, scaffold_command, compatible_motion, gotchas |
tiers | production, prerelease, experimental |
sample entry | nextjs-15-app-router, Next.js 15 (App Router), TS/JS, SSR, RSC, compatible with Tailwind 4 / CSS Modules / vanilla-extract / styled-components / panda-css |
Other stacks include Astro, SvelteKit, Remix, Nuxt 3, Solid Start, Qwik, Blade+Alpine, Hotwire, Phoenix LiveView, Hydrogen 2025.
ux-guidelines.json: 112 named UX laws| Field | Description |
|---|---|
entries | 112 |
keys per entry | id, name, category, source, principle, application, examples, caveats, related_laws |
categories | Decision Cost, Attention, Memory, Motor Control, Visual Perception, Social, Emotional, Form, Error Handling, Onboarding, Empty State, etc. |
sample entry | hicks-law, Decision time grows logarithmically with the number of choices presented |
Used by /ux-audit (6-lens scoring) and /ux-critique (taste anchor).
motion-presets.json: 57 motion presets| Field | Description |
|---|---|
entries | 57 |
keys per entry | id, name, category, tokens (duration_ms, easing, transform_from/to, opacity_from/to), stacks (framer_motion, gsap, css), accessibility (reduced-motion fallback), when_to_use |
categories | Entry, Exit, Hover, Focus, Tap, Loading, Empty, Success, Error, Scroll-linked |
sample entry | fade-up-12px, 360ms, cubic-bezier(0.16, 1, 0.3, 1), translateY(12px) → 0, opacity 0 → 1 |
Every preset has a reduced-motion variant. Stack-ready code for Framer Motion, GSAP, and pure CSS.
anti-patterns.json: 171 rules| Field | Description |
|---|---|
entries | 171 |
keys per entry | id, name, severity (critical/high/medium/low), category, detection (type, pattern, flags, scope, and for many rules a post check on the parsed file), why, fix |
categories | A11y (45), Content (35), Layout (18), Typography (16), Motion (14), Visual (14), Quality (12), Color (10), Performance (5), Depth (2) |
The full rule list is in The 171 anti-AI-slop rules.
landing-patterns.json: 40 landing patterns| Field | Description |
|---|---|
entries | 40 |
keys per entry | id, name, category, purpose, anatomy, states, tokens_used, motion, anti_slop_checks, compatible_styles, exemplars, ai_slop_risk, notes |
categories | Hero (8), Features (6), Social Proof (5), CTA (5), Pricing (4), Footer (4), Navigation (4), Trust (2), Onboarding (2) |
sample entry | hero-split-screen-typewriter |
brands/*.json: 160 brand specs| Field | Description |
|---|---|
entries | 160 (plus _index.json listing all) |
keys per entry | id, name, category, voice, tokens (color, type, motion), design_principles, signature_moves, anti-moves, references |
categories | Developer Tools (36), Consumer / Lifestyle / Retail (19), Fintech / Crypto (14), Editorial / Media (13), AI / ML Platform (12), Productivity / Collaboration (8), Automotive (8) |
Full list in The 160 brand DESIGN.md specs.
ux-skill ships a deterministic linter: each rule is a pattern, and many add a check on the parsed CSS and markup, so a match counts only in the context it names. No LLM. No API. No network. Runs in CI in ~200ms on a typical Next.js app. Exits non-zero on Critical / High findings when --fail-on high is set.
The rules are sourced from data/anti-patterns.json (v2 preferred) with a references/foundations/anti-patterns.md fallback (v1 bash). Two binaries ship: bin/ux-lint.py (Python, fast, extensible) and bin/ux-lint.sh (Bash + perl-PCRE, for environments without Python).
| Severity | Rule ID | Name |
|---|---|---|
| critical | aria-hidden-on-interactive | aria-hidden on a focusable interactive element |
| critical | blink-tag | element used |
| critical | div-onclick-no-role | Click handler on without role or tabindex |
| critical | onclick-on-non-button | onclick handler on non-interactive element |
| critical | outline-none-no-focus-visible | outline removed without focus-visible replacement |
| critical | viewport-no-zoom | Viewport blocks pinch-zoom |
| high | anchor-no-href-as-button | Anchor styled as button without href |
| high | aria-live-polite-on-error | aria-live='polite' on a critical error region |
| high | cursor-not-allowed-no-visual | cursor: not-allowed with no visible disabled state |
| high | generic-alt-image-photo-icon | Generic alt text: image / photo / picture / icon |
| high | generic-alt-untitled-screenshot-logo-banner | Generic alt text: untitled / screenshot / logo / banner |
| high | hover-only-card-actions | Card actions revealed only on hover |
| high | iframe-without-title | missing title attribute |
| high | img-no-alt | Image missing alt attribute |
| high | inline-svg-no-aria | SVG without aria-label or aria-hidden |
| high | lang-attribute-missing | without lang attribute |
| high | link-onclick-no-href | Anchor with onClick but no href |
| high | link-without-href | element without an href attribute |
| high | meta-refresh-redirect |
| Severity | Rule ID | Name |
|---|---|---|
| high | cta-text-read-more | Generic CTA text: Read more / View more / See more |
| high | emoji-in-ui | Emoji used as UI element |
| high | filler-marketing-verbs | Filler marketing verb in headline |
| high | generic-cta-text | Generic CTA text (Click here, Learn more) |
| high | icon-emoji-stamp | Emoji used as icon stamp |
| high | imagery-mandatory-missing | Landing page with no photograph |
| high | lorem-ipsum-leak | Lorem ipsum in shipping code |
| high | phone-field-requires-country-code | Phone field that refuses a local number |
| high | picsum-photos-seed | Random (unseeded) picsum.photos placeholder |
| high | placeholder-as-pricing | Default AI pricing tier amounts |
| high | placeholder-com-direct | placeholder.com direct placeholder |
| high | placeholder-token-shipped | Literal placeholder token left in shipped markup |
| high | placeholder-via-com | via.placeholder.com placeholder image |
| high | placekitten-com | placekitten.com kitten placeholder |
| high | testimonial-fake-five-stars | Hardcoded five-star testimonial |
| high | unsplash-photo-id-no-alt | Unsplash photo URL with empty or missing alt |
| medium | before-after-100-percent | Magnitude-default before-after claim |
| medium | cta-text-tap-continue-go | Generic CTA text: Tap here / Continue / Go |
| medium | fake-line-of-code-count | Unsourced large-number marketing claim |
| Severity | Rule ID | Name |
|---|---|---|
| high | h-screen-no-dvh-fallback | 100vh without 100dvh fallback for mobile |
| high | three-equal-card-grid | Three equal cards in a row |
| medium | aspect-ratio-1-1-default | Square aspect-ratio as default everywhere |
| medium | avatar-stack-overlapping | Generic overlapping avatar stack |
| medium | centered-everything-hero | Centered hero composition |
| medium | cta-buttons-clustered-in-hero | Three-plus CTA buttons clustered in hero |
| medium | display-table-for-layout | display: table used for layout outside data tables |
| medium | eyebrows-over-budget | More eyebrows than the brand calls for |
| medium | fixed-height-text-block | Pixel height on a text container |
| medium | full-viewport-width-overflow | Full viewport width causes horizontal scroll |
| medium | layout-family-repeated | One layout used for three sections |
| medium | logo-cloud-no-real-logos | Logo cloud image with empty alt |
| medium | negative-margin-pull-left-right | Large negative horizontal margin on body content |
| medium | split-sections-in-a-row | More than two media-and-text splits in a row |
| low | flex-center-center-default | flex + justify-center + align-center as the default block |
| low | grid-cols-3-1fr-default | repeat(3, 1fr) as a default grid |
| low | nav-equal-hamburger-desktop | Hamburger menu on desktop |
| low | pill-rounded-full-everywhere | rounded-full applied to everything |
| Severity | Rule ID | Name |
|---|---|---|
| high | font-weight-numeric-100-or-900-on-body | Body or paragraph font-weight set to 100 or 900 |
| high | inter-as-display | Inter used as display font |
| medium | all-caps-large | ALL CAPS at body-text size or larger |
| medium | body-font-weight-bold-or-700-keyword | body / p / li set to font-weight: bold or 700 |
| medium | body-letter-spacing-too-wide | Excessive letter-spacing on body / paragraph |
| medium | body-text-shadow-on-prose | text-shadow applied to body or prose |
| medium | default-font-only | Inter or Geist as the only font, no type decision |
| medium | display-bold-700 | Display heading at 700+ font-weight |
| medium | hero-text-arbitrary-90px | Arbitrary hero font size |
| medium | letterspacing-tracking-tight-display | Tight letter-spacing on heavy display heading |
| medium | text-3xl-4xl-5xl-stack | Tailwind text-3xl text-4xl text-5xl AI hero stack |
| medium | title-case-headlines | Title Case On Display Headings |
| low | display-line-height-under-floor | Display line height under the engine's floor |
| low | font-family-monospace-fallback-default | font-family: monospace with no specific stack |
| low | font-system-only | System font stack with no chosen typeface |
| low | text-align-justify-web | Justified body text on the web |
| Severity | Rule ID | Name |
|---|---|---|
| high | animating-layout-properties | Transition on a layout property |
| high | autoplay-without-muted | without muted attribute |
| high | infinite-animation-without-reduced-motion | Infinite animation that keeps running under reduced motion |
| high | marquee-tag | element used |
| medium | animation-duration-too-long | Long animation that starts slowly |
| medium | cta-arrow-rightward-bouncing | Bouncing arrow on CTA |
| medium | marquee-more-than-one | More than one marquee |
| medium | transition-duration-500ms-or-longer | Interactive transition that answers late |
| medium | transition-property-all | transition: all (lazy property list) |
| low | cubic-bezier-material-only | Material default easing everywhere |
| low | exit-cut-by-display-none | Exit animation cut by display: none |
| low | scale-1-1-on-card-hover | Over-the-top hover scale |
| low | theme-switch-animates-everything | Theme switch animates every color on the page |
| low | timing-300ms-default | Default 300ms transition timing |
| Severity | Rule ID | Name |
|---|---|---|
| high | decorative-accent-ruler | Decorative accent ruler (hairline ornament, fade, dot, or a line or dash beside an eyebrow) |
| high | emoji-bullet-marker | Emoji at start of list item |
| high | lone-emoji-as-icon | Lone emoji used as functional icon |
| medium | align-html-attribute | Presentational align= HTML attribute |
| medium | bgcolor-html-attribute | Presentational bgcolor= attribute |
| medium | box-shadow-multilayer-default | Five-plus box-shadow layers stacked |
| medium | dynamic-island-glow-everywhere | Dynamic Island inner glow on cards |
| medium | glass-morphism-default | Backdrop-blur frosted-glass on four-plus surfaces |
| medium | noise-texture-overlay | Repeating noise or grain texture overlay |
| low | blur-bg-only-decoration | Backdrop blur with no glass surface |
| low | body-background-color-inherit | body { background-color: inherit } |
| low | border-radius-2xl-default | rounded-2xl or larger applied to everything |
| low | cursor-pointer-on-disabled | cursor:pointer applied to :disabled state |
| low | loader-spinner-border-default | Default CSS border-spin loader recipe |
| Severity | Rule ID | Name |
|---|---|---|
| high | console-log-leak | console.log in component code |
| medium | any-type-leak | TypeScript any type |
| medium | arbitrary-z-index-9999 | Lazy z-index value |
| medium | body-cursor-pointer-default | body or main given cursor: pointer |
| medium | inline-style-attribute | Inline style attribute |
| low | class-multiple-utility-than-token | Five-plus utility classes where a token would do |
| low | data-testid-in-production-markup | data-testid left in production markup |
| low | generic-class-container-wrapper-only | div with only 'wrapper' / 'box' / 'inner' as class |
| low | numbered-placeholder-classname | Numbered placeholder class names (card-1, feature-2) |
| low | padding-shorthand-4-vals-zero-first | Verbose 4-value padding/margin where 3 would do |
| low | shadcn-default-everywhere | Default shadcn token block unmodified |
| low | todo-fixme-comment | TODO or FIXME in shipping code |
| Severity | Rule ID | Name |
|---|---|---|
| high | chrome-y-multi-stop-gradient | Chrome-y multi-stop gradient |
| high | dark-text-on-dark-card | Low-contrast text on card |
| high | gradient-on-text-rainbow | Rainbow gradient on display text |
| high | purple-to-blue-gradient | Default purple-to-blue AI gradient |
| medium | card-glow-purple-shadow | Purple glow shadow on cards |
| medium | glass-without-fallback | backdrop-filter blur without background fallback |
| medium | gradient-mesh-purple-pink | Purple-pink mesh gradient hero |
| medium | gradient-text-rainbow | Multi-stop gradient text |
| medium | navy-to-purple-gradient | Navy to purple gradient |
| low | tailwind-color-named-vague | Named Tailwind colors with no semantic token |
| Severity | Rule ID | Name |
|---|---|---|
| high | img-no-dimensions | Image without width and height attributes |
| medium | css-import-render-blocking | @import in CSS (render-blocking) |
| medium | event-listener-no-passive-on-scroll | addEventListener('scroll' | 'touchmove' | 'wheel') without passive |
| medium | image-format-jpg-no-webp-avif | without source AVIF/WebP |
| low | animated-grain-noise-no-perf-class | Animated grain or noise without GPU hint |
| Severity | Rule ID | Name |
|---|---|---|
| medium | glow-shadow-zero-offset | Glow shadow with zero offset and large blur |
| medium | hairline-border-heavy-shadow | 1px border combined with a heavy drop shadow |
One-off scan:
uxskill lint .
# or
python3 bin/ux-lint.py src/
# or
bash bin/ux-lint.sh src/
CI gate (GitHub Actions):
- name: ux-lint
run: bash bin/ux-lint.sh --ci --fail-on high
Pre-commit hook:
# .git/hooks/pre-commit
#!/usr/bin/env bash
bash bin/ux-lint.sh --staged --fail-on high
Output (sample):
─── /ux-lint report ───
src/components/Hero.tsx:24 [high] purple-to-blue-gradient
evidence: bg-gradient-to-br from-purple-500 to-blue-500
fix: replace with the recommended palette's primary gradient or remove gradient
src/components/Pricing.tsx:11 [high] three-equal-card-grid
evidence: grid grid-cols-3 gap-6 (3 equal Card children)
fix: feature one card; flank with two reduced-emphasis cards
3 files scanned · 2 high · 0 medium · 0 low · exit 1
Recommended next: /ux-polish --fix (LLM-driven, addresses both lintable and aesthetic findings)
Real brands. Real design languages. Real DESIGN.md specs, not generic palettes. Tell the plugin "build a landing in Stripe's style" and it reads the actual brand vocabulary: voice rubric, color tokens, motion conventions, signature moves, anti-moves.
Each brand ships as a structured JSON (data/brands/<slug>.json) plus a prose reference (references/brands/<slug>.md).
ClickHouse, Composio, Cursor, Datadog, dbt Labs, Expo, Fivetran, Fly.io, Framer, HashiCorp, Honeycomb, IBM, Lovable, Mintlify, Modal, MongoDB, Neon, Ollama, OpenCode, PostHog, Railway, Raycast, Render, Replicate, Resend, Retool, Sanity, Sentry, Slack, Snowflake, Sourcegraph, Supabase, Superhuman, Vercel, Warp, Webflow
Aesop, Airbnb, Allbirds, Apple, Apple Music, Glossier, HP, Hims & Hers, Instagram, Meta, Nike, Patagonia, Pinterest, PlayStation, Shopify, Spotify, Starbucks, TikTok, Uber
Binance, Brex, Coinbase, Kraken, Mastercard, Mercury, Monzo, N26, Plaid, Ramp, Revolut, Robinhood, Stripe, Wise
Bloomberg, Clay, Dezeen, NVIDIA, Pitchfork, Substack, The Atlantic, The Economist, The New York Times, The Verge, The Wall Street Journal, Vodafone, Wired
Anthropic, Claude, Cohere, ElevenLabs, MiniMax, Mistral AI, OpenAI, Perplexity, Runway, Together AI, VoltAgent, xAI
Airtable, Cal.com, Figma, Intercom, Linear, Miro, Notion, Zapier
BMW, BMW M, Bugatti, Ferrari, Lamborghini, Renault, SpaceX, Tesla
The other 8 popular Claude UX plugins generate "modern minimal" or "clean dashboard", variants of the same default aesthetic. ux-skill lets you ask for Linear's clarity, Stripe's seriousness, Apple's restraint, Tesla's monolith, Notion's friendliness, Cursor's gradient discipline, Raycast's hairline density, Claude's warm editorial, and the engine pulls the right tokens, voice, motion conventions, and signature moves from the brand spec.
ux-skill ships a Model Context Protocol server. Run ux-mcp and the engine becomes a long-running stdio process that any MCP-capable host, Claude Desktop, Cursor, Windsurf, generic agents, can call into. 25 tools: ux_recommend, ux_system_detect, ux_lint, ux_styles, ux_palettes, ux_type_pairs, ux_components, ux_industries, ux_motion_presets, ux_anti_patterns, ux_brands, ux_landing_patterns, ux_persist_save, ux_persist_load, ux_stats, ux_image_extract, ux_synthesize, ux_decisions_query, ux_decisions_stats, ux_system_build, ux_system_import, ux_system_enhance, ux_system_extend, ux_system_export, ux_contracts_check. Same Python handlers the slash commands use; same data manifests; same deterministic recommender.
Why this is the asymmetric move: none of the top eight Claude UX skills (ui-ux-pro-max-skill, open-design, taste-skill, huashu-design, stitch, nothing-design, hallmark, material-3) ship an MCP server. They are locked inside Claude Code's plugin runtime. ux-skill is reachable from any host that speaks MCP, including agents that have never heard of a Claude Code plugin.
pip install 'uxskill[mcp]' # mcp is an opt-in extra
ux-mcp # stdio JSON-RPC server starts
Point your client at the ux-mcp binary. Full tool docs, JSON examples, and per-client config for Claude Desktop, Cursor, and Windsurf live at docs/mcp.html and in commands/ux-mcp.md.
uxskill init (or /ux-init inside Claude Code) auto-detects which IDE you're using and writes the right artifact. Same Python engine. Same recommendations. Different glue per IDE.
| IDE / Tool | Detection signal | Installed artifact |
|---|---|---|
| Claude Code | .claude/ or CLAUDE.md | Plugin manifest at .claude-plugin/plugin.json + all 18 commands (and 7 aliases) + all 5 sub-agents |
| Cursor | .cursor/ or .cursorrules | .cursorrules prompt header pointing at the engine |
| Windsurf | .windsurf/ or .windsurfrules | .windsurfrules with the same prompt header |
| GitHub Copilot | .github/copilot-instructions.md or .vscode/ | .github/copilot-instructions.md |
| Gemini CLI | GEMINI.md | GEMINI.md |
| Codex | AGENTS.md | AGENTS.md |
| Kiro | .kiro/ | .kiro/instructions.md |
| Cline | .cline/ | .cline/instructions.md |
| Continue | .continue/ | .continue/config.json patch |
| Aider | .aider.conf.yml | .aider.conf.yml + AIDER.md |
| Zed | .zed/ | .zed/instructions.md |
| JetBrains AI | .jetbrains-ai/ or .idea/ | .jetbrains-ai/instructions.md |
| Pieces | .pieces/ | .pieces/instructions.md |
| Tabby | .tabby/ | .tabby/instructions.md |
| Tabnine | .tabnine/ | .tabnine/instructions.md |
| CodeWhisperer | .aws-codewhisperer/ | .aws-codewhisperer/instructions.md |
| Roo Cline |
In every IDE, the same uxskill recommend / uxskill lint / uxskill stats CLI commands work from the terminal. The Python engine is the source of truth; the IDE artifacts are thin prompt-headers that route into it.
Eight real scenarios. Pick the one closest to your situation and adapt the invocation.
You're in Cursor working on a MENA neobank dashboard. You install the plugin and run discovery, recommendation, then dashboard generation.
pip install uxskill
uxskill init # detects Cursor, writes .cursorrules
uxskill discover # 10-field intake
uxskill recommend \
--project-type=dashboard \
--industry=fintech-neobank \
--tone=clinical --tone=precise \
--must-have=dark-mode --must-have=a11y-AA --must-have=RTL \
--forbidden=brutalism --forbidden=purple-gradients \
--stack=nextjs-15-app-router \
--region=mena
Then in Cursor, ask: "Generate the dashboard surface using the recommendation in .ux/last-recommendation.json". Cursor reads the .cursorrules header, loads the recommendation, dispatches a dashboard generation with explicit constraints.
/plugin marketplace add Laith0003/ux-skill
/plugin install ux@ux-skill
/ux-discover
> Project type? landing
> Industry? fintech-payments
> Tone? serious, technical, confident
> Must have? dark-mode, AA, mobile-first
> Forbidden? purple-gradients, three-equal-cards
> Reference brands? stripe
> Stack? nextjs-15-app-router
> Region? global
> Success metric? signup conversion
/ux-discover --recommend
> [returns picked style, palette, type pair, motion presets, components, brand exemplars]
/ux-design "generate the landing using the Stripe brand spec as exemplar"
> [frontend-engineer generates the page]
/ux-lint .
> [passes, Stripe brand spec was respected]
You shipped a Next.js app two weeks ago. You want a hard floor against AI fingerprints on every PR.
# .github/workflows/ux-lint.yml
name: ux-lint
on: [pull_request]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with: { python-version: '3.11' }
- run: pip install uxskill
- run: uxskill lint . --ci --fail-on high
PRs that introduce purple-to-blue gradients, Inter at 96px, "John Doe" testimonials, or emoji-as-icons fail CI. No LLM cost. ~200ms.
You inherited a React app that looks like every other AI-generated SaaS site. You want to make it not look like that.
/ux-critique src/components/Hero.tsx
> [3 wins, 3 misses, 1 strategic move, the take is honest]
/ux-lint src/
> [15 high-severity AI fingerprints flagged]
/ux-polish src/components/Hero.tsx
> [LLM-driven cosmetic pass + AI-slop kill]
/ux-fix
> [applies findings as atomic commits, re-runs the linter]
Three commands, one polished surface, atomic commits per fix.
/ux-design --component command-palette --brief="Linear-style, dark, monospace shortcuts, recent items first"
> [reads data/brands/linear.app.json for tokens + signature moves]
> [reads data/components.json for the command-palette anatomy + states]
> [dispatches frontend-engineer with explicit Linear spec]
The generated component uses Linear's actual color tokens, type stack, motion conventions, hairline densities, not "generic dark UI."
You have a room of 5 people for 90 minutes. You want them to leave with a game plan, not a vibe.
/ux-workshop "loyalty wallet pivot" \
--participants="2 PMs, 1 designer, 1 eng lead, 1 customer rep" \
--minutes=90
The plugin facilitates the five phases (exploration → heat map → stakeholder map → solution sketch → game plan) end-to-end, time-boxed, with concrete per-phase artifacts. The output is .ux/last-workshop.json, the game plan, not just "interesting findings."
You shipped the loyalty wallet. You want a portfolio piece.
/ux-case-study --format=html --slug=northwind-loyalty
> [reads .ux/last-frame.json, last-workshop.json, last-research.json, last-design.json, last-a11y.json, last-polish.json, last-recommendation.json, last-discovery.json]
> [generates monochrome editorial case study with numbered (A)-(G) sections, hairline separators, bilingual-safe layout]
> [writes case-studies/northwind-loyalty.html]
The case study is a finished, publishable artifact, not a draft. Pure monochrome, editorial typography, ready to ship to your portfolio.
You're scoping a project. You don't need a recommendation yet, you need a structured brief.
uxskill discover
# 10-field intake, saves to .ux/last-discovery.json
cat .ux/last-discovery.json
# {
# "project_type": "...",
# "audience": "...",
# ...
# }
You can hand the JSON to your team, paste into a Notion doc, or feed it into a separate AI tool. ux-skill is also a structured intake tool in addition to being an engine.
After /ux-discover (or /ux-discover --recommend), persist the picked style + palette + type + motion + components + brand exemplars + guardrails as a human-readable Markdown file your team can review, diff, and version-control.
python3 -m engine.cli.main persist save --project-root .
Writes .ux/design-system/MASTER.md (YAML frontmatter + body) and .ux/design-system/pages/<name>.md per generated surface via persist save-page. Idempotent, same input produces byte-identical output, so re-running on unchanged state is a no-op in git.
Short summary table. Full table-by-table comparison is at uxskill.laithjunaidy.com/compare.html.
| Dimension | ux-skill | ui-ux-pro-max | open-design | taste-skill | huashu-design | stitch-skills | nothing-design | hallmark | material-3 |
|---|---|---|---|---|---|---|---|---|---|
| Slash commands | 18 | 1 | 19 | 1 | 1 | multi | 1 | 1 | 1 |
| Components | 148 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | (MD3) |
| Motion presets | 57 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| Brand specs | 160 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| Anti-pattern rules | 171 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| CI-safe deterministic linter | yes | no | no | no | no | no | no | no | no |
| IDEs supported | 17 | 18 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
| Discovery gate | 10 fields | implicit | implicit | implicit | implicit | implicit | implicit | implicit | implicit |
.ux/ state chain | yes | no | no | no | no | no | no | no | no |
| Stars (2026-05-28) | 14 | 83,958 | 54,406 | 25,202 | 15,455 | 5,762 | 2,391 | 2,164 | 955 |
For full detail per dimension, see compare.html.
Next, in no fixed release:
Also open:
uxskill lint --fix for safe rewrites of mechanically fixable findings (button-no-type, img-no-alt empty string, console-log-leak removal).data/anti-patterns.local.json.uxskill plan: multi-page site planning from a brief, not just one surface.Issues and PRs welcome. Three high-leverage areas:
data/anti-patterns.json, add an entry with id, name, severity, category, detection.pattern, detection.flags, detection.scope, evidence_template, fix, references.tests/linter/, one file that triggers the rule, one that doesn't.uxskill lint tests/linter/should-trigger/<rule>.tsx, confirm it fires. Run on tests/linter/should-not-trigger/<rule>.tsx, confirm it doesn't.data/brands/<slug>.json with id, name, category, voice, tokens, design_principles, signature_moves, anti-moves, references.references/brands/<slug>.md.data/brands/_index.json.data/motion-presets.json, add an entry with id, name, category, tokens, stacks (framer_motion, gsap, css), accessibility.reduced_motion_fallback, when_to_use.MIT. Use it, fork it, build on it. If it saves you from shipping AI slop, star the repo, it's the cheapest way to support it.
Laith Aljunaidy: solo founder of Dot, a MENA-first loyalty platform. Building ux-skill so the AI-generated frontend doesn't all look the same.
data/ux-guidelines.json.data/brands/, their public design systems are the source of truth for the brand specs.ux-skill · v4.0.0 · Built so Claude Code, Cursor, Windsurf, and every other AI coding tool output frontend that doesn't read as AI-generated.
Star the repo at github.com/Laith0003/ux-skill · Install via
pip install uxskillornpx uxskill init· Browse the comparison at uxskill.laithjunaidy.com/compare.html
| 1 |
| hamen/material-3-skill | 955 | MD3 components + audit | 1 | - | (MD3 only) | 0 | 0 | 1 |
| Laith0003/ux-skill (ux-skill) | 14 | Python engine + 12 manifests + 18 commands + 5 sub-agents + CI linter | 18 | 171 deterministic rules | 160 | 148 | 57 | 17 |
| redirect |
| high | overflow-hidden-on-html | overflow: hidden applied to |
| high | placeholder-as-label | Input placeholder used as the only label |
| high | pointer-events-none-on-link | with pointer-events: none and no aria-disabled |
| high | role-button-on-anchor-without-href | with no href |
| high | select-without-label | with no associated or aria-label |
| high | tabindex-positive | Positive tabindex value |
| high | target-blank-no-noopener | target="_blank" without rel="noopener noreferrer" |
| high | text-ink-at-low-alpha | Text in ink at low alpha |
| high | tooltip-on-required-info | Load-bearing copy hidden in a title attribute |
| high | video-without-captions | element without |
| medium | aria-busy-without-aria-live | aria-busy='true' with no aria-live companion |
| medium | button-no-type | Button missing type attribute |
| medium | cursor-pointer-non-interactive | cursor:pointer on non-interactive element |
| medium | fieldset-without-legend | missing a child |
| medium | focusable-at-opacity-zero | Focusable control left at opacity 0 |
| medium | generic-alt-decorative-not-empty | alt='decorative' instead of empty alt |
| medium | heading-skip-h1-h3 | Skipped heading level |
| medium | href-empty-hash | Dead link: href="#" placeholder |
| medium | href-javascript-void | Dead link: javascript: URL as href |
| medium | infinite-scroll-no-pagination | Infinite scroll without keyboard fallback |
| medium | inline-style-display-none-no-aria | Interactive element hidden via inline display:none without aria-hidden |
| medium | menu-row-disabled-without-reason | Disabled menu row with no reason |
| medium | repeated-action-same-name | Actions in repeated items share one name |
| medium | safe-area-inset-only-bottom | safe-area-inset-bottom without top/left/right siblings |
| medium | screen-reader-only-without-class | Skip-to-content link with no sr-only / visually-hidden class |
| low | scroll-to-top-button-everywhere | Fixed scroll-to-top button on short pages |
| medium | fake-name-john-doe | Generic placeholder names |
| medium | marketing-buzz-ai-powered-driven | Buzzword: AI-powered / AI-driven |
| medium | marketing-buzz-best-in-class | Buzzword: best-in-class |
| medium | marketing-buzz-cutting-edge | Buzzword: cutting-edge |
| medium | marketing-buzz-game-changing | Buzzword: game-changing / game-changer |
| medium | marketing-buzz-industry-leading | Buzzword: industry-leading |
| medium | marketing-buzz-leverage-ai-harness | Buzzword: leverage / harness the power of |
| medium | marketing-buzz-next-generation | Buzzword: next-generation |
| medium | marketing-buzz-world-class | Buzzword: world-class |
| medium | marketing-unlock-unleash-potential | Buzzword: unlock / unleash the potential, reach new heights |
| medium | one-action-several-labels | One action under several labels |
| medium | round-number-stats | Round number marketing stat |
| medium | timestamp-just-now | Fake just-now timestamp in static markup |
| medium | trust-badge-no-source | Unsourced trust-by claim |
| low | footer-built-with-love-coffee | Footer: Built with love / Made with coffee / Crafted with care |
| low | version-1-0-0-evergreen | Hardcoded v1.0.0 in nav or footer |
.roo/.roo/instructions.md |