
1. 从impeccable这个词说起为什么前端设计总在AI编码环节掉链子第一次看到impeccable被拿来命名一个跟AI编码代理相关的工具我脑子里冒出来的第一个念头是这词挑得挺狠。impeccable无瑕的、挑不出毛病的。放在前端设计这个语境里它其实戳中了一个所有用过AI编码代理的人都心知肚明、但很少被摆到台面上讲的痛点——AI写出来的前端代码功能上往往能跑但视觉上、交互上、细节上经常是能用但难看能跑但别扭。我自己用各类CLI形态的编码代理codex cli、zcode cli、trae cli这些做过不少前端项目从落地页到后台管理面板都试过。一个很典型的场景是你让代理生成一个卡片组件它给你返回的代码里padding是随手写的16px圆角是8px阴影是那种默认的、毫无层次感的box-shadow颜色用的是最基础的十六进制值间距全靠感觉。代码能渲染但你把几个组件拼到一起整个页面就透着一股AI味——对齐不齐、节奏混乱、层级不清。这就是impeccable这类工具想解决的问题。它不是一个框架也不是一个UI库而更像是一层设计约束层插在AI编码代理和你最终产出的前端代码之间。它的核心价值在于把那些资深前端工程师脑子里默认存在的设计规范、间距系统、色彩逻辑、响应式断点策略变成AI代理在生成代码时必须遵守的硬性规则。从热搜词能看出来现在围绕CLI形态的AI编码工具已经形成了一个不小的生态codex cli有它自己的一套命令/compact、/model、/resume这些zcode cli、trae cli、minimax cli、openspec cli各有各的玩法甚至还有boos cli、gitlab cli安装这类偏工程化的需求。但大家讨论的焦点几乎都集中在怎么装怎么用有哪些命令上很少有人认真聊生成出来的东西质量到底怎么样。impeccable切入的正是这个被忽略的环节。这篇文章我想聊的不是impeccable怎么安装这种说明书式的内容而是围绕它背后那套逻辑把AI编码代理做前端设计时最容易翻车的几个环节拆开讲为什么AI生成的前端总是差一口气、设计约束到底应该约束什么、CLI工具和浏览器扩展这两种形态各自适合什么场景、以及我在实际项目里踩过的那些坑。不管你是刚接触codex cli这类工具的新手还是已经用了一阵子但总觉得产出不够精致的老手应该都能从里面找到点有用的东西。2. AI编码代理生成前端代码时到底在哪几个环节最容易失手2.1 间距与节奏AI最没有手感的地方前端设计里最考验功力的从来不是某个组件写得好不好看而是整个页面的节奏感。节奏感这东西说白了就是间距的一致性。一个专业的界面它的间距往往遵循某个基数系统——比如4px或8px的倍数标题和正文之间、卡片内边距、卡片之间的间隙、区块之间的留白全都落在这个系统里。人眼未必能说出为什么但一看就觉得舒服。AI编码代理在这件事上几乎是天然失手的。原因很简单它在生成代码时是在做token级别的概率预测而不是在做空间规划。你让它写一个卡片它可能给padding写20px给margin写12px给gap写10px。单看每个值都合理但凑在一起就没有任何数学关系。我实测过好几次让同一个代理连续生成三个卡片组件三次的padding值分别是16px、20px、24px完全没有一致性可言。impeccable这类工具的做法是在代理生成代码之前先注入一套间距token。比如定义--space-1: 4px到--space-12: 48px这样一套阶梯然后要求代理在写任何padding、margin、gap时只能从这套token里取值。这看起来是个很小的约束但效果立竿见影——因为一旦间距被限制在有限的几个值里页面的节奏感自然就出来了。提示如果你现在用的CLI代理还不支持注入设计token一个土办法是在项目根目录放一个design-rules.md在每次对话开始时让代理先读这个文件。codex cli这类工具支持在会话里引用文件效果虽然不如原生集成但比什么都不做强得多。2.2 色彩层级不是颜色不够多而是层级没拉开第二个高频翻车点是色彩。AI生成的前端配色常见毛病不是丑而是平。它会给主色、背景色、文字色各挑一个值然后整个页面就这三个颜色平铺直叙没有hover态、没有active态、没有disabled态、没有不同层级的灰。结果就是界面看起来像一张静态图缺少交互的暗示。专业的前端配色是一套层级系统。以文字为例至少要有primary、secondary、tertiary、disabled四个层级每个层级的对比度都要满足可访问性要求。背景色也要分surface、surface-raised、surface-overlay。这些层级之间的差异往往很微妙——可能只是透明度差5%或者明度差3%——但正是这些微妙的差异撑起了界面的高级感。impeccable在这块的思路是预定义一套语义化的色彩token比如--text-primary、--text-secondary、--surface-base、--surface-elevated并且规定代理只能引用语义token不能直接写十六进制值。这个约束的妙处在于它逼着代理去思考这个文字是什么角色而不是这个文字该是什么颜色。角色想清楚了颜色自然就对了。2.3 响应式断点AI经常假装这件事不存在响应式是AI编码代理最容易糊弄过去的环节。你让它写一个页面它给你一个漂亮的桌面端布局然后加一句media (max-width: 768px)里面随便堆几个flex-direction: column就算完事。移动端的字号、间距、触控区域、导航形态基本没认真处理过。真正做过响应式的人都知道断点不是随便定的。它取决于你的内容在什么宽度下开始挤而不是取决于某个设备的像素值。而且移动端不是桌面端的缩小版交互模式完全不同——hover在触屏上不存在点击区域要至少44px横向滚动要尽量避免。这些细节AI默认是不会主动考虑的。impeccable这类工具通常会内置一套断点策略和移动端规则强制代理在生成任何布局时都要同时考虑多个视口。有些实现还会要求代理为每个组件显式声明它在不同断点下的行为而不是靠一个笼统的media query打发。2.4 交互状态被遗忘的hover、focus、active最后一个重灾区是交互状态。AI生成的按钮往往只有默认态hover态要么没有要么就是简单地把背景色调深一点。focus态基本被忽略——这对键盘用户来说是灾难。active态、disabled态、loading态更是经常缺席。一个impeccable的按钮至少要有六种状态default、hover、focus-visible、active、disabled、loading。每种状态的视觉反馈都要清晰但不突兀。focus态尤其重要它不能简单地用outline: none去掉而要用box-shadow或者自定义outline做出既明显又不破坏设计的效果。我在实际项目里的做法是把交互状态的要求写进设计约束里明确列出每个交互组件必须实现哪些状态。这听起来很啰嗦但一旦形成规则代理的产出质量会稳定很多。3. 设计约束层该怎么搭从token系统到代理指令的完整链路3.1 为什么是约束而不是模板很多人第一反应会问既然AI生成的前端不够精致那直接给它一套现成的UI组件库不就行了用现成的模板不就绕过了所有细节问题这个思路听起来合理但实际用起来问题很大。模板的本质是固定答案而前端项目的需求千变万化。你用一个固定的卡片模板遇到需要变体的场景就抓瞎你用一个固定的配色方案遇到品牌色不同的项目就得推倒重来。更关键的是模板会限制AI的发挥空间——它本来可以帮你处理各种边界情况结果被模板框死了。约束的思路完全不同。约束不规定长什么样只规定必须遵守什么规则。比如所有间距必须是4的倍数所有颜色必须来自语义token所有交互组件必须有focus态。这些规则不限制具体设计但保证了产出的下限。AI仍然可以根据具体需求自由发挥只是发挥的边界被框住了。这个区别有点像给厨师一份固定菜谱和给厨师一套厨房规范。前者只能做出那道菜后者能让厨师做出任何菜但保证每道菜都符合卫生和出品标准。impeccable走的是后一条路。3.2 token系统的三层结构原始值、语义、组件一套能用的设计token系统通常分三层。最底层是原始值primitive比如--blue-500: #3b82f6、--gray-100: #f3f4f6这些是纯粹的色值不带任何语义。中间层是语义tokensemantic比如--color-primary: var(--blue-500)、--color-text-secondary: var(--gray-600)这一层把原始值映射到具体用途。最上层是组件tokencomponent比如--button-bg: var(--color-primary)、--card-padding: var(--space-4)。为什么要分三层因为这样改起来最灵活。品牌色要换只改中间层的映射就行原始值不用动。某个组件的间距要调只改组件token就行不影响全局。AI代理在生成代码时应该只引用最上层的组件token或者至少是语义token绝对不允许直接写原始值。我在实际配置里会把这三层token写成一个CSS文件然后在代理的指令里明确要求生成任何样式时颜色只能引用--color-*开头的变量间距只能引用--space-*开头的变量禁止出现任何硬编码的十六进制色值或像素值。这条规则一加产出的代码质量立刻上了一个台阶。3.3 把设计规则翻译成代理能听懂的指令token系统搭好了接下来要解决的是怎么让代理遵守。不同的CLI工具支持的方式不一样。codex cli这类工具通常支持在项目里放一个配置文件或者规则文件代理在每次会话开始时会自动读取。有些工具支持通过命令行参数注入系统提示词。还有些工具支持在对话中用/开头的命令动态调整行为。不管用哪种方式指令的写法有几个要点。第一要具体不能含糊。注意间距一致性这种话代理听不懂所有padding和margin必须是4px的倍数才听得懂。第二要可验证最好能给出正例和反例。用var(--space-4)而不是16px比使用设计token有效得多。第三要分优先级哪些是硬性规则、哪些是建议要标清楚否则代理会在冲突时随机选择。我自己的规则文件大概长这样开头是一段总则说明这个项目的设计系统基于什么原则然后是硬性规则清单每条都用必须/禁止开头最后是几个典型组件的示例代码让代理有个参照。这个文件大概两三百行写一次能用很久性价比很高。3.4 浏览器扩展形态和CLI形态的分工热搜词里同时出现了CLI和browser extension这其实对应了两种不同的使用场景。CLI形态适合在项目开发阶段用代理直接读写项目文件生成的是源码。浏览器扩展形态适合在看到什么改什么的场景用比如你在浏览某个页面时觉得某个组件不错想直接提取它的设计规则或者想实时预览某个改动。这两种形态不是替代关系而是互补。CLI负责从零生成扩展负责实时校验和微调。我在实际工作流里是这样用的先用CLI代理生成整个页面的骨架和组件然后在浏览器里打开预览用扩展检查间距、对比度、响应式表现发现问题再回到CLI里让代理修。这个循环跑几轮产出质量就稳定了。注意浏览器扩展形态的工具在读取页面样式时可能会受到跨域限制或者CSS-in-JS的影响提取出来的规则未必完整。如果你的项目用了CSS-in-JS方案建议以CLI形态为主扩展只做辅助校验。4. 实测流程用CLI代理跑一个前端页面的完整记录4.1 项目初始化阶段该做哪些准备我拿一个真实的落地页项目来演示整个流程。项目需求很简单一个产品介绍页包含导航栏、hero区、三个特性卡片、一个CTA区、页脚。技术栈是纯HTMLCSS不引入任何框架这样能最清楚地看到代理的原始产出。第一步是初始化项目结构。我建了一个空目录然后放了三个文件index.html、styles.css、design-rules.md。design-rules.md就是前面说的设计约束文件里面定义了token系统、间距规则、色彩层级、响应式断点、交互状态要求。这个文件是整个流程的核心代理每次生成代码前都会先读它。第二步是确认代理能读到这个文件。不同CLI工具的读取方式不一样有的需要显式在对话里引用有的会自动扫描项目根目录。我用的工具支持自动读取根目录下的规则文件所以直接开始对话就行。如果你用的工具不支持可以在第一条消息里把规则文件的内容贴进去或者用文件引用语法。第三步是明确任务边界。我不会一上来就让代理生成整个页面而是拆成小块。先让它生成导航栏确认风格对了再生成hero区以此类推。这样做的好处是如果某个环节的风格跑偏了能及时发现并纠正不用等到整个页面生成完再返工。4.2 第一轮生成导航栏和hero区第一条指令我写的是读取design-rules.md然后生成一个导航栏包含logo、四个导航链接、一个登录按钮和一个注册按钮。所有样式写在styles.css里使用设计token。代理返回的代码质量让我有点意外。它确实读了规则文件导航栏的padding用的是var(--space-4)链接之间的gap用的是var(--space-6)按钮的背景色用的是var(--color-primary)。整个导航栏的高度是64px正好是8的倍数。hover态和focus态都实现了focus态用的是box-shadow而不是outline: none。但也不是没有问题。它给logo用的字号是var(--font-size-xl)而我在规则里其实建议logo用var(--font-size-2xl)。这是个小事但说明代理对规则的理解还是会有偏差。我在下一轮指令里纠正了这一点并且把logo必须用2xl字号写进了规则文件的硬性规则里。hero区的生成相对顺利。代理按照规则生成了标题、副标题、两个按钮间距全部落在token系统里。响应式方面它在768px断点处把布局从横向改成了纵向按钮变成了全宽。这部分做得不错但移动端的字号没有相应缩小标题在手机上显得有点大。这个问题我在后面单独处理了。4.3 特性卡片间距一致性的一次真实考验特性卡片是这次实测里最能体现设计约束价值的环节。三个卡片并排每个卡片包含一个图标、一个标题、一段描述。如果没有约束代理很可能会给每个卡片写不同的padding或者卡片之间的gap和卡片内部的padding不成比例。实际生成的结果是卡片padding统一用var(--space-6)卡片之间gap用var(--space-8)图标和标题之间用var(--space-4)标题和描述之间用var(--space-2)。整个间距体系是自洽的视觉上看起来很舒服。这就是token系统的威力——代理不需要理解设计它只需要从有限的选项里取值取出来的组合自然就是和谐的。不过我发现一个小问题三个卡片的图标大小不一致。代理给第一个图标用了24px第二个用了28px第三个用了32px。这明显是它在生成过程中自由发挥了。我在规则文件里补了一条所有图标必须使用统一的尺寸token然后让代理重新生成问题就解决了。4.4 响应式断点的实际表现与修正整个页面生成完之后我在浏览器里从320px到1440px逐段测试。桌面端和移动端的大布局都没问题但在平板尺寸768px到1024px之间出现了一个尴尬的情况三个特性卡片在这个宽度下还是三列每个卡片被挤得很窄文字换行很频繁看起来很局促。这是典型的断点没设够的问题。代理只设了一个768px的断点没有考虑中间尺寸。我在规则文件里补充了断点策略小于640px单列640px到1024px两列大于1024px三列。然后让代理重新生成卡片的响应式部分。这次它用了两个断点中间尺寸下卡片变成两列第三个卡片自动换到第二行布局就舒服多了。这个修正过程让我意识到设计约束文件不是一次写完就完事的它需要在实际使用中不断补充。每次发现代理在某个环节失手就把对应的规则补进去下次就不会再犯。用了几轮之后这个文件就变成了一份相当完整的设计规范。4.5 交互状态的补全与验证最后一轮是补全交互状态。我让代理检查所有可交互元素确保每个都有default、hover、focus-visible、active、disabled五种状态。代理返回的结果里按钮和链接的状态都补全了但导航链接的focus态用的是默认的浏览器outline跟整体设计不搭。我让它把focus态改成自定义的box-shadow颜色用var(--color-focus-ring)。改完之后用键盘Tab键走了一遍整个页面每个可聚焦元素的focus态都清晰可见而且风格统一。这一步做完整个页面的完成度就上来了。5. 那些规则文件里没写、但实际会踩的坑5.1 代理会忘记规则需要周期性提醒这是我在实际使用中最头疼的问题。代理在会话开始时读了规则文件前几轮生成都遵守得很好但对话进行到十几轮之后它开始忘记某些规则。比如突然给某个元素写了硬编码的#333或者用了不在token系统里的间距值。这个现象的原因不难理解随着对话变长早期的上下文在代理的注意力里被稀释了。规则文件的内容虽然还在上下文里但权重下降了。解决办法有两个一是定期在对话里重新强调关键规则比如每隔几轮就说一句记住所有颜色必须用语义token二是把最重要的规则放在规则文件的最前面因为代理对开头的注意力通常更高。我现在养成的习惯是每生成三到四个组件就主动检查一遍代码里有没有硬编码的值。发现一个就纠正一个同时把这条规则在对话里再强调一遍。虽然有点麻烦但比最后返工要省事得多。5.2 不同CLI工具对规则文件的支持差异codex cli、zcode cli、trae cli这些工具虽然都是CLI形态但对规则文件的支持程度差别很大。有的支持自动读取项目根目录下的特定文件名有的需要在配置里显式指定路径有的干脆不支持文件读取只能靠对话里粘贴。我在切换工具的时候踩过坑。在一个工具里跑得好好的规则文件换到另一个工具里代理完全无视生成出来的代码又回到了AI味十足的状态。后来才发现是新工具不自动读取那个文件名。解决办法是查一下新工具的文档看它支持什么文件名和路径把规则文件改成对应的名字。如果你经常在多个工具之间切换一个省事的做法是把规则文件的内容做成一个模板每次开新会话时直接粘贴到第一条消息里。虽然不如自动读取优雅但胜在通用什么工具都能用。5.3 规则太严会限制代理的合理发挥设计约束的目的是保证下限不是限制上限。我一开始把规则定得特别死比如所有间距只能是4、8、16、24、32这几个值结果代理在遇到一些特殊场景时完全没法处理。比如一个需要视觉冲击力的hero区它想用一个大一点的留白但规则里没有对应的值只能硬套一个32px效果就很平庸。后来我把规则改成了间距优先从token系统取值特殊场景可以例外但必须在代码注释里说明理由。这样代理在大多数情况下还是遵守token系统但遇到确实需要突破的场景时可以合理发挥。这个平衡点找了挺久核心原则是规则约束的是默认行为不是所有行为。5.4 浏览器扩展校验时的样式污染问题用浏览器扩展做校验的时候有个容易被忽略的问题扩展注入的样式可能会污染页面本身的样式。有些扩展为了高亮显示间距或者对比度问题会往页面里插入额外的DOM元素或者CSS规则。这些注入的内容有时候会影响到页面本身的布局导致你看到的问题其实是扩展造成的而不是页面本身的问题。我的做法是用扩展发现问题后先禁用扩展刷新页面确认一下。如果问题还在那才是真问题。另外尽量用扩展的只读模式不要用那些会修改页面的功能避免引入干扰。5.5 生成代码的可维护性往往被忽视AI生成的代码有个通病能跑但不好维护。它可能会生成一堆嵌套很深的div类名起得随意CSS选择器写得过于具体。这些问题在项目小的时候不明显项目一大就变成灾难。设计约束文件里应该加一条关于代码结构的规则比如避免超过三层的DOM嵌套类名使用BEM命名法CSS选择器嵌套不超过两层。这些规则不会直接影响视觉效果但会显著影响代码的长期可维护性。我吃过这个亏一个用代理生成的页面三个月后想改一个布局发现CSS选择器层层嵌套改一处牵动全身最后只能重写。6. 把impeccable的思路用到你自己的项目里6.1 从最小可用的规则文件开始如果你现在就想试试这套思路不用一上来就搞一套完整的设计系统。从最小可用的规则文件开始就行。我建议先定三件事一套间距token哪怕只有4、8、16、24、32五个值、一套语义色彩tokenprimary、secondary、surface、text-primary、text-secondary这几个够用了、一条关于交互状态的规则所有可交互元素必须有hover和focus态。这三件事写下来大概也就三四十行但已经能拦住AI生成前端时最常见的几类问题。用一段时间之后你会发现某些问题反复出现就把对应的规则补进去。规则文件是长出来的不是一次设计出来的。6.2 建立发现问题就补规则的循环这套方法的核心不是规则文件本身而是那个发现问题、补充规则、验证效果的循环。每次代理生成的东西不符合预期不要只是手动改代码而是想一想这个问题能不能用一条规则避免如果能就把规则补进去。这样你的规则文件会越来越完善代理的产出也会越来越稳定。我在自己的项目里维护了一个问题日志每次遇到代理失手的情况就记一笔周末统一整理成规则。坚持了两个月之后规则文件从最初的三十行涨到了三百多行代理的产出质量也从需要大量手动修改变成了基本可以直接用。6.3 团队协作时规则文件的版本管理如果你在团队里用这套方法规则文件一定要纳入版本管理。它本质上是一份设计规范应该跟代码一起走Git流程。每次有人发现新的问题并补充了规则就提一个PR其他人review之后合并。这样规则文件就成了团队共识的载体而不是某个人的私人配置。我们团队的做法是规则文件放在项目根目录跟README同级。新成员入职第一件事就是读这个文件了解项目的设计约束。代理生成代码时也读同一个文件保证人和AI遵守的是同一套规则。这个做法看起来简单但效果很好团队里几个人用不同的CLI工具产出的代码风格却能保持一致。6.4 什么时候该放弃约束、手动接管最后说一个反直觉的经验不是所有场景都适合用设计约束。有些高度定制化的页面比如营销活动页、品牌展示页它们的设计往往是反规范的需要打破常规才能出效果。这种场景下硬套token系统反而会限制创意。我的判断标准是如果这个页面的核心价值在于规范、一致、可维护那就用约束如果核心价值在于独特、有冲击力、一次性那就手动接管让代理只做辅助工作。分清这两种场景比无脑套用规则要重要得多。用impeccable这套思路做前端最大的收获其实不是AI能生成好看的前端了而是我终于能把脑子里那些说不清道不明的设计直觉变成AI能执行的规则。这个过程本身就是对前端设计理解的一次梳理。规则写得越清楚说明你对设计的理解越透彻。从这个角度看受益的不只是AI还有你自己。