1. 从“impeccable”这个词说起:它到底想解决什么问题
第一次看到“impeccable”作为项目名,我脑子里蹦出来的不是词典释义,而是一个很具体的场景:你让AI coding agent帮你改一段前端代码,它改完了,语法没错,逻辑也通,但你就是觉得“哪里不对”——间距差了两个像素、颜色对比度不够、hover状态没过渡、移动端断点错位。这些不是bug,但离“impeccable”差着十万八千里。
这个项目本质上是在做一件事:给AI coding agents装上一双设计师的眼睛。它不是一个独立的编辑器,也不是一个全新的框架,而是一层“设计质量校验层”,通过CLI和browser extension两种形态,让AI在生成或修改frontend design时,能够实时感知到视觉层面的问题,而不是只盯着代码能不能跑。
适合谁来关注这个内容?三类人:一是已经在用AI coding agents(比如各种CLI形态的代码助手)做前端开发、但被“AI味设计”折磨过的工程师;二是想把自己的设计规范沉淀成可执行检查项的技术负责人;三是对CLI工具链和browser extension协同工作方式感兴趣的工具党。不管你用的是哪种agent,只要它输出前端代码,impeccable就有介入的空间。
我实测下来的感受是,它解决的不是“能不能写出来”的问题,而是“写出来能不能看”的问题。这两者之间的差距,做过前端的人都懂。
2. 核心设计思路拆解:为什么是CLI加浏览器扩展
2.1 单一形态不够用:CLI和extension的分工逻辑
一开始我也纳闷,为什么不做成一个纯CLI工具,或者干脆只做浏览器插件?后来自己搭了一遍流程才明白,这两种形态解决的是完全不同阶段的问题。
CLI形态负责的是生成前和生成后的静态校验。当AI agent在终端里跑代码生成任务时,impeccable的CLI可以在代码写入文件之前,对生成的HTML/CSS/JS片段做一轮设计规则扫描。比如检查是否使用了系统字体栈、间距是否落在8px网格上、颜色是否来自预定义的design token集合。这一步是“预防性”的,在代码还没进入浏览器之前就拦住明显不合规的输出。
Browser extension负责的是渲染后的动态校验。有些设计问题只有页面真正跑起来才能发现:元素重叠、对比度在实际背景上不达标、响应式断点触发后的布局塌陷、动画性能导致的掉帧。这些静态分析很难覆盖,必须有一个运行在浏览器里的观察者。
两者通过一个共享的规则配置文件(通常是项目根目录下的impeccable.config.json)保持同步。CLI读它做静态检查,extension读它做运行时检查。这个设计的好处是,你不需要维护两套规则,改一处两边都生效。
注意:CLI和extension的规则集并不是完全对等的。CLI能检查的规则偏向语法和结构层面,extension能检查的偏向渲染和交互层面。配置文件中会有明确的
scope字段来区分。
2.2 为什么不做成IDE插件
这个问题我专门想过。IDE插件看起来是最自然的载体,但它有一个致命缺陷:AI coding agents的工作流正在从IDE里剥离出来。现在越来越多的agent是以CLI形态运行的,它们在终端里接收指令、生成代码、执行测试,整个过程可能根本不经过IDE的图形界面。如果impeccable只做IDE插件,就等于把自己绑在了一个正在被绕过的环节上。
CLI加extension的组合,本质上是在跟随agent的工作流走。agent在终端里跑,CLI就在终端里等着;agent生成的页面在浏览器里预览,extension就在浏览器里盯着。这种“跟随式”的设计,比“嵌入IDE”更灵活,也更符合当前AI coding agents的实际使用习惯。
2.3 规则引擎的取舍:为什么不用现成的linter
市面上已经有stylelint、eslint-plugin-css这类工具,为什么还要自己搞一套规则引擎?我对比过,核心差异在于检查目标的粒度。传统linter检查的是代码风格和潜在错误,比如“不要用!important”、“选择器嵌套不要超过三层”。impeccable检查的是设计意图的落地质量,比如“这个按钮的点击区域是否达到44x44px的最小可触达尺寸”、“这个卡片的阴影是否与设计系统中的elevation层级匹配”。
前者是代码层面的规范,后者是设计层面的规范。两者有交集,但重心完全不同。impeccable的规则引擎里内置了一套“设计质量基线”,这些基线不是凭空来的,而是从大量实际项目中提炼出来的常见问题模式。你可以把它理解为一个“设计审校清单”的自动化版本。
3. 核心细节解析与实操要点
3.1 安装与初始化:从零到跑通第一条规则
impeccable的CLI安装方式取决于你用的包管理器。我习惯用npm全局装,这样在任何项目目录下都能直接调用:
npm install -g impeccable-cli装完之后,在项目根目录执行初始化:
impeccable init这个命令会做三件事:生成默认的impeccable.config.json配置文件、在当前项目安装browser extension所需的本地依赖、输出一段引导文字告诉你如何把extension加载到浏览器里。
配置文件的结构不复杂,核心是三个部分:
{ "rules": { "spacing": { "enabled": true, "baseUnit": 8 }, "color": { "enabled": true, "contrastRatio": 4.5 }, "typography": { "enabled": true, "maxFontFamilies": 2 }, "interaction": { "enabled": true, "minTouchTarget": 44 } }, "scope": { "cli": ["spacing", "color", "typography"], "extension": ["color", "interaction", "layout"] }, "ignore": ["node_modules/**", "dist/**"] }baseUnit设为8,意味着所有间距值必须是8的倍数。这个规则看起来死板,但实际用下来,它能拦住大量“随手写个13px”的情况。contrastRatio设为4.5是WCAG AA级标准,低于这个值的文字颜色组合会被标记。
实操心得:初始化之后不要急着开所有规则。先把
spacing和color打开跑一遍现有代码,看看误报率。如果项目历史代码比较随意,建议先把规则设为warn模式而不是error模式,给自己一个过渡期。
3.2 CLI的核心命令与工作流嵌入
impeccable CLI最常用的命令是check和watch。check做一次性扫描,适合在CI流程里跑:
impeccable check --path ./src --format json输出是结构化的JSON,每个问题包含文件路径、行号、规则名、严重级别和建议修复方式。我一般会把它接到pre-commit hook里,这样AI agent生成的代码在提交前就会被拦一道。
watch模式更适合开发过程中用:
impeccable watch --path ./src --notify它会监听文件变化,一旦检测到违规就通过系统通知提醒。--notify这个参数很实用,因为你在终端里跑着agent的时候不一定盯着impeccable的输出窗口,系统通知能确保你不会漏掉。
还有一个我常用的命令是explain:
impeccable explain spacing它会输出spacing规则的详细说明,包括为什么设这个规则、常见的违规模式、以及推荐的修复方式。这个命令在团队协作时特别有用,新人问“为什么我的间距被标红了”,直接让他跑一下explain就行。
3.3 Browser Extension的加载与运行时检查
Browser extension的加载方式取决于你用的浏览器。以Chromium内核为例,在扩展管理页面打开“开发者模式”,然后选择“加载已解压的扩展程序”,指向项目目录下的impeccable-extension文件夹。
加载成功后,打开任意本地开发页面,extension会自动注入一个检查脚本。你可以在DevTools里看到一个新的面板叫“Impeccable”,里面列出了当前页面所有被标记的设计问题。
运行时检查的几个典型场景:
- 对比度实时计算:extension会遍历页面上所有文本节点,计算其前景色与背景色的对比度。如果低于配置的阈值,会在元素上叠加一个半透明标记,并在面板中列出。
- 触达区域检测:对于按钮、链接等可交互元素,extension会测量其实际渲染尺寸。小于
minTouchTarget的元素会被标记,并给出“建议增大到44x44px”的提示。 - 布局偏移监控:在页面加载和交互过程中,extension会记录布局偏移事件。如果某个元素的偏移量超过阈值,会记录下发生偏移的时间点和元素信息。
注意:extension的检查是在页面渲染完成后进行的,所以对于动态加载的内容(比如懒加载的图片、异步渲染的组件),需要确保检查时机在内容渲染之后。配置文件里有一个
checkDelay参数,默认是500ms,对于重交互页面可以适当调大。
3.4 与AI coding agents的集成方式
这是impeccable最核心的使用场景。我试过几种集成方式,按侵入性从低到高排列:
方式一:作为agent的后置检查步骤。在agent完成代码生成后,手动或自动触发impeccable check。这种方式最简单,不需要改agent的任何配置,但问题是反馈链路比较长,agent已经“认为”自己完成了任务。
方式二:通过agent的hook机制嵌入。一些CLI形态的agent支持在特定事件(如文件写入前)触发外部命令。把impeccable check --file ${FILE_PATH}挂到写入前事件上,agent在写入每个文件之前都会先过一遍检查。如果检查不通过,agent会收到错误信息并尝试修复。
方式三:作为agent的tool调用。如果agent支持自定义tool,可以把impeccable封装成一个tool,让agent在需要的时候主动调用。这种方式最灵活,但需要agent本身有比较完善的tool调用机制。
我目前用的是方式二,在agent的配置文件里加了一行hook:
{ "hooks": { "beforeFileWrite": "impeccable check --file ${FILE_PATH} --fail-on error" } }--fail-on error的意思是遇到error级别的问题就返回非零退出码,agent会把这个当作写入失败,从而触发它的重试或修复逻辑。
4. 实操过程与核心环节实现
4.1 一个完整的前端生成任务实录
我拿一个实际任务来演示:让AI agent生成一个“用户资料卡片”组件,包含头像、姓名、简介和一个关注按钮。
第一步:agent生成初始代码。agent输出的HTML结构大致如下:
<div class="card"> <img src="avatar.jpg" class="avatar"> <h3>张三</h3> <p>前端工程师,关注AI与设计系统</p> <button>关注</button> </div>配套的CSS是agent自己写的,间距用的是margin: 13px、padding: 7px这种随手值,按钮没有设置最小尺寸,文字颜色是#888配白色背景。
第二步:CLI拦截。因为挂了beforeFileWritehook,agent在写入文件之前,impeccable先跑了一遍检查。输出如下:
[impeccable] card.html line 2: spacing/margin - 13px 不在8px网格上,建议改为16px或8px line 4: spacing/padding - 7px 不在8px网格上,建议改为8px line 5: color/contrast - #888 on #fff 对比度3.2:1,低于4.5:1阈值 line 5: interaction/touch-target - button高度28px,低于44px最小触达尺寸第三步:agent根据反馈修复。agent收到这些错误后,重新生成了代码:
<div class="card"> <img src="avatar.jpg" class="avatar"> <h3>张三</h3> <p>前端工程师,关注AI与设计系统</p> <button>关注</button> </div>.card { padding: 16px; } .avatar { margin-bottom: 8px; } p { color: #595959; margin-bottom: 16px; } button { min-height: 44px; min-width: 44px; padding: 12px 24px; }这次CLI检查全部通过,代码被写入文件。
第四步:extension运行时校验。在浏览器里打开页面,extension面板显示:
[impeccable] 运行时检查 - 对比度:全部通过 - 触达区域:全部通过 - 布局偏移:检测到1次偏移(avatar图片加载导致),偏移量0.12布局偏移这个问题是静态检查发现不了的。extension给出了建议:给avatar图片设置明确的宽高属性,或者用CSS aspect-ratio占位。
第五步:修复布局偏移。在img标签上加上width和height属性,或者在CSS里设置aspect-ratio: 1。重新加载页面,extension显示布局偏移为0。
整个流程走下来,从生成到最终通过检查,agent一共迭代了三次。如果没有impeccable,这个组件可能第一次生成就被提交了,那些间距和对比度问题会一直留到代码审查阶段才被发现。
4.2 参数计算:对比度阈值和间距网格的设定依据
对比度阈值设为4.5不是拍脑袋定的。WCAG 2.1 AA级标准规定,正常文本的对比度至少为4.5:1,大文本(18pt以上或14pt粗体)至少为3:1。impeccable默认用4.5,但配置文件里可以按文本大小分别设置:
{ "color": { "contrastRatio": { "normalText": 4.5, "largeText": 3.0 } } }间距网格设为8px,这个数字在业界有比较广泛的共识。8能被2和4整除,意味着你可以用8、16、24、32、40这样的值,同时也能用4、12、20这样的半格值。相比10px网格,8px网格在响应式缩放时更灵活,因为8是2的幂次相关数,在2x、3x屏幕上的计算更干净。
实操心得:如果你的项目已经有既定的间距体系(比如用的是4px网格),不要硬改成8px。在配置文件里把
baseUnit改成4就行,规则引擎会自动适配。关键是“一致性”,而不是“必须是8”。
4.3 忽略规则的精细控制
实际项目中总有一些地方需要“破例”。比如品牌色可能天然对比度不够,但设计上就是要求用那个颜色。impeccable提供了几种忽略机制:
文件级忽略:在文件顶部加注释:
/* impeccable-ignore-file */行级忽略:
color: #888; /* impeccable-ignore-line color/contrast */配置级忽略:在impeccable.config.json里用ignore字段指定路径或规则:
{ "ignore": [ "src/legacy/**", { "path": "src/brand/**", "rules": ["color/contrast"] } ] }我一般建议团队尽量用配置级忽略,而不是行级忽略。行级忽略散落在代码里,时间久了没人记得为什么加,容易变成技术债。配置级忽略集中管理,审查的时候一目了然。
5. 常见问题与排查技巧实录
5.1 CLI报错“配置文件未找到”怎么办
这是新手最常见的问题。impeccable check默认从当前工作目录向上查找impeccable.config.json。如果你在子目录里执行命令,而配置文件在项目根目录,理论上应该能找到。但如果你的项目结构比较特殊(比如monorepo),可能需要显式指定配置路径:
impeccable check --config ../../impeccable.config.json另一个可能的原因是配置文件命名不对。impeccable支持.impeccablerc、impeccable.config.json、impeccable.config.js三种命名,但优先级不同。如果你同时存在多个,可能会加载到不是你预期的那个。
5.2 Extension加载后不生效的排查顺序
按这个顺序查,基本能覆盖90%的情况:
- 确认extension已启用:在扩展管理页面看impeccable的开关是不是打开的。
- 确认页面URL匹配:extension默认只对
localhost和127.0.0.1生效。如果你用的是自定义域名或局域网IP,需要在extension的设置里添加。 - 确认DevTools面板可见:有些浏览器需要手动在DevTools的“更多面板”菜单里把Impeccable勾选出来。
- 检查控制台报错:extension的注入脚本如果有错误,会在页面控制台里输出。看有没有
[impeccable]开头的错误信息。 - 确认配置文件被读取:extension会尝试从页面同源路径读取
impeccable.config.json。如果页面是file://协议打开的,可能会因为跨域限制读不到配置。建议用本地服务器(如npx serve)来跑页面。
5.3 Agent不响应impeccable的检查结果
这种情况通常是因为hook的退出码没有被agent正确识别。检查两点:一是hook命令是否真的返回了非零退出码(可以手动在终端里跑一下同样的命令,看echo $?的输出);二是agent的hook配置里是否把非零退出码当作失败处理。有些agent默认只把超时或崩溃当作失败,需要显式配置failOnNonZeroExit: true。
还有一个可能是agent的修复能力有限。如果impeccable报了一个agent“不知道怎么修”的问题,它可能会选择忽略而不是重试。这时候可以看看agent的日志,确认它是否真的收到了错误信息。
5.4 常见问题速查表
| 问题现象 | 可能原因 | 排查动作 |
|---|---|---|
| CLI命令找不到 | 未全局安装或PATH未更新 | 重新执行npm install -g impeccable-cli,检查which impeccable |
| 检查结果为空 | 路径参数不对或文件被ignore | 用--verbose看扫描了哪些文件 |
| Extension面板不出现 | 浏览器版本不兼容或未开启开发者模式 | 确认浏览器为Chromium 90+,重新加载extension |
| 对比度误报 | 背景是渐变或图片 | 在配置中对该选择器设置ignore,或改用contrastRatio的skipDynamic选项 |
| Agent反复修复同一问题 | 规则冲突或修复建议不明确 | 用impeccable explain <rule>查看规则详情,必要时调整规则阈值 |
| 布局偏移误报 | 字体加载导致的FOUT | 在配置中设置layoutShift.ignoreFontSwap: true |
避坑技巧:如果项目里用了CSS-in-JS方案(如styled-components),CLI的静态检查可能会漏掉动态生成的样式。这时候需要依赖extension的运行时检查来兜底。另外,CSS-in-JS生成的类名是哈希值,在extension面板里定位元素时可能不太直观,建议在开发模式下给组件加上
>impeccable check --path ./src --fail-on error --output report.json然后在CI的artifact里保存
report.json,方便回溯。如果团队用GitHub Actions,可以加一个step把报告摘要贴到PR评论里。注意:CI环境里通常没有浏览器,所以extension的运行时检查跑不了。CI里只能跑CLI的静态检查。运行时检查需要在本地开发或专门的E2E测试环境里做。
6.3 与设计系统的联动
如果团队已经有设计系统(比如一套Figma组件库加对应的CSS变量),impeccable可以跟它联动。具体做法是把设计系统里的token导出成JSON,然后在impeccable配置里引用:
{ "tokens": { "spacing": "./design-tokens/spacing.json", "color": "./design-tokens/color.json" } }这样规则引擎在检查间距和颜色时,会直接跟设计token对比,而不是跟硬编码的数值对比。设计系统更新了token,impeccable的检查标准自动跟着更新,不需要手动改配置。
这个联动是我觉得impeccable最有价值的地方之一。它把“设计系统”从一个静态的文档变成了一个可执行的检查规则。设计师改了token,工程师的代码如果没跟上,CI会直接报错。
7. 一些实测下来的体会
impeccable不是那种“装完就万事大吉”的工具。它的价值取决于你愿意花多少精力去调规则、接流程、跟agent磨合。我刚开始用的时候,觉得误报太多,差点放弃。后来把规则从
error降到warn,跑了两周,收集了足够的数据,才慢慢把真正重要的规则调回error级别。另一个体会是,不要试图用impeccable覆盖所有设计问题。它擅长的是那些“有明确数值标准”的检查:间距、对比度、触达尺寸、字体数量。对于“这个布局好不好看”、“这个动效是否流畅”这类主观判断,它帮不上忙。把精力集中在它能做好的事情上,剩下的交给人工审查。
最后分享一个小技巧:如果你同时用多个AI coding agents,可以给每个agent配一套不同的impeccable规则集。比如快速原型阶段用宽松规则,生产代码阶段用严格规则。通过环境变量切换配置:
IMPECCABLE_ENV=prototype impeccable check IMPECCABLE_ENV=production impeccable check配置文件里根据
IMPECCABLE_ENV的值加载不同的规则组合。这样同一个工具就能适配不同的开发阶段,不用来回改配置。