Figma Typings Audit logo

Figma Typings Audit

CommunityPopular
awdr74100
figma-typings-audit

Upgrade @figma/plugin-typings and absorb what the new version exposes. Diffs the .d.ts between the installed and the target version (that package ships no changelog), sorts the changes into breakage / new API / silently-added fields, maps each onto the sandbox handlers, the hand-written Zod mirrors in shared, and the tool registry — then bumps the package and builds whatever the user picks. Use whenever the user wants @figma/plugin-typings updated or audited, or asks what a new plugin-typings version would break or newly enable — including a Renovate bump PR for that package.

Overview

Publisherawdr74100
Repositoryfigwright
Skill namefigma-typings-audit
Stars
1.2K
Forks
67
Bundled files
Instructions only
LicenseMIT
Links
  • Markdown instructions

    A SKILL.md file the model loads on demand, so it only costs tokens when a request actually matches.

  • Works with any LLM

    AI skills are plain Markdown, not provider-specific code, so this works with GPT, Claude, Gemini, Grok, or a local model.

  • Self-contained

    Everything the model needs lives in the instructions — no extra files to sync.

  • Open source

    Published by awdr74100 on GitHub. Read the source before you install it.

Installation

Install the Figma Typings Audit AI skill in TypingMind to use it with any LLM, or drop it into another agent that reads SKILL.md.

1

Install in TypingMind

TypingMind installs a skill straight from its GitHub folder — it reads SKILL.md, bundles the resource files, and stores the result locally.

  1. Open the app and go to Plugins → Skills.
  2. Choose "Install from GitHub".
  3. Paste the skill folder URL below and confirm.
    https://github.com/awdr74100/figwright/tree/main/.claude/skills/figma-typings-audit
  4. Enable the skill in any chat where you want it available.
Plugins → Skills → Add skill → From GitHub URL, then paste the folder URL and press Continue.
2

Install in another agent

Any agent that reads the Agent Skills format can use this skill — copy the folder into that agent's skills directory.

Claude Code — .claude/skills
git clone --depth 1 https://github.com/awdr74100/figwright.git /tmp/figwright
mkdir -p .claude/skills
cp -r /tmp/figwright/.claude/skills/figma-typings-audit .claude/skills/figma-typings-audit
Restart Claude Code after copying so it picks up the new skill.

Use it in TypingMind

Enable Figma Typings Audit in any TypingMind chat and the model takes it from there. Its name and description sit in the system prompt, and the moment a request matches, the model loads the full instructions itself — you never invoke it by hand, and it costs no tokens until it is actually used.

The model loads Figma Typings Audit on its own as soon as a request matches it.

Works with any AI model

AI skills are plain Markdown instructions rather than provider-specific code, so Figma Typings Audit is not tied to the model it was written for. Install it once in TypingMind and use it with GPT-5, Claude, Gemini, Grok, DeepSeek, Mistral, Llama, or a local model you run yourself — all on your own API keys.

  • Loaded only when it is needed

    The system prompt carries just the name and description. The instructions are fetched on the first matching request, so an idle skill costs nothing.

  • Switch models mid-chat

    Because the skill is instructions rather than code, changing model does not break it — the next model reads the same SKILL.md.

Skill instructions

This is the SKILL.md content the model loads. Read it before installing — a skill is instructions your model will follow.

Absorbing a @figma/plugin-typings release into Figwright, end to end: audit → upgrade → implement what's worth having.

One hard ordering constraint: diff before upgrading. The audit compares the installed version against the target, so upgrading first destroys the baseline. (Recoverable — the old version is in git history and npm pack can still fetch it — but don't create the problem.)

Target version: whatever the user named, otherwise the latest on npm.

Stage 0 — Resolve versions

bash
grep '@figma/plugin-typings' packages/plugin/package.json          # the declared range
grep '"version"' packages/plugin/node_modules/@figma/plugin-typings/package.json  # what is installed
npm view @figma/plugin-typings version                              # latest
npm view @figma/plugin-typings versions --json                      # how many releases are being skipped

Compare against the installed version, not the declared range — a caret range can already be satisfied by something newer than what the lockfile pinned.

If installed and target are equal, say so and stop. Don't spend tokens on the rest.

Stage 1 — Get the authoritative diff

There is no other source. figma/plugin-typings ships no CHANGELOG and no GitHub Releases (the releases API returns an empty array), and its commit messages are content-free (1.132.0, Release v1.132 updates). The .d.ts diff is the only ground truth.

Work in the session scratchpad directory ($SCRATCH below):

bash
cd "$SCRATCH" && mkdir -p typings-audit && cd typings-audit
npm pack @figma/plugin-typings@<installed> @figma/plugin-typings@<target> --pack-destination .
for v in <installed> <target>; do
  mkdir -p "$v" && tar -xzf "figma-plugin-typings-$v.tgz" -C "$v" --strip-components=1
done
diff -rq <installed> <target>            # which files differ at all — start here
diff -u <installed>/package.json <target>/package.json
diff -u <installed>/index.d.ts <target>/index.d.ts

diff -rq first, so the set of changed files is observed rather than assumed. Every file it names has to be accounted for — including plugin-api-standalone.d.ts, whose trailing export { ... } is one enormous single line where a removed symbol is easy to miss.

index.d.ts declares the figma global, fetch and timers — small, but high blast radius. package.json looks irrelevant and isn't: its devDependencies.prettier explains formatting noise. When that version moves, the .d.ts diff fills with reflowed unions and extends clauses that mean nothing. Check it before reading a single hunk.

Normalize before diffing the .d.ts

Never classify hunks straight out of diff -u. Reformat both versions with the target's own formatter first, so what survives is guaranteed to be semantic:

bash
mkdir -p norm
for v in <installed> <target>; do
  for f in plugin-api.d.ts plugin-api-standalone.d.ts; do cp "$v/$f" "norm/$v.$f"; done
done
cp <target>/.prettierrc norm/.prettierrc          # the package ships its own config
npx --yes prettier@<version from target package.json devDeps> --write "norm/*.d.ts"
diff -u norm/<installed>.plugin-api.d.ts norm/<target>.plugin-api.d.ts
diff -u norm/<installed>.plugin-api-standalone.d.ts norm/<target>.plugin-api-standalone.d.ts

Watch prettier's own per-file output: the target files should report unchanged. That confirms you picked the right formatter version, and turns "the noise is upstream reformatting" from a guess into an observation.

Classify from these normalized diffs. plugin-api.d.ts is the one that matters — packages/plugin/tsconfig.json sets types: ["@figma/plugin-typings"], whose index.d.ts references it — and standalone serves as a cross-check that nothing was missed.

Measured on 1.134.0 → 1.135.0: 328 raw lines collapsed to 32, all of them one change. Never estimate the size of a release from raw diff line count — 1.134.0 was smaller (228 lines) and carried three real buckets.

When the jump spans several releases, diff the two endpoints; the cumulative effect is what matters. Go release-by-release only to attribute a specific change to a version.

Stage 2 — Classify every hunk

Drop hunks that are JSDoc-only (comment/example churn, no signature change) — the file is mostly documentation and these dominate the line count without meaning anything.

Sort the rest into three buckets:

  1. Breaking — a removed symbol, a narrowed type (optional → required, union → smaller union), a changed signature, or a newly-added @deprecated. Look at - lines first.
  2. New API — a new method, node type, enum member, or namespace. A new capability, so a candidate for a new tool or a new argument on an existing one.
  3. New field on an existing type — an added property on something Figwright already reads (Paint, Effect, TextStyle, a node interface…). ⚠️ The dangerous bucket. No compiler will ever flag it and the read path will keep silently omitting the dimension. It is this repo's recurring bug class: a multi-dimensional Figma property collapsed to one field or dropped on the way out.

Stage 3 — Map the diff onto the repo

The three source trees have completely different exposure. Don't treat them alike:

TreeCoupling to typingsWho catches a break
packages/plugin/src/**Real. The only tree that calls figma.* and loads the global types (tsconfig.json → types: ["@figma/plugin-typings"])tsc
packages/plugin/ui/**None — the Vue panel never touches the Figma APIn/a, skip
packages/shared/src/**★ None — and that's the trap. serialized-node.ts, styles.ts, queries.ts are hand-written Zod mirrors of Figma shapes; shared/tsconfig.json never loads typingsNobody but this audit
  • Bucket 1 — grep the affected symbols under packages/plugin/src/ (handlers, serializer.ts, traverse.ts, reveal.ts). Confirm with Stage 4 rather than reasoning about it.
  • Bucket 3 — for each added field, check whether the Zod mirror in packages/shared/src/ carries it, and whether serializer.ts or handlers/get-design-context.ts projects it. A miss here is a real fidelity gap with every gate green.
  • Bucket 2 — check coverage against packages/mcp/src/tools/registry.ts (ALL_TOOL_SPECS is the authority on the tool count; prose in READMEs is hand-written and stale).

Stage 4 — Sandbox typecheck (only if Stage 2 found bucket 1)

Type-check the real sandbox sources against the new typings without touching the repo. Never overwrite the copy in node_modules — pnpm hard-links it into the global store, so writing there corrupts the store for every project on the machine.

Write $SCRATCH/typings-audit/tsconfig.probe.json:

json
{
  "compilerOptions": {
    "target": "ES2023",
    "module": "ESNext",
    "moduleResolution": "Bundler",
    "lib": ["ES2023", "DOM", "DOM.Iterable"],
    "strict": true,
    "noUncheckedIndexedAccess": true,
    "noImplicitOverride": true,
    "noFallthroughCasesInSwitch": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "exactOptionalPropertyTypes": true,
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "isolatedModules": true,
    "verbatimModuleSyntax": true,
    "resolveJsonModule": true,
    "skipLibCheck": true,
    "noEmit": true,
    "types": []
  },
  "files": ["./<target>/index.d.ts"],
  "include": [
    "<REPO_ROOT>/packages/plugin/src/**/*.ts",
    "<REPO_ROOT>/packages/plugin/protocol/**/*.ts"
  ]
}

Expand <REPO_ROOT> to git rev-parse --show-toplevel — the tsconfig lives outside the repo, so those entries have to be absolute. Never hard-code a machine-specific path into a committed file.

types: [] keeps the installed (old) typings out; the files entry pulls the new ones in via its /// <reference path="./plugin-api.d.ts" />. Module resolution still works because it is anchored to each source file's own location, not to the tsconfig's.

bash
./node_modules/.bin/tsc -p "$SCRATCH/typings-audit/tsconfig.probe.json"

Run the same probe against the installed version first. A clean baseline is what makes a failure on the new version mean something.

Stage 5 — Decide, then upgrade

  • Anything in bucket 1 → stop and report. Present what breaks and what it would cost to absorb, and let the user decide. Never upgrade past a breaking change on your own initiative.
  • Otherwise upgrade and prove the tree is still green:
bash
pnpm -C packages/plugin add -D @figma/plugin-typings@^<target>
pnpm typecheck && pnpm lint && pnpm format:check && pnpm knip && pnpm build && pnpm test

This is the first step that writes to the repo — packages/plugin/package.json and pnpm-lock.yaml. Everything before it was read-only.

Stage 6 — Report, then let the user pick

Report in 繁體中文台灣用語, ordered by consequence:

  1. 會壞掉的 — symbol, call sites under packages/plugin/src/, probe verdict. Say so explicitly when the list is empty.
  2. 靜默漏接風險 (bucket 3) — added field → the shared mirror that lacks it → the projection that would need to carry it. Flag that no gate catches these.
  3. 新能力 (bucket 2) — one line each: what Figma now exposes, and the smallest change that would surface it.

Report only what the diff and the probe actually showed. Don't pad with plausible-sounding changes, and never claim a live verification you didn't run.

Then AskUserQuestion (multi-select) over the items from 2 and 3.

Stage 7 — Implement the picks

Choosing where a new capability lands is the part worth thinking about:

  • Follow the real usage path, not the closest-sounding tool name. Ask when an agent would actually want this value, and put it on the tool that is already being called at that moment.
  • Keep the semantics honest. Editor-wide state does not belong inside a per-node object — make it a sibling field, and say so in the JSDoc.
  • Smallest change that closes the gap: a field on an existing result < a new argument < a new tool. The tool count is already large; a new tool needs to earn itself.
  • A new read dimension usually touches four places: the Zod schema in packages/shared/src/, the sandbox handler in packages/plugin/src/handlers/, the tool description in packages/mcp/src/tools/ (it is the LLM's only spec — fix it if it misreports the shape), and a test.
  • exactOptionalPropertyTypes is on: assign optional fields conditionally (if (x !== undefined) result.x = x), never result.x = undefined.
  • Guard editor-dependent APIs on figma.editorType rather than try/catch, so reads that deliberately don't assert the editor stay non-throwing in FigJam / Dev Mode without swallowing real errors.
  • Several handlers have no test file at all. If the one you touch is bare, write the test file.
  • Attack your own test. Break the guard on purpose and confirm the test goes red; a test that passes either way is decoration. Then put it back.

Re-run all six gates when done.

Stage 8 — Hand off the live verification

Unit tests don't prove a read path works against real Figma. Before claiming anything:

  • The MCP server runs the built dist → pnpm build, then the user reconnects the MCP server.
  • The plugin sandbox runs the dist it loaded at launch → the user must close and reopen the plugin inside Figma. Reconnecting MCP alone is not enough.
  • Some values can't be verified automatically at all — anything reflecting editor UI state (an open timeline, a playhead, a viewport) can be read but not staged through the plugin API. Design a contrast instead of a single reading: measure once in the neutral state, have the user set up the state, then measure again. A lone "field is absent" is unreadable — it can't distinguish "the plugin never reloaded" from "the state genuinely isn't there".
  • Building probe material on the canvas writes to the user's file. Ask first, and delete it after.

Report what was actually run. If the live step didn't happen, say that.

Frequently asked questions

What does the Figma Typings Audit AI skill do?

Upgrade @figma/plugin-typings and absorb what the new version exposes. Diffs the .d.ts between the installed and the target version (that package ships no changelog), sorts the changes into breakage / new API / silently-added fields, maps each onto the sandbox handlers, the hand-written Zod mirrors in shared, and the tool registry — then bumps the package and builds whatever the user picks. Use whenever the user wants @figma/plugin-typings updated or audited, or asks what a new plugin-typings version would break or newly enable — including a Renovate bump PR for that package.

Why use Figma Typings Audit on TypingMind?

Because you install it once and use it with any model. Figma Typings Audit is plain Markdown rather than provider-specific code, so the same skill runs on GPT-5, Claude, Gemini, Grok, or a local model — and you can switch model mid-chat without it breaking. TypingMind runs on your own API keys, so you pay providers directly instead of a per-seat subscription, and your skills and chats stay in your own storage.

How do I install Figma Typings Audit in TypingMind?

Open Plugins → Skills → Install from GitHub in TypingMind and paste https://github.com/awdr74100/figwright/tree/main/.claude/skills/figma-typings-audit. TypingMind reads its SKILL.md and installs it as a skill you can enable per chat.

Which AI models can use Figma Typings Audit?

Any model you connect in TypingMind. AI skills are plain Markdown instructions rather than provider-specific code, so GPT, Claude, Gemini, Grok, and local models can all load this skill when a request matches it.

How many AI models can I use with Figma Typings Audit?

As many as you like. As long as a model supports skills, you can use Figma Typings Audit with it — GPT, Claude, Gemini, Grok, DeepSeek, Mistral, Llama and more — all on TypingMind with your own API keys.

Is the Figma Typings Audit AI skill free?

Yes. It is published on GitHub by awdr74100 under the MIT license. You only pay your own AI provider for the tokens you use.

What are AI skills?

An AI skill is a reusable instruction bundle that teaches an AI model how to do one specific task. It follows the open Agent Skills format: a SKILL.md file with a name and description, plus any scripts, templates or reference files the model may need. The model reads the instructions only when your request matches the skill, so an installed skill costs nothing until it is used.

How are AI skills different from plugins or MCP servers?

A plugin or MCP server gives a model new tools to call — code that runs somewhere and returns a result. An AI skill gives the model knowledge and process instead: how to approach a task, which steps to follow, what good output looks like. Skills are plain Markdown, so they need no server, no API key and no runtime, and they work with any model.

View all

Set up your own AI workspace now

Get notified about new features and future giveaways by subscribing to our newsletter 👇