wth2jhl.online

Back

Impeccable

仓库:pbakaus/impeccable ↗ · 官网:impeccable.style ↗ Apache-2.0 · 17 个 crate / 约 1.9 万行 Rust · 1 个 skill · 24 commands · 61 detector rules · 16 个 AI harness 当前最后更新 2026-09-22(e0881d2 —— 修「DESIGN.md 自定义 token 被误判」)

如果你过去半年让 Claude Code、Cursor、Codex 写过任何前端,你大概注意到了三件事:

  1. 字体永远是 Inter,渐变永远是紫到蓝;
  2. 卡片永远在卡片里,kicker 永远在 heading 上;
  3. 没人告诉模型这有什么问题,因为审美判断没法写进 commit hook。

但 Anthropic 的 frontend-design ↗ 开源之后,这件事第一次有了标准答案 ——「这是 AI 生成 UI 的指导 skill」。Paul Bakaus —— Google Web Designer 创始人、Awwwards 评委 —— 在这之上做了 Impeccable ↗,把它从一份「指南」推到了「装好就能用」:

不只是告诉 AI 「你设计的不好」,而是让它的 24 个命令共享同一套设计词汇,让它的 61 条规则在它写代码时就把它拦下来,让它写的页面在你本地的 dev server 里就能让你挑、选、生、接、入。

这篇文章会按下面的顺序展开:

  • 第一部分先讲问题 —— 「AI 写 UI 烂」这件事为什么不是模型的锅,而是缺乏可执行反馈
  • 第二节把一核三层铺开看:SKILL.md / 24 commands / 61 detector rules
  • 第三节挑三个最有意思的设计决策拆:craft-floor 的 Verify+Refuse、live browser 的 poll 循环、detector 的 Design System 信任边界
  • 第四节是与 Pi、Cline、Aider 的对比 —— 设计 skill 该怎么跨 harness 共享
  • 最后讲讲它的贡献,以及这件事对我们做工程的人意味着什么

文章较长,大约 30 分钟读完。建议先在心里装一个具体的场景:你在做一个 SaaS landing page,Cursor 帮你写 hero,默认输出是紫色渐变 + Inter 字体 + 三个相同尺寸的卡片堆叠 —— 带着这个「默认 AI 输出」读,效果更好。


一、当「设计」变成「拍脑袋」#

设计是真实的世界。

把这句话翻译成工程语言:审美判断,本质上是高度主观、缺乏正反馈循环的事。

一个后端程序员写 API,输入是参数,输出是 JSON,中间跑了多少个 case 都能量化。CI 跑过没?性能达标没?安全审计过没?这些都是「可执行的反馈」。

但一个前端程序员写组件,输入是「我要做登录页」,输出是一段 JSX。这段 JSX 好不好,取决于太多不能量化的东西:

  • 用户在 1.5 秒后能不能找到「登录」按钮?(没有 ground truth)
  • 字体 Inter 用在这里到底对不对?(看 brand)
  • 卡片嵌套 3 层是不是太重了?(看 audience)
  • 渐变文字在彩色背景上还能不能读?(看 contrast)

而当写代码的不是人而是 AI,这件事更糟 —— 你甚至没法问「你为什么这么设计」,因为它大概率回答「这是我训练数据里最常见的做法」。

Impeccable 的切入点不是「教 AI 更好的审美」,而是把可量化的问题找出来,做成规则,在 AI 还没写完时拦下来。

1.1 61 条规则的样本#

为了让你感受「什么样的事是可以做成规则的」,先看几条:

规则 ID触发条件为什么是问题
side-tabborder-left/right: ≥2px + border-radius把卡片当表格单元 —— AI 的招牌动作
gradient-textbg-clip: text + bg-gradient想做「高亮词」的廉价做法,几乎是 AI 出身的指纹
overused-fontInter / Geist / system sans 命中训练数据里最常见的 SaaS 字体,AI 不查直接 default
gray-on-colortext-gray-* 在 bg-red-500 类色上灰字 + 彩底 = 视觉打滑,白底灰字是默认到彩底不变
bounce-easingcubic-bezier(0.68,-0.55,0.265,1.55) 或 animate-bounce弹性曲线 = 2003 年的风,AI 没受过 motion design 教育
ai-color-palette紫色 (260-310°) 文字 + heading 上下文「AI 高端感」的第一反应,实测 impeccable-site 上 218 次
layout-transitiontransition: width/height/top/left/...触发 layout thrashing,GPU 加速不了的属性动画
em-dash-overuseem-dash 数量 ≥ 阈值 / 文本长度「streamline your — empower your — unleash your」的句式

注意这些规则不是「我觉得这样不好看」,而是「客观上 + 经验上 + 大概率上这件事有问题」。每一条都有触发模式、有量化阈值、有明确的修复建议。

1.2 规则的运行方式#

这些规则装在三个地方:

  1. npx impeccable detect <dir> —— CLI,纯静态扫
  2. 浏览器扩展 —— 装上之后扫线上站点
  3. 设计 hook —— 装在 Claude Code / Cursor / Codex / GitHub Copilot / Grok 的 settings.json,AI 写完一文立刻跑

第三种是关键 —— 不是「你让 AI 设计完去扫一遍」,而是「AI 一边写一边被拦」。当模型写出一个带 border-left: 4px solid blue 的 div,hook 立刻返回:

❌ side-tab: border-left: 4px solid #3B82F6 + border-radius: 8px
   Impeccable: A colored side border above 1px on a rounded element
   makes the element look like a tab, not a card. Replace with a
   badge, icon, or weight/size emphasis.
plaintext

模型拿到这条反馈,能改的就地改;不能改的会写在它的解释里。


二、一核三层#

Impeccable 的架构分三层,共享一个 SKILL.md。下面这张图是从 README 抠出来的全景:

架构

下面分三层拆开。

2.1 SKILL.md —— 跨 16 个 harness 的契约#

第一层是 SKILL.md,一个标准的 agentskills.io ↗ 规范的 skill 文件。它定义:

  • name: impeccable
  • description: 「Use when the user wants to design, redesign, shape, critique, audit, polish, clarify, distill, harden, optimize, adapt, animate, colorize, extract, or otherwise improve a frontend interface. …」
  • allowed-tools: Bash(npx impeccable *) + Bash({{scripts_path}}/impeccable *)
  • 入口文档:Setup 步骤 + 24 个命令 + routing 逻辑

注意 allowed-tools 字段 —— 这是 Anthropic 推出 Skill 规范 ↗ 之后,Impeccable 第一次把所有执行路径都明示出来。不是「AI 可以做一切」,而是「这个 skill 只会通过这两个 launcher 执行命令」。

这是渐进披露(progressive-disclosure)的标准做法:SKILL.md 只放目录,不展开具体内容;每个 reference/<cmd>.md 文件是 lazy load 的,只在用到时才读。

但 Impeccable 走得更远 —— 它自己实现了一套 launcher(scripts/impeccable),直接 spawn 一个 Rust 编译的引擎二进制:

npx impeccable install    # CLI installer,装到项目 .impeccable/
npx impeccable update    # 更新
npx impeccable detect <dir>  # 跑检测
bash

不需要 Node runtime(除了 npx 本身),不需要 Python,不需要任何依赖。Windows 下有 impeccable.cmd 后备。整个二进制下载一次缓存到 ~/.impeccable/bin/,后续纯本地执行。

这种「离线引擎 + 多 harness 适配」的设计,直接对比 Pi agent harness 那种「TypeScript 全栈、跟着 harness 走」的路线,完全是另一种思路。

2.2 24 个命令 —— 共享一套设计词汇#

第二层是 24 commands。这是用户实际使用 Impeccable 的接口 —— 在 Claude Code 里打 /impeccable polish the hero,或者在 Cursor 里 @impeccable audit blog。

24 个命令不是按「技术动作」分类的(不是「review」「fix」「generate」),而是按**「用户此刻想要什么」**分类:

24 个命令全景

这张图一目了然,我把每一类的边界讲一下:

  • Build(5 个) —— 搭建阶段,从产品真值到视觉世界。init 写 PRODUCT.md;shape 写 UX 计划;document 从代码生成 DESIGN.md;extract 把通用件抽进设计系统。
  • Evaluate(2 个) —— 评估,不修东西。critique 是 UX 设计评审(启发式打分),audit 是技术质量(a11y/perf/responsive)。
  • Refine(6 个) —— 修整,在已存在的设计上做微调。polish 是上线前的最后一轮;bolder 放大胆子;quieter 降一档;distill 砍复杂度;harden 错误状态/i18n/边界;onboard 首次使用/空状态。
  • Enhance(6 个) —— 加料,在已存在的设计上加维度。animate motion;colorize 战略色;typeset 字体;layout 间距;delight 记忆点;overdrive 技术极致手段。
  • Fix(3 个) —— 修,具体问题。clarify UX copy;adapt 多设备;optimize 性能。
  • Iterate(2 个) —— 迭代,在浏览器里做。live 是人工挑元素;generate 是自动出 N 个变体。

注意没有 fix bug 类 —— Impeccable 不修功能性 bug,只管设计。这是个清晰的边界:它不替代你的 IDE 的 debug 工具,不替代你的 a11y 检查器,它专门管「设计」这件事。

这种分类让命令语义对用户是清晰的:你打 /impeccable bolder hero,模型立刻知道你要「让 hero 更夸张」,不是「让它更紧凑」或「修一个 bug」。

2.3 61 条 detector 规则 —— 三引擎并联#

第三层是 61 detector rules,装在 crates/core/src/checks/ 和 crates/browser/src/ 里。这是 Impeccable 真正的「设计规则库」,也是最有技术含量的一层。

它的核心架构是三引擎并联:

  • regex 引擎 —— crates/detect/src/regex_matchers.rs,1725 行。源码静态扫,管 Tailwind class、CSS 文本、JSX 的字符串内容。它跑得快(几千行 CSS 一秒内),但它不知道 DOM 结构。
  • **HTML 引擎** —— crates/html/`,DOM 解析 + 模式匹配。它管结构(heading 层级、链接数量)和文本内容(em-dash 数量、numbered section markers)。
  • **browser 引擎** —— crates/browser/`,1700+ 行,跑真实 Chrome,读 computed style。它管动态效果(rgb 转 oklch、background-blend-mode、actual rendered color)。

每一条规则都跑全部三个引擎 —— 比如 side-tab 既能 regex 命中 css 里的 border-left: 4px solid,也能 HTML 引擎扫到带 border-left 的 div,也能 browser 引擎从 computed style 里读出来。这就是为什么 check_element_*_dom 系列函数会出现在 crates/core/src/browser/element_checks.rs。

为了让你感受「规则为什么这么写」,我把 side-tab 的判定逻辑抠出来 —— 这是从 crates/core/src/checks/rules.rs 第 35 行的 check_borders 函数:

注意三件事:

  1. 置信度条件 —— 「其他三边都 ≤1px 或 w ≥ max_other × 2」。这不是「凡是左侧 border 就报」,而是「左侧比其他三边明显更粗」。AI 默认写法往往是 border: 1px solid; border-left: 4px solid #color;,所以 max_other × 2 这个条件专门抓住这种「不对称」模式。
  2. 副作用豁免 —— radius > 0.0 走 side-tab,否则阈值要 ≥3px 才报(纯几何上的边线不算)。
  3. top/bottom 走另一条规则 border-accent-on-rounded —— 因为顶部彩色边线在卡片上有可能是设计意图(像 Notion 的 icon tile),不全是错。

这种「规则不是阈值,是节奏」的写法贯穿所有 61 条规则。规则的目的是「拦下大概率是错的写法」,而不是「定义正确」。

2.4 16 个 harness 适配#

Impeccable 一份 SKILL.md,跑在 16 个 AI 编程工具上:

16 个 harness

它怎么做到的?关键是 「skill 是文本,binary 是 Rust」 这个分工:

  • skill 这层是纯文本(SKILL.md + reference/*.md),所有 harness 都能读;
  • 二进制这层是 Rust 自包含的,所有平台都能跑;
  • scripts/impeccable 是 shim 脚本,handler 是 Bash 命令,所有 harness 都允许。

所以「适配一个新 harness」的边际成本是写一份 5KB 的 hook manifest({command_prefix}}impeccable hook),把它写到 harness 的 settings.json/hooks.json,让 harness 在模型写完文件后调用一次 impeccable detect。

这 16 个 harness 包括:Claude Code、Cursor、Codex、GitHub Copilot、Gemini CLI、Pi、OpenCode、Grok Build、Hermes、Kiro、Trae、Rovo Dev、Qoder、Vibe、Veto、Antigravity —— 都是当前主流或新兴的 AI 编程工具。


三、三个最有意思的设计决策#

把 Impeccable 当 skill 读完,我挑三个让我觉得「这个团队是认真在生产环境里被咬过」的设计决策。

3.1 craft-floor.md 的「Verify + Refuse」双面#

每个 init 流程写完 PRODUCT.md 之后,模型必须读 reference/craft-floor.md 才能开始改 UI。这份文件分两面:

  • Verify(9 条交付底线) —— 每一条都是「已交付」的检查:对比度、阴影有方向、间距有节奏、tracking 下限、motion 一次 authored moment、States 五件套、Browser surfaces(selection / caret / scrollbar / focus ring / 表格数字)、Copy 设计、Coverage。
  • Refuse(20+ 条默认套路) —— 不写「禁止」,而写「默认」。同尺寸卡片堆叠、卡片套卡片、hero-metric 模板、kicker / eyebrow(这个是「ban」不是「default」,任何简报都回不来)、01/02/03 章节编号、modal for 无中断任务、gradient text、glass + blur、≥2px 彩色 border-left、硬偏移 box-shadow、sparkline / 进度环、Unicode 当图标、几何遮罩假装 alpha 蒙版、按品类选亮/暗…

craft-floor 全图

注意 Refuse 部分的语言是「默认」(default),不是禁止(ban)。craft-floor 的第一句话:

Load this after the direction is settled, and build without announcing the checklist. A pinned brief or the committed visual world overrides anything here; your own habit does not.

这意味着:用户简报里明确写了「我就要 neobrutalist,4px 4px 0 硬偏移」,craft-floor 让路;但如果用户没写,模型就选 Refuse 列表里被警告的那条。

这是一种**「礼貌的默认」的设计**:它不剥夺你的选择,只是把选择变成显式。每一个默认被推翻,都要一次「我就要这个」的显式声明。

这种「简报赢默认」(the brief wins)的写法贯穿整个 Impeccable —— 在 SKILL.md 第 28 行也有同样的话:「Honor pinned aesthetics, eras, materials, fonts, and palettes even when they conflict with a saturated-pattern warning. Redirecting a clear brief toward your taste is failure.」

3.2 live browser 的 poll 循环与 journal 重连#

live mode 是 Impeccable 最复杂的设计。它的工作流是:

live 闭环

但让它做对的关键不在「五步闭环」本身,而在三个技术决策:

  1. poll 循环不超时 —— 默认 600,000ms(10 分钟)长连。Claude Code 调 background task,Codex 调长 foreground,Cursor 调一shot poll。轮询活着,模型在场。
  2. 变体在源上,不浏览器 —— 模型在源文件上写 wrapper 块一次性写好,变体全部 net-new,不切换 progressive publishing,不重新发现 element。原子单次编辑。
  3. accept 不只展示 —— carbonize 把变体真正写入源码,live-complete 收尾,journal append-only。中途打断 = 下次续,不靠用户重按按钮。

第三点尤其关键。live mode 的核心契约是对话是一次握手,不是 N 次请求。当你点 Accept,模型就要把「用户最终选了这个变体」写进源文件,而不是只展示给用户看。如果中途 Chat 中断、helper 重启、浏览器刷新 —— journal 还在,事件会从 journal 重放。

为了让这件事可靠,Impeccable 用了一组双任务模式:live.js 在浏览器里读,impeccable live-poll 在 agent 这边读。两者之间用 SSE,长连接。断线重连后,从 journal 重新组装 state。

这是 event sourcing 的一种实操形态 —— 当前的「用户在浏览器里选了什么」这件事不是状态,而是事件;状态可以从事件重放。

3.3 detector 的 Design System 信任边界#

61 条规则里最微妙的一条是 ai-color-palette。它的定义:

检测 heading 上下文里的紫色 (260-310°) 文字。

但 2026-09-22 那个 commit 修了一个 edge case:

check_element_ai_palette_dom 现在接受 scan 的 design system,跳过任何 DESIGN.md 里声明的 gradient stop 或 text color。所以如果一个站点的 documented palette 自己就是 verdigris oklch(70% 0.12 188),ai-color-palette 的 findings 会从 218 降到 8 —— 剩下 8 个是真正紫的。

这是什么意思?Impeccable 信任 DESIGN.md 里的色板,把它当作「declared color」。

这看起来简单,但工程上要做的事很多:

  1. DESIGN.md 解析 —— crates/detect/src/design_system.rs(2530 行)从 markdown 里抽 palette / font / radius;
  2. oklch 转 RGB 再容差匹配 —— browser_colors_close tolerance 复用 design-system-color 规则的;
  3. 声明色与浏览器计算色一致性 —— 这次 commit 加了一个 file:// 真实浏览器回归测试(crates/browser/tests/design_system_palette.rs),覆盖两种情况:declared 静默、undeclared 触发。

它的本质是把**「这套站点有自己颜色」**当成一个声明,把 detector 视为「待声明校验」而不是「待重新打脸」。这是我对 Impeccable 印象最深的一个设计 —— 它不假设自己永远是对的,它假设自己大概率对,然后把「我错了」的成本降到零(用 inline impeccable-disable 注释)。


四、与 Pi、Cline、Aider 的对比#

把 Impeccable 放进当前 AI 编程工具生态里,横向比较一下设计 skill 这件事:

项目形式适配工具数规则形式设计哲学
Impeccable1 skill + 1 binary + 24 commands16 harness61 确定性规则「不剥夺你的选择,把选择变显式」
Anthropic frontend-design1 skill + 自然语言 promptClaude 家族全靠 LLM 审美「教 AI 更好的审美」
ClineVSCode extension + rule setsVSCode/ClineLint 规则 + LLM「lint + AI review」
AiderCLI + convention 文件任何 LLM自然语言「让 AI 知道你的代码习惯」
Pi agent harnessTS 全栈 harness主要是自己的 agentTS 类型即规则「erasable TypeScript only,types as law」

每条线的核心差异是**「规则放哪儿」**:

  • Impeccable:规则放在 Rust 二进制里,确定性、跨工具、可单独跑。
  • Anthropic frontend-design:规则放在 markdown 里,LLM 自由发挥、不确定性、Claude 专属。
  • Cline:规则在 TS 里,跟 IDE 走、跟 Lint 走、依赖运行时。
  • Aider:规则在 convention 文件里,纯文本、纯 LLM。

Impeccable 的优势是「确定性」。它的 61 条规则不依赖 LLM 审美,跑出来就是「这件事做了 / 没做」,不需要「我觉得 / 你觉得」。这也是为什么 impeccable detect 不需要 API key。

Impeccable 的代价是「覆盖面」。只有能写成正则 / DOM 模式 / 计算样式的事才能做成规则。审美这件事很大一部分 —— 「这字体搭配得好不好」「这个颜色是不是太跳」「这个留白是不是太多」—— 不能写进规则,只能交给 critique 命令(LLM-based)处理。

Anthropic frontend-design 的优势是覆盖面,代价是确定性。同一段 prompt,不同模型给不同输出;同一个模型,不同 temperature 给不同输出。

两者不是替代关系,是互补关系。Impeccable 的 README 第一段也写明了:

Anthropic’s frontend-design was the first widely-used design skill for Claude. Impeccable started from there.

它就是在 Anthropic 之上加了一层确定性。


五、贡献与启示#

Impeccable 是一个**「把脏活做成工具」**的项目。它把 100 个设计师脑子里的「这不对」,具象成 61 条规则,把 10 个 AI harness 的 hook 集成写成 16 个适配,把「在浏览器里挑元素让它换样式」这件事做成 SSE 协议 + journal 重放。

它的最大贡献不是技术 —— Rust + SSE + journal 这些都是熟悉组件 —— 而是**「设计有规则」这件事的工程化证明**。在它之前,设计师写代码靠经验,AI 写代码靠训练数据;在它之后,设计师的判断可以变成 CI hook,AI 的输出可以被规则拦下。

读完之后,有几件事是我想留下来的:

  1. 「AI 烂」不是模型的锅,是缺乏反馈。如果能让模型写完一段代码后立刻看到一条「这里不对」的提示,模型会学得很快。问题是反馈得有具体规则。
  2. 「规则」不等于「禁止」,等于「默认」。每个规则都是「如果你没说明,我就这么判」,而不是「这事不许做」。规则给的是默认值,不是绝对值。
  3. 「确定性」和「覆盖面」是两条路,不是对立。Impeccable + frontend-design 的关系,就像 lint + review 的关系。
  4. 「跨工具分发」是真实可行的。只要你的 skill 是文本、binary 是自包含、hook 是声明式的,你就能跑在 Claude Code、Cursor、Codex、Gemini CLI、Pi、OpenCode、Grok Build、Hermes、Kiro、Trae、Rovo Dev、Qoder、Vibe、Veto、Antigravity 上。没有重新发明轮子的部分。

我猜,接下来一年,会有更多这种「AI 工具时代的 Lint」项目出现 —— 不是替换 lint,是给 lint 加一层「这件事 AI 容易写错」的判断。Impeccable 是这条路上第一个把所有事做齐的项目。


写在最后#

如果你正在做 AI 编程工具,装一下 Impeccable,至少让 impeccable detect 在你的 CI 里跑一遍。你大概会发现 10-30 个 finding,大多数是真的。

如果你正在做前端,读一下 reference/craft-floor.md。那份 56 行文档是我见过的对「设计底线」最凝练的描述 —— Verify 九条 + Refuse 二十条,每条都附规则编号(<!-- rule:skill-ban-... -->)和简短的「为什么」。

如果你正在拆解一个有趣的项目,学一下 Impeccable 的 hook 架构。16 个 harness 适配,只需要 16 个 5KB 的 hook manifest + 1 份 SKILL.md + 1 个二进制。这是「渐进披露 + 自包含二进制 + 声明式 hook」的标准范本。

如果上面任何一条戳到你,你可以从 npx impeccable install 开始。它装好之后,你下次让 Cursor 写 hero section 的时候,它会告诉你「左边 border 去掉」而不是「看起来不错」。

这是「设计感官」该有的反馈。


如果觉得这篇深度解析有帮助,可以关注我的博客 ↗看后续拆解 —— 我每两周拆一个开源项目的内核,重点不在代码量,在工程取舍。

本文配图由 matplotlib + Noto Sans CJK 渲染,代码在 aniya-blog/tools/figures/impeccable_make_figs.py ↗ 公开。 配图设计原则:深色背景 + 低饱和色板,卡片间距自动校验(Sheet.assert_clean())防止文字溢出。

深入解析 Impeccable:24 命令 + 61 规则,跨 16 个 AI 编程工具
https://wth2jhl.online/blog/impeccable-design-skill-deep-dive/
Author 小吴同学
Published at September 24, 2026