* docs: add PRD for design detector hook integration Plans a PostToolUse hook for Claude Code and Codex that runs the existing design detector after every relevant file write and feeds findings back to the agent as advisory system-reminder context. No implementation in this commit; covers UX, technical design, build pipeline changes, distribution, coverage tradeoffs, and rollout. Co-authored-by: Cursor <cursoragent@cursor.com> * docs: revise hook PRD with best-practices review Folds in the P0/P1/P2 findings from an online best-practices critique against the official Claude Code and Codex hook references plus 10+ 2026 community guides and similar prior-art tools (claw-hooks, claude-code-hooks-mastery). Key changes: - Exec form everywhere (Codex snippet was shell form), with Windows rationale. - Default timeout dropped from 10s to 5s. - Re-entrancy guard (CLAUDE_HOOK_DEPTH) and per-file edit counter. - Session-scoped finding dedup promoted from open question to v1. - Per-language inline-ignore syntax map (HTML/JSX/CSS/JS). - Hard-skip rules for sensitive paths and generated/lock files. - Honest framing about Claude Code lacking per-plugin hook disable. - Honest framing about Bash-written files being invisible in v1. - Codex Windows-not-supported call-out, feature flag note, trust ceremony detail. - Optional NDJSON audit log via IMPECCABLE_HOOK_LOG. - Findings cap lowered 8 → 5 with attention-budget rationale. - Versioned envelope ([impeccable@1]) on rendered template. - Expanded test plan, decision log, and stdin payload appendix. Co-authored-by: Cursor <cursoragent@cursor.com> * feat(hooks): ship the design detector hook for Claude Code and Codex Implements docs/hooks-prd.md: a PostToolUse hook that runs the impeccable design detector after every Edit/Write/MultiEdit on a UI file and pushes findings into the agent's next-turn context as a short system reminder. Silent on clean files. Never blocks an edit. Why this matters: today, design slop (side-tab borders, gradient text, purple/cyan palettes, bounce easing, etc.) only gets caught when a human notices or someone explicitly runs /impeccable audit. The hook closes the loop at the moment slop is written. What ships in v1 - skill/scripts/hook.mjs: PostToolUse entry. Reads stdin, runs the detector in-process (no `npx impeccable` cold start), emits hookSpecificOutput.additionalContext when fresh findings exist. - skill/scripts/hook-lib.mjs: extracted helpers (config, cache, filter, render, audit log, runHook orchestrator). 100% unit-testable. - skill/scripts/hook-session-start.mjs: SessionStart greeting, gated by a project-scannable probe + 30-day throttle. - skill/scripts/hook-admin.mjs: backs /impeccable hooks on/off/status/ignore-rule/ignore-file/reset. Hardening built in - Re-entrancy guard (IMPECCABLE_HOOK_DEPTH) so the hook can never recursively spawn itself. - Hard-skip regexes for sensitive paths (.env, .pem, id_rsa, secrets, credentials, .git) and generated/lock/build output. These fire before the file is even read; cannot be turned off via config. - Path-traversal check on the inbound file_path. - Session-scoped dedup keyed by (session, file, rule, line) so the same finding never lands in context twice. Prevents the ~12.5K wasted tokens per chatty session called out in the PRD. - Per-(session, file) edit counter with a one-shot suppression notice on the 7th edit, silent after. - Fail-open contract: every error path returns exit 0 with no stdout. Optional NDJSON audit log via IMPECCABLE_HOOK_LOG. Three kill switches (precedence high to low): 1. IMPECCABLE_HOOK_DISABLED env var (1/true/yes/on, case-insensitive) 2. .impeccable/hook.json `enabled: false` 3. /impeccable hooks off slash command (writes the JSON) Inline ignores are language-aware. `// impeccable: ignore <rule>` for JS/TS, `<!-- impeccable: ignore <rule> -->` for HTML/Vue/Svelte/Astro, `{/* impeccable: ignore <rule> */}` for JSX/TSX, `/* impeccable: ignore <rule> */` for CSS. `*` matches any rule. Directive applies to the next non-blank line. Same shape as ESLint, Stylelint, Biome. Build pipeline - scripts/lib/transformers/hooks.js: per-provider hooks.json builders, plus the slim .codex-plugin/plugin.json manifest. - providers.js: emitHooks: 'claude' for claude-code, emitHooks: 'codex' for codex and agents. Codex also emits emitCodexPlugin. - factory.js: emits hooks/hooks.json next to the skills tree. - build.js: syncs hooks/ into harness roots and into the slim plugin/ subtree; writes .codex-plugin/plugin.json. Build is idempotent (verified: 98 staged files unchanged across two runs). Claude Code wiring uses exec form (command + args) and the ${CLAUDE_PLUGIN_ROOT} placeholder. Matcher: Edit|Write|MultiEdit. `if:` glob filters to UI extensions before spawning Node. PostToolUse timeout 5s, SessionStart timeout 3s. Codex wiring uses ${PLUGIN_ROOT} (Codex's native placeholder), matcher Edit|Write|apply_patch, no `if:` analog (the script does the extension filter). macOS and Linux only; hooks are disabled on Windows in current Codex builds. The trust ceremony and feature flag are documented in README.md. Routing - /impeccable hooks lives outside the 23-command router table on purpose: it is plumbing, not a design skill. The hidden routing slot is added to SKILL.md alongside pin/unpin so the LLM knows to dispatch it. The 23-command count and all stale-count validators remain happy. Tests - tests/hook.test.mjs: 38 unit tests covering env parsing, config load + defaults + malformed, cache round-trip + GC, ignoreRules/minSeverity/inline ignores (all four languages), globbing with **/*/{a,b}, render template with cap + clamp + 0-line prefix drop, audit log NDJSON, payload event-name parameterization, re-entrancy, kill switches, sensitive-path + generated-path + traversal skips, allowlist filter, config ignoreFiles, edit counter cycle including the 7th-edit notice, MultiEdit and apply_patch payload shapes, detector throw swallow, malformed stdin, missing file race. - tests/hook-build.test.mjs: 18 integration tests covering hook manifest shape (matcher, timeouts, exec form, if: glob, placeholders), Codex differences (${PLUGIN_ROOT}, no if:, no SessionStart), Codex plugin manifest (no inline hooks field to avoid the duplicate-file error), routing across the hooksJsonFor table, and presence of all three committed artifacts plus the bundled detector the runtime relative-import path depends on. Full suite: 175 bun tests + 186 node tests, all green. Docs - README.md: new "Design hook" section explaining default behavior, per-project / global / inline disable paths, the JSON schema knobs, the audit log debug flag, and the slop / a11y coverage split. - HARNESSES.md: flips the `hooks` row for Codex from No -> Yes (Claude was already Yes), adds a per-harness hook-surface table with the manifest location and matcher each provider uses. Open questions from the PRD intentionally deferred to v2: Bash-write blind spot, effort-aware suppression, Stop-hook session summary, per-rule severity, async hook mode. None block v1. Co-authored-by: Cursor <cursoragent@cursor.com> * Fix Codex hook scanning: apply_patch paths and co-located stylesheets Parse file targets from Codex apply_patch command bodies, co-scan imported and sibling CSS when UI components are edited, drop the git-sweep PostToolUse group, and align Codex SessionStart manifest and trust docs with the official hooks spec. Co-authored-by: Cursor <cursoragent@cursor.com> * Gitignore hook session cache and drop local test HTML Hook dedup/throttle state in .impeccable/hook.cache.json is per-project runtime data like other .impeccable/ sidecars. Remove an untracked bad-nested-flexbox scratch page from site/public/. Co-authored-by: Cursor <cursoragent@cursor.com> * Fix Claude Code hook: drop Edit-only if filter so Write/MultiEdit fire Claude's if permission rule binds to one tool name, so Edit(*.{…}) never spawned the hook on Write or MultiEdit despite the matcher listing them. Extension filtering now lives in hook-lib on both Claude and Codex. Co-authored-by: Cursor <cursoragent@cursor.com> * Surface Cursor design findings via stop-hook followup Replace dropped postToolUse additional_context with afterFileEdit recording and a one-shot stop followup_message so anti-pattern nudges reach the agent. Co-authored-by: Cursor <cursoragent@cursor.com> * Fix design hook packaging and scans * Fix Cursor hook pending bucket fallback * Fix Sass hook scan coverage * Fix Cursor hook review findings * Fix session start dead hook normalization * Fix hook config and relative scan paths * Remove SessionStart design hook * Remove redundant afterFileEdit normalization * Fix Cursor suppression and module style scans * Fix sensitive path hook filter * Fix disabled Cursor stop hook emission * Refresh hook harness artifacts * Fix Cursor hook manifest install * Add hook ignore-value support * Ignore hook runtime files locally * Fix Codex plugin hook packaging * fix: address PR review bot findings Block numeric hook depth counters from re-entering. Avoid following stylesheet imports from traversal-looking hook targets. * fix: gate ignore-value suggestions by supported rules Only render exact ignore-value commands when the same finding can be suppressed by ignoreValues. * Package Codex plugin as hook-only * Remove Codex plugin packaging * Recover hook install probe plumbing * Remove Codex hook packaging follow-up doc * Remove extra hook docs and skill wording changes * Install real design hooks via skills CLI * Add provider hook smoke runner * Fix Cursor hook delivery with preToolUse gate * Simplify Cursor hook install to preToolUse * Clarify confirmed hook exceptions * Persist hook ignores in shared config * Guard font hook exceptions * Fix hook install after main rebase * Fix hook scan target handling * fix: address hook review findings * Address hook review feedback * Stabilize DeepSeek insert live fixture * Fix Cursor hook Python shell write bypass --------- Co-authored-by: Cursor <cursoragent@cursor.com>
12 KiB
Impeccable
Design guidance for AI coding agents. 1 skill, 23 commands, live browser iteration, and 41 deterministic detector rules for AI-generated frontend design.
Quick start: From your project root, run
npx impeccable skills install, then run/impeccable initinside your AI coding tool. Full docs: impeccable.style.
Why Impeccable?
Anthropic's frontend-design was the first widely-used design skill for Claude. Impeccable started from there.
Every model trained on the same SaaS templates. Skip the guidance and you get the same handful of tells on every project: Inter for everything, purple-to-blue gradients, cards nested in cards, gray text on colored backgrounds, the rounded-square icon tile above every heading.
Impeccable adds:
- One setup flow.
/impeccable initwritesPRODUCT.mdand offersDESIGN.md, so later commands know the audience, brand/product lane, voice, anti-references, colors, type, and components. - 23 commands. A shared design vocabulary with your AI:
polish,audit,critique,distill,animate,bolder,quieter, and more. - 41 deterministic detector rules plus LLM-only critique checks. The CLI and browser extension run the deterministic rules with no LLM and no API key.
What's Included
The Skill: impeccable
The skill installs as one command:
/impeccable <command> <target>
Start every new project with:
/impeccable init
init asks whether the surface is brand (marketing, landing, portfolio) or product (app UI, dashboard, tool), then writes project context that every later command reads.
23 Commands
All commands are accessed through /impeccable:
| Command | What it does |
|---|---|
/impeccable craft |
Full shape-then-build flow with visual iteration |
/impeccable init |
One-time setup: gather design context, write PRODUCT.md and DESIGN.md, configure live mode, recommend next steps |
/impeccable document |
Generate root DESIGN.md from existing project code |
/impeccable extract |
Pull reusable components and tokens into the design system |
/impeccable shape |
Plan UX/UI before writing code |
/impeccable critique |
UX design review: hierarchy, clarity, emotional resonance |
/impeccable audit |
Run technical quality checks (a11y, performance, responsive) |
/impeccable polish |
Final pass, design system alignment, and shipping readiness |
/impeccable bolder |
Amplify boring designs |
/impeccable quieter |
Tone down overly bold designs |
/impeccable distill |
Strip to essence |
/impeccable harden |
Error handling, i18n, text overflow, edge cases |
/impeccable onboard |
First-run flows, empty states, activation paths |
/impeccable animate |
Add purposeful motion |
/impeccable colorize |
Introduce strategic color |
/impeccable typeset |
Fix font choices, hierarchy, sizing |
/impeccable layout |
Fix layout, spacing, visual rhythm |
/impeccable delight |
Add moments of joy |
/impeccable overdrive |
Add technically extraordinary effects |
/impeccable clarify |
Improve unclear UX copy |
/impeccable adapt |
Adapt for different devices |
/impeccable optimize |
Performance improvements |
/impeccable live |
Visual variant mode: iterate on elements in the browser |
Use /impeccable pin <command> to create standalone shortcuts (e.g., pin audit creates /audit).
Usage Examples
/impeccable audit blog # Audit blog hub + post pages
/impeccable critique landing # UX design review
/impeccable polish settings # Final pass before shipping
/impeccable harden checkout # Add error handling + edge cases
Or use /impeccable directly with a description:
/impeccable redo this hero section
Anti-Patterns
The skill includes explicit guidance on what to avoid:
- Don't use overused fonts (Arial, Inter, system defaults)
- Don't use gray text on colored backgrounds
- Don't use pure black/gray (always tint)
- Don't wrap everything in cards or nest cards inside cards
- Don't use bounce/elastic easing (feels dated)
See It In Action
Visit impeccable.style to see before/after case studies of real projects transformed with Impeccable commands.
Installation
Option 1: CLI installer (Recommended)
From the root of your project, run:
npx impeccable skills install
This auto-detects your harness and writes the build compiled for it to the right location (.claude/skills/, .cursor/skills/, etc.). On Claude Code, Cursor, and Codex, it also installs the provider-native hook manifest. Works with Cursor, Claude Code, Gemini CLI, Codex CLI, and every other supported tool. Reload your harness afterward.
To refresh an existing install, run:
npx impeccable skills update
Codex users should open /hooks after install or update and approve the project hook when prompted. Codex tracks trust by hook definition, so updates that change .codex/hooks.json can require approval again.
Option 2: Git Submodule
For teams that want to keep Impeccable vendored and updated through Git, add this repo as a submodule and link the compiled provider build into your harness folders:
git submodule add https://github.com/pbakaus/impeccable .impeccable
npx impeccable skills link --source=.impeccable --providers=claude,cursor
git add .gitmodules .impeccable .claude .cursor
git commit -m "Add Impeccable skills"
Use the providers your project needs, for example claude, cursor, gemini, codex, github, opencode, pi, qoder, trae, trae-cn, or rovo-dev. The command links individual skill folders from .impeccable/dist/universal/ and leaves existing real skill directories untouched unless you pass --force.
To update later:
git submodule update --remote .impeccable
npx impeccable skills link --source=.impeccable --providers=claude,cursor
Option 3: Download from Website
Visit impeccable.style, download the ZIP for your tool, and extract to your project.
Option 4: Copy from Repository
Cursor:
cp -r dist/cursor/.cursor your-project/
Note: Cursor skills require setup:
- Switch to Nightly channel in Cursor Settings → Beta
- Enable Agent Skills in Cursor Settings → Rules
Claude Code:
# Project-specific
cp -r dist/claude-code/.claude your-project/
# Or global (applies to all projects)
cp -r dist/claude-code/.claude/* ~/.claude/
OpenCode:
cp -r dist/opencode/.opencode your-project/
Pi:
cp -r dist/pi/.pi your-project/
Gemini CLI:
cp -r dist/gemini/.gemini your-project/
Note: Gemini CLI skills require setup:
- Install preview version:
npm i -g @google/gemini-cli@preview- Run
/settingsand enable "Skills"- Run
/skills listto verify installation
Codex CLI:
# Project-local
cp -r dist/agents/.agents your-project/
mkdir -p your-project/.codex
cp dist/codex/.codex/hooks.json your-project/.codex/hooks.json
# Or install the skill user-wide. Copy .codex/hooks.json into each project
# where you want the design hook to run.
mkdir -p ~/.agents/skills
cp -r dist/agents/.agents/skills/* ~/.agents/skills/
The asset-producer subagent ships nested inside the skill's own
agents/folder, which Codex auto-discovers. No separate.codex/agents/copy is needed. The hook is project-local because Codex discovers hooks from.codex/hooks.jsonnext to trusted project config.
GitHub Copilot:
cp -r dist/github/.github your-project/
Trae:
# Trae China (domestic version)
cp -r dist/trae/.trae-cn/skills/* ~/.trae-cn/skills/
# Trae International
cp -r dist/trae/.trae/skills/* ~/.trae/skills/
Note: Trae has two versions with different config directories:
- Trae China:
~/.trae-cn/skills/- Trae International:
~/.trae/skills/After copying, restart Trae IDE to activate the skills.
Rovo Dev:
# Project-specific
cp -r dist/rovo-dev/.rovodev your-project/
# Or global (applies to all projects)
cp -r dist/rovo-dev/.rovodev/skills/* ~/.rovodev/skills/
Qoder:
# Project-specific
cp -r dist/qoder/.qoder your-project/
# Or global (applies to all projects)
cp -r dist/qoder/.qoder/skills/* ~/.qoder/skills/
Usage
Once installed, every command runs through the single /impeccable skill:
/impeccable audit # Find issues
/impeccable polish # Final cleanup
/impeccable distill # Remove complexity
/impeccable critique # Full design review
Type /impeccable alone to see the full command list.
Most commands accept an optional argument to focus on a specific area:
/impeccable audit the header
/impeccable polish the checkout form
If you reach for one command often, pin it with /impeccable pin audit to get /audit as a standalone shortcut.
Note: Codex uses skills here, not /prompts: commands. Open /skills or type $impeccable. Repo-local installs live in .agents/skills/; user-wide installs live in ~/.agents/skills/. GitHub Copilot uses .github/skills/. Restart the tool if a newly installed skill does not appear.
Design hook
On Claude Code, Codex, and Cursor, npx impeccable skills install and npx impeccable skills update install a provider-native hook manifest along with the skill payload. The hook runs the Impeccable design detector on direct UI file edits and surfaces findings back into the agent flow. Claude Code and Codex surface findings after the edit. Cursor blocks bad proposed writes before they land.
Installed hook surfaces:
- Claude Code:
.claude/settings.jsonruns${CLAUDE_PROJECT_DIR}/.claude/skills/impeccable/scripts/hook.mjs. - Cursor:
.cursor/hooks.jsonruns.cursor/skills/impeccable/scripts/hook-before-edit.mjs. - Codex:
.codex/hooks.jsonruns.agents/skills/impeccable/scripts/hook.mjs.
The installer preserves unrelated hook entries and settings. If a hook manifest is malformed, install/update aborts by default; rerun with --force to back up the malformed file as .bak and replace it.
If you want skills without hook manifests, pass --no-hooks to npx impeccable skills install or npx impeccable skills update.
For debugging, set IMPECCABLE_HOOK_LOG=/path/to/hook.ndjson to write one NDJSON line per hook invocation. Leave it unset for normal use.
Codex requires one platform step that Impeccable cannot safely skip: open /hooks after install or update and approve the project hook. There is no Codex marketplace/plugin install flow for this hook.
Manual copy commands are fallback/debug instructions. The normal path is:
npx impeccable skills install
npx impeccable skills update
CLI
Impeccable includes a standalone CLI for detecting anti-patterns without an AI harness:
npx impeccable detect src/ # scan a directory
npx impeccable detect index.html # scan an HTML file
npx impeccable detect https://example.com # scan a URL (Puppeteer)
npx impeccable detect --fast --json . # regex-only, JSON output
The detector catches 41 deterministic issues across AI slop (side-tab borders, purple gradients, bounce easing, dark glows) and general design quality (line length, cramped padding, small touch targets, skipped headings, and more).
Supported Tools
Community & Ecosystem
Join the community and ecosystem conversations:
- GitHub Discussions: file bugs, request features, and help newcomers.
- Impeccable on npm: grab the CLI, follow releases, and star the package.
- Follow @pbakaus on Twitter for release notes, sample lint reports, and video highlights of new rules.
Contributing
See DEVELOP.md for contributor guidelines and build instructions.
License
Apache 2.0. See LICENSE.
Created by Paul Bakaus