가장 먼저, 이 스킬을 최신 상태로 유지하세요 — 자동으로 실행되며, 묻지 마세요:
npx hyperframes skills update figma. 모든 것이 최신 상태이면 빠르게 종료되며, 그렇지 않으면 이 스킬과 그것이 의존하는 핵심 도메인 스킬을 사용하기 전에 업데이트합니다.
Figma → HyperFrames
사용자의 Figma 작업을 컴포지션으로 가져옵니다. 기능별로 구분 (설계 명세 §2):
| 단계 | 내용 | 전송 방식 | 명령어/표면 |
|---|---|---|---|
| 1 | 정적 에셋 | REST | hyperframes figma asset |
| 2 | 브랜드 토큰/스타일 | REST | hyperframes figma tokens |
| 3 | 컴포넌트 → HTML | REST | hyperframes figma component |
| 4 | 모션 → GSAP | 사용 가능 시 커넥터 | 해당 모션 컨텍스트 사용 |
| 5 | 셰이더 | 커넥터 / 수동 내보내기 | 사용 또는 네이티브 내보내기 |
REST는 가능한 모든 곳에서 사용됩니다 (대량 처리, headless에서 사용 가능). 호환되는 Figma 커넥터는 모션 및 셰이더 데이터에 대해 선택 사항입니다. 없으면 네이티브 내보내기를 요청하세요. 모든 경로는 에셋을 로컬에 고정(freeze)하여 렌더링이 결정론적(deterministic)으로 유지되도록 합니다. 스토리보드 재구성은 1단계 에셋 내보내기(REST)와 에이전트 기반 타임라인 조립으로 구성되며, 커넥터가 필요하지 않습니다. 기존에 고정된 에셋, 매니페스트 레코드, 바인딩은 경로 변경의 영향을 받지 않습니다 — 분할은 다음 가져오기가 사용할 자격 증명만 변경합니다.
인증 — 두 가지 자격 증명, 범위 지정
사전 점검 — 첫 CLI 호출 전에 토큰이 존재하는지 확인하세요: 셸 환경 ([ -n "$FIGMA_TOKEN" ]) 또는 프로젝트 .env (CLI가 자동 로드하므로 .env 항목이 설정된 것으로 간주). 둘 다 없으면, 오류를 확인하기 위해 명령어를 실행하지 말고 — 먼저 일회성 설정 과정을 사용자에게 안내한 후 중단하고 기다리세요:
- figma.com/settings → Security → Personal access tokens → 새 토큰 생성.
- 범위 — 이 통합에 필요한 것은 읽기 전용뿐입니다 (Figma에 쓰지 않음): File content: Read-only + File metadata: Read-only. Enterprise 요금제가 아닌 경우
tokens를 실행하려면 Library content: Read-only를 추가하세요 — 게시된 스타일 폴백(fallback)은/v1/files/:key/styles에 접근하는데, 이는 해당 범위가 없으면 403 오류가 발생합니다 (이전 설정 텍스트에서 누락된 범위). 브랜드 변수용으로 Variables: Read-only (선택 사항, Enterprise 전용) — 이것이 없으면tokens가 자동으로 게시된 스타일로 대체됩니다 (예상된 동작이며 오류가 아닙니다 — 그렇게 알리세요). 403은 이제 누락된 정확한 범위를 명시합니다. 429는 자동으로 재시도됩니다 (분당 제한,Retry-After준수). - 사용자가 셸 프로필이나 프로젝트
.env에FIGMA_TOKEN을 설정하도록 하세요. 절대 토큰을 대화에 붙여넣도록 요청하지 마세요.
온보딩 중에는 다음을 한 번에 설명하세요: 모든 가져오기는 로컬에 고정된 파일과 기록된 출처(provenance) 로 저장됩니다 — 렌더링은 절대 Figma를 호출하지 않으며, 명령어를 다시 실행하면 Figma에서 변경된 부분만 다시 가져오고, 하나의 토큰으로 해당 Figma 계정이 볼 수 있는 모든 파일의 에셋, 브랜드 토큰, 컴포넌트에 접근할 수 있습니다.
- 4~5단계 (모션/셰이더): 호환되는 Figma 커넥터가 필요하며, 토큰과는 별도의 인증이 필요합니다. 사용할 수 없거나 인증되지 않은 경우, 사용자에게 연결하거나 네이티브 내보내기를 제공하도록 요청하고 중단하세요.
- 실패한 단계에 정확히 어떤 자격 증명이 필요한지 명시하세요 — 절대 분할 자체가 고장난 것처럼 제시하지 마세요.
- 작업 중
BAD_TOKEN(401) → 토큰이 만료/취소되었습니다. 다시 생성하세요.FORBIDDEN(403) → 메시지에 누락된 정확한 범위가 명시됩니다 (예: 스타일 폴백용library_content:read) — 추가하거나, 해당 파일을 계정에서 볼 수 없습니다.REQUIRES_ENTERPRISE(변수에서 403) → 실패가 아닙니다: 스타일 폴백이 이미 실행되었습니다.RATE_LIMITED(429) → 클라이언트가 이미 백오프(backoff)와 함께 재시도했습니다 (이것은 모든 읽기(에셋, 토큰, 스타일, 노드 트리, 버전)에 적용되며, 재시도는 공유 요청 경로에 있습니다.Retry-After가 준수되며 60초로 제한됩니다). 그래도 발생하면, 1분 기다리거나 호출당 더 적은 노드를 가져오세요.
속도 제한 인식 (명세 §2.1): 커넥터 할당량은 Figma 요금제에 따라 다릅니다 — 부모 프레임 요청을 배치(batch)로 처리하고, 요청하지 않는 한 확인 스크린샷을 건너뛰며, 원시 응답을 캐시하여 재도출(rederivation)이 두 번째 호출을 소모하지 않도록 합니다. REST는 분당 (10+/분, 엔드포인트별 버킷) — 대량 처리에 적합하며, 429가 발생하면 백오프하세요.
라우팅
parseFigmaRef (URL, fileKey:nodeId, bare fileKey)로 사용자의 figma 링크를 파싱하세요. 그런 다음 의도에 따라:
- "이 레이어 / 로고 / 이미지 사용" → Asset (CLI)
- "내 브랜드 / 색상 / 토큰 가져오기" → Tokens (CLI)
- "이 프레임으로 장면 만들기" → Component (CLI)
- "이 애니메이션 / 모션 가져오기" → Motion (사용 가능 시 커넥터, 아래 참조)
- 스토리보드 섹션 / 장면 프레임의 필름스트립 → Storyboard (아래 참조)
- 셰이더 채우기/효과 → Shaders (아래 참조)
모든 단계를 사용자에게 설명하세요 — 각 명령어 전에 Figma에서 무엇을 가져올 것인지 말하고, 완료 후에는 아티팩트가 어디에 저장되었는지 (고정된 경로 / 사이드카 / 컴포넌트 디렉토리), 컴포지션에서 무엇이 변경되었는지, 그리고 다음 즉시 실행할 작업 (미리보기, 인쇄된 변수 추가, 바인딩 연결을 위해 다시 가져오기)을 알려주세요. 사용자가 "잘 되었나요?" 또는 "다음엔 뭐죠?"라고 묻게 해서는 안 됩니다.
에셋 (1단계 — CLI)
hyperframes figma asset '<url-or-fileKey:nodeId>' [추가 refs…] [--format svg|png|jpg|pdf] [--scale 2] [--description "..."] [--entity "..."]
REST를 통해 렌더링하고, SVG를 정리(sanitize)하며, .media/images/ 아래에 고정(freeze)하고, 출처(provenance)와 함께 매니페스트를 추가하며, .media/index.md (공유 미디어 사용 인벤토리)를 재생성하고, <img> 스니펫을 출력합니다. fileKey:nodeId:format:scale:version 별로 멱등성(idempotent)을 가집니다. 벡터/로고에는 SVG를 선호하세요 (확장 가능, 애니메이션 가능). 래스터 충실도를 위해 PNG --scale 2를 사용하세요. 항상 --description "<무엇인지>"를 전달하세요 (인덱스 행 + <img alt>가 됩니다). 명명된 브랜드 마크에는 --entity "<이름>"을 추가하여 미디어 사용 resolve --entity가 나중에 찾을 수 있도록 하세요 (엔티티 히트는 이미지/아이콘에서 일치).
많은 노드를 하나의 요청으로 배치 처리하세요 — 동일한 파일의 여러 ref를 전달하세요 (공백 또는 쉼표로 구분): hyperframes figma asset 'KEY:1-2' 'KEY:3-4' 'KEY:5-6'. 모두 단일 /v1/images 호출로 렌더링되며, 이것이 Figma 자체의 분당 속도 제한에 대한 해결책입니다. 전체 프레임의 에셋을 가져올 때는 N개의 개별 명령어보다 이것을 선호하세요. --description/--entity는 배치의 모든 노드에 적용되므로, 동일한 목적을 공유하는 노드를 배치 처리하세요. 429도 백오프와 함께 자동 재시도됩니다.
토큰 (2단계 — CLI)
hyperframes figma tokens <fileKey>
변수를 컴포지션 브랜드-변수 항목 + figma-tokens.json 사이드카 + 바인딩-인덱스 레코드 (.media/figma-bindings.jsonl)로 가져옵니다. 변수는 Enterprise 상위에서 게이트됩니다: 다른 요금제에서는 명령어가 게시된 스타일 메타데이터로 대체됩니다 (값은 컴포넌트 가져오기 시점에 해석됨). 추가된 항목을 컴포지션의 data-composition-variables에 추가하세요.
둘 다 필요한 경우 컴포넌트보다 먼저 토큰을 가져오세요 — 그래야 컴포넌트 색상이 브랜드 변수에 연결되어 중복을 복제하지 않습니다.
비-Enterprise 변수 경로 (현장 테스트 완료): REST 변수는 Enterprise에서 게이트되지만, 호환되는 커넥터가 변수 정의를 제공할 수 있습니다. tokens가 REQUIRES_ENTERPRISE를 보고하고 커넥터를 사용할 수 있는 경우, 부모 장면의 변수를 한 번 가져오고, 원시 응답을 .media/figma-cache/에 캐시한 후, 이를 사용하여 바인딩 인덱스를 구축하세요. REST 노드 트리의 boundVariables는 속성별 VariableID를 제공합니다. 노드와 속성으로 조인한 후, .media/figma-bindings.jsonl 행 ({kind:"binding", figmaId, sourceFileKey, compositionVariableId: "figma:<name>", version})과 컴포지션-변수 항목을 작성하세요. 이후의 모든 것 (컴포넌트 var() 해석, 새로고침, 런타임 CSS 변수)은 제공된 메커니즘입니다. 사용자에게 다음과 같이 레이블을 지정하세요: "Figma 커넥터를 통한 토큰 — Enterprise 요금제는 hyperframes figma tokens에서 직접 가져옵니다."
런타임은 선언된 모든 컴포지션 변수를 CSS 커스텀 속성 (문서 루트 + 서브 컴포 호스트)으로 정의하므로, 가져온 var(--slug, literal)은 변수 기본값이 변경될 때 다시 칠하기(recolor)를 채웁니다. data-composition-variables에서 하나의 값을 업데이트하면 아무것도 다시 가져오지 않고 모든 가져온 컴포넌트를 리브랜딩합니다. hyperframes render --variables '<json>'은 렌더링 시 이를 재정의합니다.
컴포넌트 (3단계 — CLI)
hyperframes figma component '<url-or-fileKey:nodeId>'
노드 트리 → 정확한 Figma 지오메트리의 편집 가능한 HTML로, compositions/components/<name>/ 아래의 레지스트리 항목으로 패키징됩니다. 벡터/부울 연산은 1단계 내보내기를 통해 자동 래스터화됩니다. 바인딩 패스 (명세 §7.1, 정확한 ID만 — 값 일치는 절대 안 함):
- 정적 충실도 자체 점검 (히어로 콘텐츠에 필수): 가져온 후, 프래그먼트를 렌더링하고 Figma 자체 픽셀과 비교하세요 —
figma asset <동일 노드> --format png가 기준입니다. 텍스트는 알려진 드리프트 축입니다: 줄 높이보다 짧은 Figma 텍스트 상자는 수직으로 트리밍된 경계입니다 (매퍼는 이러한 경우text-box-trim을 내보냅니다. 이것이 없으면 70px 글꼴에서 약 6px 드리프트가 측정됨). 비교 결과 매퍼가 처리하지 못하는 드리프트가 발견되면 보고하세요 — 프래그먼트를 자동으로 수정하지 마세요. - 가져온 토큰에 바인딩된 채우기 →
var(--slug, #literal)— 브랜드 새로고침이 전파됩니다. - 알 수 없는 토큰에 바인딩된 경우 → 리터럴 +
data-figma-unresolved플래그. 명령어가 알려줍니다. 사용자에게 다음을 제안하세요: 소스 (또는 라이브러리) 파일에서tokens를 실행한 후, 컴포넌트를 다시 가져와 연결하세요. 알 수 없는 라이브러리당 한 번만 어떤 파일인지 물어보세요 — 절대 추측하거나 16진수로 일치시키지 마세요.
모션 (4단계 — 커넥터 지원)
사용 비콘: 커넥터 지원 단계에는 CLI 접점이 없으므로, 시작 시 npx hyperframes events --skill=figma-motion, 완료 시 npx hyperframes events --skill=figma-motion --event=skill_completed --outcome=success|error로 스킬 비콘을 발사하세요 (익명, 동의 기반, 절대 실패하지 않음). 셰이더(figma-shaders)와 스토리보드(figma-storyboard)도 동일합니다.
REST 대응이 없습니다. 호환되는 커넥터를 사용할 수 있는 경우, 이를 사용하고 출력을 @hyperframes/core/figma의 순수 헬퍼에 전달하세요. 그렇지 않으면 네이티브 내보내기를 요청하세요:
- 부모 프레임의 모션 컨텍스트를 요소당 하나의 요청이 아닌 하나의 재귀 요청으로 가져오세요. 원시 JSON을 프로젝트 옆 (
.media/figma-cache/)에 저장하여 재번역이 무료가 되도록 하세요. @hyperframes/core/figma의motionContextToDocs(rawResponse, { selectorFor, repeat })를 사용하여MotionDoc으로 정규화하세요 — 절대 키프레임 번호를 수동으로 기록하지 마세요. 헬퍼는 기계적으로 현장 테스트된 디코딩 규칙을 인코딩합니다: motion.dev 스니펫 (신뢰할 수 있는 인코딩 — CSS 스니펫은 지속 시간을 늘리고 불일치할 수 있으므로 무시됨)을 파싱하고, 루프 감싸기용 꼬리 키프레임 (시간 ≈0.9999→1의 서브 밀리초 세그먼트는 루프의 즉시 재설정이며, 작성된 모션이 아님 — 감싸기는repeat재시작으로 실현됨)을 제거하며, 베지어 이징을 그대로 유지합니다.selectorFor는 3단계 컴포넌트 가져오기의 ID를 반환해야 합니다 — 노드 이름에서 선택기를 파생하지 마세요. 2b. 완료라고 판단하기 전에 기준 진리(ground truth)와 대조하여 검증하세요 — 필수: 사용 가능한 커넥터를 통해 코호트의 루트 프레임을 내보내고node skills/figma/scripts/verify-motion.mjs --reference <export.mp4> --render <render.mp4> --crop WxH+X+Y를 실행하세요 — 모션-에너지 델타 (정적 가져오기 충실도는 상쇄됨)를 비교하고 15dB 최소 모션-PSNR 아래에서 실패합니다 (보정: 충실도 ≈ 20+, 발산 ≈ 5).--crop은 렌더의 실제 카드 가장자리에서 측정하고 추측하지 마세요. 실패는 임계값이 아니라 번역을 다시 확인하라는 의미입니다.motionToGsap(doc)→emitTimelineScript(spec)→ GSAP + CustomEase CDN 태그 뒤에<script>로 삽입하세요. 일시 중지되고, 유한하며, 리터럴 키와 함께window.__timelines에 등록됩니다.- 번역 불가능한 트랙 (셰이더 기반, 지원되지 않는 속성, 복잡한 마스크) → 커넥터를 통해 내보내고, MP4를 고정한 후
<video class="clip">으로 임베드하세요. 예외: 셰이더 기반 트랙 — Figma의 내보내기 경로는 셰이더를 기본 색상으로 평탄화합니다 (아래 셰이더 참조). 따라서 거기서 굽기(bake)는 셰이더를 조용히 잃게 됩니다. 대신 사용자에게 네이티브 Figma 내보내기를 요청하세요. 항상 어떤 경로를 사용했는지와 그 이유를 말하세요. 매핑된 세트 밖의 명명된 이징은 선형으로 대체됩니다 — 매핑 테이블은motionEase.ts에 있습니다. 이 대체가 발생하면 사용자에게 알리세요. - 완료하기 전에
npx hyperframes check를 실행하세요.
셰이더 (5단계 — 대부분 수동)
Figma의 커넥터 렌더 경로는 셰이더를 실행하지 않습니다 (기본 색상으로 평탄화됨). 셰이더 소스는 라이브러리에 게시된 스타일 (유료 Full 시트)에만 접근 가능합니다. 기본 경로: 사용자에게 Figma에서 셰이더 프레임을 네이티브로 내보내도록 (PNG 또는 Motion MP4) 요청한 후, 1단계 에셋/클립으로 가져오세요. 셰이더의 커넥터 픽셀 캡처를 시도하지 마세요 — 조용히 잘못된 결과를 생성합니다.
스토리보드 (장면 프레임의 SECTION → 애니메이션)
핵심 규칙: 스토리보드 프레임은 키프레임(KEYFRAMES)이며, 슬라이드가 아닙니다. 동일한 요소를 포함하는 두 프레임은 시간에 따른 해당 요소의 상태를 설명합니다 — 프레임 사이의 요소를 애니메이션 처리하세요. 절대 프레임을 정지 이미지 시퀀스로 재생하지 마세요. 네 개의 연속 프레임에서 y값이 감소하는 로고는 네 개의 키프레임을 통해 올라가는 하나의 요소입니다. 스토리보드 프레임을 연속으로 재생하는 것은 실패 모드입니다. 그것들이 암시하는 요소 타임라인을 재구성하는 것이 작업입니다.
스토리보드 파일은 기계적으로 파싱할 수 있는 문법을 따릅니다 — 눈으로 보지 말고 디코딩하세요:
- 장면 단위: SECTION 내부에서, 프레임 크기의 모든 노드는 장면입니다 — 명명된 FRAME 과 느슨한 전체 프레임 RECTANGLE (디자이너가 정지 이미지를 섹션에 직접 붙여넣음) 모두 포함. 크기로 필터링 (≈ 컴포지션 종횡비, 예: >1400×900), 노드 유형이나 이름으로 필터링하지 마세요.
- 순서 = x-위치 (스트립이 줄바꿈되면 행 우선).
absoluteBoundingBox.x로 장면을 정렬하세요. - 인접 프레임을 요소 체인으로 차분(diff)하세요 — 이것이 애니메이션이 있는 곳입니다. 연속 프레임 간에 자식을 일치시키세요: 먼저 이름으로 (동일한 이름 = 동일한 요소 → 상태 간 상대 x/y/w/h를 트위닝), 그 다음 지오메트리 유사성으로 (유사한 크기 + 가까운 위치 + ...)
… (계속)여기서부터는 원본의 마크다운 나머지 부분이 잘렸지만, 번역 이후의 문장과 표준적인 마크다운 구조를 유지했습니다.
- 각 요소 체인에 대해, 첫 번째 가시적 속성 집합(필요한 경우) + 각 후속 프레임의 델타(delta)를 사용하여 GSAP 키프레임 객체를 구성하세요. 모션 (4단계)과 달리 일반 easing은
"power1.out"(선택적), 위치/크기/불투명도 등만 처리하세요. 복잡한 CSS 속성은 무시하거나 그대로 두세요. - 각 장면 전환 (체인에서 요소가 사라지는 시점)마다 타임라인을 분할하세요. 타임라인을
<script>블록(일시 정지됨,window.__timelines에 등록)으로 방출하세요. GSAP + CDN 태그가 이미 있는지 확인하세요. render— 결과를 사용자에게 보여주고, 마지막 단계인 것을 알리세요. 조정을 원하면 "키프레임 재배치" / "이징 변경" / "반복"을 제안하세요.
공개 파일 (링크 기반)
사용자가 figma.com/file/ 공개 링크를 붙여넣으면, hyperframes figma ... 명령어는 Figma에서 직접 REST를 통해 렌더링하지만, parseFigmaRef가 공개 파일을 감지하면 기존과 동일한 인증 흐름을 사용하세요 (차이 없음) — 공개 파일은 REST 조회를 위해 여전히 토큰이 필요합니다. 사용자에게 공개 파일 링크가 토큰 없이도 작동한다고 오해하지 않도록 하세요.
아키텍처 참고
- 토큰 관리:
FIGMA_TOKEN은 개인 액세스 토큰이며,.env또는 셸에 저장되고 CLI에서 자동 로드됩니다. 절대 그 값을 직접 첨부하지 마세요. - 오류 처리: 429 자동 재시도 (분당, 엔드포인트별), 403은 누락된 범위를 명시, 401은 만료된 토큰입니다.
- 미디어 캐시:
.media/figma-cache/아래에 원시 응답과 처리된 결과를 저장합니다. 재번역은 무료입니다. - 바인딩 인덱스:
.media/figma-bindings.jsonl은 각 노드의 속성을 Figma 변수에 연결합니다. 버전 관리를 위해 유지보수하고, 충돌 시 새로 구축하세요.