@dannote/figma-use 0.5.1 → 0.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.5.2] - 2026-01-18
11
+
12
+ ### Fixed
13
+
14
+ - Multiplayer connection works with Figma's updated protocol (sessionID now from plugin API)
15
+ - Proxy properly handles file switches (closes stale connections)
16
+ - `figma-use status` now shows full connection diagnostics (proxy, plugin, DevTools, file)
17
+
10
18
  ## [0.5.1] - 2026-01-18
11
19
 
12
20
  ### Added
package/SKILL.md CHANGED
@@ -36,7 +36,7 @@ figma-use plugin
36
36
 
37
37
  ## JSX Rendering (Fastest Way)
38
38
 
39
- For complex layouts, use `render --stdin` with JSX. LLMs know Reactno learning curve:
39
+ For complex layouts, use `render --stdin` with pure JSX. No imports neededelements are built-in:
40
40
 
41
41
  ```bash
42
42
  echo '<Frame style={{padding: 24, gap: 16, flexDirection: "column", backgroundColor: "#FFF", borderRadius: 12}}>
@@ -45,11 +45,34 @@ echo '<Frame style={{padding: 24, gap: 16, flexDirection: "column", backgroundCo
45
45
  </Frame>' | figma-use render --stdin
46
46
  ```
47
47
 
48
+ **Elements:** `Frame`, `Rectangle`, `Ellipse`, `Text`, `Line`, `Star`, `Polygon`, `Vector`, `Group`
49
+
48
50
  **Style props:** `width`, `height`, `x`, `y`, `padding`, `paddingTop/Right/Bottom/Left`, `gap`, `flexDirection` (row|column), `justifyContent`, `alignItems`, `backgroundColor`, `borderColor`, `borderWidth`, `borderRadius`, `opacity`, `fontSize`, `fontFamily`, `fontWeight`, `color`, `textAlign`
49
51
 
50
- **Elements:** `Frame`, `Rectangle`, `Ellipse`, `Text`, `Line`, `Star`, `Polygon`, `Vector`, `Group`
52
+ ### Buttons Example (3 sizes)
51
53
 
52
- For reusable components and variants, see `figma-use render --examples`.
54
+ ```bash
55
+ echo '<Frame style={{gap: 16, flexDirection: "row", padding: 24}}>
56
+ <Frame name="Small" style={{paddingLeft: 12, paddingRight: 12, paddingTop: 6, paddingBottom: 6, backgroundColor: "#3B82F6", borderRadius: 6, flexDirection: "row", justifyContent: "center", alignItems: "center"}}>
57
+ <Text style={{fontSize: 12, color: "#FFF"}}>Button</Text>
58
+ </Frame>
59
+ <Frame name="Medium" style={{paddingLeft: 16, paddingRight: 16, paddingTop: 8, paddingBottom: 8, backgroundColor: "#3B82F6", borderRadius: 6, flexDirection: "row", justifyContent: "center", alignItems: "center"}}>
60
+ <Text style={{fontSize: 14, color: "#FFF"}}>Button</Text>
61
+ </Frame>
62
+ <Frame name="Large" style={{paddingLeft: 24, paddingRight: 24, paddingTop: 12, paddingBottom: 12, backgroundColor: "#3B82F6", borderRadius: 6, flexDirection: "row", justifyContent: "center", alignItems: "center"}}>
63
+ <Text style={{fontSize: 16, color: "#FFF"}}>Button</Text>
64
+ </Frame>
65
+ </Frame>' | figma-use render --stdin
66
+ ```
67
+
68
+ ### Advanced: Components & Variants
69
+
70
+ For `defineComponent`, `defineComponentSet`, `defineVars` — use files with imports:
71
+
72
+ ```bash
73
+ figma-use render --examples # Full API reference
74
+ figma-use render ./MyComponent.figma.tsx
75
+ ```
53
76
 
54
77
  ---
55
78
 
package/dist/cli/index.js CHANGED
@@ -22839,16 +22839,49 @@ async function getParentGUID() {
22839
22839
 
22840
22840
  // packages/cli/src/commands/status.ts
22841
22841
  var status_default = defineCommand({
22842
- meta: { description: "Check if plugin is connected" },
22842
+ meta: { description: "Check connection status (plugin, DevTools, multiplayer)" },
22843
22843
  args: { json: { type: "boolean", description: "Output as JSON" } },
22844
22844
  async run({ args }) {
22845
+ const result = {
22846
+ proxy: false,
22847
+ plugin: false,
22848
+ devtools: false,
22849
+ fileKey: null,
22850
+ multiplayer: false
22851
+ };
22845
22852
  try {
22846
22853
  const status = await getStatus();
22847
- console.log(status.pluginConnected ? "\u2713 Plugin connected" : "\u2717 Plugin not connected");
22848
- } catch {
22849
- console.log("\u2717 Proxy not running");
22850
- process.exit(1);
22854
+ result.proxy = true;
22855
+ result.plugin = status.pluginConnected;
22856
+ } catch {}
22857
+ try {
22858
+ result.fileKey = await getFileKey();
22859
+ result.devtools = true;
22860
+ result.multiplayer = true;
22861
+ } catch {}
22862
+ if (args.json) {
22863
+ console.log(JSON.stringify(result, null, 2));
22864
+ return;
22851
22865
  }
22866
+ console.log(result.proxy ? "\u2713 Proxy running" : "\u2717 Proxy not running (run: figma-use proxy)");
22867
+ console.log(result.plugin ? "\u2713 Plugin connected" : "\u2717 Plugin not connected (open plugin in Figma)");
22868
+ console.log(result.devtools ? "\u2713 DevTools available" : "\u2717 DevTools not available (run: figma --remote-debugging-port=9222)");
22869
+ if (result.devtools) {
22870
+ if (result.fileKey) {
22871
+ console.log(`\u2713 Figma file ready (${result.fileKey})`);
22872
+ } else {
22873
+ console.log("\u2717 No Figma file open (open a file from figma.com, not local)");
22874
+ }
22875
+ }
22876
+ if (result.proxy && result.plugin && result.multiplayer) {
22877
+ console.log(`
22878
+ \u2713 Ready for render command`);
22879
+ } else if (result.proxy && result.plugin) {
22880
+ console.log(`
22881
+ \u26A0 CLI commands work, but render requires DevTools + Figma file`);
22882
+ }
22883
+ if (!result.proxy)
22884
+ process.exit(1);
22852
22885
  }
22853
22886
  });
22854
22887
  // packages/cli/src/commands/proxy.ts
@@ -4637,22 +4637,6 @@ var init_prompt = __esm(() => {
4637
4637
  });
4638
4638
 
4639
4639
  // packages/cli/src/multiplayer/protocol.ts
4640
- function parseVarint(data, pos) {
4641
- let value = 0;
4642
- let shift = 0;
4643
- while (pos < data.length) {
4644
- const byte2 = data[pos];
4645
- if (byte2 === undefined)
4646
- break;
4647
- pos++;
4648
- value |= (byte2 & KIWI.VARINT_VALUE_MASK) << shift;
4649
- if (!(byte2 & KIWI.VARINT_CONTINUE_BIT)) {
4650
- break;
4651
- }
4652
- shift += KIWI.VARINT_BITS_PER_BYTE;
4653
- }
4654
- return [value, pos];
4655
- }
4656
4640
  function isKiwiMessage(data) {
4657
4641
  return data.length >= 2 && data[0] === KIWI.MESSAGE_MARKER;
4658
4642
  }
@@ -4684,7 +4668,7 @@ function buildMultiplayerUrl(fileKey, trackingId) {
4684
4668
  });
4685
4669
  return `wss://www.figma.com/api/multiplayer/${fileKey}?${params}`;
4686
4670
  }
4687
- var MESSAGE_TYPES, ZSTD_MAGIC, KIWI, SESSION_ID, FIG_WIRE_MAGIC = "fig-wire", PROTOCOL_VERSION = 151;
4671
+ var MESSAGE_TYPES, ZSTD_MAGIC, KIWI, FIG_WIRE_MAGIC = "fig-wire", PROTOCOL_VERSION = 151;
4688
4672
  var init_protocol = __esm(() => {
4689
4673
  MESSAGE_TYPES = {
4690
4674
  JOIN_START: 0,
@@ -4711,10 +4695,6 @@ var init_protocol = __esm(() => {
4711
4695
  VARINT_VALUE_MASK: 127,
4712
4696
  VARINT_BITS_PER_BYTE: 7
4713
4697
  };
4714
- SESSION_ID = {
4715
- MIN: 1e4,
4716
- MAX: 1e6
4717
- };
4718
4698
  });
4719
4699
 
4720
4700
  // node_modules/kiwi-schema/kiwi-esm.js
@@ -11868,12 +11848,6 @@ class FigmaMultiplayerClient {
11868
11848
  if (!isKiwiMessage(decompressed))
11869
11849
  return;
11870
11850
  const msgType = getKiwiMessageType(decompressed);
11871
- if (msgType === MESSAGE_TYPES.JOIN_START && decompressed[2] === KIWI.SESSION_ID_FIELD) {
11872
- const [val] = parseVarint(decompressed, 3);
11873
- if (val > SESSION_ID.MIN && val < SESSION_ID.MAX) {
11874
- sessionID = val;
11875
- }
11876
- }
11877
11851
  if (msgType === MESSAGE_TYPES.JOIN_END) {
11878
11852
  joinEndReceived = true;
11879
11853
  }
@@ -11890,10 +11864,10 @@ class FigmaMultiplayerClient {
11890
11864
  this.options.onMessage(message);
11891
11865
  } catch {}
11892
11866
  }
11893
- if (sessionID && reconnectSequenceNumber && joinEndReceived && (this.state === "connecting" || this.state === "connected")) {
11867
+ if (joinEndReceived && (this.state === "connecting" || this.state === "connected")) {
11894
11868
  clearTimeout(timeout);
11895
11869
  this.state = "ready";
11896
- this.sessionInfo = { sessionID, reconnectSequenceNumber };
11870
+ this.sessionInfo = { sessionID: sessionID || 0, reconnectSequenceNumber };
11897
11871
  resolve(this.sessionInfo);
11898
11872
  }
11899
11873
  } catch {}
@@ -11967,6 +11941,9 @@ class FigmaMultiplayerClient {
11967
11941
  isReady() {
11968
11942
  return this.state === "ready";
11969
11943
  }
11944
+ isConnected() {
11945
+ return this.state === "connected" && this.ws !== null && this.ws.readyState === WebSocket.OPEN;
11946
+ }
11970
11947
  close() {
11971
11948
  if (this.ws) {
11972
11949
  this.ws.close();
@@ -26821,11 +26798,23 @@ function cleanupIdleConnections() {
26821
26798
  }
26822
26799
  async function getMultiplayerConnection(fileKey) {
26823
26800
  await ensureInitialized();
26801
+ for (const [key, conn] of connectionPool) {
26802
+ if (key !== fileKey) {
26803
+ consola.info(`Closing stale connection to ${key} (switched to ${fileKey})`);
26804
+ conn.client.close();
26805
+ connectionPool.delete(key);
26806
+ }
26807
+ }
26824
26808
  const existing = connectionPool.get(fileKey);
26825
26809
  if (existing) {
26826
- existing.lastUsed = Date.now();
26827
- consola.debug(`Reusing multiplayer connection for ${fileKey}`);
26828
- return { client: existing.client, sessionID: existing.sessionID };
26810
+ if (existing.client.isConnected()) {
26811
+ existing.lastUsed = Date.now();
26812
+ consola.debug(`Reusing multiplayer connection for ${fileKey}`);
26813
+ return { client: existing.client, sessionID: existing.sessionID };
26814
+ } else {
26815
+ consola.warn(`Multiplayer connection to ${fileKey} died, reconnecting...`);
26816
+ connectionPool.delete(fileKey);
26817
+ }
26829
26818
  }
26830
26819
  consola.info(`Creating multiplayer connection for ${fileKey}`);
26831
26820
  const cookies = await getCookiesFromDevTools2();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dannote/figma-use",
3
- "version": "0.5.1",
3
+ "version": "0.5.2",
4
4
  "description": "Control Figma from the command line. Full read/write access for AI agents.",
5
5
  "type": "module",
6
6
  "bin": {