# How to Use the use_figma Tool with the Figma Plugin API

> Learn how to use the use_figma tool with the Figma Plugin API to execute JavaScript directly in Figma. Understand async harnesses and atomic operations for seamless integration.

- Repository: [OpenAI/plugins](https://github.com/openai/plugins)
- Tags: how-to-guide
- Published: 2026-06-10

---

**The `use_figma` tool enables AI assistants to execute JavaScript directly inside Figma files by loading the `figma-use` skill, wrapping code in an async harness, and requiring a JSON return value, with all operations executing atomically so errors roll back changes.**

The `use_figma` tool in the `openai/plugins` repository serves as a bridge between AI assistants and the Figma design environment. By leveraging the official Figma Plugin API, this tool allows programmatic manipulation of design files through JavaScript execution. Understanding how to structure scripts, handle page navigation, and manage data persistence is essential for building reliable automation workflows.

## Loading the Mandatory figma-use Skill

Every invocation of the `use_figma` tool requires loading the `figma-use` skill first. According to [`plugins/figma/skills/figma-use/SKILL.md`](https://github.com/openai/plugins/blob/main/plugins/figma/skills/figma-use/SKILL.md), omitting this prerequisite causes hard-to-debug failures. When calling the tool, always include `skillNames: "figma-use"` in the request parameters.

## Script Structure and Execution Model

The `use_figma` tool wraps your JavaScript in an async function automatically, allowing top-level `await` without manual IIFE wrapping. However, strict rules govern how scripts communicate results and handle side effects.

### The Return Statement Requirement

Scripts must use a `return` statement to send data back to the assistant. Methods like `console.log`, `figma.closePlugin()`, and `figma.notify()` are ignored or throw "not implemented" errors. Always return a JSON-serializable object containing node IDs, counts, or status information.

### Atomic Execution Guarantees

Execution is atomic: if your script throws an error, **no changes** are applied to the file. The error message returns to the assistant for correction, leaving the document unchanged. This safety mechanism prevents partial modifications that could corrupt the design.

## Complete Workflow Example

The following script demonstrates the canonical pattern for `use_figma` calls, as defined in [`plugins/figma/skills/figma-use/SKILL.md`](https://github.com/openai/plugins/blob/main/plugins/figma/skills/figma-use/SKILL.md):

```javascript
// 1️⃣ Load the skill (handled by the assistant)
//    skillNames: "figma-use"

// 2️⃣ Switch to the target page (must be the first operation)
const targetPage = figma.root.children.find(p => p.name === "Landing");
await figma.setCurrentPageAsync(targetPage);

// 3️⃣ Create a frame with auto-layout
const frame = figma.createAutoLayout('VERTICAL', { name: "Card", itemSpacing: 12 });
targetPage.appendChild(frame);

// 4️⃣ Add a rectangle fill
const rect = figma.createRectangle();
rect.resize(300, 180);
rect.fills = [{type: "SOLID", color: {r: 0.1, g: 0.6, b: 0.9}}];
frame.appendChild(rect);

// 5️⃣ Add a text node (must load the font first)
await figma.loadFontAsync({family: "Inter", style: "Bold"});
const txt = figma.createText();
txt.characters = "Hello Figma";
txt.fontSize = 24;
txt.fills = [{type: "SOLID", color: {r: 1, g: 1, b: 1}}];
frame.appendChild(txt);

// 6️⃣ Take an inline screenshot of the finished card
await frame.screenshot();

// 7️⃣ Return IDs so the assistant can reference them later
return { createdNodeIds: [frame.id, rect.id, txt.id] };

```

This example illustrates several critical rules: using `await figma.setCurrentPageAsync(page)` for navigation, loading fonts before text manipulation, and returning serializable objects with node IDs.

## Page Navigation and State Management

The `figma.currentPage` property resets on every `use_figma` call. To work on specific pages, you must explicitly switch contexts using the asynchronous setter.

Use `await figma.setCurrentPageAsync(page)` instead of the synchronous setter, which is unsupported in this environment. Always perform page switching as the first operation in your script.

## Creating Nodes and Auto-Layout

When constructing UI elements, prefer `figma.createAutoLayout()` for container frames. This method accepts direction parameters (`'VERTICAL'` or `'HORIZONTAL'`) and configuration options like `itemSpacing`.

Critical constraint: For child nodes to use `layoutSizingHorizontal` or `layoutSizingVertical` values of `"FILL"`, the parent must already be an auto-layout frame before appending children.

```javascript
const frame = figma.createAutoLayout('VERTICAL', { name: "Card", itemSpacing: 12 });
const rect = figma.createRectangle();
rect.layoutSizingHorizontal = "FILL"; // Works because frame is auto-layout
frame.appendChild(rect);

```

## Data Persistence and Variable Scoping

The `use_figma` environment supports `getSharedPluginData` and `setSharedPluginData` for storing data accessible across plugins, but **does not** support `getPluginData` or `setPluginData`.

When creating variables, always explicitly set `variable.scopes`. The default `ALL_SCOPES` value pollutes every property picker in the UI, so narrow scoping is essential. Reference [`plugins/figma/skills/figma-use/references/variable-patterns.md`](https://github.com/openai/plugins/blob/main/plugins/figma/skills/figma-use/references/variable-patterns.md) for detailed scoping strategies.

## Querying Nodes and Capturing Screenshots

Instead of verbose `findAll` loops, use the `node.query(selector)` method for CSS-like searches within the node tree.

For visual feedback, call `await node.screenshot()` to generate inline PNG images directly in the response. This avoids separate `get_screenshot` calls and provides immediate visual confirmation of changes.

```javascript
const buttons = frame.query(".button-primary");
const screenshot = await frame.screenshot();

```

## Incremental Workflow Constraints

Keep each `use_figma` call to **10 or fewer logical operations** (creation, setting properties, and parenting). Split larger jobs into multiple calls and validate after each step. Return comprehensive ID lists in your payload to enable subsequent operations.

## Key Reference Documentation

The following files in the `openai/plugins` repository provide authoritative documentation:

- [`plugins/figma/skills/figma-use/SKILL.md`](https://github.com/openai/plugins/blob/main/plugins/figma/skills/figma-use/SKILL.md) - Primary skill definition and critical rules
- [`plugins/figma/skills/figma-use/references/plugin-api-standalone.index.md`](https://github.com/openai/plugins/blob/main/plugins/figma/skills/figma-use/references/plugin-api-standalone.index.md) - Complete API surface index and type definitions
- [`plugins/figma/skills/figma-use/references/variable-patterns.md`](https://github.com/openai/plugins/blob/main/plugins/figma/skills/figma-use/references/variable-patterns.md) - Variable creation and scoping patterns
- [`plugins/figma/skills/figma-use/references/plugin-api-patterns.md`](https://github.com/openai/plugins/blob/main/plugins/figma/skills/figma-use/references/plugin-api-patterns.md) - Common API patterns for node creation and layout
- [`plugins/figma/skills/figma-use/references/gotchas.md`](https://github.com/openai/plugins/blob/main/plugins/figma/skills/figma-use/references/gotchas.md) - Catalog of typical pitfalls and solutions

## Summary

- **Always load the skill**: Include `skillNames: "figma-use"` before calling `use_figma`
- **Return data explicitly**: Use `return` statements with JSON-serializable objects; avoid `console.log` and `figma.notify()`
- **Handle pages asynchronously**: Use `await figma.setCurrentPageAsync(page)` to switch contexts
- **Leverage auto-layout**: Create auto-layout frames before appending children that use `"FILL"` sizing
- **Execute atomically**: Script failures roll back all changes, preventing file corruption
- **Query efficiently**: Use `node.query(selector)` instead of manual traversal loops
- **Capture inline screenshots**: Call `await node.screenshot()` for immediate visual feedback

## Frequently Asked Questions

### What happens if my use_figma script throws an error?

If your script throws an error, **no changes are applied** to the Figma file. The execution is atomic, meaning the entire operation rolls back if any part fails. The error message returns to the assistant, allowing you to fix the script and retry without leaving the document in a partial state.

### Can I use console.log or figma.notify() for debugging?

No. In the `use_figma` sandbox environment, `console.log` statements are ignored and `figma.notify()` throws a "not implemented" error. You must use the `return` statement to communicate debug information or status back to the assistant.

### How do I switch between pages in a Figma file?

Call `await figma.setCurrentPageAsync(page)` with the target page node. The synchronous `figma.currentPage` setter is unsupported. Because `figma.currentPage` resets on every tool invocation, always perform page switching as the first operation in your script. Find target pages by searching `figma.root.children` by name or ID.

### What is the difference between shared plugin data and regular plugin data?

The `use_figma` tool supports `getSharedPluginData` and `setSharedPluginData`, which store data accessible across different plugins. However, **it does not support** `getPluginData` or `setPluginData`, which store data private to a specific plugin instance. Use the shared variants for all data persistence needs.