1. 从“impeccable”这个词说起:一个被低估的前端质量信号
第一次看到“impeccable”作为项目标题,我脑子里蹦出来的不是词典释义,而是一个很具体的场景:你让 AI coding agent 帮你改一个按钮的 hover 状态,它改完了,功能也对,但间距从 16px 变成了 15px,圆角从 8px 变成了 6px,颜色从#3B82F6变成了#3b82f6——功能没坏,但整个界面开始“不对劲”了。
这就是“impeccable”要解决的问题域。它不是一个框架,不是一个库,更像是一种对前端产出质量的极致要求:无可挑剔的视觉一致性、无可挑剔的代码结构、无可挑剔的交互细节。当 AI coding agents 开始大规模介入前端开发,这个词从一个形容词变成了一个工程问题——你怎么让机器产出的东西,达到“impeccable”的标准?
围绕这个词,热搜里出现了AI coding agents、frontend design、CLI、browser extension这几个关键词。把它们串起来,画面就很清晰了:用 CLI 工具驱动 AI coding agent,通过 browser extension 做视觉验证,最终产出 impeccable 的前端设计。这是一条完整的工具链,也是我最近几个月一直在折腾的方向。
这篇文章适合三类人看:一是已经在用 AI 写前端、但被“差不多但就是不对”折磨过的开发者;二是想搭建一套可复现的前端质量保障流程的技术负责人;三是对 CLI + browser extension 这套组合拳感兴趣、想看看别人怎么落地的人。我会把这条链路上的每个环节拆开讲,包括我踩过的坑和目前跑得比较稳的方案。
2. 为什么 AI 写前端总是“差一口气”
2.1 功能正确不等于视觉正确
AI coding agent 在前端领域的表现有一个很明显的分界线:逻辑层面越来越强,视觉层面始终不稳。你让它写一个表单验证、一个数据请求、一个状态管理,它基本能一次过。但你让它“把这个卡片调得好看一点”,它给出的结果往往需要你再手动调三轮。
根本原因在于,AI 的训练目标里,“功能正确”的权重远高于“视觉正确”。一个按钮能点击、能触发事件,在功能测试里就是满分;但它的 padding 是 12px 还是 16px,border-radius 是 8px 还是 12px,在大多数评估体系里根本不扣分。可对于真实产品来说,这些细节恰恰是“impeccable”和“能用”之间的差距。
我做过一个粗略统计:让 AI 独立完成一个中等复杂度的页面组件,功能一次通过率大概在 70% 左右,但视觉一次通过率不到 30%。剩下的 70% 里,大部分问题不是“错了”,而是“偏了”——间距偏了、层级偏了、对齐偏了。
2.2 设计系统的“隐性知识”难以传递
每个团队都有自己的设计系统,但设计系统里真正重要的部分往往是隐性的。比如:
- 卡片阴影在深色模式下要降低不透明度
- 主按钮和次按钮的间距在移动端要缩小 4px
- 表单错误提示出现时,输入框的 border 颜色变化要配合 150ms 的过渡
这些规则不会写在设计系统的文档里,它们存在于设计师的直觉和前端的手感里。AI coding agent 拿不到这些隐性知识,所以它只能按“通用最佳实践”来写,结果就是“看起来没错,但就是不像我们家的东西”。
2.3 CLI 和 browser extension 为什么被卷进来
热搜里CLI和browser extension同时出现,不是偶然。CLI 解决的是批量操作和流程自动化的问题——你不可能每次都打开 IDE 手动改,你需要一个命令行入口来驱动 agent、跑检查、出报告。Browser extension 解决的是视觉验证的问题——代码层面的 lint 只能查语法和部分规范,真正的视觉问题必须在渲染后的页面上看。
这两个工具的组合,本质上是在给 AI coding agent 装上一双“眼睛”和一双“手”:CLI 是手,负责执行;browser extension 是眼睛,负责验收。没有这两样,AI 写前端就是闭着眼睛画画。
3. 核心工具链拆解:从 CLI 到 Browser Extension
3.1 CLI 层的选型逻辑
热搜里出现了zcode cli、codex cli、gitlab cli、openspec cli、minimax cli、trae cli等多个 CLI 工具,说明这个层面还没有形成绝对垄断。我实际用下来,选型主要看三个维度:
| 维度 | 关键问题 | 我的取舍 |
|---|---|---|
| 交互模式 | 是纯命令行还是带 TUI | 带 TUI 的更适合调试,纯命令行的更适合脚本化 |
| 上下文管理 | 能否记住项目结构 | 必须能,否则每次都要重新描述项目 |
| 扩展性 | 能否接入自定义检查 | 必须能,否则没法做 impeccable 级别的校验 |
codex cli在这几个维度上比较均衡,它的/compact、/model、/resume这几个命令我用得最多。/compact用来压缩上下文,防止长对话把 token 撑爆;/model用来切换模型,复杂视觉任务用强模型,简单重构用快模型;/resume用来恢复会话,避免每次重新交代背景。
zcode cli和trae cli我更倾向于用在特定场景,比如zcode cli的代码补全响应更快,适合边写边改;trae cli的项目级重构能力更强,适合大范围调整。openspec cli我主要用来做规范检查,它能把设计系统的规则转成可执行的校验项。
提示:不要试图找一个“全能 CLI”,目前不存在。我的做法是主用
codex cli做日常开发,遇到特定任务再切到其他工具,用 alias 把常用命令固化下来。
3.2 Browser Extension 的验证能力
Browser extension 在这个链路里的角色是“视觉验收员”。我目前用的方案是一个自建的 Chrome extension,核心功能有三个:
- 截图对比:对同一页面在修改前后分别截图,用像素级 diff 标出差异区域
- 样式审计:读取渲染后的 computed style,检查是否有偏离设计系统的值
- 交互录制:记录 hover、focus、active 等状态的变化,验证过渡动画是否符合预期
这三个功能里,样式审计是最有价值的。因为 AI 改代码的时候,经常会在 CSS 里写一个“看起来对”的值,但实际渲染出来因为继承、优先级、盒模型的原因,computed style 和预期不一致。只有读渲染后的值,才能发现这类问题。
我举个例子:AI 把按钮的padding从12px 24px改成了0.75rem 1.5rem,代码层面完全等价,但如果根字号不是 16px,渲染出来就是 15px 和 30px,和设计稿的 12px/24px 对不上。这种问题 lint 查不出来,只有 browser extension 读 computed style 才能抓到。
3.3 两者如何协同
CLI 和 browser extension 的协同方式,我目前跑通的是这个流程:
# 1. 用 CLI 驱动 agent 修改代码 codex cli --task "调整卡片组件的间距和阴影" --model gpt-4 # 2. CLI 修改完成后,自动触发 browser extension 的审计 # 这一步通过 CLI 的 post-hook 实现 codex cli --hook "node ./scripts/audit.js" # 3. audit.js 调用 browser extension 的 API,输出审计报告 # 4. 如果审计不通过,CLI 自动回滚并重新尝试这个流程的关键在于自动回滚。AI 改错了不可怕,可怕的是改错了你不知道,或者知道了要手动回滚。把审计和回滚串起来之后,整个流程的容错率会高很多。
4. 实操:搭建一套 impeccable 前端工作流
4.1 环境准备与 CLI 安装
先说明一下,下面这套流程是我在 macOS 上跑的,Linux 基本一致,Windows 需要把部分命令换成 PowerShell 等价写法。
第一步是装 CLI。以codex cli为例,安装方式通常是:
# 通过 npm 全局安装 npm install -g @codex/cli # 验证安装 codex --version # 初始化项目配置 codex initcodex init会在项目根目录生成一个配置文件,我一般会改这几个地方:
{ "model": "gpt-4", "context": { "include": ["src/**/*.tsx", "src/**/*.css", "design-tokens.json"], "exclude": ["node_modules", "dist", "*.test.tsx"] }, "hooks": { "postEdit": "node ./scripts/audit.js" } }context.include里我特意加了design-tokens.json,这是整个 impeccable 流程的基础。后面会详细讲这个文件怎么用。
Browser extension 的安装分两种:一种是直接用现成的,比如一些开源的视觉审计工具;另一种是自己写一个。我建议先用现成的跑通流程,再根据自己团队的需求定制。自己写的话,核心就是 Chrome extension 的content script加上chrome.tabs.captureVisibleTab这个 API。
4.2 设计令牌的提取与固化
这是整个流程里最容易被忽略、但最重要的一步。AI 之所以改不对,很多时候不是它能力不行,而是它不知道“对”的标准是什么。设计令牌就是把“对”的标准显式化。
我的做法是从现有的设计系统里提取令牌,生成一个design-tokens.json:
{ "spacing": { "xs": "4px", "sm": "8px", "md": "16px", "lg": "24px", "xl": "32px" }, "radius": { "sm": "4px", "md": "8px", "lg": "12px", "full": "9999px" }, "color": { "primary": "#3B82F6", "primaryHover": "#2563EB", "textPrimary": "#111827", "textSecondary": "#6B7280" }, "shadow": { "sm": "0 1px 2px rgba(0,0,0,0.05)", "md": "0 4px 6px rgba(0,0,0,0.1)" } }这个文件的作用有两个:一是给 AI 提供明确的取值参考,二是给 browser extension 提供审计基准。AI 改代码的时候,CLI 会把这份令牌注入到上下文里;审计的时候,extension 会拿渲染后的值和这份令牌做比对。
注意:令牌的粒度要适中。太粗了 AI 还是会自由发挥,太细了 AI 会被限制死、失去灵活性。我的经验是间距和圆角要细,颜色和阴影可以粗一点。
4.3 用 CLI 驱动 AI 修改前端代码
环境准备好之后,就可以开始实际修改了。我一般不会让 AI 一次性改整个页面,而是按组件粒度来。比如要调整一个卡片组件:
codex cli --task "调整 Card 组件的间距和阴影,使其符合 design-tokens.json 中的 md 间距和 md 阴影" \ --file "src/components/Card.tsx" \ --model gpt-4这里有几个细节值得说:
第一,任务描述要具体到令牌名称。不要只说“调整间距”,要说“符合 design-tokens.json 中的 md 间距”。这样 AI 会去读令牌文件,而不是凭感觉给一个值。
第二,指定文件范围。不指定的话,AI 可能会去改其他文件,引入不必要的变更。
第三,模型选择。视觉相关的任务我一般用强模型,因为弱模型对间距、颜色的理解明显更差。实测下来,同一个任务,强模型的一次通过率能到 60% 左右,弱模型只有 30%。
改完之后,CLI 会自动触发postEdithook,也就是前面配置的audit.js。这个脚本会调用 browser extension 的 API,对修改后的页面做审计。
4.4 Browser Extension 审计脚本的编写
audit.js的核心逻辑是:启动一个 headless browser,加载页面,读取关键元素的 computed style,和design-tokens.json做比对,输出差异报告。
const puppeteer = require('puppeteer'); const tokens = require('./design-tokens.json'); async function audit(url, selectors) { const browser = await puppeteer.launch(); const page = await browser.newPage(); await page.goto(url); const issues = []; for (const selector of selectors) { const styles = await page.$eval(selector, (el) => { const computed = window.getComputedStyle(el); return { padding: computed.padding, borderRadius: computed.borderRadius, boxShadow: computed.boxShadow, color: computed.color }; }); // 比对间距 if (!Object.values(tokens.spacing).includes(styles.padding.split(' ')[0])) { issues.push({ selector, property: 'padding', actual: styles.padding, expected: Object.values(tokens.spacing).join(' | ') }); } // 比对圆角 if (!Object.values(tokens.radius).includes(styles.borderRadius)) { issues.push({ selector, property: 'borderRadius', actual: styles.borderRadius, expected: Object.values(tokens.radius).join(' | ') }); } } await browser.close(); return issues; }这个脚本跑完之后,如果issues数组不为空,就说明修改没有达到 impeccable 标准,CLI 会自动回滚并重新尝试。
4.5 自动回滚与重试机制
回滚机制我是在 CLI 的 hook 里实现的。audit.js返回非零退出码时,CLI 会触发回滚:
# audit.js 发现问题时 if [ $? -ne 0 ]; then git checkout -- src/components/Card.tsx echo "审计未通过,已回滚,准备重试" # 重新触发修改,最多重试 3 次 fi重试的时候,我会把上一次的审计报告作为上下文传给 AI,让它知道哪里出了问题:
codex cli --task "上次修改的 padding 是 15px,不符合 design-tokens.json 中的 md 间距(16px),请修正" \ --file "src/components/Card.tsx" \ --context "./audit-report.json"这个“审计报告作为上下文”的做法,是我试下来提升通过率最明显的一招。AI 看到具体的差异之后,第二次修改的准确率能到 80% 以上。
5. 常见问题与排查技巧实录
5.1 AI 改完代码后页面样式没变化
这是最常见的问题,原因通常有三个:
缓存问题。浏览器缓存了旧的 CSS,或者构建工具没有重新编译。排查方法是强制刷新(Cmd+Shift+R),或者检查构建输出目录的时间戳。
选择器优先级问题。AI 写的样式被更高优先级的规则覆盖了。这种情况 lint 查不出来,但 browser extension 读 computed style 能发现。我的做法是在审计脚本里加一条:如果某个属性的实际值和 AI 写入的值不一致,就标记为“优先级冲突”。
CSS-in-JS 的运行时问题。如果项目用的是 styled-components 或 emotion,AI 改的可能是静态样式,但运行时被动态样式覆盖了。这种情况需要检查组件的 props 传递逻辑。
5.2 审计通过但视觉上还是不对
这种情况说明审计的覆盖范围不够。我遇到过几次,审计只查了间距和圆角,但问题出在字体粗细或者行高上。解决办法是扩展审计维度,把fontWeight、lineHeight、letterSpacing也加进去。
另一个原因是相对关系没查。比如两个元素各自的间距都符合令牌,但它们之间的间距不对。这种需要审计脚本支持“元素对”的检查,复杂度会高一些,但值得做。
5.3 CLI 上下文丢失导致重复劳动
长对话之后,CLI 可能会丢失早期的上下文,导致 AI 忘记之前的设计决策。codex cli的/compact命令可以缓解这个问题,但更好的做法是把关键决策写进项目里的一个decisions.md文件,每次 CLI 启动时自动加载。
# 设计决策记录 - 卡片间距统一用 md(16px),不用 lg - 深色模式下阴影不透明度减半 - 主按钮 hover 状态用 primaryHover 色值这个文件不大,但能显著减少 AI 的“失忆”问题。
5.4 排查速查表
| 现象 | 可能原因 | 排查动作 |
|---|---|---|
| 样式没变化 | 缓存/构建 | 强制刷新,检查构建输出 |
| 样式被覆盖 | 优先级冲突 | 读 computed style,检查选择器权重 |
| 审计通过但视觉不对 | 审计维度不足 | 扩展审计属性,增加元素对检查 |
| AI 忘记设计决策 | 上下文丢失 | 维护 decisions.md,启动时加载 |
| 重试多次仍不通过 | 任务描述不清 | 把审计报告作为上下文传入 |
提示:排查的时候,先看 browser extension 的审计报告,再看 CLI 的日志,最后才看代码。这个顺序能帮你快速定位问题在哪一层。
6. 我目前跑下来的效果和几个关键心得
这套流程我跑了大概三个月,覆盖了团队里两个中等规模的前端项目。效果上,AI 修改前端代码的一次通过率从最初的 30% 左右提升到了 65% 左右,加上自动重试,最终通过率能到 85% 以上。剩下的 15% 主要是涉及复杂交互或者设计系统本身有歧义的情况,还是需要人工介入。
几个我觉得最关键的心得:
设计令牌的粒度决定上限。令牌越细,AI 的自由发挥空间越小,通过率越高,但灵活性也越低。我的经验是间距和圆角要细到 4px 粒度,颜色和阴影可以粗一点,字体相关的最好单独维护一套。
审计维度要逐步扩展。一开始只查间距和圆角就够了,跑顺了之后再加颜色、阴影、字体。一次性加太多维度,排查成本会很高。
回滚比重试更重要。AI 改错了不可怕,可怕的是改错了还留在代码里。自动回滚是这套流程的安全网,一定要先跑通回滚,再考虑提升通过率。
decisions.md 比想象中有用。这个文件看起来很简单,但它解决了 AI 的“长期记忆”问题。我现在的做法是每次人工介入修正之后,都把修正原因写进这个文件,下次 AI 就不会再犯同样的错。
最后分享一个小技巧:如果你的项目用的是 Tailwind,可以把design-tokens.json和tailwind.config.js做双向同步。这样 AI 改代码的时候,无论是写p-4还是写padding: 16px,审计脚本都能正确识别。这个同步脚本我写了大概 50 行,跑起来很稳,省了很多手动对齐的功夫。