Was macht Figma Bridge?
Figma hat keine öffentliche Schreib-API. Dieser Skill verwendet eine lokale Brücke: benannte Operationen über HTTP, die innerhalb von Figma durch ein Plugin über die Figma Plugin API ausgeführt werden. Kein OAuth, keine Tokens.
Repository: https://github.com/iggypcnfsky/figma-bridge — AGENTS.md, docs/ops-reference.md.
Vorbedingungen – vor allem anderen prüfen
figma ist im PATH, also niemals das Dateisystem nach dem Repository durchsuchen:
figma doctor # Repository, Server, verbundene Fenster, img-forge + FAL-Key in einem Durchlauf
figma clients # ID, Datei, Seite jedes verbundenen Figma-Fensters
figma rules # Projektbeschränkungen: Typ-Mindestgröße, Raster, Rahmengröße, Versionsbenennung
Lies figma rules vor dem Entwerfen. Es enthält die nicht offensichtlichen Grenzen – z. B. „Poppins 20/25 ist die
Untergrenze“ – die dir kein noch so genaues Betrachten der Leinwand verrät. Behandle "confirmed": false als eine
Annahme, die mit dem Benutzer zu überprüfen ist, und {} als „fragen, nicht erfinden“.
Fehlt der Befehl, verwende node "$(figma where)/server.mjs" nur nach Rückfrage; suche nicht das
Repository mit find und rate keine Pfade.
pluginConnected: false→ anhalten. Den Benutzer bitten,Plugins → Entwicklung → Figma Bridgeim Fenster der zu bearbeitenden Datei auszuführen. Wiederholen hilft nicht.503von/runbedeutet dasselbe.504 PLUGIN_GONEbedeutet, dass der Benutzer das Plugin-Fenster geschlossen hat.409bedeutet, dass mehrere Figma-Fenster verbunden sind und keines ausgewählt wurde. Wähle die vom Benutzer genannte Datei (--file <NAME>) oder eine Client-ID (--client <ID>); wiederhole niemals blind, sonst könntest du die falsche Datei bearbeiten.
Der Ablauf
- Orientieren.
./bin/figma status→ Dateiname, aktuelle Seite, Auswahl, alle Seiten. - Lesen.
selection 2,node <id> 2,find {"name":"Header","allPages":true}. Rate niemals einenodeId– Figma-IDs sehen aus wie4022:2und sind nicht ableitbar. - Planen. Entscheide über Parent, Größe, Reihenfolge. Neue Knoten werden auf der aktuellen Seite platziert, es sei denn, es wird eine
parentIdangegeben. - Schreiben.
./bin/figma run '[{...},{...}]'. - Verifizieren.
./bin/figma export <id> out/check.png PNG 2und sieh dir das Bild tatsächlich an.
Befehle
./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":"Titel","fontSize":24,"color":"#FFFFFF"}]'
./bin/figma op '{"op":"varFill","nodeId":"12:34","variableName":"farbe/hg/oberflaeche"}'
./bin/figma export 12:34 out/karte.png PNG 2
./bin/figma image 12:34 out/cover.png FILL # lokale Bilddatei → Füllung (kein Cloud-Upload)
Operationen: 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.
Vollständige Parameter: docs/ops-reference.md.
Nützliche Abkürzungen für Designarbeit:
- Raster bedeutet GITTERRASTER: Wenn der Benutzer „setze ein Raster“ sagt, meint er das quadratische Layoutraster, nicht Spalten:
{"op":"setGrids","nodeId":"…","grid":true}(40-Pixel-Zellen, standardmäßig 40%) oder"grid":40. Verwendecolumns/rowsnur, wenn er Spalten, ein 12-Spalten-Raster oder Angaben zu Abstand/Margin macht. Erstelle niemals ein Raster mit Rechtecken;applyStylemitkind:"grid"wendet einen gespeicherten Raster-Stil an. - Reihen von Elementen: Erstelle sie, dann
{"op":"align","nodeIds":[…],"mode":"TOP"}und{"op":"distribute","nodeIds":[…],"axis":"HORIZONTAL","gap":24}. - Tiefe:
{"op":"effects","nodeId":"…","shadow":{"y":8,"blur":24,"color":"#00000033"}}oder{"op":"effects","nodeId":"…","blur":{"type":"BACKGROUND","radius":20}}. - Verläufe:
{"op":"gradient","nodeId":"…","kind":"linear","angle":135,"stops":[[0,"#8B76FF"],[1,"#0E0E12"]]}– Winkel 0 ist links → rechts, 90 ist oben → unten. Erstelle niemals einen Verlauf durch gestapelte Rechtecke. - Designsystem:
createInstancemit einerCOMPONENT-ID, danninstancePropsfür Varianten (lies zuerst die Namen) undinstanceText, um Text zu ändern, ohne die Instanz zu trennen;applyStylefür Stile. Zeichne nichts neu, was die Bibliothek bereits liefert, und trenne keine Instanz, um ihren Text zu „korrigieren“. - Abstandsprüfungen:
{"op":"measure","a":"1:2","b":"1:3"}gibt Abstände pro Seite und Mittelpunktabstand zurück; verwende dies, anstatt einen Screenshot zu exportieren, um die Ausrichtung zu beurteilen. - Stile:
saveStyleerstellt oder aktualisiert einentext- /paint- /effect- /grid-Stil nach Namen, undapplyStylewendet ihn an. Erstelle das Token einmal und wende es überall an. - Responsive:
sizingsetztHUG/FILL/FIXEDpro Achse plus min/max;constraintsdeckt Nicht-Auto-Layout-Kinder ab (STRETCH/MIN/MAX/CENTER/SCALE). Lese beide vonnode, bevor du sie änderst –sizinggibtskippedmit Figmas Begründung zurück, wenn eine Eigenschaft nicht zutrifft.
Bilder
Benötigst du Grafiken? Erzeuge sie mit dem zugehörigen img-forge-CLI
(https://github.com/iggypcnfsky/img-forge) und platziere sie dann – die Generierung bleibt außerhalb von
Figma, sodass der API-Key nie in den Plugin-Code gelangt und eine langsame Darstellung die Leinwand nicht blockieren kann:
cd ../img-forge
./img gen --prompt "abstrakter Verlaufshintergrund, lila zu schwarz" --preset 16:9@2k --out out/cover.png
./img edit --prompt "mach es nachtblau mit Neonakzenten" --ref out/cover.png # oder ein vorhandenes Asset bearbeiten
cd ../figma-bridge
./bin/figma image 12:34 ../img-forge/out/cover.png FILL
FILL beschneidet auf den Knoten, FIT letterboxt, TILE wiederholt, CROP respektiert den vorhandenen Beschnitt.
Um zu bearbeiten, was der Benutzer ausgewählt hat, exportiere es zuerst (./bin/figma export <nodeId> out/sel.png PNG 2) und
übergib diese Datei als --ref.
Das Plugin-Fenster hat außerdem ein Generate/Edit-Panel für Menschen (Modell, Größen-Voreinstellungen, Kosten, Einfügen).
Steuere das Panel nicht programmatisch – verwende das CLI; es bietet mehr (Maske, Varianten, Probelauf).
Im Panel gespeicherte Voreinstellungen liegen in figma-bridge/presets.json.
Arbeiten an einem vorhandenen Entwurf
Ein Entwurf, der „nicht fertig“ ist, codiert dennoch Entscheidungen: was neben was liegt, was gruppiert ist, die Reihenfolge der Elemente, den Rhythmus der Abstände. Lese ihn vor dem Entwerfen und behalte ihn dann bei.
{"op":"inventory"}– die Rahmen, ihre Größen und typografischen Statistiken.{"op":"structure","nodeId":"<Rahmen>"}– Kinder, gruppiert in Zeilen mit Abständen und einerreadingOrder; das ist die vom Autor gewählte Gruppierung.{"op":"node",…,"depth":2}gibt denselben Baum mit mehr Tiefe.- Erkenne das Muster (einen wiederkehrenden linken Rand, einen Titel, der immer über drei Spalten steht) und behalte es. Ändere, was die Anforderung braucht, lasse den Rest, wo er ist.
- Berichte die Abweichungen, die du vorgenommen hast – „die Fußzeile um 40 nach oben verschoben“, nicht nur „Layout verbessert“.
Normalisiere niemals einen Entwurf stillschweigend. Wenn Konsistenz das Verschieben vom Benutzer platzierter Elemente erfordern würde, sage dies und frage nach; eine ordentlich aussehende Folie, die ihre Gruppierungen verloren hat, ist ein Rückschritt, keine Verbesserung.
Regeln
- Vor dem Schreiben lesen. Mindestens zwei Aufrufe: inspizieren, dann mutieren.
- Ein Batch = ein Gedanke. Eine Operation kann nicht auf das Ergebnis einer vorherigen Operation verweisen; wenn du
die
iddes neuen Knotens benötigst, teile den Aufruf in zwei auf. - Respektiere die Anordnung, die du vorfindest: Geschwister-Reihenfolge, Nähe und Gruppierung sind Absicht. Ordne einen Entwurf nicht neu an, um ihn ordentlicher aussehen zu lassen, es sei denn, du wirst dazu aufgefordert; frage zuerst, wenn Konsistenz ihre Elemente verschieben würde.
- Berühre niemals vorhandene Benutzerebenen (
update,remove,reparent) ohne ausdrückliche Anweisung. Versehe deine eigenen Erzeugnisse mit einem Präfix:Bridge / …. - Eine Überarbeitung kommt direkt neben das Original, so nah wie möglich. Bei der Bitte, eine
Folie/einen Bildschirm/einen Abschnitt zu überarbeiten: dupliziere sie, rufe
{"op":"placeNear","nodeId":"<neue ID>","move":true,"gap":80,"name":"Bridge / v2 — <Name>"}auf, damit die Kopie auf der ersten freien Seite statt an einer geratenen Koordinate landet, und lasse das Original unberührt. Wenn das Toolfree: falsemeldet, frage, wo es platziert werden soll. Ersetze Elemente an Ort und Stelle nur, wenn der Benutzer dies ausdrücklich verlangt. gotoändert die Ansicht des Benutzers – nur auf Anfrage.execist das letzte Mittel. Es funktioniert (Figmas Sandbox erlaubtnew Function) und umgeht alle Parameter-Validierung. Gib nur JSON-serialisierbare Werte zurück.- Räume auf – entferne Test-Artefakte oder frage, ob sie behalten werden sollen.
Fallstricke
- Verwende
localhost, niemals127.0.0.1: das Plugin-Manifest erlaubt nurhttp://localhost:3847(devAllowedDomains); Figma lehnt IPs ab. Der Server hört sowohl auf127.0.0.1als auch auf::1. figma.currentPageist die Seite, die in diesem Figma-Fenster geöffnet ist – kein gespeicherter Zeiger. Ein Tab-Wechsel ändert, was du beim nächsten Aufruf siehst.- Positionen sind relativ zum Parent, und eine fehlende
parentIdbedeutet die aktuelle Seite. - Typografiefragen (welche Schriften, Größen, Anzahlen) sind ein einziger Aufruf:
{"op":"fonts"}; füge"allPages":truefür die gesamte Datei hinzu. Durchlaufe keine Rahmen mit eigenem Skript. - Eine Folienübersicht ist ebenfalls ein Aufruf:
{"op":"inventory"}gibt jeden Rahmen mit Geometrie,minFontSize, Schriften, Rasteranzahl und Füllungen zurück – genug, um „Rahmen 11–19“ auszuwählen oder Text unterhalb einer Mindestgröße zu finden. - Indiziere niemals ein Feld, das die Referenz nicht auflistet.
summaryträgtfont,fontSize,lineHeightundletterSpacingfür TEXT; alles andere stammt vonexecmit dem echten API-Namen. Gemischte Stile sind der String"MIXED", also schütze dich mit.get()und Fallbacks. - Ein Rechteck kann keine Kinder haben; verwende einen Frame, wenn Text oder Symbole in einer Form sitzen müssen.
- Keine lokalen Variablen →
variablesgibtcollections: []zurück undvarFillschlägt fehl. Prüfe zuerst. - Text benötigt eine Schriftart:
createTextlädt sie überloadFontAsync; fehlt die Familie, verwendeInter. exportist auf 8 MB begrenzt – verringerescalestatt zu wiederholen.- Das Lesen von Kindern einer nicht aktuellen Seite erfordert
loadAllPagesAsync; die Brücke wiederholt einmal automatisch, aber bevorzugefindmitallPages: true. - Nach dem Bearbeiten von Plugin-Dateien (
code.js,ui.html) muss der Benutzer das Plugin neu ausführen; Änderungen anmanifest.jsonerfordern einen erneuten Import.