{
  "markdown": "# PluginOS\n\n[![npm version](https://img.shields.io/npm/v/pluginos.svg)](https://www.npmjs.com/package/pluginos)\n\nAgent-native Figma operations platform. Run any Figma plugin operation from any LLM agent at **~230 tokens per call** instead of ~28,000.\n\nBuilt by [Dimitrios Arapis](https://arapis.de) - the full story of this toolchain is at [arapis.de/work/open-tooling](https://arapis.de/work/open-tooling).\n\n![PluginOS](PluginOS.png)\n\n## Why PluginOS\n\nTraditional Figma MCP integrations register dozens of tools — each with a full JSON schema the LLM must read on every conversation turn. For a server with 80+ tools, that's **~12,000 tokens of overhead before the agent even does anything.**\n\nPluginOS takes a fundamentally different approach:\n\n- **5 MCP tools, unlimited operations.** The server is a thin router. Operations are discovered dynamically, not hardcoded as tool schemas.\n- **15x cheaper per workflow.** A complex multi-step task costs ~6,600 tokens vs ~105,000 with traditional approaches — 94% savings.\n- **Pre-summarized results.** Operations return structured summaries, not raw node dumps. Agents reason better with less noise.\n- **Extensible by design.** Add custom operations as simple manifest + execute pairs. No server changes needed.\n- **Multi-file support.** Connect multiple Figma files simultaneously. The server tracks active files and routes operations to the right one.\n\n## Quick Start\n\n### 1. Install for your agent\n\n**Recommended — Claude Desktop (one click, no terminal):**\n\n1. Download [`pluginos.dxt`](https://github.com/LSDimi/pluginos/releases/latest/download/pluginos.dxt) from the latest GitHub Release.\n2. Double-click the downloaded file. Claude Desktop opens an install dialog.\n3. Confirm. PluginOS appears in Claude Desktop's connector list.\n\nNo JSON editing, no terminal. Note: Claude.ai web is **not** supported — it cannot reach local MCP servers.\n\nUsing Cursor or Claude Code CLI? Open the section below for the right config.\n\n<details>\n<summary><strong>Other AI tools</strong> (Cursor, Claude Code CLI, manual config)</summary>\n\n**Cursor (`.cursor/mcp.json`):**\n\n```json\n{\n  \"mcpServers\": {\n    \"pluginos\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"pluginos@latest\"]\n    }\n  }\n}\n```\n\nThen paste the Tier 1 rules below into `.cursorrules` so Cursor prefers PluginOS over the generic Figma MCP.\n\n**Claude Code (CLI — engineers):**\n\n```bash\n/plugin marketplace add LSDimi/pluginos\n/plugin install pluginos\n```\n\nInstalls the MCP server registration and the `pluginos-figma` skill in one step.\n\n**Manual (other MCP-capable clients):** Use the same `mcpServers` JSON block as Cursor above and paste the Tier 1 rules below into your project's custom instructions.\n\n</details>\n\n**Tier 1 rules (paste into Cursor / Claude Desktop / other clients):**\n\n```\nWhen working with Figma, always use PluginOS tools exclusively:\n- Use `list_operations` (pluginos) first to discover available Figma operations.\n- Use `run_operation` (pluginos) to execute them.\n- Use `execute_figma` (pluginos) only for one-off custom logic not covered by built-in ops.\n- Do NOT use `mcp__Figma__*` tools — they bypass the plugin and return raw, token-heavy data. PluginOS returns pre-summarized, structured results at ~230 tokens/call.\n- If PluginOS returns \"No plugin connected\", open the PluginOS Bridge plugin in Figma before retrying.\n\nAudit/lint/check operations default to `scope: \"selection\"`. Pass `scope: \"page\"` explicitly (and `confirm: true` for pages over 500 nodes) to scan the whole page. Responses carry `_hint` and `_next_hints` fields — respect them when deciding what to do next.\n```\n\n### 2. Install the Bridge Plugin in Figma\n\n1. Download `pluginos-bridge-v<version>.zip` from the [latest release](https://github.com/LSDimi/pluginos/releases/latest). Unzip anywhere.\n2. Open Figma Desktop. Menu → **Plugins → Development → Import plugin from manifest…**\n3. Select the `manifest.json` from the unzipped folder.\n4. Run **PluginOS Bridge** — it auto-connects to the MCP server.\n\nFull setup walkthrough (with screenshots, troubleshooting, and team distribution): [INSTALL.md](INSTALL.md).\n\n### 3. Use it\n\nTell your agent:\n\n> \"Check the contrast ratios in my design\"\n\nThe agent calls `run_operation(\"check_contrast\", {scope: \"page\"})` and gets back a clean summary. ~230 tokens, done.\n\n> \"Create a 300x200 frame with auto-layout and add some text\"\n\nThe agent calls write operations to create frames, set text, and modify fills — all through the same 5-tool interface.\n\n## How It Works\n\n```\nAgent ── MCP (stdio) ──> PluginOS Server ── WebSocket ──> Bridge Plugin ──> Figma\n         5 tools           thin router        localhost      many operations  full API\n         ~600 tokens       routes by name     ports 9500-    executes locally figma.*\n         per turn          + params only      9510           returns summaries\n```\n\n**Two execution paths:**\n\n| Path         | When                        | Token cost  | How                                                          |\n| ------------ | --------------------------- | ----------- | ------------------------------------------------------------ |\n| **Fast**     | Built-in operation exists   | ~230 tokens | `run_operation(\"check_contrast\", {scope: \"page\"})`           |\n| **Fallback** | Custom/one-off logic needed | ~700 tokens | `execute_figma(\"return figma.currentPage.findAll().length\")` |\n\n## Available Operations (29)\n\n| Operation                | Category      | Description                                                            |\n| ------------------------ | ------------- | ---------------------------------------------------------------------- |\n| `lint_styles`            | lint          | Find layers without styles                                             |\n| `lint_detached`          | lint          | Find detached instances                                                |\n| `lint_naming`            | lint          | Find default-named layers                                              |\n| `validate_ds_compliance` | lint          | Full DS audit in one pass (style, detached, naming, contrast, spacing) |\n| `check_contrast`         | accessibility | WCAG contrast audit                                                    |\n| `check_touch_targets`    | accessibility | Touch target size check                                                |\n| `find_instances`         | components    | Find component instances                                               |\n| `analyze_overrides`      | components    | Report instance overrides                                              |\n| `create_frame`           | components    | Create frames with auto-layout                                         |\n| `clone_node`             | components    | Clone and reposition nodes                                             |\n| `rename_layers`          | cleanup       | Batch rename layers                                                    |\n| `remove_hidden`          | cleanup       | Remove hidden layers                                                   |\n| `round_values`           | cleanup       | Round fractional values                                                |\n| `delete_node`            | cleanup       | Delete nodes by ID                                                     |\n| `list_variables`         | tokens        | List all variables                                                     |\n| `export_tokens`          | tokens        | Export tokens as JSON                                                  |\n| `audit_spacing`          | layout        | Audit spacing values                                                   |\n| `move_node`              | layout        | Move nodes to new positions                                            |\n| `resize_node`            | layout        | Resize nodes                                                           |\n| `set_fills`              | colors        | Set fill colors on nodes                                               |\n| `extract_palette`        | colors        | Extract unique colors with counts                                      |\n| `find_non_style_colors`  | colors        | Find hardcoded (unstyled) colors                                       |\n| `audit_text_styles`      | typography    | Audit font/size/weight consistency                                     |\n| `list_fonts`             | typography    | List all fonts with usage counts                                       |\n| `set_text`               | content       | Set text content on nodes                                              |\n| `populate_text`          | content       | Fill text with lorem or custom text                                    |\n| `extract_css`            | export        | Extract CSS properties from nodes                                      |\n| `list_comments`          | collab        | List threaded file comments via REST (unresolved by default)           |\n| `reply_comment`          | collab        | Reply to a file comment via REST (confirm-gated)                       |\n\n## Comments (REST)\n\n`list_comments` and `reply_comment` read and reply to Figma file comments by calling the Figma REST API directly from the bridge plugin's sandbox (`api.figma.com` is allowlisted in the plugin manifest) — no MCP server round-trip involved.\n\n**One-time setup:** paste a Figma Personal Access Token into the Bridge plugin's ⚙ Setup panel, \"Figma REST access\" section. Required scopes: `file_comments:read`, `file_comments:write`, `file_metadata:read`. The token is stored only in `figma.clientStorage`, never sent to the MCP server.\n\n- `list_comments` returns threaded, unresolved-by-default comments joined to live node names/paths. The first call needs the file URL or key; it's then verified and remembered in the file for later calls.\n- `reply_comment` posts publicly as the user and requires `confirm: true` — the agent shows a preview first.\n- Resolving comments is manual in Figma; the REST API has no resolve endpoint.\n\n**Also in 0.7:** fixed a serializer bug where deep scalar values corrupted to `\"[max depth]\"`; file identity is now stable (synthetic IDs replace `\"unknown\"` fileKeys) with resilient server targeting (name match, single-file fallback); `execute_figma` now echoes back the `requestedTimeout` it used.\n\n## Token Economics\n\n| Scenario                        | Traditional MCP | PluginOS      | Savings |\n| ------------------------------- | --------------- | ------------- | ------- |\n| Tool schema overhead (per turn) | ~12,000 tokens  | ~650 tokens   | 95%     |\n| Single operation call           | ~1,500 tokens   | ~230 tokens   | 85%     |\n| Complex workflow (8 steps)      | ~105,000 tokens | ~6,600 tokens | 94%     |\n| 10 users × 5 runs/day × 30 days | ~157M tokens    | ~10M tokens   | 94%     |\n\n## Adding Custom Operations\n\nCreate a file in `packages/bridge-plugin/src/operations/`:\n\n```typescript\nimport { registerOperation } from \"./registry\";\n\nregisterOperation({\n  manifest: {\n    name: \"my_operation\",\n    description: \"What it does\",\n    category: \"custom\",\n    params: {\n      scope: { type: \"string\", required: false, description: \"'page' or 'selection'\" },\n    },\n    returns: \"{ result, summary }\",\n  },\n  async execute(params) {\n    const nodes = figma.currentPage.findAll();\n    return { result: nodes.length, summary: `Found ${nodes.length} nodes.` };\n  },\n});\n```\n\nRegister it in `operations/index.ts` and rebuild. The agent discovers it automatically via `list_operations`.\n\n## Architecture\n\n```\npackages/\n  shared/          Types, protocol messages, categories\n  mcp-server/      MCP server (stdio) + WebSocket + HTTP (bootloader)\n  bridge-plugin/   Figma plugin (webpack -> code.js + bootloader.html)\n```\n\n- **Monorepo** with npm workspaces\n- **MCP protocol** over stdio (server <> agent)\n- **WebSocket** on localhost:9500-9510 (server <> plugin)\n- **Bootloader pattern** — plugin fetches fresh UI from server on startup\n- **Port scanning** — plugin auto-discovers the server\n- **Multi-file** — multiple Figma files connect simultaneously\n\n## Development\n\n> **All commands must be run from the repo root** (`PluginOS-main/` or wherever you cloned/unzipped it). Running them from inside a package subfolder will fail.\n\n```bash\n# 1. Install all dependencies (run once from repo root)\nnpm install\n\n# 2. Build shared types first — mcp-server depends on them\nnpm run build -w packages/shared\n\n# 3. Build the Figma bridge plugin (outputs to packages/bridge-plugin/dist/)\nnpm run build -w packages/bridge-plugin\n\n# 4. Load the plugin in Figma\n#    Figma → Plugins → Development → Import plugin from manifest\n#    Select: packages/bridge-plugin/manifest.json\n```\n\n```bash\n# Hot-reload development\nnpm run dev:server    # MCP server with hot reload\nnpm run dev:plugin    # Webpack watch for bridge plugin\nnpm test              # Tests across all packages\n```\n\n## License\n\nMIT\n",
  "bytes": 12912,
  "sha": "dec22b8d6edaa00e852dca64a5ace41aa83130983bf90872f33202b7184bf3e9",
  "repo_slug": "lsdimi/pluginos",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/plg_lsdimi_pluginos_pluginos_figma_operation_0a5e69ba/readme"
}