figma-local 1.6.0 → 1.8.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 +2 -1
- package/package.json +1 -1
- package/plugin/manifest.json +1 -0
- package/skills/figma-library/SKILL.md +153 -0
- package/src/index.js +224 -0
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
|
|
398
|
+
figma-local ships as a Claude Code plugin with 9 skills that teach coding agents how to use it automatically:
|
|
399
399
|
|
|
400
400
|
| Skill | Triggers on |
|
|
401
401
|
|-------|------------|
|
|
@@ -407,6 +407,7 @@ figma-local ships as a Claude Code plugin with 8 skills that teach coding agents
|
|
|
407
407
|
| **figma-document** | "document this component", "full spec sheet", "deep breakdown" |
|
|
408
408
|
| **figma-screenshot** | "take a screenshot", "export as PNG/SVG", "capture this" |
|
|
409
409
|
| **figma-compare** | "compare", "does this match", "visual diff", "check against design" |
|
|
410
|
+
| **figma-library** | "library components", "import from library", "team library variables" |
|
|
410
411
|
|
|
411
412
|
### Install the skills
|
|
412
413
|
|
package/package.json
CHANGED
package/plugin/manifest.json
CHANGED
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: figma-library
|
|
3
|
+
description: |
|
|
4
|
+
Use this skill when the user wants to access, browse, import, or use components and variables from a Figma team library or external Figma file. Triggers on: "library components", "import component", "library variables", "team library", "use components from another file", "get the button from the library", "what components are available", "design system components", "import from library", "library collections". Also use when building UI and the user references a design system or component library in another Figma file.
|
|
5
|
+
allowed-tools:
|
|
6
|
+
- Bash(fig library *)
|
|
7
|
+
- Bash(fig library)
|
|
8
|
+
- Bash(fig inspect *)
|
|
9
|
+
- Bash(fig read *)
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# Figma Library
|
|
13
|
+
|
|
14
|
+
Access team library components and variables from other Figma files. Import components by key and browse available design tokens.
|
|
15
|
+
|
|
16
|
+
## Prerequisites
|
|
17
|
+
|
|
18
|
+
- The `fig` CLI must be connected: `fig daemon status`. If not: `fig connect --safe`.
|
|
19
|
+
- The Figma plugin must have `teamlibrary` permission in its manifest. If library commands fail with a permission error, re-import the plugin in Figma (Plugins → Development → Import from manifest).
|
|
20
|
+
- Libraries must be enabled in the current Figma file (check Assets panel → team library icon).
|
|
21
|
+
|
|
22
|
+
## Usage
|
|
23
|
+
|
|
24
|
+
### List library variable collections
|
|
25
|
+
|
|
26
|
+
See what variable collections are available from linked libraries:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
fig library collections
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Returns: collection name, library name, and collection key for each.
|
|
33
|
+
|
|
34
|
+
### List library variables
|
|
35
|
+
|
|
36
|
+
Browse all variables across all linked library collections:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
fig library variables
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Filter by name:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
fig library variables --name "color"
|
|
46
|
+
fig library variables --name "spacing"
|
|
47
|
+
fig library variables --name "radius"
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Returns: variable name, type (COLOR, FLOAT, STRING), key, collection, and library name.
|
|
51
|
+
|
|
52
|
+
### List library components
|
|
53
|
+
|
|
54
|
+
Find library components that are already used on the current page:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
fig library components
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Filter by name:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
fig library components --name "button"
|
|
64
|
+
fig library components --name "input"
|
|
65
|
+
fig library components --name "card"
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Returns: component name, component set, key, description, and whether it's remote (library) or local.
|
|
69
|
+
|
|
70
|
+
### Import a component by key
|
|
71
|
+
|
|
72
|
+
Import a library component onto the canvas by its key:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
fig library import --key "abc123def456..."
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Import and rename:
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
fig library import --key "abc123def456..." --name "PrimaryButton"
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
The imported component instance is placed at the viewport center and selected.
|
|
85
|
+
|
|
86
|
+
### JSON output
|
|
87
|
+
|
|
88
|
+
All commands support `--json` for structured output:
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
fig library collections --json
|
|
92
|
+
fig library variables --json
|
|
93
|
+
fig library variables --name "color" --json
|
|
94
|
+
fig library components --json
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Workflow: Building with library components
|
|
98
|
+
|
|
99
|
+
1. **Discover** what's available:
|
|
100
|
+
```bash
|
|
101
|
+
fig library collections
|
|
102
|
+
fig library variables --name "color"
|
|
103
|
+
fig library components --name "button"
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
2. **Import** the components you need:
|
|
107
|
+
```bash
|
|
108
|
+
fig library import --key "<key-from-step-1>"
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
3. **Inspect** the imported component to get its specs:
|
|
112
|
+
```bash
|
|
113
|
+
fig inspect --deep
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
4. **Read** variables to get token values:
|
|
117
|
+
```bash
|
|
118
|
+
fig library variables --name "primary" --json
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
5. **Replicate** in code using the exact specs and token values.
|
|
122
|
+
|
|
123
|
+
## Workflow: Extracting a design system
|
|
124
|
+
|
|
125
|
+
1. List all variable collections:
|
|
126
|
+
```bash
|
|
127
|
+
fig library collections --json
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
2. Export all variables grouped by type:
|
|
131
|
+
```bash
|
|
132
|
+
fig library variables --name "color" --json > colors.json
|
|
133
|
+
fig library variables --name "spacing" --json > spacing.json
|
|
134
|
+
fig library variables --name "radius" --json > radii.json
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
3. Find key components:
|
|
138
|
+
```bash
|
|
139
|
+
fig library components --json
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
4. Import and document each:
|
|
143
|
+
```bash
|
|
144
|
+
fig library import --key "<key>"
|
|
145
|
+
fig document --json
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## Tips
|
|
149
|
+
|
|
150
|
+
- If `fig library components` returns empty, drag some components from the Assets panel onto the page first — the command scans instances on the current page.
|
|
151
|
+
- Use `fig library variables --json` and pipe to `jq` for filtering: `fig library variables --json | jq '.[] | select(.resolvedType == "COLOR")'`
|
|
152
|
+
- After importing a component, use `fig inspect --deep` to get full specs including variable bindings.
|
|
153
|
+
- Component keys are stable across file versions — save them for repeated imports.
|
package/src/index.js
CHANGED
|
@@ -10573,4 +10573,228 @@ program
|
|
|
10573
10573
|
}
|
|
10574
10574
|
});
|
|
10575
10575
|
|
|
10576
|
+
// ============ LIBRARY — access team library components & variables ============
|
|
10577
|
+
|
|
10578
|
+
program
|
|
10579
|
+
.command('library <action>')
|
|
10580
|
+
.description('Access team library components and variables from other Figma files')
|
|
10581
|
+
.option('--key <key>', 'Component key for importing')
|
|
10582
|
+
.option('--name <name>', 'Filter by name (partial match)')
|
|
10583
|
+
.option('--json', 'Output raw JSON')
|
|
10584
|
+
.addHelpText('after', `
|
|
10585
|
+
Actions:
|
|
10586
|
+
collections List all available library variable collections
|
|
10587
|
+
variables List variables from a library collection (use --name to filter)
|
|
10588
|
+
components List available library components (use --name to filter)
|
|
10589
|
+
import Import a component by key (use --key)
|
|
10590
|
+
|
|
10591
|
+
Examples:
|
|
10592
|
+
fig library collections List all library variable collections
|
|
10593
|
+
fig library variables List all library variables
|
|
10594
|
+
fig library variables --name "color" List variables matching "color"
|
|
10595
|
+
fig library components List available library components
|
|
10596
|
+
fig library components --name "button" Find button components
|
|
10597
|
+
fig library import --key "abc123..." Import a component by its key
|
|
10598
|
+
fig library import --key "abc123..." --name "MyButton" Import and rename
|
|
10599
|
+
`)
|
|
10600
|
+
.action(async (action, options) => {
|
|
10601
|
+
checkConnection();
|
|
10602
|
+
const spinner = ora('Accessing library...').start();
|
|
10603
|
+
|
|
10604
|
+
try {
|
|
10605
|
+
if (action === 'collections') {
|
|
10606
|
+
spinner.text = 'Fetching library variable collections...';
|
|
10607
|
+
const code = `(async function() {
|
|
10608
|
+
try {
|
|
10609
|
+
var cols = await figma.teamLibrary.getAvailableLibraryVariableCollectionsAsync();
|
|
10610
|
+
return cols.map(function(c) {
|
|
10611
|
+
return { name: c.name, key: c.key, libraryName: c.libraryName };
|
|
10612
|
+
});
|
|
10613
|
+
} catch(e) {
|
|
10614
|
+
return { error: e.message || 'Failed to fetch library collections. Make sure teamlibrary permission is enabled.' };
|
|
10615
|
+
}
|
|
10616
|
+
})()`;
|
|
10617
|
+
const result = await daemonExec('eval', { code });
|
|
10618
|
+
if (result.error) {
|
|
10619
|
+
spinner.fail(result.error);
|
|
10620
|
+
process.exit(1);
|
|
10621
|
+
}
|
|
10622
|
+
spinner.succeed(`Found ${result.length} library variable collection${result.length !== 1 ? 's' : ''}`);
|
|
10623
|
+
if (options.json) {
|
|
10624
|
+
console.log(JSON.stringify(result, null, 2));
|
|
10625
|
+
} else {
|
|
10626
|
+
if (result.length === 0) {
|
|
10627
|
+
console.log(chalk.yellow('No library variable collections found. Make sure you have libraries enabled in this file.'));
|
|
10628
|
+
}
|
|
10629
|
+
for (const col of result) {
|
|
10630
|
+
console.log(` ${chalk.cyan(col.name)} ${chalk.gray('from')} ${chalk.white(col.libraryName)}`);
|
|
10631
|
+
console.log(` ${chalk.gray('key:')} ${col.key}`);
|
|
10632
|
+
}
|
|
10633
|
+
}
|
|
10634
|
+
} else if (action === 'variables') {
|
|
10635
|
+
spinner.text = 'Fetching library variables...';
|
|
10636
|
+
const nameFilter = options.name ? options.name.toLowerCase() : '';
|
|
10637
|
+
const code = `(async function() {
|
|
10638
|
+
try {
|
|
10639
|
+
var cols = await figma.teamLibrary.getAvailableLibraryVariableCollectionsAsync();
|
|
10640
|
+
var allVars = [];
|
|
10641
|
+
for (var i = 0; i < cols.length; i++) {
|
|
10642
|
+
try {
|
|
10643
|
+
var vars = await figma.teamLibrary.getVariablesInLibraryCollectionAsync(cols[i].key);
|
|
10644
|
+
for (var j = 0; j < vars.length; j++) {
|
|
10645
|
+
allVars.push({
|
|
10646
|
+
name: vars[j].name,
|
|
10647
|
+
key: vars[j].key,
|
|
10648
|
+
resolvedType: vars[j].resolvedType,
|
|
10649
|
+
collection: cols[i].name,
|
|
10650
|
+
library: cols[i].libraryName
|
|
10651
|
+
});
|
|
10652
|
+
}
|
|
10653
|
+
} catch(e2) {}
|
|
10654
|
+
}
|
|
10655
|
+
${nameFilter ? `allVars = allVars.filter(function(v) { return v.name.toLowerCase().indexOf('${nameFilter}') !== -1; });` : ''}
|
|
10656
|
+
return allVars;
|
|
10657
|
+
} catch(e) {
|
|
10658
|
+
return { error: e.message || 'Failed to fetch library variables.' };
|
|
10659
|
+
}
|
|
10660
|
+
})()`;
|
|
10661
|
+
const result = await daemonExec('eval', { code });
|
|
10662
|
+
if (result.error) {
|
|
10663
|
+
spinner.fail(result.error);
|
|
10664
|
+
process.exit(1);
|
|
10665
|
+
}
|
|
10666
|
+
spinner.succeed(`Found ${result.length} library variable${result.length !== 1 ? 's' : ''}`);
|
|
10667
|
+
if (options.json) {
|
|
10668
|
+
console.log(JSON.stringify(result, null, 2));
|
|
10669
|
+
} else {
|
|
10670
|
+
if (result.length === 0) {
|
|
10671
|
+
console.log(chalk.yellow('No variables found.' + (nameFilter ? ` Try a different search term.` : '')));
|
|
10672
|
+
}
|
|
10673
|
+
let currentCollection = '';
|
|
10674
|
+
for (const v of result) {
|
|
10675
|
+
const collLabel = `${v.collection} (${v.library})`;
|
|
10676
|
+
if (collLabel !== currentCollection) {
|
|
10677
|
+
currentCollection = collLabel;
|
|
10678
|
+
console.log(chalk.cyan(`\n ${collLabel}`));
|
|
10679
|
+
}
|
|
10680
|
+
console.log(` ${chalk.white(v.name)} ${chalk.gray(`[${v.resolvedType}]`)} ${chalk.gray('key:')} ${v.key}`);
|
|
10681
|
+
}
|
|
10682
|
+
}
|
|
10683
|
+
} else if (action === 'components') {
|
|
10684
|
+
spinner.text = 'Fetching library components...';
|
|
10685
|
+
const nameFilter = options.name ? options.name.toLowerCase() : '';
|
|
10686
|
+
const code = `(async function() {
|
|
10687
|
+
try {
|
|
10688
|
+
var collections = await figma.teamLibrary.getAvailableLibraryVariableCollectionsAsync();
|
|
10689
|
+
var libraryNames = collections.map(function(c) { return c.libraryName; });
|
|
10690
|
+
} catch(e) { var libraryNames = []; }
|
|
10691
|
+
try {
|
|
10692
|
+
// Get components from the assets panel search
|
|
10693
|
+
var components = [];
|
|
10694
|
+
// Try to find components by listing component sets and instances on the current page
|
|
10695
|
+
function findComponents(node) {
|
|
10696
|
+
if (node.type === 'INSTANCE' && node.mainComponent) {
|
|
10697
|
+
try {
|
|
10698
|
+
var mc = node.mainComponent;
|
|
10699
|
+
var parent = mc.parent;
|
|
10700
|
+
components.push({
|
|
10701
|
+
name: mc.name,
|
|
10702
|
+
key: mc.key,
|
|
10703
|
+
componentSetName: parent && parent.type === 'COMPONENT_SET' ? parent.name : null,
|
|
10704
|
+
description: mc.description || '',
|
|
10705
|
+
remote: mc.remote
|
|
10706
|
+
});
|
|
10707
|
+
} catch(e) {}
|
|
10708
|
+
}
|
|
10709
|
+
if ('children' in node) {
|
|
10710
|
+
for (var i = 0; i < node.children.length; i++) {
|
|
10711
|
+
findComponents(node.children[i]);
|
|
10712
|
+
}
|
|
10713
|
+
}
|
|
10714
|
+
}
|
|
10715
|
+
findComponents(figma.currentPage);
|
|
10716
|
+
// Deduplicate by key
|
|
10717
|
+
var seen = {};
|
|
10718
|
+
var unique = [];
|
|
10719
|
+
for (var i = 0; i < components.length; i++) {
|
|
10720
|
+
if (!seen[components[i].key]) {
|
|
10721
|
+
seen[components[i].key] = true;
|
|
10722
|
+
unique.push(components[i]);
|
|
10723
|
+
}
|
|
10724
|
+
}
|
|
10725
|
+
${nameFilter ? `unique = unique.filter(function(c) { return c.name.toLowerCase().indexOf('${nameFilter}') !== -1 || (c.componentSetName && c.componentSetName.toLowerCase().indexOf('${nameFilter}') !== -1); });` : ''}
|
|
10726
|
+
return { components: unique, note: unique.length === 0 ? 'No library components found on this page. Drag some components from the Assets panel first, or use fig library import --key <key> if you have the component key.' : null };
|
|
10727
|
+
} catch(e) {
|
|
10728
|
+
return { error: e.message || 'Failed to fetch library components.' };
|
|
10729
|
+
}
|
|
10730
|
+
})()`;
|
|
10731
|
+
const result = await daemonExec('eval', { code });
|
|
10732
|
+
if (result.error) {
|
|
10733
|
+
spinner.fail(result.error);
|
|
10734
|
+
process.exit(1);
|
|
10735
|
+
}
|
|
10736
|
+
const comps = result.components || [];
|
|
10737
|
+
spinner.succeed(`Found ${comps.length} component${comps.length !== 1 ? 's' : ''} on this page`);
|
|
10738
|
+
if (options.json) {
|
|
10739
|
+
console.log(JSON.stringify(result, null, 2));
|
|
10740
|
+
} else {
|
|
10741
|
+
if (result.note) {
|
|
10742
|
+
console.log(chalk.yellow(` ${result.note}`));
|
|
10743
|
+
}
|
|
10744
|
+
for (const c of comps) {
|
|
10745
|
+
const setLabel = c.componentSetName ? chalk.gray(` (set: ${c.componentSetName})`) : '';
|
|
10746
|
+
const remoteLabel = c.remote ? chalk.blue(' [library]') : chalk.gray(' [local]');
|
|
10747
|
+
console.log(` ${chalk.white(c.name)}${setLabel}${remoteLabel}`);
|
|
10748
|
+
console.log(` ${chalk.gray('key:')} ${c.key}`);
|
|
10749
|
+
if (c.description) console.log(` ${chalk.gray('desc:')} ${c.description}`);
|
|
10750
|
+
}
|
|
10751
|
+
}
|
|
10752
|
+
} else if (action === 'import') {
|
|
10753
|
+
if (!options.key) {
|
|
10754
|
+
spinner.fail('--key is required. Get the key from: fig library components, or fig library variables');
|
|
10755
|
+
process.exit(1);
|
|
10756
|
+
}
|
|
10757
|
+
spinner.text = `Importing component ${options.key}...`;
|
|
10758
|
+
const importName = options.name || '';
|
|
10759
|
+
const code = `(async function() {
|
|
10760
|
+
try {
|
|
10761
|
+
var component = await figma.importComponentByKeyAsync('${options.key}');
|
|
10762
|
+
if (!component) return { error: 'Component not found for key: ${options.key}' };
|
|
10763
|
+
// Create an instance
|
|
10764
|
+
var instance = component.createInstance();
|
|
10765
|
+
// Place it in the center of the viewport
|
|
10766
|
+
var vp = figma.viewport.center;
|
|
10767
|
+
instance.x = Math.round(vp.x);
|
|
10768
|
+
instance.y = Math.round(vp.y);
|
|
10769
|
+
${importName ? `instance.name = '${importName}';` : ''}
|
|
10770
|
+
figma.currentPage.selection = [instance];
|
|
10771
|
+
return {
|
|
10772
|
+
name: instance.name,
|
|
10773
|
+
id: instance.id,
|
|
10774
|
+
componentName: component.name,
|
|
10775
|
+
w: Math.round(instance.width),
|
|
10776
|
+
h: Math.round(instance.height)
|
|
10777
|
+
};
|
|
10778
|
+
} catch(e) {
|
|
10779
|
+
return { error: e.message || 'Failed to import component. Check the key is valid.' };
|
|
10780
|
+
}
|
|
10781
|
+
})()`;
|
|
10782
|
+
const result = await daemonExec('eval', { code });
|
|
10783
|
+
if (result.error) {
|
|
10784
|
+
spinner.fail(result.error);
|
|
10785
|
+
process.exit(1);
|
|
10786
|
+
}
|
|
10787
|
+
spinner.succeed(`Imported "${result.componentName}" as ${result.name} (${result.w}x${result.h})`);
|
|
10788
|
+
console.log(` ${chalk.gray('id:')} ${result.id}`);
|
|
10789
|
+
console.log(chalk.gray(' Component is now selected on the canvas.'));
|
|
10790
|
+
} else {
|
|
10791
|
+
spinner.fail(`Unknown action: ${action}. Use: collections, variables, components, import`);
|
|
10792
|
+
process.exit(1);
|
|
10793
|
+
}
|
|
10794
|
+
} catch (e) {
|
|
10795
|
+
spinner.fail(`Library access failed: ${e.message}`);
|
|
10796
|
+
process.exit(1);
|
|
10797
|
+
}
|
|
10798
|
+
});
|
|
10799
|
+
|
|
10576
10800
|
program.parse();
|