1. 从"impeccable"这个词说起:它到底在解决什么问题
第一次看到"impeccable"这个词,是在几个前端开发群里有人甩出一张截图,配文是"这玩意儿审我的UI比我自己还狠"。点进去一看,是一个跑在命令行里的工具,对着一个前端项目目录扫一遍,然后吐出一份关于设计质量的报告——间距不统一、颜色对比度不够、组件命名混乱、响应式断点缺失,一条条列得清清楚楚。
"impeccable"这个词本身的意思是"无可挑剔的、完美的"。放在前端设计语境下,它指向的是一个很具体的痛点:代码能跑,不代表界面能看。我们写前端的时候,功能逻辑往往有测试兜底,TypeScript 有类型检查,ESLint 有代码规范,但"这个按钮和那个按钮的圆角差了2px""这个卡片的内边距在移动端挤成一团"这类问题,没有任何工具会拦你。它们不会让构建失败,不会让测试变红,但会让产品看起来"差一口气"。
这个工具的核心定位,就是把"设计质量"这件事从主观感受变成可检查、可量化的工程指标。它通过 CLI 的方式接入开发流程,同时提供浏览器扩展做实时预览,配合当下流行的 AI coding agents(比如 Codex CLI、Zcode CLI 这类命令行智能体),让"写完代码顺手审一遍设计"变成和"提交前跑一遍 lint"一样自然的动作。
适合谁来用?三类人最受益:一是独立开发者,没有专职设计师帮忙把关,自己写完自己审容易灯下黑;二是小团队的前端,设计规范靠口头约定,落地全靠自觉;三是任何想把 AI coding agent 真正用起来的人——因为 impeccable 这类工具本质上是在给 AI 智能体提供"设计维度的反馈信号",让它不只是能写代码,还能判断代码写得好不好看。
下面我会从它背后的设计检查逻辑、CLI 的实际接入方式、浏览器扩展的用法、和 AI coding agents 的配合,以及我自己踩过的坑,一层层拆开讲。
2. impeccable 的设计检查逻辑:它凭什么判断"好不好看"
2.1 设计质量为什么能被"检查"
很多人第一反应是:审美是主观的,工具怎么审?这个疑问合理,但混淆了两个层次的东西。审美偏好是主观的,但设计系统的一致性是可验证的。一个界面"看起来专业",很大程度上不是因为用了多高级的配色,而是因为它在无数细节上保持了一致:所有间距来自同一套刻度、所有圆角来自同一组数值、所有字号来自同一个比例阶梯、所有颜色来自同一个调色板。
impeccable 的检查逻辑就建立在这个认知上。它不评判"你这个蓝色好不好看",它检查的是"你这个蓝色和你设计系统里定义的蓝色是不是同一个"。前者无法自动化,后者完全可以。这就像 ESLint 不评判"你这个函数名取得好不好",但它能检查"你的缩进是不是统一用了2个空格"。
具体来说,它扫描的是这几类信号:
- 间距一致性:提取所有 margin、padding、gap 的值,看它们是否落在有限的几个刻度上。如果出现 7px、13px、19px 这种零散值,就会标记出来。
- 颜色系统:统计项目里出现的所有颜色值,识别是否存在"近似但不相同"的颜色(比如 #3B82F6 和 #3A81F5),这类往往是手抖或复制粘贴导致的。
- 排版层级:检查字号、字重、行高的组合是否形成了清晰的层级关系,还是说标题和正文的区分度不够。
- 响应式覆盖:检查关键断点是否都有对应的样式处理,有没有组件在某个宽度区间"漏掉"了。
- 组件命名与结构:从类名和组件名里推断语义,标记出命名风格不统一的地方。
2.2 它和传统 lint 工具的本质区别
这里必须说清楚一个容易混淆的点。ESLint、Stylelint 这类工具检查的是语法和规范,它们关心的是"你写的代码符不符合预设规则"。impeccable 检查的是设计意图和实现之间的一致性,它关心的是"你写出来的界面,是不是你脑子里想要的那个界面"。
举个具体例子。Stylelint 可以检查你有没有用!important,但它不会告诉你"这个页面上有四种不同的卡片阴影,看起来像是四个人分别写的"。impeccable 会。因为它的分析维度是跨文件的、聚合的——它把整个项目当成一个整体来看,找出那些"单看每个文件都合理,合在一起就乱套"的问题。
提示:这类工具的价值不在于替代设计师,而在于把设计师脑子里的隐性规范显性化。如果你的项目压根没有设计规范,那它扫出来的问题会非常多,这时候正确的做法不是逐条改,而是先花时间建立一套最小规范。
2.3 检查结果的呈现方式
impeccable 的输出不是简单的"错误列表",而是带优先级和上下文的报告。它会区分几个等级:
| 等级 | 含义 | 典型问题 |
|---|---|---|
| Critical | 影响可用性 | 对比度不足导致文字看不清、点击区域过小 |
| Major | 影响一致性 | 间距刻度混乱、颜色近似重复 |
| Minor | 影响精致度 | 圆角不统一、阴影层级不清晰 |
| Info | 优化建议 | 可以合并的样式、可以抽取的变量 |
这个分级很重要,因为它决定了你该先改什么。我见过太多人一上来就纠结"这个圆角是4px还是6px",结果页面上有个按钮在深色背景上根本看不清文字——那才是真正该先修的。
3. CLI 接入实战:从安装到跑通第一条检查
3.1 环境准备里最容易被忽略的一步
impeccable 的 CLI 走的是标准的 Node 生态,安装本身没什么门槛。但有一个前置条件经常被跳过:你的项目得有一个能被解析的样式来源。如果你用的是纯 CSS,那没问题;如果你用的是 CSS-in-JS 或者 Tailwind 这类原子化方案,需要确认工具能正确识别你的样式产出。
我建议在安装前先做一件事:确认你的项目能正常构建,并且构建产物里的 CSS 是可读的(不是被压缩成一行的)。因为 impeccable 需要解析样式规则,压缩过的 CSS 虽然也能解析,但报错信息里的定位会很难看。
安装命令大致是这样:
npm install -g impeccable-cli # 或者作为项目依赖 npm install --save-dev impeccable-cli装完之后先别急着扫全项目,用--help看一眼当前版本支持的参数。这类工具迭代快,网上搜到的教程可能对应的是旧版本,参数名对不上是常事。
3.2 第一次扫描应该怎么跑
第一次跑,我强烈建议只扫一个目录,不要扫全项目。原因很简单:全项目扫出来的问题可能有几百条,你根本不知道从哪下手,很容易直接放弃。选一个你最近改过的、比较有代表性的页面或组件目录,先看看它报什么。
impeccable scan ./src/components/Button --format=table--format参数决定了输出形式。table 适合人看,json 适合喂给其他工具(后面讲 AI agent 配合时会用到)。第一次跑完,你大概率会看到几类问题:间距值不在刻度上、颜色有近似重复、某些状态(hover、focus、disabled)缺少样式定义。
这里有个经验:先看 Critical 和 Major,Minor 先放着。因为 Minor 级别的问题往往是"改起来工作量巨大但收益很小"的,比如全项目统一圆角,可能涉及几十个文件。而 Critical 级别的问题通常集中在少数几个地方,改起来快,效果立竿见影。
3.3 配置文件怎么写才不折腾
impeccable 支持通过配置文件定制检查规则。默认规则是通用型的,但每个项目的设计系统不一样,你需要告诉它"我的间距刻度是哪些值""我的主色是什么"。
配置文件一般长这样:
{ "spacing": { "scale": [0, 4, 8, 12, 16, 24, 32, 48, 64], "tolerance": 1 }, "colors": { "palette": ["#1A1A1A", "#3B82F6", "#10B981", "#EF4444"], "allowAlpha": true }, "typography": { "scale": [12, 14, 16, 20, 24, 32, 48] } }tolerance这个参数值得说一下。它表示允许的误差范围,单位是像素。设成 1 意味着 7px 和 8px 会被认为是同一个刻度(因为差1px),不会报错。这个参数的存在是因为现实中总有一些"不得不"的微调,比如为了对齐图标而把 padding 调了1px。设得太严会导致大量误报,设得太松又失去了检查意义。我的经验是从 1 开始,如果误报太多就调到 2,但不要超过 2。
注意:配置文件里的颜色调色板要和你的实际设计系统保持同步。如果你改了主色但忘了更新配置,工具会把你所有正确的新颜色都标成"不在调色板内",那就本末倒置了。
3.4 把检查接进开发流程
单独跑一次检查意义有限,真正有价值的是让它成为流程的一部分。两个接入点最实用:
一是pre-commit hook。在提交前自动跑一次检查,只检查本次改动涉及的文件。这样问题在进入代码库之前就被拦住了。用 husky 配合 lint-staged 可以做到:
{ "lint-staged": { "*.{css,scss,tsx,jsx}": ["impeccable scan --staged --format=compact"] } }--staged参数让它只检查暂存区的文件,速度快,不会因为全项目扫描而拖慢提交。
二是CI 流水线。在 CI 里跑一次全量扫描,把报告作为构建产物存下来。这样每次 PR 都能看到设计质量的变化趋势。如果某个 PR 让 Major 级别的问题数量上升了,review 的时候就有据可依。
这里有个坑要提醒:CI 里跑全量扫描,第一次接入时问题数量会非常吓人。我的做法是先设一个"基线",把当前的问题数量记录下来,然后配置成"只在新问题出现时才失败"。这样既能防止质量倒退,又不会因为历史遗留问题卡住整个团队。
4. 浏览器扩展:把检查从"事后"变成"实时"
4.1 扩展解决的是 CLI 解决不了的问题
CLI 的问题是它有延迟——你写完代码,跑一次检查,看到问题,回去改,再跑。这个循环在改单个组件的时候还行,但在调整个页面布局的时候就很别扭,因为你没法一边拖拽调整一边看检查结果。
浏览器扩展补的就是这个环节。装上之后,它会在页面上叠加一层可视化标记,把有问题的元素直接框出来。间距不对的地方标黄,颜色重复的地方标红,对比度不足的地方标紫。你改一行代码,页面热更新,标记实时变化,反馈闭环从"分钟级"缩短到"秒级"。
安装方式取决于你用的浏览器,一般是在扩展商店里搜名字,或者从项目的 release 页面下载 crx 文件手动加载。手动加载的话记得开启开发者模式,这个步骤在扩展管理页面右上角。
4.2 扩展面板里那几个容易被忽略的功能
大部分人装上扩展之后只会看页面上的标记,但扩展自带的面板里有几个功能其实更有用:
- 元素检查器联动:点面板里的某条问题,页面上对应的元素会高亮,同时在 DevTools 里选中。这个联动省去了手动找元素的功夫。
- 实时计算值:面板会显示当前选中元素的实际计算样式,包括那些被继承、被覆盖之后最终生效的值。很多时候你以为你设了 16px,实际生效的是 14px,因为被某个优先级更高的规则覆盖了。
- 快照对比:可以保存当前页面的检查结果作为快照,改完代码后再对比,看问题数量是增是减。这个功能在重构的时候特别好用。
4.3 扩展和 CLI 的分工
我的使用习惯是这样分工的:开发阶段用扩展,提交阶段用 CLI。写代码的时候扩展一直开着,边写边看标记,大部分低级问题当场就改了。等到要提交了,跑一次 CLI 做全量检查,确保没有遗漏,同时生成一份报告存档。
这样分工的好处是,CLI 跑出来的问题数量会少很多,报告看起来清爽,review 的人也更容易聚焦在真正重要的问题上。如果反过来,开发时不管,全靠提交前 CLI 扫,那报告会又长又杂,改起来痛苦。
提示:扩展在开发环境用就好,不要装到日常浏览的浏览器里。因为它会往每个页面上注入标记脚本,虽然一般不影响正常浏览,但遇到一些对 DOM 结构敏感的老网站可能会出问题。
5. 和 AI coding agents 配合:让智能体也懂设计
5.1 为什么要把设计检查喂给 AI agent
现在用 Codex CLI、Zcode CLI 这类命令行智能体写代码的人越来越多。它们的强项是理解需求、生成代码、修复 bug,但有一个共同的短板:它们不知道自己的产出"好不好看"。你让它写一个卡片组件,它能写出来,功能也对,但间距可能随手写了 13px,颜色可能随手挑了个没在调色板里的值。
impeccable 在这里扮演的角色,是给 AI agent 提供设计维度的反馈信号。流程是这样的:agent 写完代码,跑一次 impeccable 扫描,把 JSON 格式的报告喂回给 agent,让它根据报告自我修正。这就形成了一个闭环——agent 不只是"能写",还能"写完自己审,审完自己改"。
5.2 具体怎么串起来
关键在于 impeccable 的--format=json输出。这个格式是结构化的,agent 能直接解析。一个典型的配合流程:
# agent 写完代码后 impeccable scan ./src --format=json > design-report.json # 把报告内容作为上下文喂给 agent # 提示词大致是:根据 design-report.json 里的问题,修正对应文件的样式在提示词里,我建议明确告诉 agent 两件事:一是只修 Critical 和 Major,Minor 先不动,避免它为了追求"完美"把整个项目改得面目全非;二是修改要最小化,能改一个值就不要重构整个样式块。AI agent 有个通病,就是容易"顺手"做很多你没让它做的事,限制范围很重要。
5.3 实测下来最稳的几种提示词模式
我试过几种不同的提示词写法,效果差异挺大。最稳的是这种结构:
读取 design-report.json。对于每条 Critical 和 Major 级别的问题,定位到对应文件的具体行,做最小修改。修改后重新运行扫描,确认该问题消失。不要修改报告中未提及的文件。
这个提示词的关键在于"最小修改"和"不要修改未提及的文件"这两句。少了这两句,agent 很容易开始"自由发挥",把一些它觉得不好看但报告没提的地方也改了,结果引入新问题。
另一种模式适合批量修复同类问题,比如全项目的间距统一:
design-report.json 中有 N 条关于间距刻度的问题。请先列出所有涉及的间距值,然后给出一个映射方案(把每个非标准值映射到最接近的标准刻度),确认方案后再批量修改。
先让它出方案再执行,比直接让它改要稳。因为批量修改一旦方向错了,回滚成本很高。
5.4 一个真实的配合案例
我拿一个中等规模的项目试过完整流程。项目大概有 40 多个组件,之前没有设计规范,样式是几个人陆续写的。第一次跑 impeccable,报出来 200 多条问题,其中 Critical 12 条,Major 60 多条。
我先把 Critical 的 12 条手动改了——这些主要是对比度和点击区域的问题,涉及具体业务判断,交给 agent 不放心。然后剩下的 Major 问题,用 agent 批量处理。整个过程大概跑了三轮:第一轮 agent 改了 40 多条,第二轮又扫出来 10 多条(因为第一轮的修改引入了新的不一致),第三轮基本清干净了。
最后剩下的 Minor 问题我没管,因为那些主要是圆角和阴影的细微差异,改起来涉及文件太多,收益又小。知道什么时候停下来,比知道怎么改更重要。
6. 踩过的坑和几条实在的经验
6.1 误报是怎么产生的,怎么处理
误报是这类工具最让人头疼的地方。我遇到过的误报主要有三种来源:
第一种是动态样式。有些样式是通过 JS 在运行时计算的,比如根据屏幕宽度动态设置 padding。impeccable 静态扫描的时候看不到这些运行时值,就会把静态部分标成"不在刻度上"。这种情况需要在配置里把相关文件或选择器加入白名单。
第二种是第三方组件。你引入了一个 UI 库,它的内部样式不受你控制,但扫描的时候会被一起扫进来。解决办法是在配置里排除 node_modules 或者指定只扫描你自己的源码目录。
第三种是设计上的有意为之。有些地方就是要用非标准值,比如为了视觉补偿而微调的间距。这种情况我建议在代码里加注释标记,然后在配置里设置忽略规则。不要为了"让报告好看"而强行改成标准值,那样反而破坏了设计意图。
6.2 不要一上来就追求零问题
这是我踩过的最大的坑。刚开始用的时候,看到报告里几百条问题,强迫症发作,想全部清掉。结果花了整整两天,改到最后发现有些改动反而让界面变难看了——因为那些"非标准值"其实是之前有人精心调过的。
正确的做法是分批处理,先解决影响可用性的,再解决影响一致性的,最后才考虑精致度。而且每一批改完都要在真实设备上看一眼效果,不能只看报告数字下降就完事。工具是辅助,最终判断还得靠眼睛。
6.3 团队协作时的推行策略
如果你是想在团队里推行这个工具,我的建议是先自己用两周,摸清楚它的脾气,再推给团队。直接推的话,同事第一次跑出来几百条问题,第一反应大概率是"这工具是不是有病",然后就再也不会用了。
自己用两周之后,你手里会有几个真实的案例:哪些问题它报得准,哪些是误报,配置怎么调,流程怎么接。拿这些案例去跟团队沟通,说服力完全不一样。而且你可以先帮团队把配置文件写好,把明显的误报排除掉,让大家第一次跑出来的报告就是"可读"的。
另外,不要把它设成强制卡点。至少在初期不要。设成卡点会让所有人产生抵触情绪,觉得是来添乱的。先作为"建议性"的检查跑一段时间,等大家习惯了、认可了,再考虑要不要升级成强制。
6.4 关于性能的一点观察
全量扫描大项目的时候,速度是个问题。我试过一个大概 500 多个组件的项目,全量扫描要跑将近一分钟。这个时间在 CI 里可以接受,但在本地开发时如果每次保存都跑,就很烦。
我的做法是本地只跑增量(--staged或者指定改动目录),全量扫描只在 CI 里跑。另外,如果你的项目用了 CSS-in-JS,扫描速度会比纯 CSS 慢不少,因为需要先解析 JS 才能提取样式。这种情况可以考虑在构建产物上扫描,而不是在源码上扫。
7. 这套东西往后还能怎么用
用了一段时间之后,我发现 impeccable 这类工具的价值其实不止于"检查"。它输出的那份结构化报告,本身就是一个设计系统的现状快照。你可以把不同时间点的报告存下来做对比,看设计一致性是在变好还是变差。也可以把报告里的颜色数据提取出来,反向生成一份调色板文档。
更进一步,它和 AI coding agents 的结合还有很大空间。现在的用法是"agent 写完,工具检查,agent 再改",未来完全可以做成"agent 在写的过程中就实时查询设计规范"。比如 agent 要写一个 padding,它先去查配置里的刻度表,直接选一个标准值,而不是写完再改。这需要工具提供更细粒度的查询接口,但方向是清晰的。
我自己现在的习惯是,每个新项目初始化的时候就把 impeccable 的配置建好,把设计刻度、调色板、字号阶梯都定义清楚。这样从第一行样式代码开始就有约束,后面就不用花大力气去"治理"了。设计质量这件事,防患于未然的成本远低于事后补救。这个道理和代码规范是一样的,只不过设计规范长期被忽视了,现在有了工具,是时候把它捡起来了。