reborn-stitch 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,51 @@
1
+ # reborn-stitch
2
+
3
+ **Google Stitch 로 만든 UI 디자인 시스템을 MCP 로 클로드 코드에 붙이는 절차**를 안내하는 스킬입니다.
4
+
5
+ ```
6
+ npx --yes reborn-stitch --check ← 깔지 않고 이 컴퓨터를 먼저 잽니다
7
+ npx --yes reborn-stitch ← 안내 스킬을 깝니다
8
+ ```
9
+
10
+ ## 무엇을 하나
11
+
12
+ `--check` 가 **이 컴퓨터에서 다섯 칸을 실제로 잽니다.**
13
+
14
+ | 칸 | 왜 |
15
+ |---|---|
16
+ | 노드 18 이상 | 이 설치기가 도는 최소 판 |
17
+ | 클로드 코드 | Stitch MCP 를 **붙일 대상**입니다. 없으면 붙일 데가 없습니다 |
18
+ | **MCP 등록** | ★가장 많이 막히는 자리 |
19
+ | API 키 자리 | ★**AI Studio 가 아닙니다** — Stitch 자체 설정에서 받습니다 |
20
+ | 디자인 시스템 | 붙여도 Stitch 쪽이 비어 있으면 가져올 게 없습니다 |
21
+
22
+ ## ★이 설치기가 있는 이유
23
+
24
+ **MCP 등록이 빠져도 에러가 안 납니다.**
25
+
26
+ 클로드는 아무 말 없이 전처럼 프론트를 **짐작해서** 짓습니다.
27
+ 「붙였는데 안 바뀐다」는 말의 대부분이 이 자리이고, 조용한 실패라 사람이 못 잡습니다.
28
+ 그래서 기계가 잽니다.
29
+
30
+ ## 안 하는 것
31
+
32
+ - **키를 대신 받지 않습니다.** 보지도, 넣지도 않습니다. `<본인 키>` 자리는 사용자가 채웁니다.
33
+ - **대신 등록하지 않습니다.** 명령을 정확히 알려 줄 뿐입니다.
34
+ - Stitch 코드를 **재배포하지 않습니다.**
35
+
36
+ ## 말하지 않는 것
37
+
38
+ 가격·크레딧 한도 · 현재 쓰는 모델 · 한국에서 되는지 — **공식 출처를 못 찾은 값은 말하지 않습니다.**
39
+ 확인된 것만 `skill/stitch.json` 에 출처와 함께 적혀 있습니다.
40
+
41
+ ---
42
+
43
+ Stitch © Google. **우리가 만든 제품이 아니고 제휴 관계도 없습니다.**
44
+ 우리가 만든 것은 이 안내뿐입니다. — REBORN LABS · MIT
45
+
46
+ ## 다음 칸
47
+
48
+ 같은 방식으로 고른 안내 스킬 48종을 한 곳에 모아 뒀습니다 — **리본랩스 스킬팩(8,900원)**.
49
+ `rebornlabs.kr/skillpack`
50
+
51
+ 목록과 **직접 까는 명령까지 그 페이지에 그대로** 적혀 있습니다. 안 사셔도 됩니다.
package/cli.mjs ADDED
@@ -0,0 +1,289 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Stitch 안내 설치기 — **붙이기 전에 이 컴퓨터가 되는지 재 주고**, 안내 스킬을 깐다.
4
+ *
5
+ * npx --yes reborn-stitch 안내 스킬을 깐다 (이게 전부다)
6
+ * npx --yes reborn-stitch --check ★깔지 않고 **이 컴퓨터를 실제로 잰다**
7
+ * npx --yes reborn-stitch --dry-run 무엇을 할지 보여주기만 한다
8
+ * npx --yes reborn-stitch --local 홈이 아니라 현재 폴더에 깐다
9
+ * npx --yes reborn-stitch --self-test 자기시험 (네트워크 안 씀)
10
+ *
11
+ * ★★우리가 만든 제품이 아니다.
12
+ * Google Stitch 는 구글 제품이고 우리는 제휴 관계가 없다. 우리는 **대신 등록하지 않는다** —
13
+ * 키를 받지도, 보지도, 넣지도 않는다. 안내만 한다.
14
+ *
15
+ * ★★--check 가 이 설치기의 존재 이유다
16
+ * Stitch 는 「말로 적으면 UI 가 나온다」로 읽힌다. 그런데 실제로 막히는 자리는 셋이다:
17
+ * ① **API 키 자리** — AI Studio 가 아니라 **Stitch 자체 설정**에서 받는다.
18
+ * 여기서 한참을 헤맨다(공식 코드랩이 그 경로를 적어 뒀는데 아무도 안 본다).
19
+ * ② ★★★**MCP 등록** — 안 돼 있어도 **에러가 안 난다.** 클로드는 그냥 전처럼
20
+ * 프론트를 짐작해서 짓는다. 「붙였는데 안 바뀐다」의 대부분이 이 자리다.
21
+ * 조용한 실패라 사람이 못 잡는다 — 그래서 **기계가 잰다.**
22
+ * ③ **가져올 프로젝트** — MCP 를 붙여도 Stitch 쪽이 비어 있으면 가져올 게 없다.
23
+ * 그래서 말로 「준비물이 있습니다」 하지 않고, **지금 이 컴퓨터에서 다섯 개를 직접 재 준다.**
24
+ * 못 재면 「못 쟀다」고 한다 — 「있다」고 하지 않는다.
25
+ */
26
+ import { existsSync, readFileSync, mkdirSync, cpSync, readdirSync } from "node:fs";
27
+ import { homedir, platform } from "node:os";
28
+ import { dirname, join } from "node:path";
29
+ import { fileURLToPath } from "node:url";
30
+ import { execFileSync } from "node:child_process";
31
+ import { TAIL, 링크, 마지막 } from "./tail.mjs";
32
+
33
+ const HOME = homedir();
34
+ const 여기 = dirname(fileURLToPath(import.meta.url));
35
+ const 인자 = process.argv.slice(2);
36
+ const 확인만 = 인자.includes("--check");
37
+ const 미리보기 = 인자.includes("--dry-run");
38
+ const 여기에 = 인자.includes("--local");
39
+ const 자기시험모드 = 인자.includes("--self-test");
40
+
41
+ const c = { g: "\x1b[32m", r: "\x1b[31m", y: "\x1b[33m", d: "\x1b[90m", cy: "\x1b[36m", b: "\x1b[1m", 0: "\x1b[0m" };
42
+ const 굵게 = (t) => String(t).replace(/\*\*(.+?)\*\*/g, `${c[0]}${c.b}$1${c[0]}${c.d}`);
43
+
44
+ const 퍼널 = "stitch";
45
+ const 스킬이름 = "stitch-guide";
46
+ const 원본 = join(여기, "skill");
47
+ const 대상뿌리 = 여기에 ? join(process.cwd(), ".claude", "skills") : join(HOME, ".claude", "skills");
48
+ const 대상 = join(대상뿌리, 스킬이름);
49
+
50
+ /* ══ 원장 ═══════════════════════════════════════════════════════════ */
51
+
52
+ function 원장읽기() {
53
+ const p = join(원본, "stitch.json");
54
+ if (!existsSync(p)) return { 됨: false, 이유: `원장이 없다 — ${p}` };
55
+ try { return { 됨: true, d: JSON.parse(readFileSync(p, "utf8")) }; }
56
+ catch (e) { return { 됨: false, 이유: `원장을 못 읽었다 — ${e.message}` }; }
57
+ }
58
+
59
+ /** ★조건 없이 단정하는 말 [[kmong-no-unbounded-guarantee]] */
60
+ const 금칙 = [/완전\s*무료/, /무제한/, /평생/, /100\s*%\s*보장/, /누구나\s*바로/, /무조건/,
61
+ /반드시\s*빨라/, /비용\s*걱정\s*없/, /디자이너가\s*필요\s*없/];
62
+ const 금칙면제 = /(하지\s*않는다|말하지\s*마라|쓰지\s*않는다|아니다|틀리다|금칙|안\s*된다|하지\s*마라|말하지\s*않는다|은\s*아니다|되지\s*않는다|마라|않는다|다른\s*이야기)/;
63
+ /** ★검사기가 자기 인용을 막지 않게 낫표 안은 벗기고 잰다 [[forbidden-word-checker-blocks-its-own-quotes]] */
64
+ const 인용벗기기 = (s) => String(s).replace(/「[^」]*」/g, "○");
65
+
66
+ function 금칙검사(텍스트, 어디) {
67
+ const 문제 = [];
68
+ for (const 줄 of String(텍스트).split("\n")) {
69
+ const 벗긴 = 인용벗기기(줄);
70
+ if (금칙면제.test(벗긴)) continue;
71
+ for (const re of 금칙) if (re.test(벗긴)) 문제.push(`${어디}: 조건 없이 단정하는 말 — ${줄.trim().slice(0, 60)}`);
72
+ }
73
+ return 문제;
74
+ }
75
+
76
+ function 원장검사(d) {
77
+ const 문제 = [];
78
+ if (!/^https:\/\/stitch\.withgoogle\.com/.test(String(d?.제품?.주소 || "")))
79
+ 문제.push("제품 주소가 stitch.withgoogle.com 이 아니다");
80
+ if (d?.제품?.만든이 !== "Google") 문제.push("만든이 칸이 Google 이 아니다 — 남의 제품이면 귀속을 박는다");
81
+ if (!String(d?.제품?.["★면책"] || "").includes("우리가 만든 것이 아니다"))
82
+ 문제.push("★면책이 사라졌다 — 남의 제품을 크게 세우면 귀속을 반드시 박는다");
83
+
84
+ /* ★★키가 예시로라도 들어가 있으면 막는다. 참고본 화면에는 제작자의 실제 키가 찍혀 있었다. */
85
+ const 전문 = JSON.stringify(d);
86
+ if (/AQ\.[A-Za-z0-9_-]{12,}/.test(전문)) 문제.push("원장에 실제 API 키처럼 보이는 문자열이 있다 — <본인 키> 로 가려라");
87
+ if (!String(d?.명령?.MCP등록 || "").includes("<본인 키>")) 문제.push("MCP 등록 명령에 키 자리가 안 가려져 있다");
88
+
89
+ const 관문 = Array.isArray(d?.관문) ? d.관문 : [];
90
+ if (관문.length < 5) 문제.push(`관문이 ${관문.length}개다 — 다섯 가지를 재기로 한 설치기다`);
91
+ for (const [i, g] of 관문.entries()) {
92
+ if (!g?.이름 || !g?.왜 || !g?.어떻게) 문제.push(`관문 ${i + 1}: 이름·왜·어떻게 중 빈 칸이 있다`);
93
+ }
94
+ if (!Array.isArray(d?.["★말하지_않는_것"]) || d["★말하지_않는_것"].length < 3)
95
+ 문제.push("★말하지 않는 것이 3개 미만이다 — 안내가 광고가 된다");
96
+ if (!String(d?.["★말하지_않는_것"]?.join(" ") || "").includes("가격"))
97
+ 문제.push("가격·한도를 막는 줄이 없다 — 확인 못 한 값이 그대로 나간다");
98
+ return 문제;
99
+ }
100
+
101
+ /* ══ 재기 ═══════════════════════════════════════════════════════════ */
102
+
103
+ const 실행 = (cmd, args, ms = 8000) => {
104
+ try {
105
+ return { 됨: true, out: String(execFileSync(cmd, args, { encoding: "utf8", timeout: ms, stdio: ["ignore", "pipe", "pipe"], shell: process.platform === "win32" })).trim() };
106
+ } catch (e) { return { 됨: false, 이유: String(e?.message || e).split("\n")[0].slice(0, 90) }; }
107
+ };
108
+
109
+ /** ★「못 쟀다」와 「없다」를 구분한다. 못 쟀는데 「없다」고 하면 그게 틀린 진단이다. */
110
+ function 재기(d) {
111
+ const 결과 = [];
112
+
113
+ /* ① 노드 판 */
114
+ const 최소 = Number(d.값.노드최소);
115
+ const 지금 = Number(String(process.versions.node).split(".")[0]);
116
+ 결과.push({
117
+ 이름: `노드 ${최소} 이상`,
118
+ 상태: 지금 >= 최소 ? "ok" : "no",
119
+ 값: `v${process.versions.node}`,
120
+ 말: 지금 >= 최소 ? "" : `노드를 먼저 올려야 한다 — 이 설치기가 도는 최소 판이 ${최소} 이다`,
121
+ });
122
+
123
+ /* ② 클로드 코드 — MCP 를 붙일 대상이다 */
124
+ const cc = 실행("claude", ["--version"]);
125
+ 결과.push({
126
+ 이름: "클로드 코드",
127
+ 상태: cc.됨 ? "ok" : "no",
128
+ 값: cc.됨 ? cc.out.split("\n")[0].slice(0, 40) : "PATH 에서 못 찾음",
129
+ 말: cc.됨 ? "" : "Stitch MCP 는 **클로드 코드에 붙이는 것**이다 — 붙일 데가 먼저 있어야 한다",
130
+ });
131
+
132
+ /* ③ ★★★MCP 등록 — 가장 많이 막히는 자리. **조용히** 실패한다 */
133
+ const ml = 실행("claude", ["mcp", "list"], 12000);
134
+ const 붙었나 = ml.됨 && /stitch/i.test(ml.out);
135
+ 결과.push({
136
+ 이름: "MCP 등록",
137
+ 상태: ml.됨 ? (붙었나 ? "ok" : "no") : "unknown",
138
+ 값: ml.됨 ? (붙었나 ? "등록돼 있다" : "목록에 없다") : "못 쟀다",
139
+ 말: ml.됨
140
+ ? (붙었나 ? ""
141
+ : `등록이 안 돼 있으면 **에러가 안 난다** — 클로드는 그냥 전처럼 짐작해서 짓는다.\n`
142
+ + ` ${c.cy}${d.명령.MCP등록}${c[0]}${c.d}`)
143
+ : "claude mcp list 를 못 불렀다 — 클로드 코드가 없거나 PATH 밖이다. 「없다」가 아니라 **「못 쟀다」**다",
144
+ });
145
+
146
+ /* ④ API 키 — ★재는 칸이 아니라 **자리를 정확히 말해 주는** 칸이다.
147
+ ★★우리가 키를 받지 않는다. 있는지 없는지도 우리가 알 일이 아니다. */
148
+ 결과.push({
149
+ 이름: "API 키",
150
+ 상태: "info",
151
+ 값: "AI Studio 아님",
152
+ 말: `**${d.값.키발급}**\n ${c.d}만든 키는 그 자리에서 복사해 둔다(다시 안 보여 준다). `
153
+ + "우리는 키를 받지도 보지도 않는다",
154
+ });
155
+
156
+ /* ⑤ 디자인 시스템 — 붙여도 가져올 게 없으면 안 바뀐다 */
157
+ const 흔적 = ["tokens.ts", "tokens.json", "tailwind.config.js", "tailwind.config.ts", "DESIGN.md"]
158
+ .filter((f) => existsSync(join(process.cwd(), f)));
159
+ 결과.push({
160
+ 이름: "디자인 시스템",
161
+ 상태: 흔적.length ? "ok" : "info",
162
+ 값: 흔적.length ? 흔적.join(" · ") : "이 폴더에는 아직 없다",
163
+ 말: 흔적.length ? ""
164
+ : "Stitch 쪽에 프로젝트가 없으면 MCP 를 붙여도 **가져올 게 없다.** "
165
+ + "먼저 Stitch 에서 화면을 한 번 만들고 Export 에서 MCP 를 고른다",
166
+ });
167
+
168
+ return 결과;
169
+ }
170
+
171
+ function 재기찍기(결과) {
172
+ const 표 = { ok: `${c.g}있음${c[0]}`, no: `${c.r}없음${c[0]}`, warn: `${c.y}확인${c[0]}`, unknown: `${c.y}못 쟀음${c[0]}`, info: `${c.cy}읽을 것${c[0]}` };
173
+ console.log(`\n ${c.b}이 컴퓨터에서 Stitch → 클로드 코드가 되는지${c[0]} ${c.d}(${platform()})${c[0]}\n`);
174
+ for (const r of 결과) {
175
+ console.log(` ${표[r.상태]} ${c.b}${r.이름}${c[0]} ${c.d}${r.값}${c[0]}`);
176
+ if (r.말) console.log(` ${c.d}${굵게(r.말)}${c[0]}`);
177
+ }
178
+ const 막힘 = 결과.filter((r) => r.상태 === "no").length;
179
+ console.log(`\n ${막힘 ? `${c.y}막히는 자리 ${막힘}개${c[0]}` : `${c.g}막히는 자리 없음${c[0]}`}`
180
+ + ` ${c.d}· 못 잰 칸은 「없다」가 아니라 「못 쟀다」입니다${c[0]}\n`);
181
+ return 막힘;
182
+ }
183
+
184
+ /* ══ 끝난 뒤 한 칸 ═══════════════════════════════════════════════════ */
185
+ function 꼬리(깔았나) {
186
+ if (!깔았나) return; /* ★못 깔았으면 안 띄운다 */
187
+ const t = TAIL[퍼널];
188
+ console.log("");
189
+ for (const l of t.이음) console.log(` ${c.d}${굵게(l)}${c[0]}`);
190
+ console.log(`\n ${c.b}${t.제목}${c[0]} ${c.d}— ${t.한줄}${c[0]}`);
191
+ console.log(` ${c.cy}${링크(퍼널)}${c[0]}`);
192
+ console.log(` ${c.d}${마지막}${c[0]}\n`);
193
+ }
194
+
195
+ /* ══ 깔기 ═══════════════════════════════════════════════════════════ */
196
+ function 깔기() {
197
+ mkdirSync(대상뿌리, { recursive: true });
198
+ cpSync(원본, 대상, { recursive: true });
199
+ return readdirSync(대상);
200
+ }
201
+
202
+ /* ══ 자기시험 — ★양방향 ════════════════════════════════════════════ */
203
+ function 자기시험() {
204
+ const 나쁨 = [];
205
+ const L = 원장읽기();
206
+ if (!L.됨) { console.error(`✗ ${L.이유}`); process.exit(1); }
207
+ 나쁨.push(...원장검사(L.d));
208
+
209
+ const skill = join(원본, "SKILL.md");
210
+ if (!existsSync(skill)) 나쁨.push("skill/SKILL.md 가 없다");
211
+ else {
212
+ const t = readFileSync(skill, "utf8");
213
+ 나쁨.push(...금칙검사(t, "SKILL.md"));
214
+ if (!t.includes("Google")) 나쁨.push("SKILL.md 가 만든이를 안 밝힌다");
215
+ if (!t.includes("제휴 관계가 없다")) 나쁨.push("SKILL.md 가 제휴 없음을 안 밝힌다");
216
+ if (!/name:\s*stitch-guide/.test(t)) 나쁨.push("SKILL.md 의 name 이 stitch-guide 가 아니다 — 스킬이 안 불린다");
217
+ /* ★★키가 예시로라도 박혀 있으면 막는다 */
218
+ if (/AQ\.[A-Za-z0-9_-]{12,}/.test(t)) 나쁨.push("SKILL.md 에 실제 키처럼 보이는 문자열이 있다");
219
+ if (!t.includes("<본인 키>")) 나쁨.push("SKILL.md 의 등록 명령에 키 자리가 안 가려져 있다");
220
+ /* ★조용한 실패를 말해 주는가 — 이 설치기의 존재 이유다 */
221
+ if (!/에러가\s*안\s*난다/.test(t)) 나쁨.push("SKILL.md 가 「MCP 미등록은 에러가 안 난다」를 안 말한다");
222
+ }
223
+ 나쁨.push(...금칙검사(JSON.stringify(L.d), "원장"));
224
+
225
+ /* ★꼬리 규율 — 클로드킷·풀스택은 스킬팩 구매 이후다 */
226
+ const 꼬리글 = JSON.stringify(TAIL[퍼널] || {}) + 링크(퍼널) + 마지막;
227
+ if (!TAIL[퍼널]) 나쁨.push(`tail.mjs 에 「${퍼널}」 칸이 없다 — 앞 회차 문안이 그대로 나간다`);
228
+ for (const 금지 of ["클로드킷", "자비스", "58,000", "158,000", "일감 진단"]) {
229
+ if (꼬리글.includes(금지)) 나쁨.push(`꼬리에 「${금지}」 가 있다 — 스킬팩 한 칸만 말한다`);
230
+ }
231
+ if (!링크(퍼널).includes(`utm_campaign=${퍼널}`)) 나쁨.push("꼬리 링크에 utm_campaign 이 없다 — 어느 릴스가 만들었는지 못 센다");
232
+
233
+ /* ★미탐 시험 — 검사기가 실제로 잡는가 */
234
+ if (!금칙검사("이건 완전 무료입니다", "시험").length) 나쁨.push("금칙 검사가 「완전 무료」를 못 잡는다");
235
+ if (금칙검사("「완전 무료」라고 말하지 않는다", "시험").length) 나쁨.push("금칙 검사가 자기 인용을 오탐한다");
236
+ if (!원장검사({ ...L.d, 제품: { ...L.d.제품, 만든이: "REBORN" } }).length) 나쁨.push("원장 검사가 만든이 어긋남을 못 잡는다");
237
+ if (!원장검사({ ...L.d, 관문: L.d.관문.slice(0, 2) }).length) 나쁨.push("원장 검사가 관문 수 부족을 못 잡는다");
238
+ if (!원장검사({ ...L.d, 명령: { ...L.d.명령, MCP등록: "claude mcp add stitch --header \"X-Goog-Api-Key: AQ.Ab8RN6l4example\"" } }).length)
239
+ 나쁨.push("원장 검사가 실제 키 모양 문자열을 못 잡는다 — 남의 키가 그대로 나갈 자리다");
240
+
241
+ /* ★재기가 던지지 않는가 (네트워크·외부 명령이 없어도 돌아야 한다) */
242
+ let 결과 = null;
243
+ try { 결과 = 재기(L.d); } catch (e) { 나쁨.push(`재기가 던졌다: ${e.message}`); }
244
+ if (결과 && 결과.length !== L.d.관문.length)
245
+ 나쁨.push(`재는 칸이 ${결과.length}개인데 원장의 관문은 ${L.d.관문.length}개다 — 원장에 적고 안 재는 칸이 생긴다`);
246
+ if (결과 && 결과.some((r) => !r.이름 || !r.상태)) 나쁨.push("재기 결과에 빈 칸이 있다");
247
+
248
+ if (나쁨.length) { console.error("✗ 자기시험 실패\n - " + 나쁨.join("\n - ")); process.exit(1); }
249
+ console.log(`✓ 자기시험 통과 — 원장 관문 ${L.d.관문.length}개 · 재는 칸 ${결과.length}개 · 금칙 검사 양방향 · 키 가림 · 꼬리 규율`);
250
+ }
251
+
252
+ /* ══ 본문 ═══════════════════════════════════════════════════════════ */
253
+ if (자기시험모드) { 자기시험(); process.exit(0); }
254
+
255
+ const L = 원장읽기();
256
+ if (!L.됨) { console.error(`✗ ${L.이유}`); process.exit(1); }
257
+ const D = L.d;
258
+
259
+ console.log(`\n ${c.b}Google Stitch${c[0]} ${c.d}— ${D.제품.만든이} 의 제품 (우리가 만든 것이 아닙니다)${c[0]}`);
260
+ console.log(` ${c.d}${D.제품.주소}${c[0]}`);
261
+
262
+ const 결과 = 재기(D);
263
+ const 막힘 = 재기찍기(결과);
264
+
265
+ if (확인만) {
266
+ console.log(` ${c.d}안내 스킬을 깔려면: ${c.cy}npx --yes reborn-stitch${c[0]}\n`);
267
+ process.exit(0);
268
+ }
269
+ if (미리보기) {
270
+ console.log(` ${c.d}깔 자리: ${대상}${c[0]}`);
271
+ console.log(` ${c.d}담을 것: ${readdirSync(원본).join(" · ")}${c[0]}\n`);
272
+ process.exit(0);
273
+ }
274
+
275
+ let 깔았나 = false;
276
+ try {
277
+ const 담긴 = 깔기();
278
+ 깔았나 = true;
279
+ console.log(` ${c.g}안내 스킬을 깔았습니다${c[0]} ${c.d}→ ${대상}${c[0]}`);
280
+ console.log(` ${c.d}담긴 것: ${담긴.join(" · ")}${c[0]}`);
281
+ console.log(`\n 클로드 코드를 다시 열고 ${c.b}「스티치 붙여줘」${c[0]} 라고 하면 스킬이 이어서 안내합니다.`);
282
+ if (막힘) console.log(` ${c.y}막히는 자리 ${막힘}개는 위에 적어 두었습니다 — 그것부터 풉니다.${c[0]}`);
283
+ } catch (e) {
284
+ console.error(`\n ${c.r}못 깔았습니다${c[0]} — ${String(e.message).slice(0, 120)}`);
285
+ console.error(` ${c.d}권한 문제면 --local 로 현재 폴더에 깔 수 있습니다.${c[0]}\n`);
286
+ process.exit(1);
287
+ }
288
+
289
+ 꼬리(깔았나);
package/package.json ADDED
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "reborn-stitch",
3
+ "version": "1.0.0",
4
+ "description": "Google Stitch 로 만든 UI 디자인 시스템을 MCP 로 클로드 코드에 붙이는 절차를 안내하는 스킬입니다. --check 가 이 컴퓨터에서 다섯 가지(노드 · 클로드 코드 · MCP 등록 · API 키 자리 · 디자인 시스템)를 실제로 재 줍니다. 가장 많이 막히는 자리는 MCP 등록입니다 — 안 돼 있어도 에러가 안 나고, 클로드는 그냥 전처럼 프론트를 짐작해서 짓습니다. Stitch 는 구글 제품이고 우리는 제휴 관계가 없습니다.",
5
+ "keywords": [
6
+ "claude",
7
+ "claude-code",
8
+ "stitch",
9
+ "google-stitch",
10
+ "mcp",
11
+ "design-system",
12
+ "design-tokens",
13
+ "ui-design",
14
+ "frontend",
15
+ "korean"
16
+ ],
17
+ "homepage": "https://rebornlabs.kr/stitch?utm_source=installer&utm_medium=cli&utm_campaign=stitch",
18
+ "bugs": {
19
+ "url": "https://mobility.rebornlabs.kr/cs"
20
+ },
21
+ "license": "MIT",
22
+ "author": "REBORN LABS",
23
+ "type": "module",
24
+ "bin": {
25
+ "reborn-stitch": "cli.mjs"
26
+ },
27
+ "files": [
28
+ "cli.mjs",
29
+ "tail.mjs",
30
+ "skill/",
31
+ "README.md",
32
+ "안내스킬.md"
33
+ ],
34
+ "engines": {
35
+ "node": ">=18"
36
+ },
37
+ "scripts": {
38
+ "test": "node cli.mjs --self-test",
39
+ "check": "node cli.mjs --check"
40
+ },
41
+ "publishConfig": {
42
+ "access": "public"
43
+ }
44
+ }
package/skill/SKILL.md ADDED
@@ -0,0 +1,109 @@
1
+ ---
2
+ name: stitch-guide
3
+ description: >
4
+ Google Stitch(stitch.withgoogle.com)로 UI 를 만들고, 그 디자인 시스템을 MCP 로
5
+ 클로드 코드에 붙여 **짐작 대신 시스템에서 짓게** 하는 절차를 안내한다.
6
+ "스티치", "Stitch", "구글 스티치", "stitch mcp", "디자인 시스템 연결",
7
+ "클로드가 디자인대로 안 만든다", "프론트가 AI 티 난다", "UI 를 말로 만들기",
8
+ "figma 말고", "디자인 토큰 가져오기" 같은 이야기가 나올 때 쓴다.
9
+ ★가장 많이 막히는 자리를 먼저 말한다 — API 키는 AI Studio 가 아니라 Stitch 설정에서 받고,
10
+ MCP 등록이 빠져도 **에러가 안 난다**(그냥 전처럼 짐작해서 짓는다).
11
+ ---
12
+
13
+ # Google Stitch → MCP → 클로드 코드
14
+
15
+ > **우리가 만든 도구가 아니다.** Stitch 는 Google 의 제품이고 우리는 제휴 관계가 없다.
16
+ > 우리가 만든 것은 이 안내뿐이다. 아래 값은 전부 `stitch.json` 원장에 출처와 함께 적혀 있다.
17
+
18
+ ## 0. 먼저 이 컴퓨터를 잰다
19
+
20
+ ```
21
+ npx --yes reborn-stitch --check
22
+ ```
23
+
24
+ 다섯 칸을 실제로 잰다 — 노드 판 · 클로드 코드 · MCP 등록 · API 키 자리 · 디자인 시스템.
25
+ **못 잰 칸은 「없다」가 아니라 「못 쟀다」고 말한다.**
26
+
27
+ ## 1. Stitch 에서 화면을 만든다
28
+
29
+ `https://stitch.withgoogle.com` 에 들어가 **만들고 싶은 앱을 평범한 말로 적는다.**
30
+ 참고 이미지(핀터레스트·드리블 등)를 같이 넣을 수 있다.
31
+
32
+ ★여기서 나오는 것은 그림 몇 장이 아니라 **UI 시스템 한 벌**이다 — 화면·레이아웃·색·타입 스케일.
33
+ 그게 뒤에서 클로드가 읽을 재료다.
34
+
35
+ ## 2. ★API 키 — 여기서 가장 많이 헤맨다
36
+
37
+ **AI Studio 가 아니다.** Stitch 자체 설정에서 받는다:
38
+
39
+ > Stitch 화면 **우상단 프로필** → **Stitch settings** → **API key** → **Create key**
40
+
41
+ ★만든 키는 **그 자리에서 복사해 안전한 곳에 둔다.** 다시 안 보여 준다.
42
+ ★★키를 코드·저장소·스크린샷에 넣지 마라. 아래 명령에서도 `<본인 키>` 자리에만 들어간다.
43
+ **우리는 그 키를 받지도, 보지도, 대신 넣지도 않는다.**
44
+
45
+ ## 3. 클로드 코드에 MCP 로 붙인다
46
+
47
+ ```
48
+ claude mcp add stitch \
49
+ --transport http \
50
+ --url "https://stitch.googleapis.com/mcp" \
51
+ --header "X-Goog-Api-Key: <본인 키>"
52
+ ```
53
+
54
+ 확인:
55
+
56
+ ```
57
+ claude mcp list
58
+ ```
59
+
60
+ 목록에 `stitch` 가 보여야 한다.
61
+
62
+ ★★**여기가 조용히 실패하는 자리다.** 등록이 안 돼 있어도 **에러가 안 난다** —
63
+ 클로드는 그냥 전처럼 프론트를 **짐작해서** 짓는다. 「붙였는데 안 바뀐다」의 대부분이 이것이다.
64
+ 그래서 `--check` 가 이 칸을 따로 잰다.
65
+
66
+ ## 4. Stitch 에서 내보낸다
67
+
68
+ Export 형식은 일곱이다 — `AI Studio` · `Figma` · `Jules` · `.zip` ·
69
+ `Code to Clipboard` · **`MCP`** · `Project Brief`.
70
+
71
+ **MCP** 를 고른다. 그러면 클로드가 프로젝트를 직접 읽는다.
72
+
73
+ ## 5. 이제 무엇이 달라지나
74
+
75
+ MCP 가 붙으면 클로드는 프로젝트 목록을 보고, 색·타이포 같은 메타를 가져오고,
76
+ 디자인 토큰과 레이아웃 규칙을 뽑아 쓸 수 있다.
77
+
78
+ | 짐작해서 만들 때 | 시스템에서 지을 때 |
79
+ |---|---|
80
+ | 색을 그때그때 고른다 | 토큰에서 색을 읽는다 |
81
+ | 간격이 화면마다 다르다 | 간격 스케일이 하나다 |
82
+ | 버튼이 세 종류가 된다 | 버튼이 한 벌로 나온다 |
83
+
84
+ 지시는 평범하게 하면 된다:
85
+
86
+ > 화면 연결하고, 애니메이션 넣고, 반응형으로 정리해 줘.
87
+
88
+ ## 6. 안 되면 여기부터 본다
89
+
90
+ | 증상 | 대개 이 자리다 |
91
+ |---|---|
92
+ | 「붙였는데 화면이 그대로다」 | `claude mcp list` 에 stitch 가 없다. 등록이 안 됐는데 **에러가 안 난 것**이다 |
93
+ | 「키가 어디 있는지 모르겠다」 | AI Studio 를 뒤지고 있을 것이다. **Stitch settings** 다 |
94
+ | 「가져올 게 없다고 한다」 | Stitch 쪽에 프로젝트가 아직 없다. 1번부터 |
95
+ | 「등록 명령이 안 먹는다」 | 클로드 코드가 PATH 에 없을 수 있다. `claude --version` 부터 |
96
+
97
+ ## ★말하지 않는 것
98
+
99
+ - Stitch 의 **가격·크레딧 한도** — 공식 출처를 못 찾았다(2026-09-10 확인 시도).
100
+ 3자 블로그에 도는 수치를 옮기지 않는다.
101
+ - Stitch 가 **지금 쓰는 모델** — 출시 당시 기사(2025-05)는 Gemini 2.5 Pro/Flash 라고 적지만
102
+ 현재 값은 확인 못 했다.
103
+ - **한국에서 되는지** — 지역 제한을 적은 공식 문서를 못 찾았다.
104
+ - 몇 % 빨라진다 · 몇 배 좋아진다 — **우리가 잰 적이 없다.**
105
+ - Stitch 가 만든 디자인의 저작·상업이용 조건 — 구글 약관이 정한다.
106
+
107
+ ---
108
+
109
+ *Stitch © Google · 이 안내는 REBORN LABS 가 만들었고 구글과 제휴 관계가 없다.*
@@ -0,0 +1,77 @@
1
+ {
2
+ "_doc": "reborn-stitch 안내 설치기의 원장. --check 가 재는 다섯 칸과, 안내 스킬이 말하는 사실이 전부 여기서 온다.",
3
+ "_규칙": "값마다 출처가 있어야 한다. 확인 못 한 값은 넣지 마라 — 안 넣는 것이 틀리게 넣는 것보다 낫다.",
4
+ "_잰날": "2026-09-10",
5
+ "제품": {
6
+ "이름": "Google Stitch",
7
+ "주소": "https://stitch.withgoogle.com",
8
+ "제목": "Stitch - Design with AI",
9
+ "한줄": "Stitch generates UIs for mobile and web applications, making design ideation fast and easy.",
10
+ "만든이": "Google",
11
+ "출시": "2025-05-20 (Google I/O 2025)",
12
+ "★면책": "우리가 만든 것이 아니다. Google 의 제품이고 우리는 제휴 관계가 없다. 우리가 만든 것은 이 안내 설치기뿐이다.",
13
+ "_출처": "stitch.withgoogle.com 직접 확인(2026-09-10) · 출시일 techcrunch.com/2025/05/20/google-launches-stitch-an-ai-powered-tool-to-help-design-apps"
14
+ },
15
+ "값": {
16
+ "노드최소": 18,
17
+ "키발급": "Stitch 화면 우상단 프로필 → Stitch settings → API key → Create key",
18
+ "_키발급출처": "codelabs.developers.google.com/design-to-code-with-antigravity-stitch (구글 공식 코드랩 · 2026-09-10 확인)",
19
+ "MCP주소": "https://stitch.googleapis.com/mcp",
20
+ "MCP헤더": "X-Goog-Api-Key",
21
+ "내보내기형식": [
22
+ "AI Studio",
23
+ "Figma",
24
+ "Jules",
25
+ ".zip",
26
+ "Code to Clipboard",
27
+ "MCP",
28
+ "Project Brief"
29
+ ],
30
+ "MCP가하는일": [
31
+ "프로젝트 목록",
32
+ "프로젝트 메타(색·타이포) 가져오기",
33
+ "디자인 토큰·레이아웃 규칙 추출"
34
+ ],
35
+ "_MCP출처": "같은 공식 코드랩. ★툴 이름 그대로가 아니라 문서가 적은 기능 설명이다 — 툴 이름을 지어내지 않는다."
36
+ },
37
+ "명령": {
38
+ "MCP등록": "claude mcp add stitch --transport http --url \"https://stitch.googleapis.com/mcp\" --header \"X-Goog-Api-Key: <본인 키>\"",
39
+ "MCP확인": "claude mcp list",
40
+ "_출처": "형식은 공식 코드랩과 같고, 값은 우리가 화면에서 읽었다. ★키 자리는 언제나 <본인 키> 다 — 예시 키를 넣지 않는다."
41
+ },
42
+ "관문": [
43
+ {
44
+ "이름": "노드 18 이상",
45
+ "왜": "이 설치기가 도는 최소 판이다. 낮으면 깔리는 듯하다 실행에서 죽는다.",
46
+ "어떻게": "process.versions.node 를 읽어 잰다"
47
+ },
48
+ {
49
+ "이름": "클로드 코드",
50
+ "왜": "Stitch MCP 는 클로드 코드에 붙이는 것이다. 클로드 코드가 없으면 붙일 데가 없다.",
51
+ "어떻게": "claude --version 을 불러 본다. 못 부르면 「없다」가 아니라 「못 쟀다」다"
52
+ },
53
+ {
54
+ "이름": "MCP 등록",
55
+ "왜": "가장 많이 막히는 자리다. 등록이 안 돼 있으면 클로드는 디자인을 못 본다 — 그런데 아무 에러도 안 난다. 그냥 전처럼 짐작해서 짓는다.",
56
+ "어떻게": "claude mcp list 에 stitch 가 있는지 본다"
57
+ },
58
+ {
59
+ "이름": "API 키",
60
+ "왜": "MCP 등록 명령에 본인 키가 들어간다. ★AI Studio 가 아니라 Stitch 자체 설정에서 받는다 — 여기서 헤매는 사람이 많다.",
61
+ "어떻게": "재지 않는다. 받는 자리를 정확히 말해 준다. ★우리가 키를 대신 받지 않는다"
62
+ },
63
+ {
64
+ "이름": "디자인 시스템",
65
+ "왜": "MCP 를 붙여도 Stitch 쪽에 프로젝트가 없으면 가져올 게 없다. 「붙였는데 안 바뀐다」의 절반이 이 자리다.",
66
+ "어떻게": "현재 폴더에 내보낸 토큰/설정 흔적이 있는지 본다. 없으면 「아직 없다」고만 한다"
67
+ }
68
+ ],
69
+ "★말하지_않는_것": [
70
+ "Stitch 의 가격 — 무료인지 · 하루 크레딧이 몇인지. 공식 출처를 못 찾았다(2026-09-10 확인 시도). 3자 블로그의 수치를 옮기지 않는다.",
71
+ "Stitch 가 지금 어느 모델을 쓰는지 — 출시 당시 기사(2025-05)는 Gemini 2.5 Pro/Flash 라고 적지만 지금은 확인 못 했다.",
72
+ "한국에서 되는지 안 되는지 — 지역 제한을 적은 공식 문서를 못 찾았다.",
73
+ "퍼센트 절감·몇 배 빠름 같은 수치 — 우리가 잰 적이 없다.",
74
+ "Stitch 가 만든 디자인의 저작·상업이용 조건 — 구글 약관이 정한다. 우리가 해석해 주지 않는다.",
75
+ "이걸 깔면 디자인이 좋아진다는 보장 — 도구가 하는 일만 말한다."
76
+ ]
77
+ }
package/tail.mjs ADDED
@@ -0,0 +1,25 @@
1
+ /**
2
+ * 「끝난 뒤 한 칸」 문안 — 정본은 `skillpack/tail_copy.mjs` 다.
3
+ * 사본이 여기 있는 이유는 하나뿐이다: npm 패키지는 폴더 밖을 import 할 수 없다.
4
+ * 고칠 일이 생기면 정본을 먼저 고치고 여기로 옮긴다. 반대로 하지 마라.
5
+ *
6
+ * 규율: ① 끝난 뒤 딱 한 칸 · ② 못 깔았으면 안 띄운다 · ③ 파일을 안 남긴다
7
+ * ④ 고지 블록 금지 · ⑤ 첫 줄은 방금 한 일에서 이어져야 한다
8
+ * ★클로드킷·자비스 풀스택은 여기서 말하지 않는다 — 스킬팩 구매 이후다(2026-08-24 전략).
9
+ */
10
+ export const 랜딩 = "https://rebornlabs.kr/skillpack";
11
+ export const 링크 = (퍼널) => `${랜딩}?utm_source=installer&utm_medium=cli&utm_campaign=${퍼널}`;
12
+
13
+ export const TAIL = {
14
+ stitch: {
15
+ 이음: [
16
+ "방금 한 일은 **이 컴퓨터에서 다섯 칸을 실제로 재 본 것**입니다 — 무엇이 있고 무엇이 없는지.",
17
+ "Stitch 는 구글이 만든 것입니다. 막히는 자리는 도구가 아니라 **조용히 빠지는 한 칸**이었습니다 — "
18
+ + "MCP 등록은 안 돼 있어도 에러가 안 납니다.",
19
+ ],
20
+ 제목: "리본랩스 스킬팩",
21
+ 한줄: "같은 방식으로 골라 담은 48종을 한 줄로. 8,900원",
22
+ },
23
+ };
24
+
25
+ export const 마지막 = "목록과 직접 까는 명령까지 그 페이지에 그대로 적어 두었습니다. 안 사셔도 됩니다.";
@@ -0,0 +1,51 @@
1
+ # reborn-stitch
2
+
3
+ **Google Stitch 로 만든 UI 디자인 시스템을 MCP 로 클로드 코드에 붙이는 절차**를 안내하는 스킬입니다.
4
+
5
+ ```
6
+ npx --yes reborn-stitch --check ← 깔지 않고 이 컴퓨터를 먼저 잽니다
7
+ npx --yes reborn-stitch ← 안내 스킬을 깝니다
8
+ ```
9
+
10
+ ## 무엇을 하나
11
+
12
+ `--check` 가 **이 컴퓨터에서 다섯 칸을 실제로 잽니다.**
13
+
14
+ | 칸 | 왜 |
15
+ |---|---|
16
+ | 노드 18 이상 | 이 설치기가 도는 최소 판 |
17
+ | 클로드 코드 | Stitch MCP 를 **붙일 대상**입니다. 없으면 붙일 데가 없습니다 |
18
+ | **MCP 등록** | ★가장 많이 막히는 자리 |
19
+ | API 키 자리 | ★**AI Studio 가 아닙니다** — Stitch 자체 설정에서 받습니다 |
20
+ | 디자인 시스템 | 붙여도 Stitch 쪽이 비어 있으면 가져올 게 없습니다 |
21
+
22
+ ## ★이 설치기가 있는 이유
23
+
24
+ **MCP 등록이 빠져도 에러가 안 납니다.**
25
+
26
+ 클로드는 아무 말 없이 전처럼 프론트를 **짐작해서** 짓습니다.
27
+ 「붙였는데 안 바뀐다」는 말의 대부분이 이 자리이고, 조용한 실패라 사람이 못 잡습니다.
28
+ 그래서 기계가 잽니다.
29
+
30
+ ## 안 하는 것
31
+
32
+ - **키를 대신 받지 않습니다.** 보지도, 넣지도 않습니다. `<본인 키>` 자리는 사용자가 채웁니다.
33
+ - **대신 등록하지 않습니다.** 명령을 정확히 알려 줄 뿐입니다.
34
+ - Stitch 코드를 **재배포하지 않습니다.**
35
+
36
+ ## 말하지 않는 것
37
+
38
+ 가격·크레딧 한도 · 현재 쓰는 모델 · 한국에서 되는지 — **공식 출처를 못 찾은 값은 말하지 않습니다.**
39
+ 확인된 것만 `skill/stitch.json` 에 출처와 함께 적혀 있습니다.
40
+
41
+ ---
42
+
43
+ Stitch © Google. **우리가 만든 제품이 아니고 제휴 관계도 없습니다.**
44
+ 우리가 만든 것은 이 안내뿐입니다. — REBORN LABS · MIT
45
+
46
+ ## 다음 칸
47
+
48
+ 같은 방식으로 고른 안내 스킬 48종을 한 곳에 모아 뒀습니다 — **리본랩스 스킬팩(8,900원)**.
49
+ `rebornlabs.kr/skillpack`
50
+
51
+ 목록과 **직접 까는 명령까지 그 페이지에 그대로** 적혀 있습니다. 안 사셔도 됩니다.