深入解析 Impeccable:24 命令 + 61 规则,跨 16 个 AI 编程工具
💬 评论Paul Bakaus 把「什么时候设计是错的」从模糊的审美判断变成可执行的规则集 —— 跨 16 个 AI 编程工具、3 个检测引擎、1 套浏览器闭环,这篇文章把它拆给你看。

仓库: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 写过任何前端,你大概注意到了三件事:
- 字体永远是 Inter,渐变永远是紫到蓝;
- 卡片永远在卡片里,kicker 永远在 heading 上;
- 没人告诉模型这有什么问题,因为审美判断没法写进 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-tab | border-left/right: ≥2px + border-radius | 把卡片当表格单元 —— AI 的招牌动作 |
gradient-text | bg-clip: text + bg-gradient | 想做「高亮词」的廉价做法,几乎是 AI 出身的指纹 |
overused-font | Inter / Geist / system sans 命中 | 训练数据里最常见的 SaaS 字体,AI 不查直接 default |
gray-on-color | text-gray-* 在 bg-red-500 类色上 | 灰字 + 彩底 = 视觉打滑,白底灰字是默认到彩底不变 |
bounce-easing | cubic-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-transition | transition: width/height/top/left/... | 触发 layout thrashing,GPU 加速不了的属性动画 |
em-dash-overuse | em-dash 数量 ≥ 阈值 / 文本长度 | 「streamline your — empower your — unleash your」的句式 |
注意这些规则不是「我觉得这样不好看」,而是「客观上 + 经验上 + 大概率上这件事有问题」。每一条都有触发模式、有量化阈值、有明确的修复建议。
1.2 规则的运行方式#
这些规则装在三个地方:
npx impeccable detect <dir>—— CLI,纯静态扫- 浏览器扩展 —— 装上之后扫线上站点
- 设计 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:impeccabledescription: 「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」),而是按**「用户此刻想要什么」**分类:

这张图一目了然,我把每一类的边界讲一下:
- 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 个) —— 加料,在已存在的设计上加维度。
animatemotion;colorize战略色;typeset字体;layout间距;delight记忆点;overdrive技术极致手段。 - Fix(3 个) —— 修,具体问题。
clarifyUX 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 函数:
// crates/core/src/checks/rules.rs (示意)
fn check_borders(tag, widths, colors, radius, opts) -> Vec<RuleHit> {
for i in 0..4 {
let w = widths[i];
if w < 1.0 || is_neutral_color(colors[i]) { continue; }
// 最大相邻 width
let max_other = widths.iter().enumerate()
.filter(|(j, _)| *j != i)
.map(|(_, x)| *x).fold(0.0, f64::max);
// 必须 w >= 2px 且 (其他三边都 ≤1px 或 w ≥ max_other × 2)
if !(w >= 2.0 && (max_other <= 1.0 || w >= max_other * 2.0)) {
continue;
}
// 只有 left/right 算 side
let is_side = i == 1 || i == 3;
let sn = ["top","right","bottom","left"][i];
if is_side {
if radius > 0.0 {
return "side-tab: border-{sn} + border-radius";
} else if w >= 3.0 {
return "side-tab: border-{sn}";
}
} else if radius > 0.0 && w >= 2.0 {
return "border-accent-on-rounded: border-{sn} + border-radius";
}
}
// ...
}rust注意三件事:
- 置信度条件 —— 「其他三边都 ≤1px 或 w ≥ max_other × 2」。这不是「凡是左侧 border 就报」,而是「左侧比其他三边明显更粗」。AI 默认写法往往是
border: 1px solid; border-left: 4px solid #color;,所以 max_other × 2 这个条件专门抓住这种「不对称」模式。 - 副作用豁免 ——
radius > 0.0走side-tab,否则阈值要 ≥3px 才报(纯几何上的边线不算)。 - top/bottom 走另一条规则
border-accent-on-rounded—— 因为顶部彩色边线在卡片上有可能是设计意图(像 Notion 的 icon tile),不全是错。
这种「规则不是阈值,是节奏」的写法贯穿所有 61 条规则。规则的目的是「拦下大概率是错的写法」,而不是「定义正确」。
2.4 16 个 harness 适配#
Impeccable 一份 SKILL.md,跑在 16 个 AI 编程工具上:

它怎么做到的?关键是 「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 蒙版、按品类选亮/暗…

注意 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 最复杂的设计。它的工作流是:

但让它做对的关键不在「五步闭环」本身,而在三个技术决策:
- poll 循环不超时 —— 默认 600,000ms(10 分钟)长连。Claude Code 调 background task,Codex 调长 foreground,Cursor 调一shot poll。轮询活着,模型在场。
- 变体在源上,不浏览器 —— 模型在源文件上写
wrapper块一次性写好,变体全部 net-new,不切换 progressive publishing,不重新发现 element。原子单次编辑。 - 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 自己就是 verdigrisoklch(70% 0.12 188),ai-color-palette 的 findings 会从 218 降到 8 —— 剩下 8 个是真正紫的。
这是什么意思?Impeccable 信任 DESIGN.md 里的色板,把它当作「declared color」。
这看起来简单,但工程上要做的事很多:
- DESIGN.md 解析 ——
crates/detect/src/design_system.rs(2530 行)从 markdown 里抽 palette / font / radius; - oklch 转 RGB 再容差匹配 ——
browser_colors_closetolerance 复用design-system-color规则的; - 声明色与浏览器计算色一致性 —— 这次 commit 加了一个 file:// 真实浏览器回归测试(
crates/browser/tests/design_system_palette.rs),覆盖两种情况:declared 静默、undeclared 触发。
它的本质是把**「这套站点有自己颜色」**当成一个声明,把 detector 视为「待声明校验」而不是「待重新打脸」。这是我对 Impeccable 印象最深的一个设计 —— 它不假设自己永远是对的,它假设自己大概率对,然后把「我错了」的成本降到零(用 inline impeccable-disable 注释)。
四、与 Pi、Cline、Aider 的对比#
把 Impeccable 放进当前 AI 编程工具生态里,横向比较一下设计 skill 这件事:
| 项目 | 形式 | 适配工具数 | 规则形式 | 设计哲学 |
|---|---|---|---|---|
| Impeccable | 1 skill + 1 binary + 24 commands | 16 harness | 61 确定性规则 | 「不剥夺你的选择,把选择变显式」 |
| Anthropic frontend-design | 1 skill + 自然语言 prompt | Claude 家族 | 全靠 LLM 审美 | 「教 AI 更好的审美」 |
| Cline | VSCode extension + rule sets | VSCode/Cline | Lint 规则 + LLM | 「lint + AI review」 |
| Aider | CLI + convention 文件 | 任何 LLM | 自然语言 | 「让 AI 知道你的代码习惯」 |
| Pi agent harness | TS 全栈 harness | 主要是自己的 agent | TS 类型即规则 | 「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 的输出可以被规则拦下。
读完之后,有几件事是我想留下来的:
- 「AI 烂」不是模型的锅,是缺乏反馈。如果能让模型写完一段代码后立刻看到一条「这里不对」的提示,模型会学得很快。问题是反馈得有具体规则。
- 「规则」不等于「禁止」,等于「默认」。每个规则都是「如果你没说明,我就这么判」,而不是「这事不许做」。规则给的是默认值,不是绝对值。
- 「确定性」和「覆盖面」是两条路,不是对立。Impeccable + frontend-design 的关系,就像 lint + review 的关系。
- 「跨工具分发」是真实可行的。只要你的 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())防止文字溢出。