1. 从"impeccable"这个词说起:一个被低估的前端设计约束工具
第一次看到"impeccable"这个项目名,我脑子里蹦出来的不是词典释义,而是一个很具体的场景:你让 AI coding agent 帮你写一个登录页,它三秒钟吐出来两百行 JSX,结构没错、逻辑没错、能跑,但你就是觉得哪里不对劲——间距忽大忽小、圆角一会儿 4px 一会儿 8px、按钮的 hover 态和 focus 态颜色对不上、移动端断点下卡片直接溢出。代码"能用",但离"impeccable"(无可挑剔)差了十万八千里。
这个项目要解决的就是这件事。它本质上是一个面向 AI coding agents 的前端设计约束层,通过一个叫PRODUCT.md的约定文件加上一套 CLI 工具链,把"什么叫好看、什么叫一致、什么叫符合这个产品的设计语言"这些原本只存在于设计师脑子里或者 Figma 文件里的隐性知识,显式地写下来,然后让 agent 在生成代码时强制遵守。
它适合谁?三类人最该关注:一是天天用 codex cli、zcode cli 这类工具写前端但总在"最后一公里"审美上翻车的开发者;二是团队里想统一设计规范、又不想每次都靠 code review 人肉拦截的 tech lead;三是自己一个人做独立产品、没有专职设计师、但又不想让产品看起来像"AI 批量生成"的独立开发者。哪怕你只是偶尔用 AI 辅助写页面,理解这套思路也能让你的产出质量上一个台阶。
我先把结论放前面:impeccable 的价值不在于它多复杂,恰恰在于它足够"轻"——一个 Markdown 文件 + 几条 CLI 命令,就能把 AI 生成前端的随机性收敛到一个可控的范围内。下面我按实际落地的顺序,把这套东西拆开讲透。
2. 核心设计思路:为什么是 PRODUCT.md 而不是一堆配置文件
2.1 传统设计系统方案的三个死穴
在讲 impeccable 之前,得先说清楚它为什么不用传统那套。过去我们做前端设计规范,无非几种路子:Tailwind config 里定义 theme、搞一个 design tokens 的 JSON、或者干脆维护一套组件库。这些方案在"人写代码"的时代没问题,但放到"AI 写代码"的场景里,全都有硬伤。
第一个死穴是信息密度和可读性的矛盾。tailwind.config.js里塞几百行颜色和间距,机器读得懂,但 agent 在生成代码时并不会真的去"理解"你的设计意图,它只是碰巧匹配到了某个 class。你写spacing: { 4: '16px' },它就用p-4,但它不知道"卡片内部用 16px、卡片之间用 24px"这种层级关系。
第二个死穴是约束是隐性的。design tokens 只告诉你"有哪些值可用",不告诉你"什么时候该用哪个"。AI 最擅长的就是在合法值里乱选——它可能给主按钮用p-2,给次要按钮用p-4,因为两个都合法。
第三个死穴是缺乏产品语境。一个面向企业客户的 B 端后台和一个面向年轻人的消费级 App,设计语言完全不同,但 tokens 文件里体现不出来。agent 不知道自己在给谁做产品,自然做不出对味的决策。
2.2 PRODUCT.md 的核心逻辑:把设计意图写成 agent 能读的"人话"
impeccable 的思路很反直觉——它不搞结构化配置,而是让你用自然语言写一个PRODUCT.md。这个文件放在项目根目录,agent 每次生成前端代码前都会读它。里面写什么?我按实际项目经验给你一个可复用的骨架:
# Product Context - 产品类型:面向中小企业的 SaaS 数据看板 - 目标用户:25-40 岁运营人员,非技术背景 - 使用场景:桌面端为主,移动端仅查看 # Design Language - 整体调性:克制、专业、信息密度高但不拥挤 - 主色:#2563EB(仅用于主操作和关键数据) - 中性色阶:从 #F9FAFB 到 #111827,共 9 级 - 圆角:卡片 12px,按钮 8px,输入框 8px,标签 4px - 阴影:仅卡片使用,且只用一层柔和阴影 # Spacing Rules - 基础单位 4px - 组件内部 padding:16px - 组件之间 gap:24px - 区块之间 margin:48px # Component Conventions - 主按钮:实心主色,hover 加深 10%,focus 有 2px 外发光 - 次要按钮:描边,hover 填充浅灰 - 危险操作:红色,且必须二次确认 - 所有可点击元素最小点击区域 44x44px # Anti-patterns(明确禁止) - 禁止使用纯黑 #000 作为文字色 - 禁止超过 3 种字号出现在同一屏 - 禁止用颜色作为唯一的信息区分手段看到没?这里面没有一行是给编译器看的,全是给"人"(或者说具备语言理解能力的 agent)看的。这就是它和 tokens 方案的本质区别:tokens 定义词汇表,PRODUCT.md 定义语法和语义。
2.3 为什么这套方案对 AI agent 特别有效
我实测下来,agent 对结构化配置的遵守率其实一般,但对自然语言约束的遵守率反而更高。原因在于现在的主流模型在训练时见过海量的设计规范文档、设计系统说明、UI 指南,它们对"卡片圆角 12px、按钮 8px"这种表述的理解,比对一个 JSON 里borderRadius: { card: '12px', button: '8px' }的映射要深得多。
而且自然语言能表达条件逻辑和例外情况,这是配置文件做不到的。比如你可以写"表格内的按钮用更小的尺寸,但点击区域仍保持 44px",这种带上下文的规则,只有自然语言能承载。
注意:PRODUCT.md 不是越长越好。我见过有人写了 800 行,结果 agent 反而抓不住重点。经验值是控制在 150-250 行,把最高频、最容易出错的规则放前面,因为模型对文档开头的注意力权重更高。
3. CLI 工具链实操:从安装到跑通第一条命令
3.1 环境准备与安装路径选择
impeccable 的 CLI 是 Node 生态的工具,所以第一步是确认 Node 环境。这里有个很多人踩过的坑:node 安装 codex cli 很慢这个问题,本质上是 npm registry 的网络问题,跟 impeccable 本身无关,但会连带影响你的整体体验。
我的建议是先把 Node 版本管理理顺。用nvm或者fnm都行,我个人偏好 fnm,启动快。确认版本:
node -v # 建议 18.x 或 20.x LTS npm -v然后安装 impeccable CLI。如果你之前装过 codex cli、zcode cli 这类工具,会发现它们的安装模式大同小异,基本都是全局安装:
npm install -g impeccable-cli装完之后验证:
impeccable --version impeccable --help如果--help能正常列出命令,说明环境通了。如果卡在安装阶段,八成是 registry 的问题,可以临时切到国内镜像源加速,装完再切回来。这一步我不展开,属于通用 Node 运维常识。
3.2 初始化项目:impeccable init 做了什么
进到你的前端项目根目录,跑:
impeccable init这条命令会做三件事,我拆开说,因为理解它做了什么,你才知道后面怎么改:
- 生成 PRODUCT.md 模板:如果你项目里还没有这个文件,它会创建一个带注释的骨架,你照着填就行。如果已经有了,它不会覆盖,只会提示你已存在。
- 写入 agent 指令钩子:它会在项目里放一个约定文件(通常是
.impeccable/rules.md或者往AGENTS.md里追加一段),告诉 agent"生成前端代码前先读 PRODUCT.md"。 - 建立校验基线:生成一个
.impeccable/baseline.json,记录当前项目的设计 token 快照,后面impeccable check会拿它做对比。
这里有个细节值得说:为什么要有 baseline?因为很多项目是"半路接入"的,已经有一堆不符合规范的代码了。如果一上来就全量校验,你会被几千个 warning 淹没。baseline 的作用是"既往不咎,从今天开始管",只校验新增和修改的部分。这个设计很务实,我在实际项目里特别欣赏这种"渐进式治理"的思路。
3.3 核心命令速查与使用场景
impeccable 的命令不多,但每条都有明确的使用时机。我整理成表,你对着用:
| 命令 | 作用 | 什么时候用 |
|---|---|---|
impeccable init | 初始化项目配置 | 项目首次接入时 |
impeccable check | 校验当前代码是否符合 PRODUCT.md | 提交前、CI 里 |
impeccable check --staged | 只校验 git 暂存区的改动 | pre-commit hook |
impeccable sync | 把 PRODUCT.md 的规则同步给 agent 配置 | 改了 PRODUCT.md 之后 |
impeccable diff | 对比当前代码与 baseline 的偏差 | 排查"为什么突然报错" |
impeccable explain <rule> | 解释某条规则为什么触发 | 看不懂报错时 |
check是最常用的。它的输出不是简单的 pass/fail,而是会告诉你哪一行、违反了哪条规则、建议怎么改。比如:
src/components/Button.tsx:24 ✗ 圆角使用了 6px,PRODUCT.md 规定按钮为 8px 建议:将 rounded-md 改为 rounded-lg这种颗粒度的反馈,比 ESLint 那种"规则 ID + 行号"友好太多,因为它直接告诉你"为什么"和"怎么改"。
3.4 和 codex cli 等 agent 工具的配合方式
这是很多人关心的点:impeccable 怎么和 codex cli、zcode cli 这些工具协同?答案是它不绑定任何特定 agent。它的工作方式是"文件约定 + 校验",而不是"插件集成"。
具体流程是这样的:你在 codex cli 里让它写一个组件,它生成代码时会读项目里的AGENTS.md(impeccable init 已经帮你写好了钩子),里面有一句"生成前端代码前必须阅读 PRODUCT.md 并遵守其中规则"。agent 读完 PRODUCT.md 再动手,产出质量立刻不一样。生成完之后,你跑impeccable check做二次校验,把漏网的抓出来。
这个"生成时约束 + 生成后校验"的双保险,是我认为 impeccable 最聪明的设计。因为再强的 agent 也会有疏忽,纯靠 prompt 约束不可靠,必须有个确定性的检查环节兜底。
实操心得:如果你用的是 codex cli,可以在它的配置里把
impeccable check --staged挂到保存钩子上,这样每次 agent 改完文件自动校验,问题当场暴露,不用等到提交。我这么用下来,返工率至少降了一半。
4. 把 PRODUCT.md 写好的五个关键技巧
4.1 用"对比"代替"描述"
新手写 PRODUCT.md 最容易犯的错是只写"是什么",不写"不是什么"。比如只写"主色是蓝色",agent 可能给你整出七八种蓝。正确的写法是给出对比:
- 主色 #2563EB 仅用于:主按钮、当前选中项、关键数据高亮 - 主色禁止用于:普通文字、图标默认色、背景大面积填充 - 如果需要一个"次要的蓝",用 #EFF6FF 作为浅色背景,不要自己调透明度这种"允许清单 + 禁止清单"的组合,能把 agent 的自由度压到最小,同时又不至于死板。
4.2 把"例外"写清楚
设计规范最怕的就是"一刀切",因为真实产品里全是例外。比如"所有按钮圆角 8px",但标签页里的按钮可能是 6px,图标按钮可能是圆形。这些例外不写清楚,agent 要么全用 8px(错的),要么自己乱猜(更错)。
我的做法是单开一节# Exceptions,把每个例外和它的触发条件写明白:
# Exceptions - 图标按钮(只有图标无文字):使用圆形,直径 40px - 表格行内操作按钮:高度 28px,圆角 6px,但点击热区扩展到 44px - 移动端底部固定操作栏内的按钮:宽度撑满,圆角只保留上方两角4.3 用具体数值锚定模糊概念
"间距要舒适""颜色要柔和"这种话对 agent 等于没说。必须落到数值。但数值也不能乱给,要有体系。我一般用"基础单位 + 倍数"的方式:
# Spacing System - 基础单位:4px - 所有间距必须是 4 的倍数 - 常用档位:4 / 8 / 12 / 16 / 24 / 32 / 48 / 64 - 禁止出现 4 的倍数以外的值(如 10px、15px)这条"禁止非 4 倍数"的规则特别有用,它能直接干掉 agent 随手写margin: 10px的毛病。
4.4 给 agent 一个"自检清单"
在 PRODUCT.md 末尾放一个 checklist,让 agent 生成完代码后自己过一遍。这招是我从 code review 流程里借鉴的,效果出奇地好:
# Self-check Before Output 生成组件后,请逐条确认: 1. 所有颜色是否来自上面定义的色板? 2. 所有间距是否是 4 的倍数? 3. 圆角是否匹配组件类型? 4. 交互态(hover/focus/active/disabled)是否都定义了? 5. 移动端断点下是否测试过布局?agent 在"生成后自检"这个环节的表现,比"生成时遵守"要稳定得多,因为它有了一个明确的、可逐条核对的清单。
4.5 版本化你的 PRODUCT.md
这一点很多人忽略:PRODUCT.md 是要进 git 的,而且要认真写 commit message。因为设计规范会演进,今天定的圆角明天可能改。当 agent 生成出不符合预期的代码时,你得能追溯"是规范改了还是 agent 没遵守"。
我习惯在 PRODUCT.md 顶部维护一个 changelog:
# Changelog - 2024-06-01: 卡片圆角从 8px 调整为 12px - 2024-05-15: 新增危险操作二次确认规则 - 2024-05-01: 初始版本这样配合impeccable diff,排查问题快很多。
5. 常见问题排查与避坑实录
5.1 校验报错但代码看起来没问题
这是最高频的问题。原因通常是规则表述有歧义。比如你写"按钮圆角 8px",但项目里用了 Tailwind 的rounded-lg,而你的 Tailwind 配置里lg是 8px——理论上对,但 impeccable 可能读的是原始 CSS 值,发现是0.5rem而不是8px,就报错了。
解决办法是用impeccable explain看它到底在比什么:
impeccable explain button-radius它会告诉你规则的原始定义、匹配逻辑、以及当前代码的实际值。看完你就知道是改代码还是改规则。
5.2 agent 读了 PRODUCT.md 还是不遵守
先确认三件事:一是 PRODUCT.md 是否在项目根目录(有些 agent 只读根目录);二是AGENTS.md里的钩子是否还在(有时候被别的工具覆盖了);三是 PRODUCT.md 是不是太长了(超过 300 行 agent 容易抓不住重点)。
如果都正常,试试把最关键的规则重复在AGENTS.md里写一遍。听起来很笨,但实测有效——因为 agent 对AGENTS.md的注意力权重通常高于其他文件。
5.3 老项目接入后 warning 太多
这就是 baseline 的用武之地。确认.impeccable/baseline.json是否生成成功,然后跑:
impeccable check --since-baseline这样只校验 baseline 之后的改动。如果还是太多,可以分模块接入,先只对src/components目录生效,配置里加个include路径限制。
5.4 和现有 ESLint / Stylelint 冲突
impeccable 的定位是"设计规范校验",不是"代码质量校验",两者职责不重叠。但如果你的 Stylelint 里也配了颜色、间距规则,就可能打架。我的处理原则是:代码层面的(语法、命名、import 顺序)交给 ESLint/Stylelint,设计层面的(颜色、间距、圆角、交互态)交给 impeccable。把 Stylelint 里的设计相关规则关掉,避免双重报错。
5.5 问题速查表
| 现象 | 可能原因 | 排查动作 |
|---|---|---|
| 命令找不到 | 全局安装失败或 PATH 问题 | npm ls -g确认,检查 PATH |
| init 后 agent 无变化 | 钩子文件被覆盖 | 检查 AGENTS.md 内容 |
| check 全量报错 | baseline 未生成 | 重新跑 init 或手动生成 |
| 规则不生效 | PRODUCT.md 表述歧义 | 用 explain 命令定位 |
| 校验结果不稳定 | 规则依赖了动态值 | 把动态值改成静态常量 |
| 与 agent 输出不一致 | agent 未读规范 | 在 AGENTS.md 重复关键规则 |
避坑技巧:每次改完 PRODUCT.md,一定要跑一次
impeccable sync,否则 agent 读到的还是旧规则。我因为这个坑浪费过整整一个下午,以为是 agent 不听话,结果是规范没同步。
6. 进阶玩法:把 impeccable 接进 CI 和团队协作
6.1 pre-commit hook 自动拦截
在.husky/pre-commit里加一行:
impeccable check --staged || exit 1这样任何不符合设计规范的改动都提交不上去。团队里新人多的时候,这一条能省掉大量 code review 里关于"这个间距不对"的扯皮。
6.2 CI 里做增量校验
在 CI 配置里,针对 PR 只校验改动的文件:
impeccable check --since origin/main配合 GitHub Actions 的 PR 评论功能,可以把违规点直接评论到对应代码行,体验很顺。
6.3 多产品线共享规范
如果你维护多个产品,可以抽一个design-system仓库放公共的 PRODUCT.md 片段,各产品用extends引入:
# extends: ../design-system/base.md # 以下是本产品特有的规则impeccable 支持这种继承,改一处全产品生效,特别适合产品矩阵。
6.4 用 PRODUCT.md 反向生成设计文档
PRODUCT.md 写得好,本身就是一份可读的设计规范文档。我试过用脚本把它转成静态站点,给设计师和产品经理看,他们反馈比 Figma 里的标注还清楚。一份文件两用,性价比很高。
7. 我个人的几点体会
用 impeccable 这套东西大半年,最大的感受是:AI 生成前端的质量问题,八成不是模型能力问题,而是约束缺失问题。同一个模型,给它一份清晰的 PRODUCT.md,和什么都不给,产出质量差距是肉眼可见的。
另一个体会是"渐进式"的重要性。别指望一次性把规范写完美,也别指望老代码一夜之间全合规。先写 20 行最关键的规则,跑起来,遇到问题再补。规范是长出来的,不是设计出来的。
最后分享一个小技巧:把 PRODUCT.md 里最常被违反的三条规则,单独拎出来贴在AGENTS.md最顶部。我这么干之后,那三条的违规率从 30% 降到了个位数。原因很简单——agent 的注意力是有限的,你得把最重要的东西放在它最先看到的地方。