关于 visant-killer
Visant Killer 是一套面向前端界面审查的技能与扫描脚本,结合确定性检测和人工判断,覆盖设计标记、文案、界面噪声及屏幕实测。它要求先确认缺陷再修改,并将审美改进作为提案交由用户逐项选择。
主要功能
- 01扫描设计标记与界面文案
- 02检查界面噪声和常见模式
- 03按目标规模分级审查
- 04要求记录已查看的屏幕
- 05确认缺陷后再修改代码
- 06将审美改进整理为提案
适用场景
- 01审查单个组件或整条界面路线
- 02检查设计令牌与文案问题
- 03验证登录后页面的实际显示
- 04梳理大型目标中的共享组件问题
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ pedrojaques99/ visant-skills-public --skill visant-killer安装后在 Claude Code 中输入/visant-killer确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/cases.mddeclutter.mddevils-advocate.mddistribution.mdenvironment.mdfalse-positives.mdgates.mdmulti-agent.mdscorecard.mdslop-catalog.mdverification.mdscripts/corta-scan.jscorta-self-test.mjscorta-url.mjsdist-scan.mjsscripts/fixtures/clip-cases.htmlcopy-extractor.tsxscripts/fixtures/dist-routes/app/layout.tsxpage.tsxscripts/fixtures/dist-routes/app/_private/thing/page.tsxscripts/fixtures/dist-routes/app/(shop)/product/[handle]/page.tsxscripts/fixtures/dist-routes/app/search/page.tsxscripts/fixtures/dist-routes/components/search-box.tsxscripts/fixtures/dist-routes/components/cart/actions.tsmodal.tsxscripts/fixtures/dist-routes/components/grid/index.tsxscripts/fixtures/dist-routes/components/layout/navbar/index.tsxscripts/fixtures/dist-routes/content/pages/terms.mdxscripts/fixtures/dist-routes/pages/_app.tsxabout.tsx详细介绍
Visant Killer
对抗式 UI 审计。屏幕是被告,不是客户。两个部分互不替代:闸门(确定性脚本,二元判断:AI 痕迹、令牌、语气、界面噪声)和评判(由加载了相关技能的你来完成),因为 AI 垃圾内容能躲过任何代码检查:问题出在决策,而不是语法。
**规则零(来自
visant-copy):**只有已确认缺陷的修复才能写入文件。通过检查的内容保持原样,即使听起来平淡无奇。 品味方面的改进列为提案表;由用户逐行选择。
**闸门全绿,不等于看过屏幕。**某个主导表单中的
AnimatePresence冻结问题通过了六道闸门。因此,killer-scan拒绝在缺少界面表和打开屏幕的记录时,宣称“闸门已通过”。
各条规则的出处:references/cases.md。
严禁事项(写代码时就要遵守,不能等到审查时再改)
| 禁止事项 | 应写成 | 原因 |
|---|---|---|
在文本中使用箭头符号(→、←、↑、↓)和手绘图标 SVG | 使用真实的库图标(@phosphor-icons/react、@radix-ui/react-icons) | 铁律。 箭头字符是 Claude 最常见的习惯:它继承字体度量,基线容易偏移,形状随字体系列变化,无法控制粗细或尺寸,而且看起来像文本。手写 SVG 只是同一种问题,代码行更多。图标必须始终使用库资源 |
hover:scale-*、whileHover={{ scale }} | 改变颜色、阴影或边框 | 悬停时缩放是模板最明显的特征;它会移动相邻布局,也无法遵循 prefers-reduced-motion |
| 悬停效果覆盖相邻文本并使其变大 | 永久预留空间,并在空间内放大 | 悬停效果应显示内容,而非压住其他元素 |
当 --accent 表示强调色时使用 hover:bg-accent | hover:bg-muted 或 hover:bg-primary | 把强调色变成鼠标状态。检查设计令牌:在 stock shadcn 中,--accent 是中性悬停色,此时 hover:bg-accent 才是正确的 |
border-accent | border-border | 同样是混淆:把强调色变成界面装饰 |
在对话框/侧边面板之外使用 backdrop-blur | 使用纯色设计令牌背景 | 每次滚动都会产生合成开销;用于卡片时,就是以帧率为代价的装饰 |
在没有 max-width 的叠加层中使用 white-space: nowrap | max-width: calc(100% - 12px),并允许换行 | 在 overflow: hidden 的父元素内,文字会被截断;而且只有字体加载后才会出现截断,任何 linter 都检测不到 |
在项目工厂函数中固定高亮(on: true、active: true) | 使用决定是否高亮的条件(on: q.live) | 如果每个项目都只执行一次高亮逻辑,整个列表就会亮起;所有内容都强调,就等于什么都没强调 |
| 同一屏幕上为同类数据提供两个入口 | 每个屏幕只保留一个入口,或使用能说明差异的名称(检测器只检查同一屏幕;不同屏幕上重复使用名称属于判断问题) | 并排放置两个相同的 URL 字段,却写入不同的数据存储:用户只能碰运气选择 |
transition-all | transition-colors 或明确列出的属性 | 会为未指定的内容添加动画,包括布局 |
交互元素使用 duration-300 及以上 | DUR.base / DUR.slow | 超过约 300 毫秒,界面就会让人觉得卡住 |
原始十六进制颜色、rgb()、rgba() | HSL 设计令牌(hsl(var(--x))) | var(--x) 本身不是颜色:设计令牌存储的是未封装的颜色通道 |
| 使用虚假框架、“悬停我”说明文字或堆叠变体的组件演示 | 将组件放大并居中,一次只展示一个,并提供低调的选择器 | 目录 35–38:在卡片中,组件会被说明内容掩盖 |
| 仅在悬停时展示精美状态(辉光、倾斜、打开的菜单) | 让组件初始就处于最佳状态;悬停时再增强效果 | 触屏、卡片视图和截图中都看不到这种状态(目录 37) |
可点击的按钮/卡片没有 cursor: pointer;可拖动元素没有 grab | 在外壳中添加规则(:is(button,[role=button],a[href])) | Tailwind v4 的预检样式会重置光标(目录 46) |
| 在库组件中使用面向特定客户端的文案 | 使用通用文本,以巴西葡萄牙语呈现 | 组件库面向所有客户端提供服务(目录 42) |
允许例外(路由切换、营销组件、作为 WCAG 对比度参考的 #fff/#000、Dialog 中的模糊效果、照片上的遮罩层)。例外必须在同一行附上书面理由,并遵循扫描器格式
(references/gates.md),绝不能使用不作说明的 audit-ignore。
脚本及其完整路径(每个步骤都会用到):
K=~/.claude/skills/visant-killer/scripts/killer-scan.mjs
R=~/.claude/skills/visant-refine/scripts/refine-scan.mjs
D=~/.claude/skills/visant-killer/scripts/dist-scan.mjs
C=~/.claude/skills/visant-copy/scripts/copy-lint.mjs
T=~/.claude/skills/visant-killer/scripts/corta-scan.js # runs IN THE BROWSER (Step 5)
V=~/.claude/skills/visant-killer/scripts/verify-screens.mjs # opens the app logged in (Step 5)
# grafo.mjs is a library (import graph for --roots and repeated-door), not a CLI
步骤 0:先检查根节点(目标范围较大时)
如果目标涉及数十个文件,应先按根节点汇总发现的问题:
node $K --roots <target>(按 fan-out × findings 为共享组件排序,
了解详情)。一个错误的容器会产生数百个症状相同的叶节点,指向错误的文件。应先处理基础组件和外壳,再处理页面;最后使用 --all,按文件拆分其余问题。
步骤 1:对目标分类(绝不跳过)
层级决定需要对目标进行多少追问;层级判断错误会浪费上下文,或对真正带来收入的部分审查得过于浅显。
| 层级 | 目标是 | 信号 | 追问数量 |
|---|---|---|---|
| T1 Leaf | 一个组件、一张卡片、一行列表 | 1 到 3 个文件,没有自己的路由,不会写入数据库 | 5 个问题 |
| T2 Route | 一个完整屏幕 | 有 page.tsx,有状态(加载中、为空、出错),有键盘交互 | 12 个问题 |
| T3 Core | 一个影响资金、身份或多个路由的流程 | 写入数据库、计费、权限、引导流程、销售管线 | 20 个问题,另加定位分析 |
混合目标:按区域而非文件夹分类(列表屏幕中的计费行属于 T2 中的 T3)。
投诉仅涉及冗余(“文字太多”“杂乱”“像模板”“tá poluído”“muita label”):直接前往 declutter.md,这条路径不需要了解项目背景(任何仓库、任何语言、无需代码检查工具)。
第 2 步:门禁(在阅读代码前运行)
先报告,后检测(退出码会让人误以为任务已完成,Agent 会就此停下):
node $K --init-report AUDIT.md <target> # skeleton, one row per route (Shell hint to confirm)
# fill the table BEFORE fixing anything
node $K --report AUDIT.md <target>
如果没有完整的 --report,它会打印 GATE INCOMPLETE 并以状态码 1 退出
(详情)。有两个必填列:
- surface:A 获取(尚未成为客户),B 工作(每天都会使用), C 信任(金钱、权限、破坏性操作)。把 A 阶段的直觉放到 B 阶段的页面上,是 最昂贵的前端错误。
- business variable:这个元素影响什么指标。破折号、“TBD”或空白都会 被拒绝:填入空值等于跳过这一步。
## Screen seen 部分(必须使用此确切标题;## Tela vista 也能解析)是
另一半:每个打开过的屏幕占一行,写明路由、宽度、数据状态和
发生了什么。请先阅读 environment.md:开发服务器会撒谎。
killer-scan 会运行四个检测器,打印一张记分表,并以一行 gates: N/4 ran [...]
结束,列出所有跳过的项目:impeccable(AI 提示);token(类似仓库
audit:design 的门禁,否则使用已标注的内置 FALLBACK 检测原始 hex/rgb/hsl 和调色板类,
并识别仓库的 token 层);copy(文案语气,仅检查用户能看到的字符串:JSX 文本、label、title、placeholder、
aria-label、alt);chrome noise(noise-scan:每一行都要有理有据,
总和则要清晰易读)。详情和 24 条噪声规则见:gates.md。
找出目标仓库的门禁。 这四个检测器只是最低要求。检查
package.json 中名为 lint/audit/design/token/ui/theme/i18n/ratchet 的脚本,
以及 scripts/ 中未接入的扫描器;在目标仓库运行现有的检查;记录运行了什么、跳过了什么,以及原因
(命令)。
辅助门禁:存在图表、仪表或动画时运行 node $R <target>;在 surface A 上,
润色之前运行 node $D <app-root>,因为页面能分享但没有卡片,或能转化却没有事件,
都无法靠 token 修复,而且不会触发任何 UI 检测器(distribution.md)。
确认每条发现都对应 file:line 后,失败的门禁就要变成修复,而不是提议
(旧代码噪声很多;修复用户看不到的行会引入 bug)。
- 确认是误报时,只有一种正确修复方式:修正规则,并将此案例加入 fixture 锁定,
绝不能在文件中添加
audit-ignore(那会掩盖下一个问题)。 - **书面例外:**在该行或其上方最多 8 行处写上
EXCEPTION to <scanner>/<rule>: reason(或EXCEÇÃO ao);禁止使用静默白名单 (约定)。 - **CI 阈值递进:**只有总数下降时才重新记录基线,绝不能用来吸收增幅,并且始终针对整个应用 (gates.md)。
- 先看规则,再看发现:发现很多、实际问题却几乎没有,说明缺陷在 规则中。按文件夹归类,阅读规则意图,在规则内部写明原因并据此限定范围,然后修复剩余问题 (false-positives.md)。
第 3 步:判断(按层级加载,而不是始终全部加载)
技能记忆不等于技能;按层级加载,并报告未加载的内容。
| 层级 | 加载 | 不加载 |
|---|---|---|
| T1 叶节点 | 除本技能外什么都不加载 | 那四项。禁用项表和 slop-catalog 足以制作卡片 |
| T2 路由 | visant-frontend + visant-motion | revenue-centric-design,除非该路由用于销售 |
| T3 核心 | 全部四项 | 无 |
精简版 T3(上下文紧张):只加载各自的 SKILL.md;只有发现问题时才查阅参考资料。
顺序:visant-frontend(筛选测试:每个元素都要说明它影响哪个业务变量,否则就删掉;第 2 步的界面表格是其产出),然后是
visant-motion(缓动/时长的 SSoT 和观感陷阱)、visant-copy
(语气;检查关卡捕捉了语法问题)、revenue-centric-design(仅作为第 4 步的论据)。
判断前先阅读 slop-catalog.md(通过所有代码检查器的糟糕内容:症状、原因、修复)。**多个 Agent 同时工作:**文件归属互斥,按片段处理 i18n 后合并一次,编辑完成后再测量(multi-agent.md)。
第 4 步:唱反调
目标是找到能让一半像素工作变得多余的概念变更。 各层级的问题列表:devils-advocate.md。
- 选择该层级的问题,不要多选(在 T1 上额外提问,只会变成对卡片的哲学探讨)。 固定问题块 F1 到 F6适用于所有层级:复用、设计系统一致性、经测量的响应能力和性能、面向 ICP 的渐进式流程、应隐藏或图标化的内容,以及达到 Silicon Valley 水准还缺少什么。
- 先自己作答,并标注
file:line。把问题原样丢回去却不尝试回答,是披着严谨外衣的懒惰。只有会改变实际构建内容、且代码无法回答的问题,才交给用户,并先给出你的建议。 - 如果存在
revenue-centric-design的机制,就说出其名称(注意力层级、Swiss Knife Index、最优玩法、将默认值作为决策、让承诺与证据的规模相匹配)。指出杠杆本身就是价值。 - 一个能推翻整个屏幕的问题,胜过十二个无关紧要的修补。如果诚实的答案是“这个屏幕不该存在”,就直说。
Step 5: 验证(能编译不代表有人看到过)
首先,打开页面(这会填入 ## Screen seen)。登录后的应用:从目标仓库运行 node $V(溢出、文字截断、原始 i18n
键、控制台、/api 4xx/5xx、空页面、主题;付费路由已锁定)。
已发布的 URL:corta-url.mjs <base> route。手动打开:在控制台中输入 $T。
标志和付费路由锁定:verification.md。
测量前,先确认 environment.md 中的四项信号:路由已预热、通过 DOM 标记确认水合(而非 readyState)、真实数据
包括最差记录、节点数与手动打开的页面一致。
然后,且仅在此之后(未运行的检查要写入报告):
| 检查 | 方法 |
|---|---|
| 类型和 lint | npx tsc --noEmit 和仓库的 lint。开发服务器运行时绝不要执行 next build(这会破坏 .next) |
| 水平溢出 | $V(estouro 列):在 390px 宽度下,文档的 scrollWidth - clientWidth;每次修复后重新测量。不是检查某个元素:曾有一个位于 overflow-hidden 下的装饰性图案造成 64px 溢出,但实际上并不存在 |
| 文字截断和叠层覆盖 | $V(corta 列)或在控制台中输入 $T:被裁切父元素截断的单词、同一角落里相互覆盖的图层、脱离容器的元素 |
| 分发 | 页面是否在自身之外也存在?title、description、分享卡片、转化事件、sitemap、robots(distribution.md) |
| 真实数据 | 显示最佳记录和最差记录的页面;空状态会隐藏所有溢出问题 |
| 浅色主题 | $V --theme both。优先适配深色主题的应用在无人留意的浅色主题下会出问题 |
| 后端故障 | 关闭后端后运行。悄无声息地显示零是最常见的谎言:请求失败后显示的“0”和真实的零无法区分 |
| 键盘 | focus-visible 能触达悬停时显示的所有内容 |
| 观感 | DevTools、Animations、25% 速度 |
Step 6: 报告
仍使用同一份 AUDIT.md,现在将发现和评分放在最前面,绝不能只写聊天文本
(scorecard.md)。评分不是赞美:即使门槛项得分为 100,但存在一个 T3 且未审视定位,审计仍不完整,报告必须说明这一点。
不要
- 未运行脚本就宣称高分,或在表面检查表为空时宣称“全面通过”。分数来自流程,而非感觉。
- 未经明确许可就创建新的设计系统组件。应复用并参数化;如果缺少某个组件,先查看 Visant 库
(ui.visantlabs.com,包含 150+ 个已审核条目;索引位于
/llms.txt,组件说明位于/r/<name>.md),然后再查看官方 shadcn 原语。两者均通过npx shadcn@latest add @visant/<name>安装(在components.json中配置注册表"@visant": "https://ui.visantlabs.com/r/{name}.json");使用前先说明。 - 先修复叶节点,再修复根节点(Step 0,
--roots)。 - 未使用
verify-screens锁定时,不要打开会在加载时消耗额度的路由。 - 未在代码中确认所报告的缺陷前,不要在其上进行重构。
诊断应提供
file:line,而非主观意见。 - 未打开页面就宣称完成:这正是这项技能存在的原因。
- 将其用于赌博、赌场或博彩产品。应拒绝并说明:这是
revenue-centric-design的复用条件,而非个人偏好。
致谢与传承
这个技能是入口;判断力来自它加载的配套技能:
visant-frontend(切图测试、界面)、visant-motion(motion-lint)、
visant-refine(refine-scan)和 visant-copy(copy-lint)。外部来源:
| 内容 | 作者 | 如何引入此处 |
|---|---|---|
impeccable | Paul Bakaus(pbakaus/impeccable,Apache-2.0) | killer-scan 的第 1 道关卡(npx impeccable detect) |
revenue-centric-design | Richard 的原则(@richardrx),由 heliocosta-dev 打包 | 为第 4 步提供弹药;devils-advocate 中的“RCD n”引文 |
Emil Kowalski 技能(emil-design-eng、apple-design、improve-animations、review-animations) | Emil Kowalski,源自 animations.dev 和 Apple 的 Designing Fluid Interfaces(WWDC 2018) | 通过 visant-motion:动效原则的来源 |
vercel-react-view-transitions | Vercel(vercel-labs/agent-skills) | 通过 visant-motion:路由过渡 |
dataviz | Anthropic(Claude 技能) | 通过 visant-frontend:图表准确性 |
| shadcn/ui 和 Radix | shadcn;WorkOS | 使用官方基础组件,而不是自行臆造组件 |
| Playwright | Microsoft | corta-scan 和 verify-screens 会打开真实屏幕 |
本技能开始使用或提炼的新技能,会在同一个提交中加入此表。