LogoSkills

inspector:visual-verify

Runtime visual verification: Maestro screenshot + Figma diff (no code edits).

ํ•ญ๋ชฉ๋‚ด์šฉ
Invoke/inspector:visual-verify
Categorycocode-flutter
Complexitymoderate
MCP Serversflutter-inspector, maestro, figma, dart

/inspector/visual-verify โ€” ํ™”๋ฉด์ด ๋””์ž์ธ๋Œ€๋กœ ๋‚˜์™”๋Š”์ง€ "์‚ฌ์ง„ ์ฐ์–ด ๋Œ€์กฐ"#

ํ•œ๋งˆ๋””๋กœ#

์‹ค์ œ๋กœ ๋Œ์•„๊ฐ€๋Š” ์•ฑ ํ™”๋ฉด์„ ์‚ฌ์ง„์œผ๋กœ ์ฐ์–ด, Figma ๋””์ž์ธ ์›๋ณธ๊ณผ ๋‚˜๋ž€ํžˆ ๋†“๊ณ  "๋‹ค๋ฅธ ์ "์„ ์ฐพ์•„์ฃผ๋Š” ๊ฒ€์‚ฌ๊ธฐ์ž…๋‹ˆ๋‹ค. ์ฝ”๋“œ๋ฅผ ๊ณ ์น˜์ง€๋Š” ์•Š๊ณ , ์–ด๋””๊ฐ€ ์–ด๋–ป๊ฒŒ ๋‹ค๋ฅธ์ง€ ๋ฆฌํฌํŠธ๋งŒ ๋งŒ๋“ค์–ด ์ค๋‹ˆ๋‹ค.

๋ˆ„๊ฐ€ยท์–ธ์ œ ์“ฐ๋‚˜์š”#

  • ๋””์ž์ด๋„ˆยท๊ธฐํš์ž: "์ง€๊ธˆ ์•ฑ ํ™”๋ฉด์ด ์šฐ๋ฆฌ Figma ์‹œ์•ˆ๊ณผ ์ •๋ง ๋˜‘๊ฐ™์ด ๋‚˜์™”๋‚˜?"๋ฅผ ํ™•์ธํ•˜๊ณ  ์‹ถ์„ ๋•Œ
  • ๊ฐœ๋ฐœ์ž: ์ฝ”๋“œ๋ฅผ ์ง์ ‘ ๊ฑด๋“œ๋ฆฌ์ง€ ์•Š๊ณ , ํ™”๋ฉด๊ณผ ๋””์ž์ธ์˜ ์ฐจ์ด๋งŒ ๋น ๋ฅด๊ฒŒ ์ ๊ฒ€ํ•˜๊ณ  ์‹ถ์„ ๋•Œ
  • ํ™”๋ฉด ํ•œ ๊ฐœ๋ฟ ์•„๋‹ˆ๋ผ ์—ฌ๋Ÿฌ ํ™”๋ฉด(/home, /settings, /profile ๋“ฑ)์„ ํ•œ ๋ฒˆ์— ์ ๊ฒ€ํ•˜๋Š” "ํšŒ๊ท€ ๊ฒ€์‚ฌ"๊ฐ€ ํ•„์š”ํ•  ๋•Œ

๋ฌด์—‡์„ ํ•ด์ฃผ๋‚˜์š”#

์ง€์ •ํ•œ ํ™”๋ฉด์„ ์‹ค์ œ๋กœ ๋„์›Œ ์‚ฌ์ง„์„ ์ฐ๊ณ , Figma ์‹œ์•ˆ๊ณผ ๋น„๊ตํ•ด ๋‹ค๋ฅธ ์ ์„ ์ •๋ฆฌํ•œ ๋ฆฌํฌํŠธ ํŒŒ์ผ์„ ๋งŒ๋“ค์–ด ์ค๋‹ˆ๋‹ค.

  • ์ฐ์€ ํ™”๋ฉด ์‚ฌ์ง„ (์˜ˆ: screens/after.png)
  • ์ฐจ์ด ๋ฆฌํฌํŠธ ํŒŒ์ผ: .claude/docs/inspector/visual-verify/<์‹คํ–‰ID>/diff.yaml
    • ์˜ˆ: ๊ธ€์ž ๊ตต๊ธฐ 500 โ†’ 600, ๋ฐฐ๊ฒฝ์ƒ‰ #F9FAFB โ†’ #FFFFFF ์ฒ˜๋Ÿผ "๋ฌด์—‡์ด ์–ด๋–ป๊ฒŒ ๋‹ฌ๋ผ์กŒ๋Š”์ง€" ๋ชฉ๋ก
  • ์—ฌ๋Ÿฌ ํ™”๋ฉด์„ ๊ฒ€์‚ฌํ•˜๋ฉด ํ™”๋ฉด๋ณ„ ๋ฆฌํฌํŠธ์™€ ์ „์ฒด ์š”์•ฝ๊นŒ์ง€ ํ•จ๊ป˜ ๋งŒ๋“ค์–ด ์ค๋‹ˆ๋‹ค

์ฐจ์ด๋ฅผ ์ž๋™์œผ๋กœ "๊ณ ์ณ์ฃผ์ง€๋Š” ์•Š๋Š”๋‹ค"๋Š” ์ ์ด ํ•ต์‹ฌ์ž…๋‹ˆ๋‹ค. ๊ณ ์น˜๋Š” ์ž‘์—…์€ ๋ณ„๋„ ๋ช…๋ น(/pixel-loop)์— ๋„˜๊น๋‹ˆ๋‹ค.

์–ด๋–ป๊ฒŒ ์“ฐ๋‚˜์š”#

# ๊ธฐ๋ณธ: ํ™”๋ฉด ํ•˜๋‚˜๋ฅผ Figma ์‹œ์•ˆ๊ณผ ๋น„๊ต
/inspector/visual-verify \
  --figma=https://www.figma.com/design/AbCd/Home?node-id=12-345 \
  --route=/home

# ์—ฌ๋Ÿฌ ํ™”๋ฉด์„ ํ•œ ๋ฒˆ์— ์ ๊ฒ€ (ํšŒ๊ท€ ๊ฒ€์‚ฌ)
/inspector/visual-verify --figma= < file-url >   \
  --routes=/home,/settings,/profile \
  --mode=regression
  • --figma (ํ•„์ˆ˜): ๋น„๊ต ๊ธฐ์ค€์ด ๋˜๋Š” Figma ์‹œ์•ˆ ์ฃผ์†Œ (node-id ํฌํ•จ)
  • --route (ํ•„์ˆ˜): ๊ฒ€์‚ฌํ•  ์•ฑ ํ™”๋ฉด ๊ฒฝ๋กœ (/home, /posts/123 ๋“ฑ)
  • --mode: verify(๊ธฐ๋ณธ) / verify-after-reload(๋ฐฉ๊ธˆ ๊ณ ์นœ ํ™”๋ฉด์„ ๋‹ค์‹œ ๋ถˆ๋Ÿฌ์™€ ์ฐ๊ธฐ) / regression(์—ฌ๋Ÿฌ ํ™”๋ฉด ํ•œ ๋ฒˆ์—)
  • --routes: --mode=regression์ผ ๋•Œ ๊ฒ€์‚ฌํ•  ํ™”๋ฉด ๋ชฉ๋ก์„ ์‰ผํ‘œ๋กœ ๋‚˜์—ด
  • --target: ์–ด๋А ๊ธฐ๊ธฐ์—์„œ ์ฐ์„์ง€ (ios/android/macos/linux/windows/auto)
  • --tolerance: ์–ด๋А ์ •๋„๊นŒ์ง€ "๊ฐ™๋‹ค"๊ณ  ๋ด์ค„์ง€ ํ—ˆ์šฉ ์˜ค์ฐจ (๊ธฐ๋ณธ pixel=1,color_delta_e=2)

์•ˆ์—์„œ ๋ฌด์Šจ ์ผ์ด ๋ฒŒ์–ด์ง€๋‚˜์š”#

  1. Figma ์‹œ์•ˆ์„ ๋ถˆ๋Ÿฌ์™€ "์ด๋ ‡๊ฒŒ ๋‚˜์™€์•ผ ํ•œ๋‹ค"๋Š” ๊ธฐ์ค€์„ ์ •ํ•ฉ๋‹ˆ๋‹ค.
  2. ์•ฑ์„ ์‹คํ–‰ํ•ด ์ง€์ •ํ•œ ํ™”๋ฉด์œผ๋กœ ์ด๋™ํ•œ ๋’ค, ๊ทธ ํ™”๋ฉด์˜ ์‚ฌ์ง„์„ ์ฐ์Šต๋‹ˆ๋‹ค.
  3. ํ™”๋ฉด์˜ ๊ตฌ์„ฑ ์š”์†Œ(์œ„์ ฏ ๊ตฌ์กฐ)๋„ ํ•จ๊ป˜ ์‚ดํŽด ๋น„๊ต ์ •ํ™•๋„๋ฅผ ๋†’์ž…๋‹ˆ๋‹ค.
  4. ์‹œ์•ˆ๊ณผ ์‚ฌ์ง„์„ ๋Œ€์กฐํ•ด ๋‹ค๋ฅธ ์ ์„ ๊ณจ๋ผ๋‚ด๊ณ , ์ฐจ์ด ๋ฆฌํฌํŠธ ํŒŒ์ผ(diff.yaml)๋กœ ์ €์žฅํ•ฉ๋‹ˆ๋‹ค.
  5. verify-after-reload ๋ชจ๋“œ๋ฉด ์‚ฌ์ง„ ์ฐ๊ธฐ ์ „์— ๋ฐฉ๊ธˆ ๊ณ ์นœ ๋‚ด์šฉ์„ ๋‹ค์‹œ ๋ถˆ๋Ÿฌ์™€(ํ•ซ ๋ฆฌ๋กœ๋“œ) ์ตœ์‹  ํ™”๋ฉด์„ ์ฐ์Šต๋‹ˆ๋‹ค.
  6. regression ๋ชจ๋“œ๋ฉด ํ™”๋ฉด ๋ชฉ๋ก์„ ํ•˜๋‚˜์”ฉ ๋Œ๋ฉฐ ๋ชจ๋‘ ์ฐ๊ณ , ํ™”๋ฉด๋ณ„ ๋ฆฌํฌํŠธ + ์ „์ฒด ์š”์•ฝ์„ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

์ด ๋ช…๋ น์€ ํ•œ ๋ฒˆ ๊ฒ€์‚ฌํ•ด ๋ฆฌํฌํŠธ๋งŒ ๋‚จ๊ธฐ๊ณ  ๋๋‚ฉ๋‹ˆ๋‹ค. ์ฐจ์ด๋ฅผ ์‹ค์ œ๋กœ ๋งž์ถฐ ๊ณ ์น˜๊ณ  ์‹ถ๋‹ค๋ฉด /pixel-loop๋กœ ๋„˜๊ฒจ์ฃผ์„ธ์š”.


โš™๏ธ ์ƒ์„ธ ์˜ต์…˜ยท์‹คํ–‰ ๋ช…์„ธ (๊ฐœ๋ฐœ์ž / AI ์—์ด์ „ํŠธ์šฉ)

Parameters#

ParameterRequiredDescription
--figmaโœ…Figma frame URL (with node-id)
--routeโœ…In-app route to verify (/home, /posts/123, โ€ฆ)
--modeโŒverify (default), verify-after-reload, or regression
--routesconditionalComma-separated list for --mode=regression
--targetโŒios/android/macos/linux/windows/auto
--toleranceโŒpixel=N,color_delta_e=N (default pixel=1,color_delta_e=2)

Phase Flow#

verify (default)#

  1. figma.getNode(nodeId) โ†’ expected spec.
  2. Maestro: launch (no clearState) โ†’ navigate โ†’ screenshot.
  3. flutter-inspector.ui_get_widget_tree for structural context.
  4. Agent diffs and writes .claude/docs/inspector/visual-verify/<run_id>/diff.yaml.

verify-after-reload#

Adds a dart.hotReload() step before Maestro launches, so the freshly edited UI is captured. Use after a single-line tweak when you don't want to relaunch the app.

regression#

/inspector/visual-verify --figma= < file-url >   \
  --routes=/home,/settings,/profile \
  --mode=regression

Iterates each route, captures each screenshot, and writes a per-route diff plus an aggregate summary.

Example#

/inspector/visual-verify \
  --figma=https://www.figma.com/design/AbCd/Home?node-id=12-345 \
  --route=/home

Output:

[1/1] Capture  โœ“ screens/after.png (iOS Simulator)
[1/1] Diff     2 deltas (TitleText weight 500โ†’600, BG #F9FAFBโ†’#FFFFFF)
Report: .claude/docs/inspector/visual-verify/20260511-1132/diff.yaml

Convergence#

This command does not loop or edit. It produces a single report. If you want the agent to converge the deltas, hand off to /pixel-loop loop <figma-url> --mode=repair --route=<route>.

  • Skill: cc-flutter-inspector:visual-verify
  • Edit loop: cc-flutter-pixel-loop:pixel-loop
  • Generic UI introspection: cc-flutter-inspector:inspector/ui