From claude-dev-kit
Establishes a desktop design philosophy from kickoff outputs, then generates a desktop design system, wireframes, and an Electron prototype. Run after /kickoff.
How this skill is triggered — by the user, by Claude, or both
Slash command
/claude-dev-kit:desktop-uiuxThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
<!-- AUTO-GENERATED by scripts/gen_skills.py — DO NOT EDIT. Edit SKILL.md.tmpl instead. -->
Run silently at the start:
python3 scripts/kit_update_check.py 2>/dev/null
If exit code is 1 (update available), show the output to the user once. Do not block the workflow.
Run these checks silently at the start. Use results to adapt behavior:
[ -f issues.md ] — if true, this project uses the sprint system. Respect issue numbering and STATUS.md.[ -f docs/sprint_state.md ] — if true and Status shows running, a sprint is active. Be aware of parallel work in worktrees.[ -f docs/prd_digest.md ] — if true, read it for quick project context before starting.gh auth status before any GitHub operation.At the start of this skill, check if contributor mode is enabled:
python3 scripts/kit_config.py get contributor_mode
If the result is true:
python3 scripts/contributor_report.py --skill <name> --step "<step>" --rating <N> --notes "<friction or suggestion>"
/kickoff must be run first so that the following files exist:
docs/ux_spec.md (core input — IA, flows, screen inventory)docs/requirements.md (functional/non-functional requirements)docs/architecture.md (tech stack reference)/kickoff.docs/ux_spec.md — extract screen inventory, IA, flowsdocs/requirements.md — identify UI elements from functional requirementsdocs/architecture.md — confirm tech stack, API endpoints$ARGUMENTS or PRD.md) as supplementary context. If docs/prd_digest.md exists, read it for quick PRD summary.docs/ux_spec.md does not exist:
/kickoff PRD.md first."docs/design_philosophy.md — check if already generated by web /uiuxdocs/copy_guide.md — check if already generated by web /uiux**/electron/**, **/main.ts, **/preload.ts, **/electron-builder.*, **/forge.config.*, **/*.tsx, **/*.ts5.5) Check if docs/design_philosophy.md already exists AND contains a "Decision Matrix" section:
Ask the user the following questions to anchor the design direction. These answers become binding constraints for Phase 2. Present all questions at once (not one-by-one) and wait for answers. Also tell the user: "If any of these are hard to answer right now, just say 'skip'. You can also skip the entire interview."
a) Brand Personality: "If this product were a person, who would they be?" (e.g., a luxury hotel concierge, a neighborhood cafe barista, a strict operating room nurse, a playful friend)
b) Emotional Target: "What one emotion do you want users to feel when they see the first screen?" (e.g., trust, curiosity, relief, excitement, calm)
c) Anti-Reference: "What competing product or design should this absolutely NOT look like?" (a feeling you want to avoid, or a specific product name)
d) Aspiration Reference: "Is there a product or brand you'd like to reference for design? (doesn't have to be the same domain)" (e.g., Stripe's cleanliness, Nintendo's playfulness, Aesop's luxury)
e) Desktop Identity: "Should this app feel like a native part of the OS, or should it have its own distinct visual identity?" (e.g., natural integration like a macOS native app vs distinct UI identity like Figma/Notion)
5.6) Handle user response:
Case A — User answers (partially or fully): Record answers in memory — these become HARD CONSTRAINTS for Phase 2. If the user skips individual questions, note them as "unconstrained" but still avoid generic defaults.
Case B — User skips the entire interview (says "skip", "pass", etc.):
CHECKPOINT — MANDATORY — NEVER SKIP Verify Phase 1 outputs:
docs/ux_spec.mdexists, PRD was read, interview answers (or auto-derived/reused constraints) are recorded. If any required input is missing: STOP and report to user.
Check if docs/design_philosophy.md already exists:
/uiux):Analyze the product's identity from PRD and UX spec:
WebFetch returns parsed text, not pixels. Asking the model to extract hex values or sidebar proportions from a Dribbble URL via WebFetch is fabrication. Visual references MUST arrive as actual images.
Pick exactly ONE of three paths:
Path (a) — user-provided images (preferred):
≈#…), sidebar/split-pane proportions, title bar treatment, command palette presence, density (compact / roomy), dark-mode handling.Path (b) — page URLs:
python3 scripts/capture_reference.py <url> --viewport 1440x900
This headless-captures the page into docs/references/<slug>.png. If the script exits non-zero, STOP this path and switch to Path (a) or Path (c).Path (c) — no images available:
Reference Anchor skipped: no image provided. Pass 1–3 desktop screenshot paths or a page URL (with Playwright/Chrome installed) to populate this section.Anti-reference: WebSearch for anti-reference titles is acceptable. Anti-cues are written from the model's own knowledge.
Synthesis (when Path (a) or (b) ran — output goes into docs/design_philosophy.md "Reference Anchors"):
sidebar 240px @ #0E0F12, JetBrains Mono 13 + Inter 13, title bar 28px frameless with traffic lights inset 12/12) — source image path under docs/references/ OR user-provided image URL/path. Strong = present in the chosen images, specific enough that no Phase 5 implementer can fall back to a generic Electron/Material default. Fewer-and-deeper beats more-and-shallow.literal_quote: "<exact string>" — <where it appears>. Desktop-friendly examples:
literal_quote: "⌘K" — command palette trigger shown in the sidebarliteral_quote: "47.2-A" — sample order ID, mono on the order detail panelliteral_quote: "조용한" — set in 96pt Inter Display, splash screen"luxury", "power user") — the literal quote is text/glyph/shortcut the prototype renders.≈ and cite the source image.Verbatim render check — Phase 5B is required to render the literal_quote string verbatim in at least one screen file under prototype-desktop/. The Phase 2 CHECKPOINT below verifies the field is populated; Phase 5B verifies it appears in rendered output.
Commit to a BOLD aesthetic direction with desktop lens:
Generate docs/design_philosophy.md:
var(--token)) — never prose-only.border-left: 3px solid var(--accent) and background: var(--accent-10) — never full-row highlight"text-transform: uppercase, letter-spacing: 0.08em, JetBrains Mono 11 — never sentence case"clip-path: polygon(...) notched bottom-right corner, 480×320 fixed — never plain rounded rectangle"grid-template-columns: 240px 1fr with a 1px hairline divider in --border-strong, no shadow"docs/references/ or a user-provided image URL/path), 1 literal_quote: field (mandatory unless Phase 1.5 was skipped), 3–5 avoided cues with reasons. If step 7.5 took Path (c) and skipped this section, omit it here too and proceed.Present the design philosophy to the user and ask for approval before proceeding.
CHECKPOINT — MANDATORY — NEVER SKIP Verify
docs/design_philosophy.mdexists with: (a) a Signature Move that is numeric/token-specific (not prose-only); (b) either a populated Reference Anchors section OR an explicit "Reference Anchors skipped (no image input)" line; AND (c) when Reference Anchors is present, exactly 2–3 adopted cues (not 1, not 4+), each citing an image path, plus aliteral_quote:field with a concrete word/number/glyph/shortcut (NOT an adjective like "luxury"). The literal_quote may only be omitted if Phase 1.5 interview was explicitly skipped — in which caseliteral_quote: (skipped — interview not run)must appear instead of the field being absent. If any of (a) / (b) / (c) fails: STOP and fix before proceeding.
docs/design_system_desktop.md reflecting the chosen aesthetic:
darwin→Cmd, win32/linux→Ctrl)transform, opacity, or filter. NEVER animate layout properties (width, height, top, left).will-change budget: Max 5 concurrent elements with will-change. Overuse creates GPU memory pressure. Apply on interaction start, remove on end.fr units over JS-driven width changes. If JS-driven, throttle via requestAnimationFrame.nativeTheme integration, system preference detection, manual overridedarwin/win32/linux keys for platform-specific values (fonts, shortcuts, window chrome, file paths)docs/wireframes_desktop.md:
grid-template-columns or column ratios — e.g., 240px 1fr 320px (sidebar / content / inspector)gap: 1px (for hairline-divided panels) or gap: 16px (for spaced panels)traffic lights at top: 12px left: 12px, custom title bar height 28pxrow height: 28px, cell padding: 6px 12px (compact) vs 40px / 12px 16px (comfortable)docs/interactions_desktop.md:
docs/copy_guide.md already exists:
## Desktop Adaptations section.
## Desktop Adaptations section covering:
docs/copy_guide.md:
docs/ux_spec.md, docs/design_philosophy.md, docs/wireframes_desktop.md, docs/interactions_desktop.md, PRD—/–) — use -, comma, period, or colon; no filler verbs (Elevate, Seamless, Unleash, Next-Gen, Revolutionize); no generic person names (John Doe) or startup-slop brand names (Acme, Nexus, SmartFlow); no fake-perfect numbers (99.99%, round 50%) — use organic values. See "Specific AI Tells" in Anti-AI-Slop Rules.
16-a) Accessibility labels (REQUIRED): Ensure copy_guide.md includes aria-label for EVERY interactive element (buttons, inputs, menus, panels, dialogs). Also include keyboard shortcut announcements for screen readers.CHECKPOINT — MANDATORY — NEVER SKIP Verify
docs/design_system_desktop.md,docs/wireframes_desktop.md,docs/interactions_desktop.md, anddocs/copy_guide.mdall exist. Cross-check: every component in wireframes has a definition in design_system_desktop.md. If any output is missing: STOP and generate it before proceeding.
prototype-desktop/ directory structure:
prototype-desktop/
package.json
tsconfig.json
.gitignore
electron/
main.ts (main process)
preload.ts (preload script)
src/
types/
index.ts (shared types)
theme/
tokens.ts
colors.ts
spacing.ts
typography.ts
components/
Sidebar.tsx
CommandPalette.tsx
SplitPane.tsx
ContextMenu.tsx
DataTable.tsx
... (as needed per design system)
screens/
... (one .tsx per screen from wireframes)
App.tsx
main.tsx (renderer entry)
index.html
prototype-desktop/package.json:
electron — runtimereact, react-dom — frameworktypescript — languagevite, @vitejs/plugin-react — bundlerelectron-builder or @electron-forge/cli — packaging@types/react, @types/react-dom — type definitionselectron-vite or vite-plugin-electron — Electron + Vite integrationdev (development with hot reload), build (production build), preview (preview build)electron, path, fs). Use build.rollupOptions.output.manualChunks to split vendor libraries (react, react-dom) from app code.cd prototype-desktop && npm install to install dependencies
17-a) Generate prototype-desktop/tsconfig.json:@/ → src/
17-b) Generate prototype-desktop/.gitignore:prototype-desktop/electron/main.ts:ready, then create the main window in background. Swap when renderer is ready (did-finish-load).utilityProcess (Electron 22+) or Node worker_threads.backgroundThrottling: false only for windows that need real-time updates; leave default (true) for auxiliary windows to save resources.
17-d) Generate prototype-desktop/electron/preload.ts:prototype-desktop/index.html:prototype-desktop/src/theme/:
colors.ts — color palette from design system, dark/light mode tokensspacing.ts — spacing scale + large-scale tokens (panel gaps, sidebar width)typography.ts — font families, modular scale, platform-specific fontstokens.ts — re-exports all theme tokens + shadows, radii, motion config, keyboard shortcut tokensprototype-desktop/src/components/:
docs/design_philosophy.md MUST be implemented as a reusable component/class/CSS-custom-property primitive. It must be importable from any screen — not duplicated per-screen.19.5) PHASE 5A — Pilot screens & gate (multi-archetype, catches AI slop before full generation):
- Step 1 — Archetype classification & pilot pick:
- Classify every screen in docs/wireframes_desktop.md into one of these desktop archetypes: list/table, detail/inspector, form/settings, hub/dashboard, command-palette/overlay, editor/canvas, empty/cold-start.
- Pick TWO pilot screens from the two most-distinct archetypes present in the inventory (typically one consumption + one input, e.g., data table + settings, or editor + command palette). If only one archetype exists, fall back to a single pilot and note it.
- Step 2 — Pilot-only generation:
- Generate ONLY the 2 pilot .tsx files in prototype-desktop/src/screens/.
- Generate a TEMPORARY minimal prototype-desktop/src/App.tsx that routes ONLY between the 2 pilots (no full router yet).
- Ensure the Electron main.ts and preload.ts from step 17-c/17-d are wired so npm run dev launches the pilot view.
- Do NOT generate the remaining screens or the full router yet.
- Step 2.5 — PILOT GATE — observe → critique → specificity → auto-correct → user HOLD
Generator-as-judge fails: the same context that produced the pilot will not reliably catch its own slop. This block routes critique through a separate sub-agent context and runs up to 3 auto-correction cycles before presenting.
Desktop pilots run live in Electron (npm run dev). If Playwright + Electron is installed, screenshot the rendered window for the critique inputs. Otherwise critique runs against pilot .tsx source (degraded mode) — record pilot_degraded: no_playwright_electron in the critique log.
- **Step 2.5.0 — Neutral observation** (mandatory; BEFORE judgment).
For each pilot, write 5 plain factual statements about what renders (screenshot) or what the source would render (degraded).
**Banned vocabulary**: `signature move`, `aesthetic`, `archetype`, `philosophy`, `direction`, `taste`, `slop`, `generic`, `bold`, `restrained`, `premium`, brand names, the chosen aesthetic name. Use only colors, sizes, shapes, positions, counts, content categories.
Save to `prototype-desktop/src/screens/<pilot>.observations.md`.
- **Step 2.5.1 — Separate-context critique** (mandatory). Invoke `design-auditor` via the Task tool. **Do NOT inline-critique in the generator's context.**
Pass:
- the pilot screenshot path (if available) AND the pilot `.tsx` path
- `prototype-desktop/src/screens/<pilot>.observations.md`
- `docs/design_philosophy.md`
- `docs/design_system_desktop.md`
Ask for a 6-axis 1–5 score (Philosophy / Hierarchy / Execution / Specificity / Restraint / Variety), one cited evidence per axis referencing observation indices, and a list of slop signals.
Where ui-reviewer's scope applies (state coverage, copy usage), invoke `ui-reviewer` separately. Disjoint scopes (ISSUE-013) — surface both outputs.
Save the structured output to `prototype-desktop/src/screens/<pilot>.critique.md`.
- **Step 2.5.2 — Specificity check** (mandatory). Ask design-auditor:
*"Name 3 details visible in this pilot that ONLY make sense for THIS specific product / domain / user. Generic UI primitives don't count. Domain content does count (real entity names, the literal_quote from Reference Anchors, brand-specific shortcuts/units). Fewer than 3 → FAIL."*
The literal_quote (from ISSUE-012) counts as exactly **1** of the 3.
- **Step 2.5.3 — Auto-correction cycle** (hard cap N=3). If any score < 3, specificity FAIL, or slop signals fire:
1. Identify the patch layer (philosophy / system / layout / pilot only).
2. Apply the patch.
3. Re-observe → re-critique → re-specificity.
4. Increment cycle counter. Append to `prototype-desktop/src/screens/<pilot>.cycles.log`:
`cycle N: layer=<L> change="<summary>" scores=P5 H4 E5 S3 R5 V4 specificity=PASS|FAIL`.
5. **Hard stop at N=3.** After cycle 3, freeze and surface to the user with the full history.
Record final scores at the top of the pilot stylesheet/screen file: `/* pre-emit critique cycle=N: P5 H4 E5 S4 R5 V5 specificity=PASS */`.
- **Step 3 — PILOT GATE — present and HOLD for user**:
- Tell the user how to run:
```bash
cd prototype-desktop && npm run dev
```
- Share `prototype-desktop/src/screens/<pilot>.critique.md` and `<pilot>.cycles.log`.
- If Step 2.5 entered degraded mode (no Playwright/Electron), say so explicitly.
- Ask: "Please run the pilots and confirm:
(a) Is the **Signature Move** (`<paste exact text>`) visible and applied on both pilots?
(b) Do both pilots feel like `<aesthetic name>` and read as the same family across the two archetypes?
(c) Do the 3 product-specific details from the specificity check belong to *this* product?
(d) Any slop signals — Electron-wrapper-website feel, default OS chrome, generic Material/Fluent components, mobile-touch-sized targets?"
- WAIT for explicit approval before continuing to Phase 5B.
- **Step 4 — On rejection** (route to the correct layer):
- Signature Move wrong/absent → revisit Phase 2 step 9.
- Color / type / density tokens off → revisit Phase 3 design system.
- Layout reads as generic → revisit Phase 4 numeric layout commitments.
- Tokens are right but pilot implementation is generic → fix the pilot `.tsx` and components only.
- Do NOT proceed to Phase 5B with an unaddressed pilot rejection.
prototype-desktop/src/screens/:
docs/copy_guide.mdReact.lazy + Suspense to avoid loading everything upfrontprototype-desktop/src/App.tsx:
useEffect returns for event listeners, IPC subscriptions, and timers. Use AbortController for fetch calls.prototype-desktop/src/main.tsx:
package.json has correct scripts (dev, build)electron/main.ts exists with proper BrowserWindow setupelectron/preload.ts exists with contextBridgeindex.html exists as renderer entrytsconfig.json exists with strict mode.gitignore existssrc/screens/ and src/components/ for hardcoded style valuessrc/theme/docs/wireframes_desktop.mdsrc/screens/docs/copy_guide.md, not placeholder textdocs/interactions_desktop.md MUST be functional
27.3) Contrast sweep (CRITICAL — catches the failures that ship most):(color, background-color) pair on a screen, verify the WCAG ratio against its computed background: body text needs ≥ 4.5:1; large text (≥24px / ≥18px bold), icons, and focus rings need ≥ 3:1.--color-accent filling a text-bearing surface without a defined, verified --color-accent-ink; any dark panel (background lightness < 50%) that did not flip its text colour (ink-on-ink). Most-missed: text in a panel that switched background but inherited color; muted text on a tinted surface.file:selector, fix, and re-check before proceeding.
27.4) Slop-proof mechanics sweep (deterministic — grep .css/theme/screens):transition: all / transition-all; bare 1fr tracks on image-bearing grids (must be minmax(0, 1fr)); font-style: italic on heading/display selectors; a second position: sticky; top: 0; all-caps display with line-height < 1.0.overflow-x: clip on html+body; input/select fields satisfy the 8-state rules (constant border-width, outline-based focus ring, reserved helper slot, multi-channel disabled) from Anti-AI-Slop "CSS mechanics (renderer)".transition:all ≡ transition: all, top:0 ≡ top: 0, overflow-x:clip ≡ overflow-x: clip.file:line, fix, and re-sweep.
27.5) Signature Move check:docs/design_philosophy.md must contain a Signature Move with numeric/token specificity (not prose-only).src/components/ or src/theme/..tsx file in src/screens/ (including the pilots) must reference that reusable Signature Move primitive at least once.literal_quote: from docs/design_philosophy.md Reference Anchors.src/screens/*.tsx for the literal string. The string MUST appear verbatim in at least one screen file (inside a string literal, NOT inside a comment).literal_quote: "⌘K" MUST appear as the literal characters ⌘K — not Cmd+K, not interpolated from a variable, not inside {/* */}.React.memouseCallbackReact.lazy + Suspense for code splittingtransform, opacity, filter) — never animate width, height, top, leftwill-change MUST NOT be applied to more than 5 elements simultaneously (excessive use increases memory)contain: layout style paint SHOULD be applied to independently-updating panels (sidebar, content, detail)requestAnimationFrame throttle or CSS-based resize (flexbox/grid) — never unthrottled mousemoveuseEffect hooks MUST return cleanup functions for event listeners, IPC subscriptions, and timersbackgroundThrottling: true (default) unless real-time updates are requiredmanualChunkselectron, path, fs) MUST be externalized, not bundled
30.5) AI Tell sweep (CRITICAL):.tsx/.css file in src/screens/, src/components/, and theme/style files for the banned tells in "Specific AI Tells" (Anti-AI-Slop Rules): em-dash (—/–) in any string literal, flex calc() column math, generic person/brand names, fake-perfect numbers, section-number eyebrows, decorative version labels, <div>-based fake product UI, decorative status dots, locale/time strips.file:line, fix it, and re-sweep. Zero tolerance on em-dash and div-based fake product UI — these must be 0 before presenting. Match CSS patterns whitespace-insensitively (height:100vh ≡ height: 100vh).cd prototype-desktop
npm run dev
npm install)issues.md or STATUS.md updates./kickoff has already created issues, if additional UI/UX-related issues are needed, add them manually to issues.md or re-run /kickoff.docs/ux_spec.md not found: stop and suggest running /kickoff first (unless user explicitly opts to skip).docs/ cannot be created: stop and report filesystem error.docs/design_system_desktop.md./desktop-uiux overwrites all outputs — safe to retry.prototype-desktop/) can be safely deleted if not needed.These rules prevent Claude from converging on generic, forgettable desktop defaults.
Primary anchor — the Signature Move. The single most effective slop-blocker is the numeric/token-specific Signature Move defined in Phase 2 step 9 and enforced at the Phase 5A pilot gate (step 19.5) and Phase 5.5 step 27.5. Negative rules below are secondary; if the Signature Move is weak or missing, the rules below will not save the output.
NEVER:
INSTEAD:
nativeTheme — automatic dark/light switchingSpecific AI Tells (hard bans — sweep every screen before presenting). Concrete signatures LLMs default to. Banned unless the brief explicitly calls for one.
Content & data:
99.99%, round 50%, 1,234,567) → organic messy values (47.2%, +1 (312) 847-1928).—) and en-dash-as-separator (–): zero tolerance in all visible text (titles, labels, menu items, body, empty/error copy). Use a regular hyphen -, comma, period, colon, or line break. The single most-violated tell.Fake product UI:
<div> rectangles (fake chart, fake terminal, fake data table) to fill a welcome/empty screen. Use a real screenshot, generated image, real component, or skip it.v0.6.2-rc.1, last sync 4s ago) as decoration (a real app-version readout in About/status bar is fine).Decorative meta:
001 · Capabilities) or 01 / 4 pagination labels — name the topic in plain language.V0.6, BETA, EARLY ACCESS, ALPHA) as decoration unless the brief is explicitly a launch/preview.Lisbon 14:23 · 18°C) or mono-caps decoration strips (BRAND. MOTION. SPATIAL.) as chrome.· to max 1 per metadata line; never as a universal separator.Typography & interaction tells:
font-style: italic on h1–h6 / display / wordmark / <em> inside a heading is a top tell. Emphasis = weight, accent colour, or a drawn underline. Italic only inside running body copy.CSS mechanics (renderer) — deterministic, all mandatory:
grid-template-columns), NEVER flex percentage math (width: calc(33% - 1rem)), which breaks on gap rounding.overflow-x: clip on BOTH html and body (use clip, not hidden — preserves descendant sticky/fixed); no horizontal scroll at any window width down to 320px.minmax(0, 1fr), never bare 1fr.overflow-wrap: anywhere; min-width: 0; all-caps display type uses line-height ≥ 1.0.position: sticky; top: 0 (the top chrome/toolbar); other sticky elements offset to top: var(--banner-height) with a lower z-index than the toolbar.align-items: center.transition: all / transition-all — name properties. Focus rings appear instantly (no transition on outline) and use outline, never border. Reserve overshoot easings for drag/physical interactions only.border-width across states (change outline/box-shadow/border-color); outline-based focus ring; input height == adjacent button height; reserve helper/error slot with min-height: 1lh; disabled = opacity + cursor: not-allowed + disabled/aria-disabled (never opacity alone).docs/design_philosophy.md and docs/copy_guide.md from web /uiux when they exist. Don't duplicate, extend.npx claudepluginhub pillip/claude-dev-kit --plugin claude-dev-kitGenerates a mobile design system, wireframes, and React Native (Expo) prototype from kickoff outputs (UX spec, requirements, architecture). Run after /prd → /kickoff.
Provides desktop UI patterns for native/cross-platform apps: menus, toolbars, status bars, layouts (document/task-centric), keyboard shortcuts for design reviews and requirements.
Craft-first product UI design for dashboards, admin panels, SaaS apps, settings, and data interfaces. Focuses on visual hierarchy, tokens, states, and design-system consistency.