skills/snapshot-all/SKILL.md
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".
npx skillsauth add tokyo-megacorp/figma-differ snapshot-allInstall 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.
Extract fileKey from the Figma URL (https://www.figma.com/design/<fileKey>/...). No node-id parameter needed.
bash scripts/auth.sh status (if it fails, tell the user to run bash scripts/auth.sh set and stop)index.json is empty, stop and tell the user the file has no indexable framesCreate tasks for each phase. Dispatch haiku subagents per phase — raw output stays forked.
TaskCreate("Fetch file tree", activeForm: "Fetching <fileName> from Figma API...")
TaskCreate("Split frame snapshots", activeForm: "Extracting <N> frame subtrees...")
TaskCreate("Export frame PNGs", activeForm: "Exporting <N> screenshots in batches...")
TaskCreate("Generate frame docs", activeForm: "Extracting text, colors, buttons, layout...")
TaskCreate("Update search index", activeForm: "Indexing frames for semantic search...")
TaskCreate("Store Figma comments", activeForm: "Downloading comment threads...")
Task lifecycle:
TaskUpdate(taskId, status: "in_progress")Agent(model: "haiku") — agent reports only counts, never raw outputTaskUpdate(taskId, status: "completed")~/.figma-differ/)Pipe directly to a temp file (do NOT store in shell variable — file trees can be 10-30MB):
TREE_FILE="/tmp/figma-tree-<fileKey>-$$.json"
bash $CLAUDE_PLUGIN_ROOT/scripts/figma-api.sh fetch_file_tree <fileKey> > "$TREE_FILE"
Extract fileName from the response: jq -r '.name' "$TREE_FILE".
Extract connector lines and prototype transitions from the tree:
node $CLAUDE_PLUGIN_ROOT/scripts/extract-flows.js <fileKey> "$TREE_FILE"
For each frame in the index, extract its subtree from the tree file using jq.
IMPORTANT: Do NOT use jq recursive descent (..) — it hangs on large trees. Use explicit path traversal to find each frame by ID:
jq --arg id "<nodeId>" '
[.document.children[].children[]? | recurse(.children[]?) | select(.id == $id)] | first
' "$TREE_FILE"
Store each frame's JSON at:
~/.figma-differ/<fileKey>/<nodeId_safe>/<timestamp>/node.json
Use the same timestamp for all frames in this snapshot (atomic file-level snapshot).
Collect all frame IDs from the index. Call:
BATCH_DIR="/tmp/figma-batch-<fileKey>-$$"
mkdir -p "$BATCH_DIR"
bash $CLAUDE_PLUGIN_ROOT/scripts/figma-api.sh fetch_batch_images <fileKey> "id1,id2,..." "$BATCH_DIR"
Move each downloaded PNG to its frame's snapshot directory and clean up:
~/.figma-differ/<fileKey>/<nodeId_safe>/<timestamp>/screenshot.png
After all PNGs are moved: rm -rf "$BATCH_DIR" "$TREE_FILE"
If QMD is available, generate searchable markdown for each frame:
node $CLAUDE_PLUGIN_ROOT/scripts/generate-frame-md.js <fileKey>
source $CLAUDE_PLUGIN_ROOT/scripts/lib/qmd.sh
qmd_reindex
This is best-effort — if QMD is not installed, skip silently. The frame.md files are still useful as human-readable summaries even without QMD.
Pipe directly to file (do NOT store in shell variable — large comment payloads will exceed argument limits):
COMMENT_DIR="$HOME/.figma-differ/<fileKey>/comments"
mkdir -p "$COMMENT_DIR"
bash $CLAUDE_PLUGIN_ROOT/scripts/figma-api.sh fetch_comments <fileKey> > "$COMMENT_DIR/<timestamp>.json"
Check if ~/.figma-differ/config.json exists and has a slack_channel_id. If so:
Read ~/.figma-differ/<fileKey>/slack-threads.json (create { "channel_id": "<channel_id>", "threads": {} } if missing)
For each frame in the index that is NOT already in the threads registry, create a parent message:
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 Figma deep-link: https://www.figma.com/design/<fileKey>/<fileName>?node-id=<nodeId with : replaced by ->
Post via mcp__claude_ai_Slack__slack_send_message:
channel_id: from configmessage: <emoji> *<Frame Name>* · <<figma-deep-link>|Figma> · _<Page Name>_Save the returned message_ts to the registry:
{ "ts": "<message_ts>", "name": "<Frame Name>", "page": "<Page Name>" }
Write the updated slack-threads.json after all parent messages are created.
Rate limit note: If there are many new frames (e.g. first run with 50+ frames), post parent messages sequentially with no artificial delay — the Slack MCP handles rate limiting. Log progress: Creating Slack thread for "<Frame Name>"... (M/N)
Snapshot complete — <fileName>
Frames: N snapshots stored
PNGs: M exported (K failed)
Comments: C total (U unresolved)
Slack threads: T created (S already existed)
Timestamp: <timestamp>
Storage: ~/.figma-differ/<fileKey>/
Run /figma-differ:diff-all <url> to check for changes later.
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".
content-media
Semantic search across all tracked Figma frames using QMD hybrid search. Finds frames by content, component names, text strings, or natural language queries like "the login screen" or "frames with portfolio charts". Use when the user runs /figma-differ:search or says "find the Figma frame for", "which frame has", "search Figma frames", or "find frames with".