skills/notify/SKILL.md
Posts diff results to Slack using persistent frame threads. Each tracked frame gets a permanent parent message; diffs and comments are thread replies. Use when the user runs /figma-differ:notify, or says "post the diff to Slack", "share the Figma diff", "notify the team about design changes", or "send diff to Slack".
npx skillsauth add tokyo-megacorp/figma-differ notifyInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
~/.figma-differ/config.json to get slack_channel_id
slack_channel_id: error — Set slack_channel_id in ~/.figma-differ/config.jsonfileKey from itlatest-diff-all.json under ~/.figma-differ/*/fileKey from the pathRead ~/.figma-differ/<fileKey>/latest-diff-all.json. This is the structured JSON output from bulk-diff.js.
Structure:
{
"total": 10,
"unchanged": 7,
"top": [
{
"id": "2895:40497",
"name": "Login Screen",
"page": "Profile",
"severity": "critical",
"changes": [
{ "type": "added", "count": 5, "details": "..." },
{ "type": "text", "details": "\"Sign In\" → \"Log In\"" },
{ "type": "fill", "details": "header #F85149 → #D29922" }
],
"nodeCount": { "before": 142, "after": 147 }
}
],
"rest": [...],
"comments": {
"new": [{ "author": "Alice", "text": "Button needs variant", "nodeId": "2895:40497" }],
"resolved": [{ "text": "Icon alignment", "resolvedBy": "Bob", "nodeId": "2895:40501" }]
}
}
If file not found: error — No diff result found. Run /figma-differ:diff-all <url> first.
Read ~/.figma-differ/<fileKey>/slack-threads.json. If it doesn't exist, initialize:
{ "channel_id": "<slack_channel_id>", "threads": {} }
Read ~/.figma-differ/<fileKey>/index.json to get:
fileName — the Figma file namepage name (from the frames array)Combine top and rest arrays from the diff JSON. For each frame with changes:
Infer a semantic emoji from the frame name:
:lock: — login, sign in, auth:gear: — settings, preferences, config:bust_in_silhouette: — profile, account, user:inbox_tray: — inbox, notifications, messages:moneybag: — net worth, balance, portfolio, finance:gift: — gift, rewards, offers, promotions:page_facing_up: — statements, documents, history:shield: — security, privacy, verification:house: — home, dashboard, overview:mag: — search, explore, discover:credit_card: — payments, cards, transactions:bar_chart: — analytics, reports, charts:iphone: — default/fallback for any screenBuild the Figma deep-link:
https://www.figma.com/design/<fileKey>/<fileName>?node-id=<nodeId with : replaced by ->
Post parent message:
<emoji> *<Frame Name>* · <<figma-deep-link>|Figma> · _<Page Name>_
Use mcp__claude_ai_Slack__slack_send_message with:
channel_id: from configmessage: the formatted parent messageSave the returned message_ts (from the tool response) to the registry:
"threads": {
"<frameId>": { "ts": "<message_ts>", "name": "<Frame Name>", "page": "<Page Name>" }
}
Build a single thread reply message grouping all changes for this frame. Format:
*Apr 2 — N changes detected*
> <change lines with emojis>
>
> _<before> → <after> nodes_
Change type emoji mapping:
added or removed → 🧩 :jigsaw: — e.g. > :jigsaw: +5 nodes addedtext → ✏️ :pencil2: — e.g. > :pencil2: 2 text changes: "Sign In" → "Log In"fill or color or stroke → 🎨 :art: — e.g. > :art: fill: header #F85149 → #D29922layout or spacing or padding → 📐 :straight_ruler:component or swap → 🔀 :twisted_rightwards_arrows:visibility → 👁️ :eye:bbox or position → 📍 :round_pushpin:baseline or resolved or none → 🤏 :pinching_hand: (matches baseline)Use mcp__claude_ai_Slack__slack_send_message with:
channel_id: from configmessage: the formatted diff replythread_ts: the ts from the registry for this frameFor each new comment in comments.new, find the frame thread by nodeId:
:speech_balloon: *<Author Name>*
> <comment text>
For each resolved comment in comments.resolved, find the frame thread by nodeId:
:speech_balloon: ~"<comment text>"~ — _resolved by <Author>_
Post each as a thread reply using thread_ts from the registry.
If a comment's nodeId doesn't have a thread, skip it (comment is on an untracked frame).
Write the updated slack-threads.json back to ~/.figma-differ/<fileKey>/slack-threads.json:
{
"channel_id": "<slack_channel_id>",
"threads": {
"<frameId>": { "ts": "<message_ts>", "name": "<name>", "page": "<page>" },
...
}
}
Slack notify complete — <fileKey>
Threads: N parent messages (M new, K existing)
Diff replies: X posted
Comment replies: Y posted
Channel: <channel_id>
mcp__claude_ai_Slack__slack_send_message with params: channel_id, message, optional thread_tschat.update or reactions.add API — never reference themApr 2, Mar 15, etc.testing
Subscribe to a Figma file for automatic syncing and semantic search. Adds the file to tracked.json, runs initial index + snapshot-all + frame.md generation, and initializes the QMD search collection. Use when the user runs /figma-differ:track or says "track this Figma file", "subscribe to Figma", "watch this design file", or "add to tracked files".
documentation
Refresh snapshots and search index for tracked Figma files. Fetches current state from Figma, generates frame.md documents, and updates the QMD search index. Use when the user runs /figma-differ:sync or says "sync Figma", "refresh snapshots", "update the Figma index", or "re-sync tracked files".
tools
Takes a snapshot of a Figma node — fetches its JSON structure and PNG screenshot and stores both to ~/.figma-differ/ for later diffing. Use when the user runs /figma-differ:snapshot with a Figma URL, or says "snapshot this Figma frame", "save a Figma baseline", or "take a Figma snapshot".
development
Bulk snapshots every frame in a Figma file — fetches all node JSONs, exports PNGs, and stores comments. Uses a single API call for the tree and batched image exports. Use when the user runs /figma-differ:snapshot-all with a Figma file URL, or says "snapshot all frames", "bulk snapshot", "baseline the whole file", or "snapshot everything in this Figma file".