Figma plugin

Find the drift.
Fix it in place.

Select anything on the canvas and find out, layer by layer, what is using your design system and what quietly is not, then fix it without leaving the panel.

The Score tab showing an overall percentage and a per-check breakdown

What it does

The plugin walks everything inside your selection, including every level of nested component, and asks four questions of each layer:

Colour

Is every fill and stroke a token from a library you listed, including each gradient stop?

Dimension

Are corner radii, gaps and padding bound to numeric tokens?

Typography

Is the text on a library text style, at the right size and line height?

Component

Is the instance current, from a listed library, and still published?

Everything it finds is grouped, counted, scored, and, where possible, fixable in one click.

What makes it different

It reads the deepest nested component

Most audits stop at the top layer. This one descends through instances inside instances inside instances, verified to sixty levels, and knows which component each layer actually came from, so a colour inherited from a library component is labelled as such instead of being blamed on you.

It tells you where a value came from

Under every row is the library the value belongs to. Hover it and it says whether the value was changed on this instance or comes straight from the component. Both count, but they mean different things when you decide what to do.

Gradients are judged stop by stop

A gradient is not one colour. Each stop is checked on its own and tagged Grad 1, Grad 2, so one bound stop cannot vouch for the rest. Applying a paint style replaces the whole fill and answers every stop at once; binding a variable touches only the stop carrying that colour.

Text coloured run by run is handled properly

A text layer with three colours in it is reported once per colour, with the run quoted on the right. Applying a token binds only the runs carrying that colour and leaves the others alone.

The picker only offers what fits

A corner radius is offered radius tokens. A gap is offered spacing tokens. Radius, gap, padding and font size are all plain numbers to Figma, so without this filter a 10 px font-size token wins a 10 px corner on raw distance.

Pro tip The Closest match section always lists exactly one token. If nothing is close enough the field reads Choose a token… and stays disabled: the plugin will not pretend a far-off colour is a suggestion.

Install and first run

  1. Find it in the Community. Search Design System Scanner in Figma Community, or open Resources Plugins from the toolbar and search there. Press Run.
  2. Afterwards, from any file. Right-click the canvas Plugins, and it will be in your recently used list.
  3. Check the Library list. On first run every library enabled on the file is already listed with all four checks ticked. Untick anything that is not a valid source, and remove what you do not use.
  4. Add a Figma token if you want components and styles traced back to the library they came from. Optional. See The Figma token.
  5. Select a frame and press Scan.
What it needs Edit access to the file you are scanning. Figma does not let anyone run a plugin on a file they can only view, so this is Figma's rule rather than the scanner's. There is no view-only mode to fall back to.
Libraries are different You do not need edit access to any library. They only need to be enabled on the file so their tokens can be read, and, if you add a Figma token, visible to that token so their names can be traced. Applying a fix imports the token or component into the file you are scanning; nothing is ever written back to a library.

Where your setup lives

Libraries, ignore rules and dismissals are stored with the file, so a teammate opening it sees the same setup and the same score. Your Figma token is the exception: it lives on your machine only and never travels with the file or with a preset.

Pro tip Setting up a second file? The save icon in the footer copies your whole setup as a preset: libraries, ignore rules, tolerance. Paste it into the new file and you are done. It never carries your token.
Note The plugin only ever looks at your selection. Nothing selected means nothing to scan. It will say so rather than quietly scanning the page.

Settings

The list of libraries that count as on-system. A token from a library that is not on this list is flagged, even though it is a perfectly real token. That is the point of the list.

Each row has four checks. Untick Colour on a library that is only an icon set, and its colours stop counting as a valid source while its components still do.

The Library tab listing four libraries with their ticked checks
Every library on the file, with the checks it is a valid source for. Press − to remove one.
Careful Library names match exactly here. [BETA] Core Library and Core Library are two different libraries, and ticking one does not approve the other. Ignore rules are the opposite. Those match on part of a name on purpose.

local (this file) means variables and components made in this file rather than in a library. Tick it if that is legitimate for your work; leave it off and everything local gets flagged.

The Figma token

Only needed so components and styles can be traced to the library they came from: the plugin API does not expose that, so it is fetched over Figma's REST API instead.

The simplest scope that works is files:read. It covers every call the plugin makes. If you would rather scope it narrowly you need library_assets:read, file_metadata:read and library_content:read together.

Careful A personal access token grants access to every file your account can open. Figma provides no way to narrow it. This plugin stores it on your machine only, never in the file and never in a preset, but treat the token itself as a password: do not paste it into shared documents or tickets.

Without a token the plugin still works. It simply cannot name libraries, so anything it cannot trace is counted as on-system rather than guessed at, and the warning line tells you how many.

Running a scan

Select something and press Scan. The footer reports progress as it reads variables, styles and layers. The result opens on Score.

The button readsMeaning
ScanNothing to apply on this tab. Press it to scan again
Apply NN layers on this tab can be fixed at once
Update NSame, on the Component tab
Scanning…In progress; the quieter Scan beside it disappears while it runs
Pro tip Scanning a large selection with many distinct components is slower, because each component costs one network lookup to trace. The results are cached: the refresh icon clears that cache if a library has changed since.

Reading the result

Five tabs. Component comes first because a stale or missing component is a bigger problem than one raw colour.

One percentage: compliant layers over checked layers. Underneath, the same figure per check, then exactly what the scan ran with: the libraries, the ignore rules and anything dismissed.

Score tab
Everything the number was built from, on one screen.

Copy result puts the whole thing on the clipboard as a markdown table, ready to paste into a ticket. Add to canvas draws it as a frame next to your work.

Pro tip The denominator never moves when you fix something, applying a fix moves a layer from failing to passing, it does not remove it from what was measured. That makes two scans of the same selection comparable.

Fixing things

The token picker open, showing one closest match, the rest of the library, and Remove the fill
The picker: exactly one closest match, then every other token grouped by library and collection, then Remove.
ControlDoesEffect on the score
ApplyBinds the chosen token on those layersThey move from failing to passing
UpdateSwaps the instance to the published versionPasses, then the tab re-scans
DismissRecords the finding as accepted, with a reasonCounts as on-system from now on
Remove in pickerStrips the value instead of tokenising itPasses. There is nothing left to judge

Remove, and when to reach for it

At the bottom of every colour and dimension picker is Remove the fill / Remove the stroke / Remove (set to 0). It is offered even when no token was close enough to suggest, which is usually exactly when you want it. A stray stroke nobody meant to add does not need a token; it needs deleting.

Note Typography and components have no Remove. There is no meaningful empty state for either.

Updating a component re-scans

The new version of a component brings its own colours, dimensions and type. So when the last update in a batch lands, the plugin scans the same layers again and the other tabs catch up: rows the new version fixed disappear, rows it broke appear, the rest stay.

Pro tip It re-scans the roots of the original scan, not whatever you have selected by then, so you can click away while it works. One scan per batch, not one per row.

Dismissing

Dismissal is a judgement you are recording, so it is written down: the row is listed on the Score tab with a reason field, it counts as on-system, and it stays dismissed across scans until you press to put it back. The reason travels with the copied result.

Fixing outside the plugin

You do not have to use the picker. Fix a layer with Figma's own right-hand panel, apply a library variable or style, and the plugin re-checks that one layer and clears its row, with a line saying how many were fixed on canvas.

Careful This is a convenience, not a guarantee. Figma does not report every change: never when an instance sublayer moves because its main component changed, and never when a style itself is edited. It also only ever removes rows: breaking something while the panel is open will not add one. Scan remains the source of truth.

Always on

Rules that need no setting and cannot be turned off:

  • Hidden layers are skipped, with everything inside them
  • Sections are skipped: a section fill is canvas labelling, not design
  • Stroke weight is never checked
  • Corner radius is judged per corner; mixed corners are expected
  • Mixed fonts or sizes in one layer are a failure with no suggestion
  • A value inherited from a library component still counts, but the row says so on hover
  • Colours are ordered by name so a family stays together: shape-danger-soft beside shape-danger-solid, and grey-2 before grey-10
  • Dimensions and type run smallest value to largest inside each group
  • A name too long for its row hands the whole thing over on hover

Troubleshooting

“N component(s) could not be read”

Figma would not say which component an instance came from. Everything inside it loses its library, so a Library ignore rule cannot reach it. The warning names the components. Either give the token access to that library, reopen the file to reload it, or use a Component ignore rule, which matches on name and needs no library.

“N item(s) could not be traced to a library”

Usually a missing or under-scoped token. Those items are counted as on-system rather than guessed at, so the score is not punished for the plugin's blind spot.

“N librar(ies) could not be named”

The token lacks file_metadata:read (or files:read). Libraries show as raw file keys until it does.

A token I know exists is not in the picker

Check the Library tab: the library has to be listed and ticked for that check. Exact name match. If it is a text or colour style rather than a variable, the plugin needs the token. Figma has no API to list a library's styles.

Figma still offers the update after I updated in the plugin

Expected. Figma's Library Updates panel tracks your file's subscription to a library version; the plugin re-points individual instances. There is no plugin API to accept a library update. Figma.teamLibrary exposes variables and nothing else. Accepting in Figma afterwards is harmless.

Every pro tip in one place

  • Ticking a check on [BETA] Library does not approve Library. Exact names.
  • A Component ignore rule is the only one that works when the library cannot be identified.
  • Choose a token… with a disabled arrow means nothing was close enough. That is information, not a bug.
  • Remove is usually the right answer for a value that should never have been there.
  • The refresh icon clears cached library lookups after a library changes.
  • Click any row to select those layers on the canvas.
  • Hover a truncated name, a library line, or a Grad tag for the full text.
  • Presets carry your whole setup and never your token.
  • The denominator never moves, so two scans of the same selection are comparable.
Design System Scanner for Figma · user guide · generated from the shipped panel, screenshots included