Communitygithub.com

figma-bridge

通过本地 Figma Bridge 驱动 Figma 文件——读取选区、构建框架/文本/形状、绑定变量、放置图片、导出 PNG/SVG。当任务需要操作 Figma 画布(检查设计、在 Figma 中实现 UI、将颜色替换为令牌、导出资源、插入生成的艺术作品)时使用。需要本地桥接服务器运行在 localhost:3847 以及 Figma Bridge 插件在目标文件中运行;如果不可用,请勿即兴发挥——请用户启动它们。

figma-bridge 是什么?

Figma Bridge 是一个 AI 代理技能,通过本地 HTTP 桥接服务器和 Figma 插件 API 实现对 Figma 文件的无令牌、无 OAuth 读写操作。它解决了 Figma 没有公开写入 API 的问题,允许 AI 代理(如 Claude Code、Cursor、Codex)以编程方式创建、修改和导出 Figma 设计元素。此技能支持多种平台,并包含一套完整的二进制工具(`figma doctor`、`figma clients`、`figma rules`)来验证先决条件、检查已连接的窗口和项目约束。其核心工作流程包括:定位文件、读取当前状态、规划操作、通过 `figma run` 批量执行写入命令,以及通过 `figma export` 验证结果。注意事项包括:必须使用 localhost 而非 127.0.0.1;节点 ID 不可猜测;以及支持图像生成和编辑的配套 `img-forge` CLI。

兼容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/iggypcnfsky/figma-bridge/tree/HEAD/.agents/skills/figma-bridge

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

Figma Bridge

Figma 没有公开的写入 API。此技能使用一个本地桥接:通过 HTTP 命名操作,由插件在 Figma 内部通过 Figma 插件 API 执行。无需 OAuth,无需令牌。

仓库: https://github.com/iggypcnfsky/figma-bridge — AGENTS.md、docs/ops-reference.md。

前提条件——执行任何操作前请检查

figma 在 PATH 中,因此永远不要搜索文件系统来查找仓库:

figma doctor        # 一次检查仓库、服务器、已连接窗口、img-forge + FAL 密钥
figma clients       # 每个已连接 Figma 窗口的 id、文件、页面
figma rules         # 项目约束:类型层级、网格、框架大小、版本命名

在设计之前阅读 figma rules。 它包含了非显而易见的限制——例如“Poppins 20/25 是基础”——这些信息仅通过阅读画布是无法获得的。将 "confirmed": false 视为需要与用户验证的假设,将 {} 视为“询问,不要自行发明”。

如果命令缺失,请在询问后使用 node "$(figma where)/server.mjs";不要 find 仓库,也不要猜测路径。

  • pluginConnected: false → 停止。请用户在他们想要操作的文件窗口中运行 Plugins → Development → Figma Bridge。重试无济于事。
  • /run 返回 503 表示同样的问题。504 PLUGIN_GONE 表示他们关闭了插件窗口。
  • 409 表示多个 Figma 窗口已连接且未选择任何一个。选择用户命名的文件(--file <NAME>)或客户端 ID(--client <ID>);永远不要盲目重试,否则可能会编辑错误的文件。

工作循环

  1. 定位. ./bin/figma status → 文件名、当前页面、选区、所有页面。
  2. 读取. selection 2、node <id> 2、find {"name":"Header","allPages":true}。 永远不要猜测 nodeId——Figma ID 看起来像 4022:2,并且无法推导。
  3. 规划. 决定父元素、大小、顺序。除非指定了 parentId,否则新节点将放到当前页面。
  4. 写入. ./bin/figma run '[{...},{...}]'。
  5. 验证. ./bin/figma export <id> out/check.png PNG 2 并实际查看图像。

命令

./bin/figma op '{"op":"status"}'
./bin/figma run '[{"op":"createFrame","name":"Card","width":320,"height":200,"fill":"#0B0B0F",
                   "props":{"cornerRadius":16,"layoutMode":"VERTICAL","paddingTop":24,"paddingLeft":24,"itemSpacing":12}}]'
./bin/figma run '[{"op":"createText","parentId":"12:34","characters":"Title","fontSize":24,"color":"#FFFFFF"}]'
./bin/figma op '{"op":"varFill","nodeId":"12:34","variableName":"color/bg/surface"}'
./bin/figma export 12:34 out/card.png PNG 2
./bin/figma image 12:34 out/cover.png FILL      # 本地图像文件 → 填充(无需云上传)

操作:ping status pages variables styles fonts inventory · selection node find · createFrame createRect createEllipse createText createPage createInstance · update clone reparent remove goto group ungroup select · grids setGrids align distribute effects · applyStyle varFill · export imageFill · exec。 完整参数:docs/ops-reference.md。

值得了解的设计工作快捷方式:

  • grid 意味着 GRID:当用户说“设置网格”时,他们想要方形布局网格,而不是列: {"op":"setGrids","nodeId":"…","grid":true}(默认 40 像素单元格,40% 的透明度)或 "grid":40。 仅当用户提到列、12 列网格或给出间隔/边距值时,才使用 columns/rows。 永远不要用矩形伪造网格;使用 applyStyle 配合 kind:"grid" 可应用已保存的网格样式。
  • 行中的项目:先构建它们,然后使用 {"op":"align","nodeIds":[…],"mode":"TOP"} 和 {"op":"distribute","nodeIds":[…],"axis":"HORIZONTAL","gap":24}。
  • 深度:{"op":"effects","nodeId":"…","shadow":{"y":8,"blur":24,"color":"#00000033"}} 或 {"op":"effects","nodeId":"…","blur":{"type":"BACKGROUND","radius":20}}。
  • 渐变:{"op":"gradient","nodeId":"…","kind":"linear","angle":135,"stops":[[0,"#8B76FF"],[1,"#0E0E12"]]} — 角度 0 表示从左到右,90 表示从上到下。永远不要用堆叠的矩形伪造渐变。
  • 设计系统:使用 COMPONENT ID 调用 createInstance,然后使用 instanceProps 设置变体(先读取名称)和 instanceText 更改文本而不解除实例链接;使用 applyStyle 应用样式。不要重绘库中已有的内容,也不要为了“修复”其文本而解除实例链接。
  • 间距检查:{"op":"measure","a":"1:2","b":"1:3"} 返回每侧间隙和中心距离;用它代替导出屏幕截图来判断对齐情况。
  • 样式:saveStyle 按名称创建或更新 text / paint / effect / grid 样式,applyStyle 应用它。创建一次令牌,随处应用。
  • 响应式:sizing 按轴设置 HUG/FILL/FIXED 以及最小/最大值;constraints 覆盖非自动布局的子元素(STRETCH/MIN/MAX/CENTER/SCALE)。在更改它们之前,先从 node 读取两者——当某个属性不适用时,sizing 会返回 Figma 的解释 skipped。

图像

需要艺术作品?使用配套的 img-forge CLI (https://github.com/iggypcnfsky/img-forge) 生成,然后放置——生成过程保持在 Figma 之外,因此 API 密钥永远不会进入插件代码,并且缓慢的渲染不会阻塞画布:

cd ../img-forge
./img gen --prompt "abstract gradient cover, purple to black" --preset 16:9@2k --out out/cover.png
./img edit --prompt "make it night with neon accents" --ref out/cover.png   # 或编辑现有资源
cd ../figma-bridge
./bin/figma image 12:34 ../img-forge/out/cover.png FILL

FILL 裁剪到节点,FIT 添加黑边,TILE 重复,CROP 尊重现有裁剪。 要编辑用户选中的内容,首先导出它(./bin/figma export <nodeId> out/sel.png PNG 2),然后将该文件作为 --ref 传递。

插件窗口还有一个供人类使用的生成/编辑面板(模型、尺寸预设、成本、插入)。不要以编程方式驱动面板——使用 CLI;它暴露了更多功能(蒙版、变体、试运行)。在该面板中保存的预设存放在 figma-bridge/presets.json 中。

在现有草稿上构建

一份“未完成”的草稿仍然编码了决策:什么放在什么旁边,什么被分组,元素的顺序,间距的韵律。在设计之前先读取它,然后保留它。

  1. {"op":"inventory"} — 框架、它们的尺寸和排版统计信息。
  2. {"op":"structure","nodeId":"<frame>"} — 子元素按行分组,带有间隙和 readingOrder;这就是作者选择的分组。{"op":"node",…,"depth":2} 提供相同但更深层的树结构。
  3. 注意模式(重复出现的左边距、始终位于三列上方的标题)并保留它。更改请求所需的内容,其余保持不变。
  4. 报告你所做的更改——例如“将页脚上移了 40 像素”,而不仅仅是“改进了布局”。

永远不要默默地规范化草稿。如果一致性需要移动用户放置的元素,请说明并询问;一个看起来整洁但丢失了他们分组的幻灯片是退步,而不是改进。

规则

  • 先读后写。 至少两次调用:检查,然后修改。
  • 一个批次 = 一个想法。 一个操作不能引用前一个操作的结果,因此如果你需要新节点的 id,请分成两次调用。
  • 尊重你继承的布局:兄弟顺序、邻近性和分组都是意图。除非被要求,否则不要重新排列草稿使其看起来更整洁;如果一致性会移动他们的元素,请先询问。
  • 未经明确指示,永远不要修改现有的用户图层(update、remove、reparent)。在你自己的创建内容前添加前缀:Bridge / …。
  • 重做版本应尽可能靠近原始版本。 如果用户要求重做幻灯片/屏幕/部分:复制它,调用 {"op":"placeNear","nodeId":"<new id>","move":true,"gap":80,"name":"Bridge / v2 — <name>"},使副本落在第一个空闲侧而不是猜测的坐标上,并保持原始版本不变。 如果工具报告 free: false,询问它应该放在哪里。仅当用户明确要求时才原地替换元素。
  • goto 会更改用户的视图——仅在用户请求时使用。
  • exec 是最后的手段。 它有效(Figma 的沙盒允许 new Function)并且绕过所有参数验证。仅返回可 JSON 序列化的值。
  • 清理测试产物,或者询问是否保留它们。

陷阱

  • 使用 localhost,永远不要使用 127.0.0.1:插件清单仅将 http://localhost:3847 列入白名单(devAllowedDomains);Figma 会拒绝 IP。服务器同时在 127.0.0.1 和 ::1 上侦听。
  • figma.currentPage 是该 Figma 窗口中打开的页面——不是保存的指针。切换标签页会更改下次调用时看到的内容。
  • 位置是相对于父元素的,省略 parentId 意味着当前页面。
  • 排版问题(使用哪些字体、大小、计数)一次调用即可解决:{"op":"fonts"};添加 "allPages":true 用于整个文件。不要用自己的脚本遍历框架。
  • 幻灯片概览也是一次调用:{"op":"inventory"} 返回每个框架的几何信息、minFontSize、字体、网格计数和填充——足以选择“框架 11–19”或查找小于最小大小的文本。
  • 永远不要索引参考文档未列出的字段。summary 为 TEXT 携带 font、fontSize、lineHeight 和 letterSpacing;其他所有内容都来自使用真实 API 名称的 exec。混合样式是字符串 "MIXED",因此使用 .get() 和后备值进行保护。
  • 矩形不能有子元素;当文本或图标必须位于形状内部时,请使用框架。
  • 没有本地变量 → variables 返回 collections: [],并且 varFill 会失败。请先检查。
  • 文本需要字体:createText 通过 loadFontAsync 加载字体;如果缺失该系列,请使用 Inter。
  • export 上限为 8 MB——请降低 scale 而不是重试。
  • 读取非当前页面的子元素需要 loadAllPagesAsync;桥接会自动重试一次,但最好使用带 allPages: true 的 find。
  • 编辑插件文件(code.js、ui.html)后,用户必须重新运行插件;对 manifest.json 的更改需要重新导入。

相关技能