4. The Plugin API in `use_figma`
A script runs in a QuickJS interpreter compiled to WebAssembly (SRS CMD-11).
4.1 The environment#
A script runs in a QuickJS interpreter compiled to WebAssembly (SRS CMD-11). It sees:
| Global | What it is |
|---|---|
figma |
The Plugin API object, implemented on the registry (4.2). |
ud |
UI Designer extras (4.4). |
console |
log, info, warn, error. Output is returned in logs, at most 1 000 lines. |
setTimeout, Promise, JSON, Math, Intl (en) |
Standard. |
There is no fetch, require, import, file system, __html__, figma.ui or figma.showUI. A script is a
function body: return ends it and gives its result. Top-level await is allowed. Limits: 30 s,
256 MB, 100 000 created nodes.
Reads during a script see the script’s own uncommitted changes. Other changes (the user’s edits) queue until the script ends, so a script sees a consistent document.
4.2 Coverage#
The coverage grows by milestone (SRS CMD-10). ud plugin-api prints the exact table for the installed
version. ud plugin-api --json gives it as data, and the MCP resource ud://plugin-api/coverage serves the
same. Typings are in ud-plugin-api.d.ts, a subset of @figma/plugin-typings plus ud. They ship with the
CLI and in the ui-designer skill.
| Area | Members | M |
|---|---|---|
| Document and pages | figma.root, figma.currentPage (read), setCurrentPageAsync, createPage, getNodeByIdAsync, getNodeById, loadAllPagesAsync (no-op), figma.fileKey, figma.notify (logged), figma.mixed |
0.1 |
| Traversal | children, parent, findAll, findOne, findChildren, findChild, findAllWithCriteria, findWidgetNodesByWidgetId → [] |
0.1 |
| Creation | createFrame, createRectangle, createEllipse, createLine, createPolygon, createStar, createSection, group, ungroup, clone, remove, appendChild, insertChild |
0.1 |
| Geometry | x, y, resize, resizeWithoutConstraints, rotation, relativeTransform, absoluteTransform, absoluteBoundingBox, width, height |
0.1 |
| Appearance | fills, strokes, strokeWeight, strokeAlign, dashPattern, cornerRadius, individual corner radii, cornerSmoothing, opacity, blendMode, visible, locked, clipsContent, effects, isMask |
0.1 |
| Selection | figma.currentPage.selection (read and write), figma.viewport.scrollAndZoomIntoView (live editor only) |
0.1 |
| Data | setPluginData, getPluginData, setSharedPluginData, getSharedPluginData, getPluginDataKeys, setRelaunchData (ignored) |
0.1 |
| Text | createText, characters, loadFontAsync, listAvailableFontsAsync, fontName, fontSize, fontWeight, lineHeight, letterSpacing, textAlignHorizontal, textAlignVertical, textAutoResize, textCase, textDecoration, paragraphSpacing, setRange* / getRange*, getStyledTextSegments, hyperlink |
0.2 |
| Vectors | createVector, vectorPaths, vectorNetwork, setVectorNetworkAsync, createBooleanOperation, union, subtract, intersect, exclude, flatten, outlineStroke, createNodeFromSvg |
0.2 |
| Images | createImage(bytes), createImageAsync(url) (http(s) and file: inside the workspace), getImageByHash, image.getBytesAsync, image.getSizeAsync |
0.2 |
| Export | exportAsync({ format: "PNG" | "JPG" | "SVG" | "SVG_STRING" | "PDF" | "JSON_REST_V1", constraint }), exportSettings |
0.2 |
| Layout | layoutMode (NONE, HORIZONTAL, VERTICAL, GRID), itemSpacing, counterAxisSpacing, padding*, primaryAxisAlignItems, counterAxisAlignItems, layoutWrap, layoutSizingHorizontal / Vertical, layoutAlign, layoutGrow, layoutPositioning, minWidth / maxWidth / minHeight / maxHeight, itemReverseZIndex, strokesIncludedInLayout, constraints, layoutGrids, grid track members |
0.3 |
| Components | createComponent, createComponentFromNode, combineAsVariants, createInstance, mainComponent, getMainComponentAsync, detachInstance, swapComponent, componentPropertyDefinitions, addComponentProperty, editComponentProperty, deleteComponentProperty, setProperties, componentProperties, variantProperties, resetOverrides, importComponentByKeyAsync, importComponentSetByKeyAsync |
0.4 |
| Styles | createPaintStyle, createTextStyle, createEffectStyle, createGridStyle, getLocalPaintStylesAsync and siblings, getStyleByIdAsync, setFillStyleIdAsync and siblings, importStyleByKeyAsync |
0.4 |
| Variables | figma.variables.createVariableCollection, createVariable, getLocalVariablesAsync, getLocalVariableCollectionsAsync, getVariableByIdAsync, importVariableByKeyAsync, setBoundVariableForPaint, setBoundVariableForEffect, setBoundVariableForLayoutGrid, createVariableAlias; collection.addMode, renameMode, removeMode; variable.setValueForMode, valuesByMode, resolveForConsumer, scopes, codeSyntax, setVariableCodeSyntax; node.setBoundVariable, boundVariables, setExplicitVariableModeForCollection |
0.4 |
| Library access | figma.teamLibrary.getAvailableLibraryVariableCollectionsAsync, getVariablesInLibraryCollectionAsync (workspace libraries) |
0.4 |
Agent conveniences (used by Figma’s figma-use skill) |
node.query(selector), node.set(props), node.placeholder (shown hatched until cleared) |
0.1 |
await node.screenshot(options), returning the same image content as get_screenshot |
0.2 | |
figma.createAutoLayout(direction, props) |
0.3 | |
| Prototyping | reactions, setReactionsAsync, flowStartingPoints, overflowDirection, numberOfFixedChildren |
0.5 |
| Handoff | annotations, figma.annotations.addAnnotationCategoryAsync, devStatus, description, descriptionMarkdown, documentationLinks |
0.6 |
| Not planned | figma.ui, showUI, figma.clientStorage (use pluginData), figma.payments, figma.codegen, figma.textreview, figma.parameters, widgets, FigJam and Slides node types, figma.createVideoAsync |
— |
Using a member that is not implemented throws UnsupportedApiError with its name and the planned milestone
(SRS CMD-14). Reading an unknown property returns undefined, as on a Figma node.
4.3 Behaviour kept from Figma#
So that scripts written for Figma run unchanged (SRS CMD-15):
- Colours are
{ r, g, b }from 0 to 1, with opacity on the paint.figma.util.rgb('#1E1E1E')andfigma.util.solidPaint('#1E1E1E')help. fills,strokes,effects,layoutGridsandexportSettingsare frozen arrays. Clone, change and assign:node.fills = [{ ...node.fills[0], opacity: 0.5 }].- Text needs
await figma.loadFontAsync(fontName)beforecharactersor any text property changes. Font style names are Figma’s:Regular,Medium,Semi Bold,Bold,Extra Bold. Fonts are found among bundled fonts (Inter, Roboto, JetBrains Mono, Noto Sans), the workspace’sfonts/folder and the system’s. figma.currentPagecannot be assigned;await figma.setCurrentPageAsync(page)switches pages. Headless,figma.currentPagestarts at the first page; in a live editor, the page the user has open.- New nodes are appended to
figma.currentPageuntil moved.createFramegives a 100×100 white frame,createTextan empty text in Inter Regular 12. All defaults are Figma’s. resizekeeps constraints;layoutSizingHorizontal = 'FILL'only works inside an auto layout parent and throws otherwise, with Figma’s message.- Mixed values read as
figma.mixed. node.idreturns the native id (nd-…).getNodeByIdAsyncaccepts every form of section 2.3.
Where Figma’s MCP forbids something that UI Designer supports, the script simply works. Examples are
setPluginData, createImageAsync and loadAllPagesAsync, which Figma’s use_figma rejects.
4.4 The ud global#
Things the Plugin API has no member for:
| Member | Does |
|---|---|
ud.run(id, params) |
Runs any registry command inside the script’s transaction and returns its result (SRS CMD-13). |
ud.inspect(node, { fields }) |
The ud inspect record of a node: resolved styles, variables, computed layout. |
ud.insertUdx(markup, parent?) |
Builds nodes from UDX (section 7) and returns the root nodes. |
ud.toUdx(node, { depth }) |
The UDX of a subtree. |
ud.lint(node, { rules }) |
The findings of ud lint for a subtree. |
ud.system() |
The design-system digest of ud system. |
ud.actor |
The actor signing the run. |
4.5 How the API maps to the registry#
Each mutating member is a registry command, so a script writes the same events as the editor. A few examples
follow; ud help <command> shows the Plugin API equivalent of every command.
| Plugin API | Registry command |
|---|---|
figma.createFrame() |
node.create { type: "FRAME" } |
node.name = "Card" |
node.update { id, props: { name } } |
node.fills = [...] |
node.update { id, props: { fills } } |
parent.appendChild(node) |
node.move { id, parent, index: "last" } |
node.remove() |
node.delete { id } |
figma.combineAsVariants(components, parent) |
component.combineAsVariants |
instance.setProperties({...}) |
instance.setProperties |
collection.addMode("Dark") |
variable.addMode |
node.setBoundVariable("itemSpacing", v) |
variable.bind |
node.exportAsync(...) |
export.render (reads only) |
Consecutive updates of one node within a script are merged into one node.update event.