Impeccable 设计检测钩子实战指南:在 Claude Code、Cursor、Codex 等 AI 编码工具中自动拦截 UI 质量缺陷
2026/9/10 1:08:41 网站建设 项目流程

Impeccable 设计检测钩子实战指南:在 Claude Code、Cursor、Codex 等 AI 编码工具中自动拦截 UI 质量缺陷

【免费下载链接】impeccableThe design language that makes your AI harness better at design.项目地址: https://gitcode.com/GitHub_Trending/im/impeccable

本文是 Impeccable 设计语言(PRODUCT.md)中design detector hook(设计检测钩子)的完整技术指南。它讲解如何让 AI 编码工具(Claude Code、Cursor、Codex、GitHub Copilot、Grok Build)在每次编辑 UI 文件后自动运行设计检测器、把发现问题注入 Agent 上下文,并通过/impeccable hooks命令完成开关、状态查看与精细化豁免管理。读完本文,你将掌握钩子的两级规则调度机制、配置文件结构、六个管理动作的用法,以及一套"先修、再豁免、后询问"的发现结果分诊方法论。

钩子是什么:项目级的自动设计质检

设计检测钩子是 Impeccable 提供给当前项目的自动质检通道:每当 AI 直接编辑到与设计相关的文件时,钩子便运行 impeccable design detector(设计检测器),并把结果以短小的系统提醒推回 Agent 上下文。

钩子扫描的文件类型由内置扩展名列表决定,见 crates/hook/src/hook_lib.rs 中的ALLOWED_EXTS

.tsx .jsx .html .htm .vue .svelte .astro .css .scss .sass .less .ts .js

其中.ts.js属于"始终扫描但保持安静"的类型:检测器仍然运行,但除非真的发现问题,否则不输出任何提醒;其余 UI 强相关扩展(ACK_EXTS)在扫描干净时会产生一个简短的确认信息(ack)。

各工具的行为差异

同一份钩子在不同 AI 编码工具中的触发机制不同,理解这点是正确使用的前提:

工具触发方式行为
Claude CodePostToolUse钩子(匹配Edit\|Write编辑后推送简短提醒;发现问题给修正提示,待处理问题再次轻推,干净文件给简短确认(除非hook.quiet
CodexPostToolUse钩子与 Claude Code 相同的提醒机制
GitHub CopilotpostToolUse钩子(匹配edit\|create\|apply_patch与 Claude Code 相同的提醒机制
CursorpreToolUse钩子在坏写入落地之前拦截;检测器发现真实问题时拒绝该次 Write/Edit,拒绝消息以工具错误的形式对 Agent 可见,让 Agent 有机会重新考虑
Grok BuildPostToolUse扫描 +Stop事件扫描标记被改动的文件,在 Stop 的additionalContext上呈现结果;不要期待逐编辑提醒——Grok 会丢弃该 stdout

这套钩子命令的识别与安装标记在 crates/context/src/hook_markers.rs 中实现:is_impeccable_hook_command同时识别"JS 时代"的node ".../hook.mjs"旧形式与"launcher 时代"的".../impeccable" hook新形式,保证旧安装能被on动作修复而不是重复安装。

两级规则体系:即时层与深层扫描

检测器规则分两层运行,钩子默认只暴露即时层(immediate tier)

  • 即时层:机械的、无歧义的、值得为它打断一次编辑的问题——坏图片、溢出或被裁剪的内容、对比度与可读性失败、渐变文字、发光阴影、设计系统漂移等。
  • 深层扫描(deep pass):其余一切(文案节奏、调色板与字体品味、布局韵律)推迟到Stop钩子事件触发时,对会话中接触过的每个 UI 文件运行完整规则集,只呈现一次,并与逐编辑阶段已报告的发现去重。

从源码看,即时层规则清单由impeccable_core::registry::IMMEDIATE_TIER_RULES提供(crates/hook/src/hook_lib.rs),split_findings_by_tier依据规则 id 是否命中该清单决定发现进入即时还是推迟队列。

各工具的深层扫描支持情况:

  • Claude Code、Codex、Grok Build:支持原生Stop钩子事件,默认启用两级调度;
  • Cursor:不提供 Stop 深层扫描(其 stop 钩子不能稳定分发,由 pre-write 闸门覆盖),因此不会推迟非即时规则;
  • GitHub Copilot:其 stop 类事件无法把上下文反馈给模型,因此每次编辑都运行完整检测器。

关键的恢复开关是配置项hook.perEditRules,设为"all"可让每次编辑都运行完整规则集;代码中per_edit_tiering_active(crates/hook/src/hook_lib.rs)正是按此逻辑判断——对 Cursor 和 GitHub 返回false(不启用分档),其余工具仅在perEditRules != "all"时分档。

此外,Grok Build 在end_turn之后还会触发一个仅观察的 Stop 事件(reason: "shutdown"),钩子应跳过该事件,只扫描end_turn

没有钩子时的兜底

每个钩子都是机械检查,扫描器抓不到的"反射动作"(reflexes)记录在 craft-floor.md 中,skill 会在编辑 UI 前加载它,因此无论钩子是否接线,这些质量底线都生效。如果某次会话没有任何自动钩子,impeccable context会给出一次MANUAL_DETECTOR_REQUIRED指令,要求在会话结束时手动运行一次检测器。

配置文件:项目级开关与开发者级覆盖

钩子按项目管理,配置写入统一配置文件.impeccable/config.json

  • 钩子运行时设置位于其hook键下;
  • 检测器的共享忽略规则位于detector键下;
  • 开发者级覆盖(包括 CLI 记录的安装同意决定hook.consent)写在 gitignored 的.impeccable/config.local.json中。

read_config(crates/hook/src/hook_lib.rs)按"先共享、后本地"的顺序合并两个文件,后者的值覆盖前者。

hook 键参数

参数默认值说明
hook.enabledtrue设为false关闭自动钩子(仅控制自动执行,不影响手动 CLI 扫描)
hook.quietfalse设为true静默干净文件/待处理问题的确认信息
hook.auditLog指向一个 NDJSON 日志文件的路径,开启审计日志
hook.perEditRules"immediate"设为"all"恢复每次编辑都运行完整规则集
hook.consent本地安装同意记录,由 CLI 在on时写入config.local.json
hook.limits.maxFindings5单次呈现的发现数量上限
hook.limits.maxChars8000提醒文本的字符预算上限
hook.limits.maxFileBytes131072参与扫描的文件字节数上限

这些默认值在HookConfig::default()中定义(crates/hook/src/hook_lib.rs);maxFindings/maxChars低于 1 时回退到默认值,且渲染时maxChars至少取 500。

遗留环境变量兼容

旧版环境变量仍然生效,且设置时覆盖配置文件

  • IMPECCABLE_HOOK_DISABLED(如=1)——一次性关闭钩子,跟随当前 shell;
  • IMPECCABLE_HOOK_QUIET——静默确认信息;
  • IMPECCABLE_HOOK_LOG——审计日志路径。

status动作会在报告末尾显示IMPECCABLE_HOOK_DISABLED的当前状态(...=1unset)。

detector 键与模板引擎扩展

detector键承载检测器的共享忽略配置:detector.ignoreRulesdetector.ignoreFilesdetector.ignoreValuesdetector.designSystem.enabled(默认开启)。手动npx impeccable detect扫描默认使用同一套项目过滤配置;hook.enabled只管自动钩子,不影响手动扫描。

当项目使用Blade、Twig、ERB 或 Handlebars等服务端模板时,需在detector.extensions中声明扩展名,否则钩子会跳过这些文件(它们不在内置列表内)。每项一条,engine选择分析器(标记模板用html,类 JS/TS/CSS 文件用text),默认html;匹配按文件名末尾进行,因此.blade.php.html.erb这类双扩展名也能工作:

{ "detector": { "extensions": [ { "ext": ".blade.php", "engine": "html" }, { "ext": ".html.erb", "engine": "html" } ] } }

注意:配置只会新增扩展,内置列表始终生效。配置项解析与匹配逻辑见 crates/hook/src/hook_lib.rs(normalize_extension_entriesmatch_configured_extension)。detector.extensions是唯一没有管理动作的字段,如需覆盖模板栈,只能直接编辑.impeccable/config.json中的该字段。

命令路由:六个管理动作

/impeccable hooks的第一个参数是动作,默认status。后台实现位于 crates/hook/src/admin.rs 的admin::run,动作表与源码中ACTIONS常量一致:

动作作用
status打印当前状态:共享/本地配置路径、被忽略的规则/文件/值、环境变量覆盖
on.impeccable/config.json写入enabled: true,在本地配置记录钩子同意为 accepted,并在 skill 已安装时为各工具安装/修复钩子 manifest
off.impeccable/config.json写入enabled: false
ignore-rule <id><id>追加到detector.ignoreRules;对overused-font必须加--all-values。在整个项目范围内压制该规则
ignore-file <glob><glob>追加到detector.ignoreFiles,对匹配文件压制所有规则
ignore-value <id> <value> [--shared] [--reason "..."]向共享.impeccable/config.json追加规则/值压制
ignore-value <id> <value> --local [--reason "..."].impeccable/config.local.json追加私有规则/值压制
ignore-value <id> "*" --file <glob> [--file <glob>...]只在匹配文件中关闭某一条规则,其余文件仍然生效。可重复--file,或使用--file=<glob>/--files=<glob>。裸"*"不带--file会被拒绝——真要项目级压制就用ignore-rule <id>
reset删除项目配置、去重缓存和 Cursor 待处理队列,并从on安装过的每个 provider manifest 中移除钩子条目,包括已提交的 Copilot 文件(团队共享的settings.json从不被on写入,因此也不被动)

从源码看,on动作会做三件事(crates/hook/src/admin.rs):写共享配置的enabled: true、写本地配置的consent: accepted、调用repair_hook_manifests修复各工具的 manifest;reset必须把这三件事全部撤销(源码注释明确引用了 issue #512 的教训:残留的 manifest 条目会在配置删除后继续调用钩子)。ignore-value解析支持--reason(空格或=两种写法)、--file/--files三种变体,且拒绝"规则根本提取不出该值"的死条目(synthetic_ignore_value为空时报错)。

执行流程

  1. 从用户参数中解析动作;未给动作时默认status

  2. 调用管理脚本,把用户输出原样透传:

    .trae/skills/impeccable/scripts/impeccable hooks <action> [args...]
  3. 动作为off时,追加一行说明:"Done. New edits will not trigger the design hook in this project until you run/impeccable hooks on."

  4. 动作为on时,追加:"Done. The design hook will fire after the next Edit/Write on a UI file."

  5. 动作为ignore-valueignore-fileignore-rule时,直接打印脚本输出。默认作用域是共享的.impeccable/config.json;仅当用户明确要求私有豁免时才加--local

  6. 动作为status时,直接打印脚本输出;除非用户追问,否则不加评论。

脚本路径在不同工具下解析为 skill 目录内的 launcher(Windows 上用impeccable.cmd)。status报告的样例结构(源码status_report生成)大致为:状态、共享/本地文件路径(损坏文件标注(malformed; ignored))、ignoreRules/ignoreFiles/ignoreValues列表、maxFindings/maxChars、环境变量覆盖、缓存文件路径。

发现结果的分诊(Triage)

钩子本身从不写忽略配置,一切豁免都走impeccable hooks。每个发现归入三类结果:

  • 真实设计问题:修复它。绝不用忽略来跳过修复或放行被拦截的写入。
  • 确信的误报或认可的例外:自行持久化最窄的忽略并在回复中披露。依据必须是你点得出的证据:有意的演示或 fixture、对坏设计的文档化、字面或领域合适的动效(比如弹跳的球),或用户已确认的选择。把证据写进--reason,格式为"<who decided: evidence>";只有用户真的确认过才写 "user confirmed"。
  • 不确定:保留发现,用一行向用户提问。只问一次——一行问题比钩子在之后每次编辑上重复触发要便宜得多。

自助操作止于ignore-valueignore-fileignore-rule压制面太大,不能凭自己的判断添加,先问用户。

豁免阶梯:从最窄到最宽

优先使用最窄的例外:

  • 发现行给出了ignore-value <rule> <value>对时,直接透传给impeccable hooks ignore-value并带--reason(默认写入共享配置)。值型发现(如overused-fontbounce-easing)用ignore-value针对具体值,不要ignore-rule overused-font去豁免某个具体字体。
  • 发现没有值型命令时(如side-tab),把该规则限定到文件:ignore-value <id> "*" --file <path>。先跑npx impeccable detect <path>看实际触发什么。
  • 仅当整个文件都不在设计评审范围内(fixture、生成产物、刻意做的 slop 演示)才用ignore-file <path>——它会永久压制该文件所有规则,包括尚未写出的规则。真实 UI 表面只有一个规则吵闹时,用上面的文件级值豁免。
  • 仅当用户要求项目级压制整条规则时才用ignore-rule <id>;对overused-font的广泛压制,只有用户要求"整体忽略过度使用字体"时才用ignore-rule overused-font --all-values

优先用配置忽略(上述命令),让压制集中在一个可评审的地方。只有豁免必须随单个文件离开仓库时(生成/导出的独立文档、邮件发送的 HTML),才用内联注释。受支持的标记为impeccable-disable <rule>(整文件)或impeccable-disable-line/impeccable-disable-next-line(单行),任意注释语法均可,可在:--后加可选理由。检测器默认遵循它;--no-inline-ignores--no-config会绕过。内联忽略的解析实现位于 crates/foundation/src/inline_ignores.rs。

实操示例

值型例外(共享配置):

.trae/skills/impeccable/scripts/impeccable hooks ignore-value overused-font Inter --shared --reason "User confirmed Inter is intentional"

自助例外(证据具名):

.trae/skills/impeccable/scripts/impeccable hooks ignore-value bounce-easing bounce-ball --shared --reason "Agent: literal ball-bounce animation, bounce easing is the subject"

整条规则的字体例外:

.trae/skills/impeccable/scripts/impeccable hooks ignore-rule overused-font --all-values --reason "User asked to ignore overused fonts generally"

单规则单文件例外(文件其余内容仍值得评审):

.trae/skills/impeccable/scripts/impeccable hooks ignore-value design-system-font-size "*" --file "src/overlay/widget.js" --reason "Injected widget builds its own type scale; DESIGN.md's ramp describes the site"

整文件例外(文件完全超出范围):

.trae/skills/impeccable/scripts/impeccable hooks ignore-file "src/legacy/Card.tsx"

支持的 harness 与安装位置

钩子随 Impeccable skill 打包,通过项目本地 manifest 安装:

工具Manifest 路径说明
Claude Code.claude/settings.local.jsongitignored,钩子保持机器本地;移入共享settings.json也会被就地生效
Codex.codex/hooks.json首次需用户通过/hooks批准
Cursor.cursor/hooks.json需在 Settings -> Hooks 确认钩子已启用
Grok Build.grok/hooks/impeccable.json需要/hooks-trust--trust
GitHub Copilot.github/hooks/impeccable.json团队共享的已提交文件,CLI 与云端 Agent 都会读取;CLI 在文件提交到默认分支后触发仓库级钩子

Manifest 的目标与命令模板定义在 crates/hook/src/admin.rs 的HOOK_MANIFEST_TARGETS中:Claude/Codex 用 launcher 命令".../impeccable" hook,Cursor 用hook-before-edit,Copilot 用仓库根锚定的"$(git rev-parse --show-toplevel)/.github/skills/impeccable/scripts/impeccable" hook;Codex 的 Windows 变体还带commandWindows指向.cmdshim。on在写入时对已有 manifest 做合并(保留非 Impeccable 的钩子条目,见merge_hook_manifests),损坏的 manifest 会先备份为.bak

约束

  • 不要从本命令手工修改.impeccable/config.json.impeccable/config.local.json;一律通过impeccable hooks写入,保证写入经过校验、文件形状保持一致。唯一例外:detector.extensions没有管理动作,用户要求覆盖模板栈时直接编辑该字段,其余部分不动。
  • 不要从该流程编辑impeccable hookimpeccable hook-before-edit背后的 launcher 或二进制——那是 skill 管道。
  • Cursor 能在检测器发现真实问题时拦截提议的写入;Claude Code、Codex 和 GitHub Copilot 不拦截编辑,而是发出编辑后提醒。关闭钩子会同时停止拦截与提醒。

失败模式

  • .impeccable/config.json.impeccable/config.local.json不可读或格式损坏,钩子忽略该文件,使用其余有效配置/默认值;impeccable hooks status会把损坏文件显示为malformed; ignored。对应实现见read_raw_config_file(crates/hook/src/admin.rs)。
  • 用户要求"全局禁用钩子"时,先用/impeccable hooks off(对本项目持久化,写入hook.enabled: false)。遗留环境变量IMPECCABLE_HOOK_DISABLED=1也可作为跟随 shell 的一次性覆盖。

小结

设计检测钩子把"每次编辑后做一次机械设计质检"从手工流程变成了多工具通用的自动化机制:两级规则调度保证编辑不被高频噪音打断、深层问题又能在 Stop 时一次性补全;统一的.impeccable/config.json让开关、静默、审计、忽略与模板扩展都在一处管理;impeccable hooks的六个动作配合"最窄豁免"阶梯,让误报处理既有据可查又不越权。无论你的主力工具是 Claude Code、Cursor、Codex、GitHub Copilot 还是 Grok Build,这套机制都能让设计质量防线与你的日常编辑流程无缝贴合。

【免费下载链接】impeccableThe design language that makes your AI harness better at design.项目地址: https://gitcode.com/GitHub_Trending/im/impeccable

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询