| 항목 | 내용 |
|---|---|
| Invoke | /pixel-loop:loop |
| Category | cocode-flutter |
| Complexity | high |
| MCP Servers | figma, maestro, dart |
/pixel-loop loop — 디자인이랑 똑같아질 때까지 자동 수정#
한마디로#
Figma 디자인과 실제 앱 화면을 나란히 놓고 비교한 뒤, 똑같아질 때까지 코드를 자동으로 고쳐주는 반복 작업입니다. "디자인 시안 보고 → 화면 고치고 → 다시 캡처해서 비교하고" 를 사람이 손으로 수십 번 반복하던 일을, AI가 알아서 돌려주는 자동 사진 맞추기라고 보면 됩니다.
누가·언제 쓰나요#
- 새 화면을 Figma 디자인 그대로 만들어야 할 때 (
create모드) - 이미 만든 화면이 시간이 지나며 디자인과 어긋났을 때, 다시 맞추고 싶을 때 (
repair모드) - "디자인이랑 픽셀 단위로 똑같이 맞춰주세요" 같은 요청이 있을 때
⚠️ 주의: 이 명령은 실제 소스 코드를 직접 고칩니다. 그래서 작업 전 변경사항이 없는 깨끗한 상태이거나, 별도 작업 브랜치에서 돌리는 것을 권장합니다.
무엇을 해주나요#
화면이 디자인과 일치할 때까지 반복한 뒤, .claude/docs/pixel-loop/<run_id>/ 폴더에 결과를 남깁니다:
- design.json / design.md — Figma에서 가져온 디자인 정보 정리본
- screens/ — 매 반복마다 찍은 실제 화면 스크린샷
- diff/ — 디자인과 실제 화면의 차이 기록
- summary.md — 최종 요약 (못 맞춘 부분이 남았다면 그 내용도 함께)
어떻게 쓰나요#
# 새 화면을 디자인대로 만들기 (기본)
/pixel-loop loop https://www.figma.com/design/AbCd/Home?node-id=12-345 \
--mode=create \
--target=ios \
--tolerance pixel=2,color_delta_e=3
# 이미 있는 화면을 디자인에 다시 맞추기 (repair 모드)
/pixel-loop loop < figma-url > --mode=repair --route=/home
주요 옵션:
figma-url(필수) — 맞출 대상 Figma 프레임 주소 (node-id가 포함된 링크)-
--mode—create(새 화면) 또는repair(어긋난 화면 보정). 기본은create --route—repair모드일 때 필수. 비교할 앱 안의 화면 경로 (예:/home)-
--target— 어떤 플랫폼에서 캡처할지 (ios,android,macos,linux,windows,auto). 기본auto --tolerance— 어디까지를 "같다"고 볼지 허용 오차 (픽셀/색상). 기본pixel=1,color_delta_e=2--iteration-cap— 최대 몇 번까지 반복할지. 기본6--no-screenshot-diff— 스크린샷 비교는 건너뛰고 구조만 비교
안에서 무슨 일이 벌어지나요#
크게 다섯 단계를 한 바퀴로 묶어, 디자인과 같아질 때까지 반복합니다.
- 읽기(Read) — Figma에서 디자인 정보(레이아웃·스타일·색상)를 가져와 저장합니다.
- 고치기(Write) — Flutter 화면 코드를 수정합니다. 한 번에 크게 바꾸지 않고, 차이 나는 부분만 최소한으로 고칩니다.
- 새로고침(Reload) — 고친 코드를 실행 중인 앱에 즉시 반영합니다(핫 리로드). 실패하면 앱을 다시 띄웁니다.
- 캡처(Capture) — 해당 화면으로 이동해 스크린샷을 찍습니다.
- 비교(Compare) — 디자인과 실제 화면을 비교합니다. 차이가 남아 있으면 다시 2번으로 돌아갑니다.
언제 멈추나요?
- 차이가 허용 오차 안으로 사라지면 → 완료
- 정해둔 최대 반복 횟수에 도달하면 → 남은 차이를
summary.md에 적고 종료 - 같은 차이가 두 번 연속 반복되면(고쳐도 안 바뀌는 상황) → 멈추고 사용자에게 물어봅니다
repair 모드에서는 맨 앞에 "수정 전" 스크린샷을 한 장 더 찍어, 요약에서 수정 전후를 비교해 볼 수 있게 해줍니다.
⚙️ 상세 옵션·실행 명세 (개발자 / AI 에이전트용)
Parameters#
| Parameter | Required | Description | Default |
|---|---|---|---|
figma-url | ✅ | Figma frame URL (file/design link with node-id) | — |
--mode | ❌ | create (new screen) or repair (drift fix) | create |
--route | conditional | Required for repair; in-app route to navigate to (e.g. /home) | — |
--target | ❌ | ios, android, macos, linux, windows, or auto | auto |
--tolerance | ❌ | pixel=N,color_delta_e=N | pixel=1,color_delta_e=2 |
--iteration-cap | ❌ | Max iterations before bailing out | 6 |
--no-screenshot-diff | ❌ | Skip visual diff (use structural diff only) | false |
Phase Flow#
- Read —
figma.getNode(nodeId)+figma.getStyles(nodeId)+figma.getVariables(nodeId). Persist to.claude/docs/pixel-loop/<run_id>/design.json. - Write — Edit Flutter source. Use CoUI primitives by default. Always prefer the smallest patch that addresses the current diff.
- Reload —
dart.hotReload(); fall back todart.hotRestart()onrequires_restart. Confirm withdart.getVMInfo(). - Capture —
maestro.runFlowwithlaunchApp(no clearState) → navigate to route →takeScreenshot. Saved underscreens/. - Compare — Visual + structural diff. If non-empty, return to step 2 with the residual deltas.
Convergence#
The loop terminates as soon as one of:
diffis empty within tolerances, oriteration-capis reached (writessummary.mdwith residual deltas), or- The same diff repeats twice in a row (oscillation guard) → command pauses and asks the user.
Example#
/pixel-loop loop https://www.figma.com/design/AbCd/Home?node-id=12-345 \
--mode=create \
--target=ios \
--tolerance pixel=2,color_delta_e=3Console transcript:
[1/6] Read ✓ figma.getNode 12:345 (Auto-layout, 14 children)
[1/6] Write ✓ patched lib/features/home/home_page.dart (+38, -12)
[1/6] Reload ✓ dart.hotReload (12ms)
[1/6] Capture ✓ maestro screenshot → screens/01.png
[1/6] Compare ✗ 3 deltas (TitleText weight, FAB y+4, BG color #F9FAFB→#FFFFFF)
[2/6] Write ✓ patched ... (+5, -3)
...
[3/6] Compare ✓ converged (Δ ≤ tolerance)Repair Mode#
/pixel-loop loop < figma-url > --mode=repair --route=/homeRepair mode inserts an initial 00_before.png capture, so the summary shows before/after for review. The agent does not assume the existing widget tree is wrong — it diffs both directions and chooses the minimal patch.
Failure Recovery#
If hot reload starts failing mid-loop (e.g. a structural change broke the isolate), the command:
- Issues
dart.hotRestart(). - Re-navigates via Maestro.
- If restart also fails, prints the Dart VM error and pauses for user input.
Output#
.claude/docs/pixel-loop/ < run_id > /
├── design.json
├── design.md
├── screens/
│ └── 0N_after_write.png
├── diff/
│ └── 0N.yaml
└── summary.md