Skip to main content
ClaudeWave
Skill298 repo starsupdated 4d ago

design-sync-upload

|

Install in Claude Code
Copy
git clone --depth 1 https://github.com/modu-ai/moai-cowork /tmp/design-sync-upload && cp -r /tmp/design-sync-upload/plugins/moai-designer/skills/design-sync-upload ~/.claude/skills/design-sync-upload
Then start a new Claude Code session; the skill loads automatically.

SKILL.md

# design-sync-upload — Claude Design 업로드 (자동 + 수동 폴백)

## 개요

디자인 시스템 자산을 Claude Design에 올리는 방식은 환경에 따라 두 가지입니다. 이 스킬은 **자동(DesignSync MCP)을 먼저 시도**하고, 인증·가용성 조건이 안 되면 **수동 폴백(UPLOAD-GUIDE.md + 스테이징 폴더)**으로 자연스럽게 강등합니다. 어느 경로든 사용자가 손으로 파일을 흩뿌리지 않고 한 번에 업로드할 수 있게 만드는 것이 목표입니다.

> 이 SKILL.md는 인증 감지·자동(DesignSync MCP) 경로·수동 폴백·사용 예시를 모두 포함합니다. DesignSync는 `method`로 디스패치하는 단일 MCP 도구이며(파라미터 상세는 §자동 경로 참조), 미인증·미가용 시 조용히 수동 폴백으로 강등합니다.

## 트리거 키워드

Claude Design 업로드, DesignSync MCP, design-login, 디자인 시스템 동기화, UPLOAD-GUIDE, 자산 스테이징, write_files, register_assets

## 입력

| 입력 | 형태 |
|---|---|
| DESIGN.md | `design-system-prep` 산출물 |
| 토큰 | `design-tokens-transformer` 산출물(DTCG/CSS/shadcn) |
| 자산 | 로고 변형(가로/정사각/마스코트/WH), 폰트, 이미지 |

## 경로 선택 — 인증 감지 분기

```
자산 준비
  → [감지] DesignSync MCP 가용 AND /design-login 인증됨?
      ├─ YES → 자동 경로 (DesignSync MCP)
      └─ NO  → 수동 폴백 (UPLOAD-GUIDE.md + 스테이징 폴더)
```

**감지 신호**

| 신호 | 확인 방법 | 판정 |
|---|---|---|
| DesignSync MCP 도구 존재 | 현재 세션 도구 목록에 `DesignSync`가 로드됐는지 | 없음 → 즉시 수동 |
| `/design-login` 인증됨 | 무해한 read 메서드(`list_projects`) 호출 시 인증 에러 미발생 | 정상 반환 → 자동 가능 |
| 미인증 에러 시그니처 | 관측된 문자열: `DesignSync needs design-system authorization. Run /design-login to authorize it with your claude.ai account` | 이 문자열 감지 → 미인증 확정 → 수동 |

**감지 순서(부작용 최소화)**: ① 도구 존재만 사전 확인 → ② 무해한 read 메서드(`list_projects`/`get_project`)로 인증 상태 판별(쓰기 없음) → ③ 여기서 미인증 에러가 나오면 폴백. 쓰기 메서드로 인증을 떠보지 않는다(부분 업로드 위험).

**감지 실패 시 기본 강등 정책**: 감지 자체가 모호하면(도구는 있으나 인증 상태 불명, read 호출이 애매한 에러 반환 등) **수동 폴백을 기본값**으로 강등한다. 인증됨을 관측 없이 가정하고 자동을 강행하면 부분·중복 업로드 위험이 있으므로, 애매하면 항상 수동이다(미관측 상태를 성공으로 가정 금지).

## 자동 경로 — DesignSync MCP

`/design-login` 인증 상태에서 DesignSync MCP 도구로 자산을 직접 등록합니다.

DesignSync는 `method`로 디스패치하는 단일 도구다. 순서 의존성이 강제된다: **read → `finalize_plan` → write**. `finalize_plan`이 먼저 경로 집합을 잠근 뒤에야 write가 허용된다(플랜 밖 경로/planId 없는 write는 거부).

1. **read** (`list_projects`/`get_project`/`list_files`/`get_file`) — 대상 프로젝트 확인(쓰기 가능 + `type: PROJECT_TYPE_DESIGN_SYSTEM`) 후 원격 구조로 컴포넌트 단위 diff 구성. 전량 교체가 아니라 증분.
2. **승인 게이트 — `finalize_plan` 호출 전.** 아래 §쓰기·삭제 승인 게이트. `finalize_plan`이 띄우는 런타임 권한 프롬프트가 이 게이트를 대신하지 못한다 — 그 프롬프트는 **경로만** 보여주고 그 경로에 무엇이 들어가는지는 보여주지 않는다.
3. **`finalize_plan`** — 승인된 경로 집합(`writes`/`deletes`, 글롭 허용)과 읽기 소스 디렉토리(`localDir`)를 확정 → `planId` 반환. 권한 프롬프트 발생.
4. **`write_files`** (+ `delete_files`) — `planId`로 파일 업로드. 각 파일은 `localPath`(디스크에서 직접 읽어 업로드 — 내용이 컨텍스트에 유입되지 않음, 권장) 또는 소량 인라인 `data`. 콜당 최대 256개(초과 시 같은 `planId`로 분할).
5. **`register_assets`** (레거시) — Design System 카드는 이제 preview HTML 첫 줄 `<!-- @dsCard group="…" -->` 마커에서 자동 인덱싱(앱이 `_ds_manifest.json`으로 컴파일)되므로 명시 등록 불필요. `@dsCard` 마커가 없는 수기 프로젝트에서만 사용.

**각 메서드 파라미터 스키마 (핵심 필드)**

| 메서드 | 필수 | 주요 파라미터 | 비고 |
|---|---|---|---|
| `finalize_plan` | — | `projectId`, `writes[]`(글롭, 최대 256), `deletes[]`, `localDir`(기본 cwd) | `planId` 반환. 사용자에게 경로 목록·소스 디렉토리 노출 |
| `write_files` | `planId` | `projectId`, `files[]`={`path`, `localPath`\|`data`, `mimeType`} | `localPath`는 `localDir` 안이어야 함. 콜당 256개 |
| `delete_files` | `planId` | `projectId`, `paths[]` | 플랜의 `deletes`에 포함된 경로만 |
| `register_assets`(레거시) | `planId` | `assets[]`={`name`, `path`, `group`, `viewport`, `subtitle`} | `path`는 플랜의 `writes`에 포함돼야 함 |
| `create_project` | — | `name` | `list_projects`가 비었거나 사용자가 신규 선택 시 |

**순서 의존성**: read → **승인 게이트** → `finalize_plan`(planId 발급) → `write_files`/`delete_files` → (필요 시) `register_assets`. planId 없이, 또는 플랜 밖 경로로 write/delete/register 호출 시 거부된다.

### 쓰기·삭제 승인 게이트

원격 디자인 시스템은 **다른 사람이 쓰고 있는 공용 자산**이다. 덮어쓴 파일의 이전 내용과 지운 파일은 원격에 남지 않는다 — 이 MCP에는 원자적 롤백이 없다(아래 §부분 실패 정책). 그래서 `finalize_plan`으로 경로를 잠그기 전에 멈춘다.

- **[HARD] 승인은 §승인 요청 계약의 경로로 받는다.** `finalize_plan`의 런타임 권한 프롬프트로 갈음하지 않는다 — 그 프롬프트는 경로 목록만 보여주고 digest·의미 diff·스냅샷 위치를 보여주지 않는다. 그 프롬프트는 경로 목록과 소스 디렉토리만 노출하며, `localPath` 경로는 **내용이 컨텍스트에 유입되지 않는 것이 설계 의도**이므로 사용자는 무엇이 덮어써지는지 보지 못한 채 승인하게 된다.
- **[HARD] 글롭은 승인 전에 펼쳐서 보여준다.** `writes[]`/`deletes[]`는 글롭을 허용한다. 펼치지 않은 글롭은 사용자가 의도한 것보다 훨씬 많이 매치될 수 있고, 그 차이는 승인 시점에 보이지 않는다. **실제로 매치된 경로를 하나씩 나열**하고 개수를 함께 적는다.
- **[HARD] 요약하지 말고 다음을 그대로 보여준다:**

| 보여줄 것 | 왜 필요한가 |
|---|---|
| 대상 프로젝트 이름·ID·타입 | 엉뚱한 프로젝트에 쓰는 사고를 막는다 |
| 펼친 경로 목록 — **신규 / 덮어쓰기** 구분 | 신규는 잃을 것이 없고, 덮어쓰기는 있다 |
| **삭제 경로 목록** (별도 구획) | 가장 되돌리기 어려운 항목이라 섞지 않는다 |
| 파일별 크기와 **digest(해시)** — 선택이 아니라 필수 | 내용을 못 봐도 규모와 동일성은 확인된다. `planId`가 잠그는 것은 **경로**뿐이므로, 내용을 묶는 것은 이 digest다 |
| 덮어쓰기 대상의 **의미 diff 요약** | 아래 규칙 참조 |
| **사본 없음 고지** | 이 작업으로 사라지는 내용은 복구되지 않는다는 사실 |

- **[HARD] 이 MCP에는 안전한 복구 스냅샷 수단이 없다. 스킬이 대신 만들지 않는다.** 원격 내용을 가져오는 유일한 경로는 `get_file`인데, 그 응답은 **모델 컨텍스트를 통과한다.** 자격증명·고객 자산·미공개 디자인이 섞여 있어도 그대로 지나가며, 받아 놓은 로컬 사본에는 권한·보존 기간·저장소 제외 규칙이 없다. **백업을 만들려다 유출 경로를 만드는 것이 더 나쁘다.**
- **[HARD] 대신 사용자에게 사실을 알린다.** 덮어쓰거나 지울 경로 목록을 보여주면서 **"이 파일들의 현재 내용은 이 작업으로 사라지며, 스킬은 사본을 만들지 않는다"** 고 명시한다. 사본이 필요하면 사용자가 직접 내려받은 뒤 진행하도록 안내한다.
- **대상은 덮어쓰기·삭제 경로뿐이다.** 신규 경로는 잃을 것이 없으므로 이 안내에서 뺀다 — 신규와 덮어쓰기를 나눠 보여주는 이유가 이것이다.
- 나중에 서버가 **내용을 응답하지 않고 제한 권한 디렉터리로 직접 내보내는** 기능을 제공하면 그때 자동 스냅샷을 다시 논한다. 그 전에는 **"복구 사본을 받아 둡니다"라고 약속하지 않는다.**
- **[HARD] 의미 diff를 만들려고 원격 원문을 가져오지 않는다.** 내용 대조를 하려면 `get_file`로 원격 전체를 받아야 하는데, 그것이 바로 위에서 막은 유출 경로다. 승인 화면에는 **원문 없이 알 수 있는 것만** 적는다 — 경로, 신규/덮어쓰기 구분, 로컬 파일의 크기와 digest, 삭제 대상.
- 내용 수준의 diff가 꼭 필요하면 **사용자가 직접 받아 둔 사본을 건네줄 때만** 만든다. 스킬이 원격에서 끌어오지 않는다.

승인 선택지는 이렇게 구성한다:

| 선택지 | 뜻 |
|---|---|
| 이 매니페스트대로 실행 (권장) | 보여준 경로 집합 그대로 `finalize_plan` → write/delete |
| 삭제는 빼고 쓰기만 | `deletes[]`를 비우고 플랜을 다시 수립 |
| 경로 좁히기 | 매니페스트를 줄여 게이트를 다시 |
| 취소 | `finalize_plan`을 호출하지 않고 종료. 원격 변경 없음 |

- **[HARD] `planId`는 승인된 그 매니페스트에 묶인다.** 승인 뒤 경로를 추가하거나 글롭을 넓히려면 **재승인**을 받고 `finalize_plan`을 다시 실행한다. 기존 `planId`에 슬쩍 얹지 않는다.
- **[HARD] `write_files` 직전에 digest를 다시 계산해 승인 시점 값과 대조한다.** `write_files`는 승인 뒤 `localPath`를 **다시 읽는다** — 승인과 업로드 사이에 파일이 바뀌면 사용자가 승인한 적 없는 내용이 같은 경로로 올라간다. 동시 편집·빌드 산출물 갱신·파일 교체가 실제로 일어나는 구간이다.
- **하나라도 어긋나면 그 `planId`를 폐기하고 재승인을 받는다.** 어긋난 파일만 빼고 진행하지 않는다 — 무엇이 왜 바뀌었는지 모르는 상태이기 때문이다.
- **[HARD] 이 대조는 창을 좁힐 뿐 닫지 못한다. 그 한계를 사용자에게 숨기지 않는다.** `write_files` 스키마에는 `e