关于 designkit
designkit 是一项从代码库现有 UI 值提取并维护 `DESIGN.md` 的技能,适用于记录设计系统的团队。它要求令牌均有代码依据,并提供只读审计模式。
主要功能
- 01从 UI 代码提取令牌
- 02创建和更新 `DESIGN.md`
- 03只读审计设计偏移
- 04同步令牌到现有存放位置
- 05调用官方 CLI 校验和导出
适用场景
- 01记录已上线 UI 中的颜色和字体
- 02UI 更新后维护设计文档
- 03检查 `DESIGN.md` 是否符合代码现状
- 04将文档令牌导出到项目现有存放位置
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ mimukit/ skills --skill designkit安装后在 Claude Code 中输入/designkit确认已加载。
详细介绍
designkit
存在于某人脑海中或 Figma 里的设计系统,对编写 UI 的 Agent 来说是不可见的。生态最终采用了 DESIGN.md 作为替代方案:这是 Google Labs 推出的开放格式(Apache-2.0,google-labs-code/design.md),将机器可读的设计令牌放在 YAML front matter 中,并配以易读的文字说明。它有意成为设计领域对应的 Agent 指令文件;编码 Agent 已经会读取 CLAUDE.md 及其同类文件。它是仓库根目录中持久的约定,跨会话保留,任何支持 DESIGN.md 的 Agent 都会读取它。
designkit 补上了生态中其他工具都空缺的那一环。其他工具都会从别处给你一套设计系统,无论是从 Stripe 逆向工程得来的文件,还是从产品类型查找表中检索出的调色板。designkit 从你已经发布的 UI 中推导出专属于你的设计系统,并在之后告诉你它何时已经过时。
这使得基于实际依据的规则成为这项技能的核心:每个令牌的值都必须出现在你的代码库中。 唯一的例外是仓库完全没有 UI 的情况,因为无从推导;此时,每个令牌的值都由你提供(参见 init 的访谈),designkit 仍不会凭空创造任何值。将四十种几乎相同的灰色聚类成一个色阶,是推导。为了更好看而挑选一个相邻的十六进制色值,则是创造,而这正是 designkit 绝不会做的事。
designkit 不是什么
- 不是 UI 生成器。 它记录设计系统;不编写组件、页面或应用 CSS。既定义审美又负责应用它的技能,无法遵守基于实际依据的规则。
- 不是审美库。 它不附带调色板、字体搭配或风格目录。如果你的项目没有设计系统,designkit 会根据代码当前使用的值提出一套;如果完全没有 UI,则根据你提供的值提出一套;两者都没有时,它会如实说明。它绝不会引入别人的设计系统。
- 不是规范实现。 检查、对比度检测、令牌导出和模式本身都属于官方 CLI。designkit 会调用它并报告结果;它不是一个更差的重复实现。
- 不是设计评审。 设计系统是否出色,由人来判断。designkit 只报告现状,包括现状一团糟时。
- 不是术语表或决策日志。 领域词汇和架构决策应放在其他地方;设计令牌不属于其中任何一类。
何时触发
init。 “编写 DESIGN.md”、“记录我们的设计系统”、“我们没有设计令牌”、“这个项目实际用了哪些颜色”。根据代码库推导文件。update。 “设计系统变了”、“更新 DESIGN.md”,或 UI 工作合入后立即进行的设计调整。根据代码当前所示内容进行更新。audit。 “我们的 DESIGN.md 还准确吗”、“根据代码检查设计系统”、“哪些地方已经偏离”。只读检查。绝不写入任何内容。sync。 “将 DESIGN.md 同步到我们的 Tailwind 主题”、“导出我们的令牌”,或在文件与令牌存放位置不一致时,init后续提示的名称。根据DESIGN.md写入项目现有的令牌存放位置。
如果无法确定模式,请先询问。 audit 不会改动任何内容,而 init 会重写项目的设计约定;绝不要在两者之间擅自猜测。
各模式允许写入的内容:
| 模式 | 写入内容 | 门槛 |
|---|---|---|
init | DESIGN.md;色板表及其 .gitignore 行 | 方案 |
update | DESIGN.md 中的令牌和文字编辑;当受门槛限制的变更需要时,写入色板表及其 .gitignore 行 | 新章节、删除内容,以及目标范围之外的偏离 |
audit | 无 | 无 |
sync | 现有的令牌存放位置(Tailwind 主题、:root 块)或 DTCG 导出文件 | 每次写入 |
产物
DESIGN.md 位于仓库根目录。这是规范的约定,也是支持 DESIGN.md 的工具发现它的方式;不要放在 docs/ 中,不管那看起来多整洁。
Token 模式
前置内容以一行恰好为 --- 的内容开头,并以同样的方式结束。这是截至 2026-08-06 记录的 alpha 模式;如果 CLI 可用,优先实时读取,因为此格式明确仍在演变。
version: <string> # optional, current: "alpha"
name: <string>
description: <string> # optional
omitted: <string[] | OmittedSection[]> # optional; sections deliberately excluded
colors:
<token-name>: <Color> # "#1A1C1E", "oklch(62% 0.18 250)", CSS named
typography:
<token-name>: <Typography> # fontFamily, fontSize, fontWeight, lineHeight,
# letterSpacing, fontFeature, fontVariation
rounded:
<scale-level>: <Dimension> # 4px, 0.5rem, 9999px
spacing:
<scale-level>: <Dimension | number>
components:
<component-name>:
<token-name>: <string | token reference> # "{colors.primary}"
值之间通过 {path.to.token} 语法交叉引用。优先使用引用,而不是重复字面值,因为未引用的 token 会触发 orphaned-tokens,而重复的字面值会导致系统逐渐偏离。
推荐的 token 名称(非规范性,但除非项目已有自己的术语,否则请遵循):颜色 primary、secondary、tertiary、neutral、surface、on-surface、error;排版 headline-display、headline-lg、headline-md、body-lg、body-md、body-sm、label-lg、label-md、label-sm;圆角 none、sm、md、lg、xl、full。
各个章节
按以下顺序排列的八个规范 ## 标题。章节顺序错误会触发 section-order;重复标题是硬性错误,会导致文件被拒绝。
| # | 章节 | 别名 | 内容 |
|---|---|---|---|
| 1 | 概览 | 品牌与风格 | 以文字描述视觉意图 |
| 2 | 颜色 | 无 | 调色板依据;colors token |
| 3 | 排版 | 无 | 字体层级;typography token |
| 4 | 布局 | 布局与间距 | 网格、留白;spacing token |
| 5 | 层次与深度 | 层次 | 阴影和表面层级 |
| 6 | 形状 | 无 | 圆角风格;rounded token |
| 7 | 组件 | 无 | 组件指南;components token |
| 8 | 应做与不应做 | 无 | 约束、反模式以及 UI 文案语气 |
由于规范会保留未知标题而不报错,因此还允许在“应做与不应做”之后添加两个章节:## Motion 和 ## Dark Mode。这两个章节只能包含文字描述,原因如下,并非出于风格偏好。
语气应归入“应做与不应做”,而不是单独设立章节。针对屏幕上文案的规则(“错误提示应说明如何修复,而不是描述失败”)属于约束,而规范已经为约束设有章节。
YAML 中绝不能包含的内容
这是通过运行 linter 验证的,并非根据文档推断。以下两种形式看起来合理,但都会让本来干净的文件产生警告:
| 看似可行的写法 | linter 的处理方式 | 应改为 |
|---|---|---|
顶层 motion: token 映射 | ⚠️ token-like-ignored,“看起来像设计 token 映射,但不是可识别的模式键……导出命令会静默忽略” | 在 ## Motion 中用文字描述 |
组件中的 transitionDuration: | ⚠️ broken-ref,“不是可识别的组件子 token” | 在 ## Motion 中用文字描述 |
**有效的组件子 token 完整列表为 backgroundColor、textColor、typography、rounded、padding、size、height、width。**没有时长、缓动、边框或间距。其他任何内容都会触发警告。
因此,**模式中的任何位置都没有适用于动效的 token。**在规范增加相应位置之前,时长和缓动曲线应以文字描述,这才是如实的表达方式。
交互状态可以使用 token,这是规范定义的关联键模式:button-primary、button-primary-hover、button-primary-active。将这些状态提取为真正的组件条目。若该模式已经能够表达某种状态,绝不要另行编造自定义键来承载它。
标记行
designkit 写入的每个文件,都会在最后一个章节之后以一行可见内容结尾:
_Extracted from `main`@`a1b2c3d` on 2026-08-06._
这两部分各有用途:当 SHA 仍可访问时,audit 会通过 git show <sha>:DESIGN.md 恢复基线;而当 squash 合并导致该 SHA 失去引用后,它会回退到日期。HTML 注释在所有渲染器中都不可见,而这正是过时文件看起来仍是最新文件的原因。
没有标记行的文件是由人编写的。接受它、与之协作,绝不要暗中声称是自己写的,并明确说明你正在编辑一个并非由 designkit 编写的文件。
CLI 是事实来源
该格式目前处于 alpha 版本,并在公开积极开发中。将架构硬编码到技能中,会让技能自信地给出错误信息,因此请在运行时读取规范,并将上方摘要视为有时效性的备用信息:
| 命令 | 用途 |
|---|---|
npx @google/design.md spec [--rules] [--format json] | 当前架构和规则集 |
npx @google/design.md lint <file> [--format json] | 验证;默认输出 JSON |
npx @google/design.md diff <before> <after> | 比较两个版本 |
npx @google/design.md export --format {json-tailwind|css-tailwind|dtcg} <file> | 输出令牌 |
退出代码:0 表示成功,1 表示错误或回归,2 表示文件读取失败。在 Windows PowerShell 中,请使用 designmd 别名,因为 .md 文件关联会劫持另一种调用形式。
每个文件都会运行这 11 条 lint 规则:broken-ref(错误)、contrast-ratio、orphaned-tokens、missing-primary、missing-typography、section-order、unknown-key、token-like-ignored(警告),以及 token-summary、missing-sections、omitted-rules(信息)。contrast-ratio 已按 4.5:1 强制执行 WCAG AA,因此绝不要自行编写对比度计算代码。
提取引擎
init、update 和 audit 共用一个引擎。init 写入输出,update 对比并应用,audit 对比并报告。audit 会跳过 展示过程,这是引擎唯一的写入操作。无需维护已监视路径清单,因此也不会因为 glob 未覆盖到某处而漏掉更改。
找出令牌所在位置
按顺序检查,找到第一个匹配项后,请在写入任何内容之前说明匹配的是哪一项:
| # | 层级 | 特征 |
|---|---|---|
| 1 | Tailwind | CSS 中的 @theme(v4),或 tailwind.config.* 中的 theme.extend(v3) |
| 2 | CSS 自定义属性 | 包含 --token: value 的 :root 块 |
| 3 | 预处理器变量 | SCSS $vars、Less @vars、映射文件 |
| 4 | CSS-in-JS 主题 | 传递给 provider 的主题对象 |
| 5 | WordPress | theme.json 中的 settings.color.palette、settings.typography |
| 6 | 无 | 任何位置都没有声明令牌;请参阅没有设计系统时 |
根据用法推导,而非根据声明
没人使用的已声明令牌并不是设计系统;四十个硬编码的十六进制颜色值才是。请同时检查两者:
- 样式表、模板和组件中的每个颜色字面值,包括十六进制、
rgb()、hsl()、oklch()和命名颜色 - 实际使用的字号、字重和行高
- 反复出现的内边距、外边距和间距值
- 实际使用的圆角和阴影
- 实际设置样式的交互状态:
:hover、:focus-visible、:active、disabled及其框架对应项 - 深色模式:搜索
.dark、prefers-color-scheme、dark:变体、[data-theme]
统计出现次数。使用了 90 次的值和只使用 1 次的值,不应被同等视为系统的一部分;这些计数也能为下一步提供依据。
对每个令牌进行分类
每个令牌都属于以下三种状态之一,并会在确认环节显示其分类:
| 状态 | 含义 |
|---|---|
extracted | 该值原样出现在代码中,且使用频率足够高,具有系统性 |
consolidated | 从 N 个近似重复值中聚合而来;请列出这些值,以便审查和撤销合并 |
omitted | 无法从代码推导;填入规范原生的 omitted 字段,绝不凭空编造 |
supplied | 在没有可供提取的 UI 的代码仓库中,由用户在 init 访谈中提供 |
omitted 是一种功能,而非失败。 该字段正是用于声明有意排除的内容,并抑制缺少章节的警告。诚实地省略 elevation 的 DESIGN.md,胜过凭空编造一套阴影刻度。
没有现成设计系统时
最可能遇到的真实情况:数百个硬编码值,没有令牌归属,也毫无一致性。designkit 会聚类并提出建议。它不会拒绝,也不会在界面上已经体现出设计风格、只是显得杂乱时,转而进行访谈。
建议必须遵守依据规则:**每个建议的令牌值都必须实际出现在代码中。**将近似值聚类,选出每个聚类中使用次数最多的值作为代表,并列出它吸收的其他值。绝不输出代码库中从未出现过的值。
根据项目调整聚类阈值,并说明所用的阈值,因为这属于主观判断;不说明的判断无法审查。颜色使用感知距离,间距和字体使用最近步进值。如果某个聚类的范围太宽,无法归为同一套系统,就将其拆分,而不是强行合并,并说明原因。
展示过程
此步骤会在 init 中运行;在 update 中,仅当需要审查受门控变更时运行。audit 会跳过此步骤,因为它会写入文件。
写入任何内容之前,先生成一份临时色板页:一个纯 HTML 页面,展示色块、字体样例、间距条和圆角,每项都标注令牌名称、状态以及吸收的值。要通过 YAML 差异审查“40 种灰色合并成 6 种”并不现实;看色板只需几秒。
这是**审查辅助材料,不是交付物。**将其写入 Git 忽略的临时路径,如果该路径尚未被忽略,就将其添加到 .gitignore,在征求同意时提及该路径,并且不要保留它。这绝不是此技能拒绝编写的生成 UI,而是一份用于验证决策的证明材料。
模式:init
1. 找到依据
运行提取引擎。在提出任何建议之前,说明匹配到的层级、各类别找到的不同值数量,以及深色模式的判断结果。每个类别(颜色、字体、间距、圆角、阴影、状态、深色模式)都有计数或标记为“未找到”后,此步骤即完成。
2. 只有无内容可读时才进行访谈
仓库中没有 UI,就没有内容可供提取。询问基本信息(品牌意图、现有调色板、字体偏好)。用户提供的每个值都会成为 supplied 令牌;designkit 不会自行添加任何值。在报告和文件的 Overview 中明确说明,结果是建议值,而非提取结果。仍未知的内容标记为 omitted。如果引擎找到了 UI,就跳过此步骤。每个架构类别都包含 supplied 令牌或标记为 omitted 后,此步骤即完成。
3. 提出建议,并设置审核关卡
展示色板页,以及 extracted / consolidated / omitted 分类、聚类阈值和发现的所有不一致。这是最关键的审核关卡,因为文件生成之前,用户可以接受、删减或调整方向。用户接受建议(无论是否删减)后,此步骤即完成。
4. 写入、添加标记并验证
在仓库根目录写入 DESIGN.md,追加标记,然后运行 lint 并逐字报告其发现,包括仍未解决的问题。选择接受的警告应报告为已接受,绝不能屏蔽。lint 以 0 退出,或报告所有剩余问题,或说明 lint 缺口后,此步骤即完成。
5. 交接
在此技能中编写所有交接内容时,请使用操作性语体:每个句子只包含一条指令,使用主动语态和现在时,不使用比喻。
变更内容。 报告创建的文件、匹配的层级、每种状态下的 token 数量,以及省略的内容。
文件位置。 指明仓库根目录下的 DESIGN.md、色板的临时路径(并说明它可丢弃),以及 lint 结果。
下一步。 阅读该文件。它描述了项目的视觉身份,是这里唯一真正需要人工检查的内容。安装了 commitkit 时,使用它提交;否则执行 git add DESIGN.md 并提交。如果项目有 token 存放位置,且文件中的值与其不同,请将 sync 作为后续步骤;如果没有,就无需同步,也不要凭空编造下一步。
模式:update
1. 确定目标
先检查未提交的工作树变更(git status --porcelain 非空时,执行 git diff HEAD,并检查未跟踪文件,因为 git diff 不会显示这些文件)。否则,比较当前分支与基准引用的差异:安装了 gitkit 时使用它,否则通过 gh repo view --json defaultBranchRef 获取仓库的默认分支。绝不要假定默认分支是 main。 用一行说明你选择的目标。该目标限定了 update 的应用范围,见克制地应用。当目标行写明范围并列出已更改的 UI 文件(包括未跟踪文件)时,此步骤即完成。
2. 重新提取并比较差异
针对当前代码运行引擎,并将结果与已提交的 DESIGN.md 进行比较。只要带有印记的 SHA 仍然可访问,还要运行 npx @google/design.md diff <baseline> <current>,执行结构化 token 级比较。重新提取整个代码库,而不只是目标范围,以确保使用次数准确。然后对每项偏差进行分类:当其值出现在目标范围内已更改的代码块或未跟踪文件中时,标记为在目标范围内;否则标记为在目标范围外。当所有偏差都完成分类时,此步骤即完成。
3. 克制地应用
更改品牌颜色时,只编辑颜色 token,不要重新生成文件。编辑前,说明哪些部分会受影响,哪些部分会刻意保持不变;保持不变的部分是关键所在,它能表明该技能清楚自己没有改动什么。
当偏差在目标范围内时,直接应用对现有 token 和正文的修改;这些修改受上述克制原则约束,并形成便于审查的差异。新增部分、删除内容和目标范围外的偏差都必须征得同意。 目标范围外的偏差早于此次更改,因此请列出这些偏差,并仅在获得同意后应用;否则将其交由 audit 处理。只因一个按钮发生变化就重写整个设计系统的技能,还不如没有技能。每项目标范围内的偏差都已应用,且每项需征得同意的内容都有处理结论时,此步骤即完成。
4. 重新盖章并验证
使用当前引用和 SHA 重新盖章,运行 lint 并报告结果。当印记标明当前 SHA 且已报告 lint 结果时,此步骤即完成。
5. 交接
变更内容。 报告已编辑的 token(每行一项,并说明值的变化)、提议的部分及其处理结论、目标范围外的偏差及其处理结论,以及刻意保持不变的部分。
文件位置。 指明 DESIGN.md,并报告 lint 结果。
下一步。 运行 commitkit;如果这是分支工作,则再运行 prkit(否则执行 git commit 和 gh pr create)。设计系统应与导致其变化的 UI 更改一同提交;这正是将它保存在仓库中的意义。
模式:audit
只读。绝不写入任何内容。 此模式只报告并转交;修复需要单独调用,特意如此设计。
三项检查:
- Lint。 运行
npx @google/design.md lint,按原样报告发现项。 - Drift。 只有 designkit 能执行此检查,因为 linter 只会将文件与自身进行验证,无法查看代码库。分两个方向:文件中不再出现在代码里的令牌,以及代码中没有令牌覆盖的值。
- Baseline。 如果 SHA 可达,则针对
git show <stamped-sha>:DESIGN.md运行npx @google/design.md diff。将基线副本写入系统临时目录(mktemp),绝不写入仓库。
运行提取引擎时不带色板。三项检查都有结果或明确指出的缺口后,审计即告完成。
报告
| 结论 | 含义 |
|---|---|
current | 文件中的令牌与代码使用的内容一致 |
stale | 代码中的某个令牌值已变更 |
orphaned | 文件中的某个令牌在代码中无处出现 |
uncovered | 代码中使用的某个值没有令牌覆盖 |
unverified | designkit 从未检查过人工编写的文件 |
开头先用一行说明覆盖范围,指出扫描了多少个文件、跳过了多少个文件,因为审计若只覆盖了部分 UI 却不作说明,读起来就像一切正常。然后给出一个优先处理的下一步。
交接
变更内容。 没有变更。明确说明;读者绝不应需要猜测只读模式是否写入了内容。
结果位置。 直接写在此回复中。默认不生成审计产物;只有用户提出要求时才提供保存选项。
下一步。 选出影响最严重的漂移,并将其转交给 update;如果文件缺失而非内容有误,则转交给 init。“没有发生漂移”是有效且明确的结果,因此应说明系统状态正常,然后结束。
模式:sync
仅在用户同意后,且仅当令牌已有归属位置时执行。 designkit 不会为尚无令牌系统的项目引入令牌系统,因为这是构建工具的决策,而非文档决策。如果没有令牌归属位置,请说明并停止;没有可同步的内容。
1. 找到归属位置和差异
运行引擎的查找令牌归属位置,并说明所在层级。将每个 DESIGN.md 令牌与归属位置中的值进行比较。每个令牌都标记为相同、不同或归属位置中不存在后,此步骤即告完成。
2. 征得同意后导出并写入
展示写入操作将产生的令牌变更,并询问一次。用户同意后,按下表写入:
| 令牌归属位置 | 方式 |
|---|---|
| Tailwind | 使用官方的 export --format json-tailwind 或 css-tailwind |
纯 :root 自定义属性 | 直接写入,因为 css-tailwind 会输出 v4 @theme 块形式的自定义属性,所以这是转录,而非转换 |
SCSS 映射、CSS-in-JS、WordPress theme.json | 使用 export --format dtcg,然后转交给 Style Dictionary 等转换工具 |
分界点在于转换,而非框架:如果官方导出器已生成所需格式,designkit 就负责写入;如果需要真正的转换,designkit 则输出 DTCG 并指出所用工具。手工编写的转换器会在任一格式发生变化时逐渐偏离。
每个不同或缺失的令牌都已写入,或已导出为 DTCG 并注明转换工具,或用户已拒绝后,此步骤即告完成。
3. 交接
变更内容。 报告写入的令牌归属位置,并为每个变更的令牌各用一行说明;或者说明用户已拒绝。
结果位置。 给出令牌归属位置的路径,或 DTCG 导出路径以及要运行的转换工具。
下一步。 如果已安装 commitkit,则将令牌归属位置和 DESIGN.md 一起提交;否则运行 git commit。
明确说明降级情况
没有 npx、网络或 CLI 是正常情况,不是错误。从上面的回退架构提取并写入内容,跳过 lint 和导出,并且在报告结果时同时说明缺失项:
已写入
DESIGN.md(12 种颜色、6 种字体样式)。未运行lint,因为没有可用的npx。架构来自随附的alpha回退方案,采集于 2026-08-06。
绝不声称做过实际上没有进行的验证。什么都没检查,却报告文件干净,比报告文件未经检查更糟。
完全没有文件系统(例如基于浏览器的 Agent)?将完成的 DESIGN.md 作为标注其路径的围栏代码块打印出来,描述色板页而不是写入它,并说明用户应自行运行哪些命令。
说明
- 依据规则优先于完整性。 内容稀疏但诚实的文件,胜过内容充实却凭空捏造的文件。如果只能在省略一个比例尺和猜测它之间二选一,就省略并说明原因。
- 按操作征求同意。 When this fires 中的按模式表格是依据。在
update中,对目标范围内现有令牌的编辑无需询问,因为它们受克制规则限制,并会形成可供审查的差异。audit无需征求同意,因为它不会进行任何更改。 - 报告警告,绝不压下警告。 如果 lint 警告仍然存在,就在报告中写明,并说明接受该警告的原因。
- 遵循现有项目惯例。 如果仓库有自己的令牌名称、文件位置或设计文档布局,就应遵循,并由 designkit 说明遵循了哪种惯例。
- 规范仍处于 alpha 阶段。 章节、架构键和规则都可能变动。运行时应通过 CLI 读取;如果实际使用的是随附的回退方案,就要说明。
- 文案用于说明理由,令牌用于保存值。 Agent 需要的是十六进制值,而不是其背后的故事。文案只保留令牌无法表达的内容:意图,以及何时不应使用某项内容。若要全面检查这类文案,请在已安装时使用 humankit。