Understanding the use_figma Capability in the OpenAI Figma Plugin

The use_figma capability is a tool that lets the AI assistant execute JavaScript inside a Figma file by leveraging the official Figma Plugin API, enabling automated design operations with atomic execution guarantees.

The use_figma capability is the core scripting interface of the OpenAI Figma plugin, hosted in the openai/plugins repository. It bridges the AI assistant and the Figma design environment, allowing programmatic manipulation of design files through standard Figma Plugin API calls wrapped in a controlled execution harness.

What is the use_figma Capability

use_figma functions as a remote JavaScript execution environment that runs code against the current state of a Figma file. According to the skill definition in plugins/figma/skills/figma-use/SKILL.md, this tool wraps user-supplied scripts in an async context and dispatches them to a running Figma session via the plugin bridge.

The capability operates under a skill-gate architecture. Before invoking use_figma, the assistant must load the figma-use skill, which enforces pre-flight checks and validates the script against the supported API surface defined in plugin-api-standalone.index.md and plugin-api-standalone.d.ts.

How use_figma Works Under the Hood

The execution flow follows six distinct phases:

  1. Skill Loading – The assistant specifies skillNames: "figma-use" when calling the tool. The loader reads plugins/figma/skills/figma-use/SKILL.md to validate API rules and constraints.

  2. Script Preparation – The assistant writes plain JavaScript with top-level await and a mandatory return statement. The harness automatically wraps the script in an async function; no IIFE is required.

  3. Dispatch to Figma – The use_figma tool transmits the script to the Figma desktop or web runtime via the plugin bridge.

  4. Execution – The script executes against the live file state. All asynchronous calls such as figma.loadFontAsync() or figma.setCurrentPageAsync() must be explicitly awaited.

  5. Return Serialization – The runtime serializes the returned value to JSON and transmits it back to the assistant. The assistant uses these return values (typically node IDs) to chain subsequent operations.

  6. Error Recovery – If the script throws an exception, the runtime aborts the entire call and leaves the file unchanged, ensuring atomic transaction semantics.

Critical Rules and Constraints

Working with use_figma requires adherence to strict architectural rules defined in the skill documentation:

  • Atomic Execution – Each script runs atomically. If any part fails, no changes are applied to the file, preventing half-modified states.

  • Mandatory Return Values – Scripts must return data to communicate results. console.log output is ignored, and figma.closePlugin() is forbidden.

  • Runtime Reset Behavior – The Figma runtime resets after each call (e.g., the current page reverts to the first page). Complex workflows must be split into multiple small use_figma calls with ID passing between steps.

  • Restricted API Surface – Certain API members are unavailable, including figma.notify and getPluginData. Colors must use 0-1 ranges rather than 0-255, and fills/strokes are read-only arrays that must be cloned before modification.

  • Page Navigation – Page switching requires await figma.setCurrentPageAsync(page); the synchronous setter is unsupported.

Practical Code Examples

The following snippets demonstrate canonical use_figma patterns from the repository documentation.

Creating and Styling Nodes

This example creates a rectangle, applies a solid red fill, and returns the node ID for subsequent operations:

const rect = figma.createRectangle();
rect.resize(200, 100);
rect.set({ 
  fills: [{ type: 'SOLID', color: { r: 1, g: 0, b: 0 } }],
  name: 'Red Box'
});
figma.currentPage.appendChild(rect);
return { createdNodeIds: [rect.id] };

Key implementation details:

  • node.set() batches property updates efficiently
  • Color values use normalized 0-1 ranges (r: 1 equals 255)
  • The return object enables reference tracking across multiple use_figma calls

Querying and Batch Updating Elements

The helper API supports CSS-like selectors for querying nodes:

const texts = figma.currentPage.query('FRAME[name^=Card] TEXT');
texts.set({
  fills: [{ type: 'SOLID', color: { r: 0.2, g: 0.2, b: 0.8 } }]
});
return { mutatedNodeIds: texts.map(n => n.id) };

The node.query() method returns a QueryResult object that supports batch operations via .set(), allowing efficient mass updates without iterating manually.

Working with Variables and Collections

Creating design tokens requires explicit scoping and async persistence:

const collection = figma.variables.createVariableCollection('Colors');
await collection.saveAsync();

const colorVar = figma.variables.createVariable('Primary', collection, 'COLOR');
colorVar.setDefaultValue({ r: 0, g: 0.6, b: 0.9 });

const rect = figma.createRectangle();
rect.resize(150, 150);
const paint = { type: 'SOLID', color: { r: 0, g: 0, b: 0 } };
rect.fills = [paint];
const boundPaint = figma.variables.setBoundVariableForPaint(paint, 'color', colorVar);
rect.fills = [boundPaint];
figma.currentPage.appendChild(rect);

return { createdNodeIds: [rect.id], variableIds: [colorVar.id] };

Critical constraints for variables:

  • Always await collection.saveAsync() to persist collections
  • setBoundVariableForPaint() returns a new paint object that must be reassigned to the node
  • Default scopes should be set explicitly rather than using ALL_SCOPES

Summary

  • The use_figma capability executes JavaScript inside Figma files via the official Plugin API, requiring the figma-use skill to be loaded first.
  • Atomic execution guarantees that failed scripts leave the file unchanged, while successful scripts must return data to communicate results.
  • Runtime limitations include session resets between calls, restricted API methods, and mandatory async patterns for page navigation and variable operations.
  • Helper methods like node.query() and node.set() streamline common batch operations, while the TypeScript definitions in plugin-api-standalone.d.ts provide precise type signatures for all supported operations.

Frequently Asked Questions

What is the figma-use skill and why is it required?

The figma-use skill is a mandatory capability gate defined in plugins/figma/skills/figma-use/SKILL.md that validates scripts against the supported Figma Plugin API surface. Loading this skill ensures the assistant understands API constraints, pre-flight checklists, and error recovery protocols before dispatching code to the Figma runtime.

Why must use_figma scripts return values instead of using console.log?

The use_figma harness explicitly ignores console.log output and only serializes the value of the final return statement back to the assistant. This design enforces structured data exchange, typically requiring scripts to return node IDs or metadata objects that enable incremental, multi-step workflows across separate use_figma invocations.

How does error handling work with use_figma?

Script execution follows atomic transaction semantics. If the JavaScript throws an exception at any point, the runtime aborts the entire operation and discards all pending changes to the Figma file. The assistant receives the error message and can retry after correcting the script, ensuring the design file never persists a partial or corrupted state.

What are the limitations when navigating pages in Figma?

Page navigation requires the asynchronous method await figma.setCurrentPageAsync(page); the synchronous figma.currentPage = page setter is unsupported. Additionally, the runtime resets to the first page after each use_figma call, so scripts that modify page context must explicitly restore the correct page at the start of subsequent calls.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →