analyze-fig
离线分析 Figma 导出文件(.fig),无需访问 Figma API:节点树、文本和位图直接从文件中读取,而作者评论(.fig 中不包含)则通过 MCP 单独获取。结果生成 spcfctn/ui/ 目录下的 Markdown 文件,后续可直接使用,避免重复读取 Figma。
何时不使用
如果用户询问的是已经分析过的布局(“过滤器评论中说了什么……”、“屏幕有哪些列……”),应直接读取 spcfctn/ui/*.md,而不是执行此技能。仅当有新的或更新的 .fig 文件,或者 Markdown 中没有答案时(参见 spcfctn-code.md),才需要分析。
目录结构(草稿目录 draft 唯一,不在 Git 中)
spcfctn/ui/draft/— 输入的.fig文件(以及其他草稿)。由用户放置。spcfctn/ui/draft/<名称>/— 解包结果:message.json(所有节点)、meta.json、images/、screens.json和screens.txt,以及收集的评论(comments.json)。从.fig重新生成,不纳入 Git。没有单独的raw/或data/(参见modeling.md)。spcfctn/ui/*.md— 分析结果;仅此内容留在 Git 中。
<名称> 是文件名去掉扩展名,全部小写并用连字符连接(例如 internal-interfaces)。
步骤 0 — 准备
- 找到项目的
spcfctn/目录。如果不存在,请让用户创建(参见spcfctn-code.md)。自行创建ui/及其子目录draft/。 - 检查
spcfctn/ui/.gitignore(这是工作副本,不是仓库):必须包含draft(参见modeling.md);缺少的条目通过gitignore.org添加。 - Fig 文件:用户指定文件名;如果未指定,则列出
spcfctn/ui/draft/*.fig并询问。 - 阅读项目的
CLAUDE.md(语言风格、约定)以及现有的spcfctn/ui/*.md:分析应延续现有的结构和术语,而不是从零开始。 - 需要
python3和zstd在PATH中。
步骤 1 — 解包和解码
python3 ~/.claude/skills/analyze-fig/scripts/fig.py spcfctn/ui/draft/X.fig spcfctn/ui/draft/<名称>
输出文件格式版本、节点数、blob 数和图片数。脚本已在版本 106 上测试;如果遇到其他版本或错误,不要猜测格式或使用其他解码器,直接告知用户。meta.json 包含 exported_at:导出时间将在步骤 5 中使用。message.json 很大,不要直接打印。
步骤 2 — 分解为章节和屏幕
python3 ~/.claude/skills/analyze-fig/scripts/screens.py spcfctn/ui/draft/<名称>
输出页面列表、章节(顶级框架)和屏幕(其子元素),附带文本和位图数量。核心内容在 screens.txt 中:对于每个屏幕,文本层按从上到下、从左到右的顺序分组为行(这样就能正确读取过滤器、列标题和按钮),外加位图引用。
- 将数量与预期值(例如来自旧的 Markdown)进行比较;如果存在差异,则停止并询问。
- 文本层无法看到没有文本的元素(纯图标)和位图的内容。对于
images/中的每个位图,打开文件(Read)并描述文本层中缺失的内容;标记为从图片读取。节点树和文本是主要证据,图片是补充。 - 组件实例(
INSTANCE)可能包含脚本未检测到的覆盖文本;screens.txt中会有警告。
步骤 3 — 写入 spcfctn/ui/*.md
- 每个章节一个 Markdown 文件(如果只有一个章节,则合并为一个文件)。如果文件已存在,则完整读取并更新,而不是重写:Markdown 文件仅由 agent 维护,但之前澄清的内容不能丢失。
- 语言风格遵循项目的
CLAUDE.md。 - 结构(示例见
job/vale/kylada项目中的spcfctn/ui/internal-dashboard.md):包含来源和验证的引言(读取的内容、导出日期、屏幕和文本数量)、布局读取规则、UI 标签与内部术语的对应关系、屏幕按顺序排列(按布局顺序的过滤器、列表按钮、列、行操作)、待解决问题。 - 所有属于你解读而非布局文本或评论的内容,均应标记为 inferred。
- 项目特定的布局读取规则(例如,列标题下的
Select用于排序控制)应从CLAUDE.md中获取并应用,不要自行编造。
步骤 4 — 通过 MCP 按链接获取评论
.fig 文件中不包含评论(已验证):它们保留在 Figma 服务器上。
- 需要指向 Figma 文件的链接(可以带
node-id,也可以不带)。如果缺少,请向用户索要。 - 仅使用项目中已连接 Figma MCP 服务器的
comments(评论)工具(服务器名称从已连接服务器列表中获取);参数file即为该链接。如果没有此工具,请告知用户。官方figma-cs不返回评论,不要直接调用 REST API 或修改.env。 - 不带
node_id的调用会返回文件所有分支的评论(编号、日期、状态、节点@id、文本、回复)。不需要时不执行refresh。评论的端点与文件读取分开计数,即使读取返回429也能正常工作。 - 绑定到屏幕:
@id与screens.json中屏幕的 ID 匹配 → 屏幕已确定;@id是章节或页面的 ID → 通过几何位置确定屏幕,需要评论的node_id和node_offset。构造字符串KEY NODE X Y(例如#144 979:3 500 5471)并输入:python3 ~/.claude/skills/analyze-fig/scripts/place.py spcfctn/ui/draft/<名称> < 字符串。输出:键、章节、屏幕;如果点不在屏幕上,则给出原因和最近的屏幕。- 检查输出:
comments工具可能 不输出node_offset(技能创建时即有此情况)。此时无法将章节或页面的评论分配到具体屏幕:不要根据文本猜测屏幕,而应将其归入章节,标记为 屏幕未确定,并告知用户需要评论的偏移量才能分配。
- 回复(
↳)属于父线程。
步骤 5 — 验证评论与文件是否一致
对于每个已确定屏幕的评论(以及章节评论组),检查:
- 评论中提到的字段、列、按钮、值是否存在于该屏幕的文本层中(例如
Amount of integrated services↔ 列Services;引号内引文;值列表)。 - 评论是否与布局矛盾(列数、顺序、元素类型、“有过滤器”/“没有”)。
- 日期:如果评论比
meta.json中的exported_at更新,则导出已过时。请用户将新导出放入spcfctn/ui/draft/。 - 评论的节点在文件中不存在(已删除或重命名)→ 孤立的评论。
- 评论没有屏幕且内容不可识别。
将所有差异汇总到一个简短的表格中(编号 #N、屏幕、差异具体内容),并询问用户哪个是正确的:不要默默修改,也不要在布局和评论之间自行选择。在用户回复前,在 Markdown 中将它们标记为 conflict。
步骤 6 — 写入总结
- 在 Markdown 中增加作者评论部分:摘要(它们澄清了什么)以及按屏幕排列的所有评论(带编号
#N)。如果评论澄清了之前标记为 inferred 的内容,则更正记录并引用该评论。 - 更新引言中的“验证”:说明已读取的内容(
.fig、版本、导出日期、文本、位图、评论、获取评论的日期)以及未覆盖的内容。 - 待解决问题单独列出;用户回复移至“已解决”。
- 未经要求,不要提交任何内容。口头(使用项目语言)总结:章节数、屏幕数、评论数、差异数以及需要澄清的具体问题。
禁止行为
- 不要带 Token 调用 Figma REST API,不要读取或编辑
.env。 - 不要读取第三方代码(kiwi 解码器等):格式已由
scripts/中的脚本实现。 - 不要将
.fig和解包结果(draft/下所有内容)放入 Git。 - 不要根据文字猜测评论的屏幕,也不要在存在文本层的情况下根据图片猜测布局内容。