figma-local 1.3.0 → 1.5.0

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/README.md CHANGED
@@ -395,7 +395,7 @@ fig-start --safe --here # launch from your project dir; Claude sees both you
395
395
 
396
396
  ## Claude Code Plugin (Skills)
397
397
 
398
- figma-local ships as a Claude Code plugin with 6 skills that teach coding agents how to use it automatically:
398
+ figma-local ships as a Claude Code plugin with 8 skills that teach coding agents how to use it automatically:
399
399
 
400
400
  | Skill | Triggers on |
401
401
  |-------|------------|
@@ -405,6 +405,8 @@ figma-local ships as a Claude Code plugin with 6 skills that teach coding agents
405
405
  | **figma-styles** | "style guide", "extract colors/fonts", "spacing scale" |
406
406
  | **figma-measure** | "measure spacing", "gap between elements" |
407
407
  | **figma-document** | "document this component", "full spec sheet", "deep breakdown" |
408
+ | **figma-screenshot** | "take a screenshot", "export as PNG/SVG", "capture this" |
409
+ | **figma-compare** | "compare", "does this match", "visual diff", "check against design" |
408
410
 
409
411
  ### Install the skills
410
412
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "figma-local",
3
- "version": "1.3.0",
3
+ "version": "1.5.0",
4
4
  "description": "Control Figma Desktop with Claude Code. Smart read, write, and AI-prompt export. No API key required.",
5
5
  "author": "elvke",
6
6
  "license": "MIT",
@@ -0,0 +1,124 @@
1
+ ---
2
+ name: figma-compare
3
+ description: |
4
+ Use this skill when the user wants to visually compare two things — two Figma elements, a screenshot vs a Figma component, two screenshots, or a design vs coded output. Triggers on: "compare", "diff", "does this match", "check against", "visual comparison", "how close is this", "spot the differences", "compare design to code", "compare these two", "are they the same". Also use when verifying coded UI matches a Figma design. Requires the fig CLI to be connected.
5
+ allowed-tools:
6
+ - Bash(fig compare *)
7
+ - Bash(fig compare)
8
+ - Bash(fig verify *)
9
+ - Bash(fig verify)
10
+ - Bash(fig screenshot *)
11
+ - Bash(fig screenshot)
12
+ - Read
13
+ ---
14
+
15
+ # Figma Compare
16
+
17
+ Visually compare any two sources: Figma selections, node IDs, Figma links, or screenshot files. Outputs both images and a structured gap report template for analysis.
18
+
19
+ ## Prerequisites
20
+
21
+ The `fig` CLI must be connected. Check with `fig daemon status`. If not connected: `fig connect --safe`.
22
+
23
+ ## Usage
24
+
25
+ ### Compare current selection vs a node
26
+
27
+ ```bash
28
+ fig compare --a selection --b "123:456"
29
+ ```
30
+
31
+ ### Compare two screenshot files
32
+
33
+ ```bash
34
+ fig compare --a design.png --b coded-output.png
35
+ ```
36
+
37
+ ### Compare a screenshot file vs a Figma node
38
+
39
+ ```bash
40
+ fig compare --a screenshot.png --b "123:456"
41
+ ```
42
+
43
+ ### Compare two Figma links
44
+
45
+ ```bash
46
+ fig compare --a-link "https://www.figma.com/...?node-id=1-2" --b-link "https://www.figma.com/...?node-id=3-4"
47
+ ```
48
+
49
+ ### Compare selection vs a Figma link
50
+
51
+ ```bash
52
+ fig compare --a selection --b-link "https://www.figma.com/...?node-id=123-456"
53
+ ```
54
+
55
+ ### Compare two nodes by ID
56
+
57
+ ```bash
58
+ fig compare --a "123:456" --b "789:012"
59
+ ```
60
+
61
+ ## Source types
62
+
63
+ The `--a` and `--b` options accept three source types:
64
+
65
+ | Source | Example | Description |
66
+ |--------|---------|-------------|
67
+ | `selection` | `--a selection` | Whatever is currently selected in Figma |
68
+ | Node ID | `--a "123:456"` | A specific Figma node by its ID |
69
+ | File path | `--a design.png` | An existing screenshot/image file on disk |
70
+
71
+ For Figma selection URLs, use `--a-link` / `--b-link` instead.
72
+
73
+ ## Options
74
+
75
+ ```bash
76
+ fig compare --a selection --b "123:456" -s 2 # 2x scale for exports
77
+ fig compare --a selection --b "123:456" --max 3000 # Max dimension 3000px
78
+ fig compare --a selection --b "123:456" --save-dir . # Save images to current dir
79
+ ```
80
+
81
+ ## Output
82
+
83
+ The command exports both sources as PNG images (saved to `/tmp/` by default) and outputs:
84
+
85
+ 1. **File paths** for both images — use `Read` tool to view them
86
+ 2. **Structured JSON** with a gap report template:
87
+ - `matches` — elements that are the same
88
+ - `differences` — table of element, property, value in A, value in B, severity
89
+ - `summary` — overall assessment
90
+
91
+ ## Workflow: Design vs Code Comparison
92
+
93
+ 1. Take a screenshot of the coded output (browser screenshot or `fig screenshot`)
94
+ 2. Get the Figma node ID or link for the original design
95
+ 3. Run compare:
96
+ ```bash
97
+ fig compare --a coded-output.png --b-link "https://www.figma.com/...?node-id=123-456"
98
+ ```
99
+ 4. Read both output images to visually analyze differences
100
+ 5. Use `fig inspect` on the Figma node to get exact specs for fixing differences
101
+
102
+ ## Workflow: Before/After Comparison
103
+
104
+ 1. Screenshot the current state: `fig screenshot --node "123:456" -o before.png`
105
+ 2. Make changes in Figma
106
+ 3. Compare: `fig compare --a before.png --b "123:456"`
107
+
108
+ ## Verify command (simpler alternative)
109
+
110
+ For quick verification of a single element without a full comparison:
111
+
112
+ ```bash
113
+ fig verify # Screenshot selection for AI review
114
+ fig verify --node "123:456" # Verify specific node
115
+ fig verify --link "https://..." # Verify from Figma link
116
+ fig verify --compare "https://..." # Compare against a prototype URL
117
+ ```
118
+
119
+ ## Tips
120
+
121
+ - Use `--save-dir .` to save comparison images in your project directory instead of `/tmp/`
122
+ - For AI-powered analysis, read both output images with the `Read` tool after running compare
123
+ - Combine with `fig inspect --deep` on the Figma source to get exact specs for fixing any differences
124
+ - When comparing design to code, screenshot the browser at the same viewport width as the Figma frame for best results
@@ -0,0 +1,73 @@
1
+ ---
2
+ name: figma-screenshot
3
+ description: |
4
+ Use this skill when the user wants to take a screenshot or export an image from Figma — current selection, a specific node, or from a Figma link. Triggers on: "screenshot", "take a screenshot", "export as PNG", "export as SVG", "capture this", "save as image", "export this frame", "get an image of". Requires the fig CLI to be connected.
5
+ allowed-tools:
6
+ - Bash(fig screenshot *)
7
+ - Bash(fig screenshot)
8
+ ---
9
+
10
+ # Figma Screenshot
11
+
12
+ Export any Figma element as an image (PNG, JPG, SVG, or PDF).
13
+
14
+ ## Prerequisites
15
+
16
+ The `fig` CLI must be connected. Check with `fig daemon status`. If not connected: `fig connect --safe`.
17
+
18
+ ## Usage
19
+
20
+ ### Screenshot current selection
21
+
22
+ The user must select an element in Figma first, then:
23
+
24
+ ```bash
25
+ fig screenshot
26
+ ```
27
+
28
+ Saves to `screenshot.png` in the current directory by default.
29
+
30
+ ### Screenshot from a Figma link
31
+
32
+ ```bash
33
+ fig screenshot --link "https://www.figma.com/design/FILEID/Name?node-id=123-456"
34
+ ```
35
+
36
+ ### Screenshot a specific node by ID
37
+
38
+ ```bash
39
+ fig screenshot --node "123:456"
40
+ ```
41
+
42
+ ### Options
43
+
44
+ ```bash
45
+ fig screenshot -o design.png # Custom output file name
46
+ fig screenshot -s 2 # 2x scale (default is 2)
47
+ fig screenshot -s 4 # 4x scale for high-res
48
+ fig screenshot -f svg # SVG format
49
+ fig screenshot -f jpg # JPG format
50
+ fig screenshot -f pdf # PDF format
51
+ ```
52
+
53
+ ### Combine options
54
+
55
+ ```bash
56
+ fig screenshot --link "https://..." -o hero-section.png -s 3
57
+ fig screenshot --node "123:456" -f svg -o icon.svg
58
+ ```
59
+
60
+ ## Export a specific node by ID (alternative)
61
+
62
+ ```bash
63
+ fig export node "123:456" # PNG at 2x
64
+ fig export node "123:456" -f svg -o out.svg # SVG
65
+ ```
66
+
67
+ ## Tips
68
+
69
+ - Default scale is 2x which gives crisp images on retina displays
70
+ - Use `-s 1` for pixel-accurate exports (1:1 with Figma dimensions)
71
+ - SVG format is best for icons and vector graphics
72
+ - For AI verification of created components, use `fig verify` instead (optimized for smaller file size)
73
+ - Screenshots can be used with `fig compare` to visually diff against other screenshots or Figma nodes
package/src/index.js CHANGED
@@ -8560,14 +8560,14 @@ Examples:
8560
8560
  if (!sel || sel.length === 0) return { error: 'Nothing selected in Figma. Select a frame or layer first.' };
8561
8561
  const node = sel[0];
8562
8562
  function walk(n, depth) {
8563
- if (depth > 4) return { type: n.type, name: n.name, truncated: true };
8563
+ if (depth > 20) return { type: n.type, name: n.name };
8564
8564
  const obj = { type: n.type, name: n.name };
8565
8565
  if (n.width) obj.w = Math.round(n.width);
8566
8566
  if (n.height) obj.h = Math.round(n.height);
8567
- if (n.type === 'TEXT') obj.text = n.characters.slice(0, 100);
8567
+ if (n.type === 'TEXT') obj.text = n.characters;
8568
8568
  if (n.fills && n.fills.length) obj.fills = n.fills.map(f => f.type === 'SOLID' ? { r: Math.round(f.color.r*255), g: Math.round(f.color.g*255), b: Math.round(f.color.b*255) } : { type: f.type });
8569
8569
  if (n.cornerRadius) obj.radius = n.cornerRadius;
8570
- if (n.children) obj.children = n.children.slice(0, 20).map(c => walk(c, depth + 1));
8570
+ if (n.children) obj.children = n.children.map(c => walk(c, depth + 1));
8571
8571
  return obj;
8572
8572
  }
8573
8573
  return { selected: sel.length, node: walk(node, 0) };
@@ -8598,14 +8598,14 @@ Examples:
8598
8598
  const node = figma.getNodeById('${nodeId}');
8599
8599
  if (!node) return { error: 'Node ${nodeId} not found on the current page.' };
8600
8600
  function walk(n, depth) {
8601
- if (depth > 4) return { type: n.type, name: n.name, truncated: true };
8601
+ if (depth > 20) return { type: n.type, name: n.name };
8602
8602
  const obj = { type: n.type, name: n.name };
8603
8603
  if (n.width) obj.w = Math.round(n.width);
8604
8604
  if (n.height) obj.h = Math.round(n.height);
8605
- if (n.type === 'TEXT') obj.text = n.characters.slice(0, 100);
8605
+ if (n.type === 'TEXT') obj.text = n.characters;
8606
8606
  if (n.fills && n.fills.length) obj.fills = n.fills.map(f => f.type === 'SOLID' ? { r: Math.round(f.color.r*255), g: Math.round(f.color.g*255), b: Math.round(f.color.b*255) } : { type: f.type });
8607
8607
  if (n.cornerRadius) obj.radius = n.cornerRadius;
8608
- if (n.children) obj.children = n.children.slice(0, 20).map(c => walk(c, depth + 1));
8608
+ if (n.children) obj.children = n.children.map(c => walk(c, depth + 1));
8609
8609
  return obj;
8610
8610
  }
8611
8611
  return { nodeId: '${nodeId}', node: walk(node, 0) };
@@ -8999,7 +8999,7 @@ const INSPECT_CODE = `(function() {
8999
8999
  // Children summary
9000
9000
  if (node.children && node.children.length > 0) {
9001
9001
  spec.childCount = node.children.length;
9002
- spec.children = node.children.slice(0, 30).map(function(c) {
9002
+ spec.children = node.children.map(function(c) {
9003
9003
  return { name: c.name, type: c.type, w: c.width ? Math.round(c.width) : undefined, h: c.height ? Math.round(c.height) : undefined };
9004
9004
  });
9005
9005
  }
@@ -9007,9 +9007,9 @@ const INSPECT_CODE = `(function() {
9007
9007
  return spec;
9008
9008
  }
9009
9009
 
9010
- // Inspect all selected nodes (up to 10)
9010
+ // Inspect all selected nodes
9011
9011
  var results = [];
9012
- var count = Math.min(sel.length, 10);
9012
+ var count = sel.length;
9013
9013
  for (var i = 0; i < count; i++) {
9014
9014
  results.push(inspectNode(sel[i]));
9015
9015
  }
@@ -9083,7 +9083,7 @@ Examples:
9083
9083
  ${options.node ? `node = figma.getNodeById('${options.node}');` : ''}
9084
9084
  ${options.link ? `node = figma.getNodeById('${parseNodeIdFromLink(options.link)}');` : ''}
9085
9085
  if (!node || !node.children) return [];
9086
- return node.children.slice(0, 30).map(function(c) { return c.id; });
9086
+ return node.children.map(function(c) { return c.id; });
9087
9087
  })()`;
9088
9088
  const childIds = await daemonExec('eval', { code: childIdsCode });
9089
9089
  if (Array.isArray(childIds)) {
@@ -9199,7 +9199,7 @@ function formatInspectSpec(spec) {
9199
9199
  if (t.textAlign) lines.push(` Text align: ${t.textAlign}`);
9200
9200
  if (t.textDecoration) lines.push(` Decoration: ${t.textDecoration}`);
9201
9201
  if (t.textTransform) lines.push(` Transform: ${t.textTransform}`);
9202
- if (t.content) lines.push(` Content: "${t.content.slice(0, 80)}${t.content.length > 80 ? '...' : ''}"`);
9202
+ if (t.content) lines.push(` Content: "${t.content}"`);
9203
9203
  }
9204
9204
 
9205
9205
  // Effects
@@ -9530,7 +9530,7 @@ function formatCSS(node) {
9530
9530
  }
9531
9531
  lines.push('}');
9532
9532
  if (node.text) {
9533
- lines.push(chalk.gray(`/* Content: "${node.text.slice(0, 60)}${node.text.length > 60 ? '...' : ''}" */`));
9533
+ lines.push(chalk.gray(`/* Content: "${node.text}" */`));
9534
9534
  }
9535
9535
  return lines.join('\n');
9536
9536
  }
@@ -9610,7 +9610,7 @@ function formatTailwind(node) {
9610
9610
  const lines = [];
9611
9611
  lines.push(chalk.gray(`{/* ${node.name} */}`));
9612
9612
  lines.push(`className="${classes.join(' ')}"`);
9613
- if (node.text) lines.push(chalk.gray(`{/* "${node.text.slice(0, 60)}${node.text.length > 60 ? '...' : ''}" */}`));
9613
+ if (node.text) lines.push(chalk.gray(`{/* "${node.text}" */}`));
9614
9614
  return lines.join('\n');
9615
9615
  }
9616
9616
 
@@ -9889,7 +9889,7 @@ const DOCUMENT_CODE = `(function() {
9889
9889
  }
9890
9890
 
9891
9891
  function extractNode(node, depth) {
9892
- if (depth > 15) return null;
9892
+ if (depth > 30) return null;
9893
9893
  var n = { name: node.name, type: node.type };
9894
9894
 
9895
9895
  // Dimensions