reborn-lottie 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,97 @@
1
+ # reborn-lottie
2
+
3
+ 영상에서 소개한 **LottieFiles Creator MCP** 를 **붙이기 전에 먼저 재 주는** 안내 스킬입니다.
4
+
5
+ ```bash
6
+ npx --yes reborn-lottie
7
+ ```
8
+
9
+ ## 이게 무엇을 하나
10
+
11
+ `~/.claude/skills/lottie-guide/` 에 안내 스킬 하나를 심습니다. 그게 전부입니다.
12
+
13
+ **MCP 는 저희가 대신 안 붙입니다.** 붙이는 건 정말로 한 줄이고,
14
+ 그 줄을 대신 실행해 주는 건 아무것도 아껴 주지 못하기 때문입니다.
15
+
16
+ ```
17
+ claude mcp add lottiefiles-creator -- npx -y @lottiefiles/creator-mcp@latest
18
+ ```
19
+
20
+ **우리 없이도 됩니다.** 위 줄을 그대로 쓰시면 붙습니다.
21
+
22
+ ## 그럼 무엇을 파나
23
+
24
+ 막히는 자리는 **그 줄 다음**에 있습니다.
25
+
26
+ | 막히는 자리 | 이 패키지가 하는 일 |
27
+ |---|---|
28
+ | 붙였는데 아무 일도 안 일어나요 | Creator 안에서 **MCP 를 켜야 한다**고 맨 앞에서 말합니다 |
29
+ | 되다가 갑자기 끊겨요 | **로그인한 Creator 탭이 살아 있어야 한다**고 말합니다 |
30
+ | 서버에 붙이려는데 안 돼요 | **로컬 stdio 전용**이라 원격 엔드포인트가 없다고 말합니다 |
31
+ | 노드 판이 안 맞아요 | Node 판을 **먼저 재고** 18 미만이면 거기서 멈춥니다 |
32
+ | 붙일 클라이언트가 있나요 | `claude` · `cursor` · `code` · `codex` 를 **실제로 찾습니다** |
33
+ | 이미 붙였던가요 | `claude mcp list` 를 **실제로 열어** 중복을 봅니다 |
34
+
35
+ ```bash
36
+ npx --yes reborn-lottie --check # 깔지 않고 이 컴퓨터만 잽니다
37
+ ```
38
+
39
+ ## 명령 한 줄 뒤에 남는 것
40
+
41
+ | | 무엇 | 안 하면 |
42
+ |---|---|---|
43
+ | ① | Creator 에서 **MCP 를 켠다** (설정 → MCP Settings → Enable MCP) | 명령은 나가는데 화면에서 아무 일도 안 일어납니다 |
44
+ | ② | 로그인한 **Creator 탭을 열어 둔다** | 탭을 닫는 순간 브리지가 끊깁니다 |
45
+ | ③ | **로컬에서만 쓴다** | 원격 서버·CI 에서는 붙지 않습니다 |
46
+
47
+ ②가 이 도구의 성격을 정합니다. **이건 에디터가 아니라 브리지입니다.**
48
+ 그리는 곳은 브라우저에서 도는 Lottie Creator 이고, MCP 는 그 탭에 명령을 실어 나르는 통로입니다.
49
+
50
+ ## 공짜의 범위 — 확인한 것과 못 한 것
51
+
52
+ | | 값 | |
53
+ |---|---|---|
54
+ | MCP 패키지 | **0원** | npm 공개 패키지 · MIT. 레지스트리를 직접 호출해 확인했습니다 |
55
+ | Creator 계정 | 사실상 필요 | 로그인한 탭이 있어야 브리지가 통신합니다 |
56
+ | 유료 플랜 연동 | **확인불가** | AI 크레딧과 물리는지 1차 출처를 못 읽었습니다 |
57
+ | 상업적 이용 | **확인불가** | 약관 원문이 403 — **일로 쓰실 거면 이걸 먼저 확인하셔야 합니다** |
58
+
59
+ 「무료」라고 저희 입으로 단정하지 않습니다.
60
+ 확인된 건 **MCP 패키지가 MIT 공개 패키지**라는 것까지입니다.
61
+
62
+ ## 무엇을 시킬 수 있나
63
+
64
+ 씬·레이어·셰이프·채우기·키프레임·재생 제어. 내보내기는 **Lottie JSON** 이 확인됐습니다.
65
+ GIF·MP4 로 바로 뽑히는지는 문서에 언급이 없어 **확인불가**로 둡니다.
66
+
67
+ State Machines · Motion Tokens 는 문서에 **예정**으로 적혀 있습니다. 아직 없습니다.
68
+
69
+ ## 헷갈리는 자리
70
+
71
+ - npm 에 **`mcp-server-lottiefiles`** 라는 비공식 서드파티 패키지가 따로 있습니다.
72
+ 커뮤니티 애니메이션을 **검색·조회만** 하는 다른 물건입니다. 잘못 깔기 쉬운 자리입니다.
73
+ - 공식 문서가 가리키는 GitHub 저장소는 접속하면 **404** 입니다.
74
+
75
+ ## 되돌리기
76
+
77
+ ```bash
78
+ rm -rf ~/.claude/skills/lottie-guide
79
+ ```
80
+
81
+ 심는 건 그 폴더 하나뿐입니다. 다른 곳은 건드리지 않습니다.
82
+ MCP 등록을 지우려면 `claude mcp remove lottiefiles-creator` — 그건 저희가 만든 게 아닙니다.
83
+
84
+ ## 자기시험
85
+
86
+ ```bash
87
+ npm test # = node cli.mjs --self-test (네트워크 안 씁니다)
88
+ ```
89
+
90
+ 원장에 확인일·확인방법이 있는지, 설치 명령의 `npx` 에 `-y` 가 있는지,
91
+ 확인 못 한 항목이 「확인불가」로 남아 있는지, 헷갈리는 서드파티 패키지를 짚는지를 봅니다.
92
+ **검사기 자체도 양방향으로 시험합니다** — 멀쩡한 원장을 막지 않는지, 망가뜨린 원장을 통과시키지 않는지.
93
+
94
+ ---
95
+
96
+ MIT · REBORN LABS · 문의 https://mobility.rebornlabs.kr/cs
97
+ LottieFiles · Lottie 는 LottieFiles 의 상표이며 저희와 아무 관계가 없습니다. 이 패키지는 안내 스킬입니다.
package/cli.mjs ADDED
@@ -0,0 +1,395 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * lottie-guide 설치기 — **영상이 말한 그 MCP 를 붙이기 전에 재 준다.**
4
+ *
5
+ * npx --yes reborn-lottie 안내 스킬을 깐다 (이게 전부다)
6
+ * npx --yes reborn-lottie --check ★깔지 않고 **이 컴퓨터를 잰다**
7
+ * npx --yes reborn-lottie --dry-run 무엇을 할지 보여주기만 한다
8
+ * npx --yes reborn-lottie --local 홈(~/.claude/skills)이 아니라 현재 폴더에 깐다
9
+ * npx --yes reborn-lottie --self-test 자기시험 (네트워크 안 씀)
10
+ *
11
+ * ★★왜 MCP 를 우리가 대신 안 붙이고 **안내 스킬**을 까나
12
+ * 붙이는 건 정말로 한 줄이다 — `claude mcp add lottiefiles-creator -- npx -y ...`.
13
+ * 우리가 그 줄을 대신 실행해 주는 건 아무것도 아껴 주지 못한다.
14
+ * 실제로 막히는 자리는 **그 줄 뒤**다:
15
+ * ① Creator 안에서 MCP 를 **직접 켜야** 한다 — 기본으로 꺼져 있다
16
+ * ② 로그인한 Creator **브라우저 탭을 열어 둔 채로** 써야 한다 — 닫으면 끊긴다
17
+ * ③ 로컬 stdio 전용이라 **원격·CI 에서는 못 쓴다**
18
+ * 참고본은 「명령어 하나로 설치하고 나서 원하는 걸 설명만 하면」이라고 말한다.
19
+ * 설치가 한 줄인 건 맞다. **한 줄이면 끝은 아니다.** 그 셋을 먼저 말하는 게 이 스킬이다.
20
+ *
21
+ * ★★--check 가 이 설치기의 존재 이유다
22
+ * 말로 「되실 겁니다」 하지 않는다. 실행 파일을 실제로 찾고 등록 목록을 실제로 연다.
23
+ * 못 찾으면 「모른다」고 한다 — 「된다」고 하지 않는다.
24
+ *
25
+ * ★★깔았다고 「됐다」고 하지 않는다.
26
+ * 복사는 조용히 실패한다(권한·경로·한글 홈디렉터리). 쓴 뒤 **다시 읽어 본다**
27
+ * [[kit-update-selfcheck]].
28
+ */
29
+ import { execFileSync } from "node:child_process";
30
+ import { cpSync, existsSync, mkdirSync, readFileSync, readdirSync, statSync } from "node:fs";
31
+ import { homedir, platform, arch } from "node:os";
32
+ import { dirname, join } from "node:path";
33
+ import { fileURLToPath } from "node:url";
34
+ import { 링크, TAIL, 마지막 } from "./tail.mjs";
35
+
36
+ const HOME = homedir();
37
+ const 여기 = dirname(fileURLToPath(import.meta.url));
38
+ const 인자 = process.argv.slice(2);
39
+ const 확인만 = 인자.includes("--check");
40
+ const 미리보기 = 인자.includes("--dry-run");
41
+ const 여기에 = 인자.includes("--local");
42
+ const 자기시험모드 = 인자.includes("--self-test");
43
+
44
+ const c = { g: "\x1b[32m", r: "\x1b[31m", y: "\x1b[33m", d: "\x1b[90m", cy: "\x1b[36m", b: "\x1b[1m", 0: "\x1b[0m" };
45
+ const 굵게 = (t) => String(t).replace(/\*\*(.+?)\*\*/g, `${c[0]}${c.b}$1${c[0]}${c.d}`);
46
+
47
+ const 퍼널 = "lottie";
48
+ const 스킬이름 = "lottie-guide";
49
+ const 원본 = join(여기, "skill");
50
+ const 대상뿌리 = 여기에 ? join(process.cwd(), ".claude", "skills") : join(HOME, ".claude", "skills");
51
+ const 대상 = join(대상뿌리, 스킬이름);
52
+
53
+ /* ══ 원장 ═══════════════════════════════════════════════════════ */
54
+
55
+ function 원장읽기() {
56
+ const p = join(원본, "lottie.json");
57
+ if (!existsSync(p)) return { 됨: false, 이유: `원장이 없다 — ${p}` };
58
+ try { return { 됨: true, d: JSON.parse(readFileSync(p, "utf8")) }; }
59
+ catch (e) { return { 됨: false, 이유: `원장을 못 읽는다 — ${e.message}` }; }
60
+ }
61
+
62
+ /** ★조건 없이 단정하는 말. 홍보문에 섞이면 잡는다. [[kmong-no-unbounded-guarantee]]
63
+ * ★이 회차는 「한 줄이면 끝」도 금칙이다 — 설치 뒤에 켜기·열어두기가 남아 있다. */
64
+ const 금칙 = [/완전\s*무료/, /무제한/, /평생/, /100\s*%\s*보장/, /누구나\s*바로/, /무조건/,
65
+ /한\s*줄이면\s*끝/, /설정\s*없이/, /공짜로\s*다/];
66
+
67
+ /** ★금칙 검사에서 빼는 자리 — 「그 말을 하지 마라」고 적어 둔 문장까지 잡으면
68
+ * 검사기가 자기 규칙 문서를 막는다(회차 ㉔에서 실제로 밟았다). 부정문만 골라 뺀다. */
69
+ const 금칙면제 = /(하지\s*않는다|말하지\s*마라|쓰지\s*않는다|아니다|틀리다|금칙|안\s*된다|하지\s*마라|말하지\s*않는다|은\s*아니다)/;
70
+
71
+ /** ★낫표 안은 **인용**이다 — 우리가 하는 말이 아니라 남이 한 말을 옮긴 것이다.
72
+ * 이 킷은 본문 절반이 「참고본은 이렇게 말했다」이므로, 인용까지 잡으면
73
+ * 검사기가 자기 존재 이유를 막는다 [[forbidden-word-checker-blocks-its-own-quotes]]. */
74
+ const 인용벗기기 = (s) => String(s).replace(/「[^」]*」/g, "○");
75
+
76
+ function 금칙검사(텍스트, 어디) {
77
+ const 문제 = [];
78
+ for (const 원줄 of String(텍스트).split(/\n|(?<=[.。])\s+/)) {
79
+ const 줄 = 인용벗기기(원줄);
80
+ if (금칙면제.test(줄)) continue;
81
+ for (const re of 금칙) if (re.test(줄)) 문제.push(`${어디}에 조건 없는 단정: ${re.source}`);
82
+ }
83
+ return 문제;
84
+ }
85
+
86
+ function 원장검사(d) {
87
+ const 문제 = [];
88
+ const 있나 = (v) => v !== undefined && v !== null && v !== "";
89
+
90
+ if (!있나(d?.확인일)) 문제.push("확인일이 없다 — 언제 잰 값인지 모르면 사실은 못 쓴다");
91
+ if (!있나(d?.확인방법)) 문제.push("확인방법이 없다 — 어디서 읽었는지 없는 말은 지어낸 것과 구분이 안 된다");
92
+ if (!있나(d?.제품?.문서)) 문제.push("제품.문서 주소가 없다");
93
+
94
+ /* ★설치 명령이 원장에 없으면 릴스·착지·DM 이 저마다 손으로 적게 된다. */
95
+ const 명령 = d?.설치?.["★명령"];
96
+ if (!있나(명령)) 문제.push("설치.★명령 이 없다 — 이 문자열 하나를 릴스·착지·DM 이 같이 읽는다");
97
+ else {
98
+ if (!/claude\s+mcp\s+add/.test(명령)) 문제.push("설치.★명령 이 claude mcp add 로 시작하지 않는다");
99
+ if (!/@lottiefiles\/creator-mcp/.test(명령)) 문제.push("설치.★명령 에 패키지 이름이 없다");
100
+ /* ★npx 안내에 -y 가 없으면 클로드 코드 안에서 무음 정지한다 [[npx-installer-needs-yes-flag]] */
101
+ if (/npx/.test(명령) && !/(^|\s)-y(\s|$)|--yes/.test(명령))
102
+ 문제.push("설치.★명령 의 npx 에 -y 가 없다 — 클로드 코드 안에서 확인 프롬프트를 기다리다 멈춘다");
103
+ }
104
+ if (!있나(d?.설치?.패키지)) 문제.push("설치.패키지 가 없다");
105
+ if (!/^\d+\.\d+\.\d+$/.test(String(d?.설치?.최신판 || ""))) 문제.push("설치.최신판 이 판 번호 모양이 아니다");
106
+
107
+ /* ★★이 킷의 존재 이유 — 「명령 하나로 안 끝난다」가 비면 통과시키지 않는다.
108
+ 이게 없으면 우리는 참고본과 똑같은 말만 하는 패키지가 된다. */
109
+ const 뒤 = d?.["★명령하나로_안_끝난다"];
110
+ if (!뒤) 문제.push("★명령하나로_안_끝난다 칸이 없다 — 이 패키지가 존재할 이유가 사라진다");
111
+ else {
112
+ /* ★「켜다」는 활용형이 갈린다 — 켜야/켭니다/켠다. 어간만 보면 「켭니다」를 놓친다.
113
+ Enable MCP 라는 실제 메뉴 이름도 같이 본다. */
114
+ if (!/켜|켭|Enable\s*MCP/.test(뒤["①켜기"] || "")) 문제.push("★명령하나로_안_끝난다.①켜기 가 Creator 에서 MCP 를 켜야 함을 말하지 않는다");
115
+ if (!/탭/.test(뒤["②열어두기"] || "")) 문제.push("★명령하나로_안_끝난다.②열어두기 가 브라우저 탭 조건을 말하지 않는다");
116
+ if (!/stdio|로컬/.test(뒤["③원격불가"] || "")) 문제.push("★명령하나로_안_끝난다.③원격불가 가 로컬 전용임을 말하지 않는다");
117
+ if (!있나(뒤.판정)) 문제.push("★명령하나로_안_끝난다.판정 이 비었다");
118
+ }
119
+
120
+ /* ★★확인 못 한 것을 확인한 것처럼 적어 두면 그게 곧 날조다. */
121
+ const 범위 = d?.["★공짜의범위"];
122
+ if (!범위) 문제.push("★공짜의범위 칸이 없다");
123
+ else {
124
+ if (!/확인불가/.test(범위.상업적이용 || ""))
125
+ 문제.push("★공짜의범위.상업적이용 이 확인불가로 적혀 있지 않다 — 약관 원문을 못 읽었다");
126
+ if (!/확인불가/.test(범위.지역 || ""))
127
+ 문제.push("★공짜의범위.지역 이 확인불가로 적혀 있지 않다");
128
+ if (!/MIT/.test(범위.MCP패키지 || ""))
129
+ 문제.push("★공짜의범위.MCP패키지 가 라이선스를 말하지 않는다");
130
+ if (!Array.isArray(범위.비교표) || 범위.비교표.length < 4)
131
+ 문제.push("★공짜의범위.비교표 가 4줄 미만이다");
132
+ }
133
+
134
+ /* ★없는 기능을 있는 것처럼 적지 않는다. */
135
+ if (!/예정|아직/.test(d?.할수있는일?.["★아직없는것"] || ""))
136
+ 문제.push("할수있는일.★아직없는것 이 예정 기능임을 말하지 않는다");
137
+ if (!/확인불가/.test(d?.내보내기?.["★GIF·MP4"] || ""))
138
+ 문제.push("내보내기.★GIF·MP4 가 확인불가로 적혀 있지 않다 — 영상으로 바로 뽑힌다고 말하면 안 된다");
139
+
140
+ /* ★남의 상표를 크게 세우므로 고지가 원장에 있어야 한다. */
141
+ if (!/상표/.test(d?.["★상표"]?.고지 || "")) 문제.push("★상표.고지 가 없다");
142
+
143
+ /* ★비슷한 이름의 다른 패키지를 안 적어 두면 사람이 그걸 깐다. */
144
+ if (!/mcp-server-lottiefiles/.test(d?.["★함정"]?.["★다른패키지"] || ""))
145
+ 문제.push("★함정.★다른패키지 가 헷갈리는 서드파티 패키지를 짚지 않는다");
146
+
147
+ for (const m of 금칙검사(JSON.stringify(d), "원장")) 문제.push(m);
148
+ return 문제;
149
+ }
150
+
151
+ /* ══ 이 컴퓨터를 잰다 ══════════════════════════════════════════════
152
+ ★말로 판정하지 않는다. 실제로 찾는다. 못 찾으면 「모른다」고 한다. */
153
+
154
+ function 실행파일있나(cmd) {
155
+ const 찾기 = process.platform === "win32" ? "where" : "which";
156
+ try {
157
+ const out = execFileSync(찾기, [cmd], { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"], timeout: 6000 });
158
+ const 첫줄 = String(out).trim().split(/\r?\n/)[0];
159
+ return 첫줄 ? 첫줄.trim() : null;
160
+ } catch { return null; }
161
+ }
162
+
163
+ /** 이미 붙어 있나. ★`claude mcp list` 는 없을 수도, 느릴 수도 있다 — 실패하면 「모른다」다. */
164
+ function 이미붙었나() {
165
+ if (!실행파일있나("claude")) return { 앎: false };
166
+ try {
167
+ const out = execFileSync("claude", ["mcp", "list"], {
168
+ encoding: "utf8", stdio: ["ignore", "pipe", "ignore"], timeout: 15000,
169
+ shell: process.platform === "win32",
170
+ });
171
+ return { 앎: true, 붙음: /lottiefiles-creator/.test(String(out)) };
172
+ } catch { return { 앎: false }; }
173
+ }
174
+
175
+ function 노드판() {
176
+ const m = /^v?(\d+)\./.exec(process.version || "");
177
+ return m ? Number(m[1]) : 0;
178
+ }
179
+
180
+ function 환경재기() {
181
+ const R = { os: platform(), arch: arch(), 노드: process.version, 노드메이저: 노드판(), 클라이언트: [], npx: null, 이미: null };
182
+
183
+ for (const [cmd, 이름] of [["claude", "Claude Code"], ["cursor", "Cursor"], ["code", "VS Code"], ["codex", "Codex"]]) {
184
+ const p = 실행파일있나(cmd);
185
+ if (p) R.클라이언트.push({ 이름, 경로: p });
186
+ }
187
+ R.npx = 실행파일있나("npx");
188
+ R.이미 = 이미붙었나();
189
+ return R;
190
+ }
191
+
192
+ function 환경보고(E, D) {
193
+ console.log(`\n${c.b}이 컴퓨터를 실제로 재 봤습니다${c[0]}`);
194
+ console.log(`${c.d}${"─".repeat(58)}${c[0]}`);
195
+
196
+ if (E.노드메이저 >= 18) {
197
+ console.log(`${c.g}✓${c[0]} Node ${E.노드} ${c.d}— 18 이상입니다${c[0]}`);
198
+ } else {
199
+ console.log(`${c.r}✗${c[0]} Node ${E.노드} — ${c.b}18 이상이 필요합니다${c[0]}`);
200
+ console.log(` ${c.y}★여기서 멈추는 게 낫습니다. 붙여 놓고 안 도는 자리입니다.${c[0]}`);
201
+ }
202
+
203
+ if (E.npx) console.log(`${c.g}✓${c[0]} npx ${c.d}${E.npx}${c[0]}`);
204
+ else console.log(`${c.y}…${c[0]} npx 를 못 찾았습니다 ${c.d}— 설치 명령이 npx 를 탑니다${c[0]}`);
205
+
206
+ console.log("");
207
+ if (E.클라이언트.length) {
208
+ console.log(`${c.g}✓${c[0]} MCP 클라이언트 ${E.클라이언트.length}개 ${c.d}${E.클라이언트.map((a) => a.이름).join(" · ")}${c[0]}`);
209
+ } else {
210
+ console.log(`${c.y}…${c[0]} Claude Code·Cursor 같은 클라이언트를 못 찾았습니다`);
211
+ console.log(` ${c.d}MCP 는 ${굵게("**붙일 쪽이 있어야**")} 의미가 있습니다.${c[0]}`);
212
+ }
213
+
214
+ if (E.이미.앎) {
215
+ if (E.이미.붙음) console.log(`${c.g}✓${c[0]} lottiefiles-creator 가 ${c.b}이미 등록돼 있습니다${c[0]} ${c.d}— 또 붙이지 마세요${c[0]}`);
216
+ else console.log(`${c.d}·${c[0]} lottiefiles-creator 는 아직 등록돼 있지 않습니다`);
217
+ } else {
218
+ console.log(`${c.d}·${c[0]} 등록 목록은 ${c.d}못 읽었습니다 — 모른다고 적습니다${c[0]}`);
219
+ }
220
+
221
+ console.log("");
222
+ console.log(`${c.d}${굵게("**명령 하나로는 안 끝납니다** — 그 줄 뒤에 남는 것:")}${c[0]}`);
223
+ const 뒤 = D["★명령하나로_안_끝난다"];
224
+ console.log(` ${c.y}①${c[0]} ${c.d}${굵게(뒤["①켜기"])}${c[0]}`);
225
+ console.log(` ${c.y}②${c[0]} ${c.d}${굵게(뒤["②열어두기"])}${c[0]}`);
226
+ console.log(` ${c.y}③${c[0]} ${c.d}${굵게(뒤["③원격불가"])}${c[0]}`);
227
+
228
+ console.log("");
229
+ console.log(`${c.d}${굵게("공짜의 범위 —")}${c[0]}`);
230
+ /* ★한글은 글자 하나가 두 칸이다 — padEnd 로 맞추면 표가 어긋난다 [[korean-text-never-use-ch-width]] */
231
+ const 표폭 = (s) => [...s].reduce((n, ch) => n + (/[ᄀ-ᇿ㄰-㆏가-힯一-鿿]/.test(ch) ? 2 : 1), 0);
232
+ const 채움 = (s, w) => s + " ".repeat(Math.max(1, w - 표폭(s)));
233
+ for (const [무엇, 값, 설명] of D["★공짜의범위"].비교표) {
234
+ console.log(` ${c.d}${채움(무엇, 20)}${c[0]}${채움(값, 14)}${c.d}${설명}${c[0]}`);
235
+ }
236
+ console.log(`${c.d}${"─".repeat(58)}${c[0]}`);
237
+ }
238
+
239
+ /* ══ 심기 ═══════════════════════════════════════════════════════ */
240
+
241
+ function 심기() {
242
+ mkdirSync(대상, { recursive: true });
243
+ cpSync(원본, 대상, { recursive: true });
244
+ /* ★쓴 뒤 다시 읽는다 — 복사는 조용히 실패한다 [[kit-update-selfcheck]] */
245
+ const 문제 = [];
246
+ for (const f of readdirSync(원본)) {
247
+ const a = join(원본, f), b = join(대상, f);
248
+ if (!existsSync(b)) { 문제.push(`${f} 가 안 복사됐다`); continue; }
249
+ if (statSync(b).size !== statSync(a).size) 문제.push(`${f} 크기가 다르다 — 잘려 복사됐다`);
250
+ }
251
+ if (!문제.length) {
252
+ try { JSON.parse(readFileSync(join(대상, "lottie.json"), "utf8")); }
253
+ catch { 문제.push("깐 원장이 JSON 으로 안 읽힌다"); }
254
+ }
255
+ return 문제;
256
+ }
257
+
258
+ /* ══ 자기시험 — 네트워크 안 씀 ══════════════════════════════════ */
259
+
260
+ function 자기시험() {
261
+ const 나쁨 = [];
262
+ const L = 원장읽기();
263
+ if (!L.됨) { 나쁨.push(L.이유); return 나쁨; }
264
+ for (const m of 원장검사(L.d)) 나쁨.push(`원장: ${m}`);
265
+
266
+ if (!existsSync(join(원본, "SKILL.md"))) 나쁨.push("skill/SKILL.md 가 없다");
267
+ else {
268
+ const md = readFileSync(join(원본, "SKILL.md"), "utf8");
269
+ if (!/^---[\s\S]*?name:\s*lottie-guide/m.test(md))
270
+ 나쁨.push("SKILL.md 머리말의 name 이 lottie-guide 가 아니다 — 클로드가 못 찾는다");
271
+ if (!/description:/.test(md)) 나쁨.push("SKILL.md 에 description 이 없다 — 발동하지 않는다");
272
+ if (!/탭/.test(md))
273
+ 나쁨.push("SKILL.md 가 브라우저 탭 조건을 말하지 않는다 — 이게 이 스킬의 첫 줄이다");
274
+ if (!/Enable MCP|MCP 를 켜|MCP Settings/.test(md))
275
+ 나쁨.push("SKILL.md 가 Creator 에서 MCP 를 켜야 함을 말하지 않는다");
276
+ if (!/확인불가|확인이 필요/.test(md))
277
+ 나쁨.push("SKILL.md 가 확인 못 한 항목을 그대로 말하지 않는다 — 모르는 걸 아는 척하면 이 스킬은 무의미하다");
278
+ for (const m of 금칙검사(md, "SKILL.md")) 나쁨.push(m);
279
+ }
280
+
281
+ /* ★검사기 자체를 양방향으로 본다 [[verifier-must-be-tested-both-ways]] */
282
+ const 좋은원장 = JSON.parse(JSON.stringify(L.d));
283
+ if (원장검사(좋은원장).length) 나쁨.push("자기시험 오탐: 멀쩡한 원장을 막는다");
284
+
285
+ const 나쁜1 = JSON.parse(JSON.stringify(L.d));
286
+ delete 나쁜1["★명령하나로_안_끝난다"];
287
+ if (!원장검사(나쁜1).length) 나쁨.push("자기시험 미탐: 명령하나로_안_끝난다 가 빠져도 통과한다");
288
+
289
+ const 나쁜2 = JSON.parse(JSON.stringify(L.d));
290
+ 나쁜2["★공짜의범위"].상업적이용 = "무료 플랜에서도 상업적으로 쓸 수 있다";
291
+ if (!원장검사(나쁜2).length) 나쁨.push("자기시험 미탐: 확인 못 한 약관을 단정해도 통과한다");
292
+
293
+ const 나쁜3 = JSON.parse(JSON.stringify(L.d));
294
+ 나쁜3.설치["★명령"] = "claude mcp add lottiefiles-creator -- npx @lottiefiles/creator-mcp@latest";
295
+ if (!원장검사(나쁜3).length) 나쁨.push("자기시험 미탐: npx 에서 -y 를 빼도 통과한다");
296
+
297
+ const 나쁜4 = JSON.parse(JSON.stringify(L.d));
298
+ 나쁜4.내보내기["★GIF·MP4"] = "GIF 와 MP4 로 바로 뽑을 수 있다";
299
+ if (!원장검사(나쁜4).length) 나쁨.push("자기시험 미탐: 확인 못 한 내보내기를 단정해도 통과한다");
300
+
301
+ const 나쁜5 = JSON.parse(JSON.stringify(L.d));
302
+ 나쁜5["★함정"]["★다른패키지"] = "";
303
+ if (!원장검사(나쁜5).length) 나쁨.push("자기시험 미탐: 헷갈리는 서드파티 패키지를 안 짚어도 통과한다");
304
+
305
+ /* ★금칙 검사가 인용을 안 잡는지 [[forbidden-word-checker-blocks-its-own-quotes]] */
306
+ if (금칙검사("참고본은 「완전 무료」라고 말한다", "시험").length)
307
+ 나쁨.push("자기시험 오탐: 낫표 안의 인용을 금칙으로 잡는다");
308
+ if (!금칙검사("이 도구는 완전 무료입니다", "시험").length)
309
+ 나쁨.push("자기시험 미탐: 우리가 하는 단정을 안 잡는다");
310
+
311
+ return 나쁨;
312
+ }
313
+
314
+ /* ══ 끝난 뒤 한 칸 ═══════════════════════════════════════════════
315
+ 규율: ① 끝난 뒤 딱 한 칸 · ② 못 깔았으면 안 띄운다 · ③ 파일을 안 남긴다
316
+ ④ 고지 블록 금지 · ⑤ 첫 줄은 방금 한 일에서 이어져야 한다 */
317
+ function 꼬리() {
318
+ const T = TAIL[퍼널];
319
+ if (!T) return;
320
+ console.log("");
321
+ for (const l of T.이음) console.log(`${c.d}${굵게(l)}${c[0]}`);
322
+ console.log("");
323
+ console.log(` ${c.b}${T.제목}${c[0]} ${c.d}${T.한줄}${c[0]}`);
324
+ console.log(` ${c.cy}${링크(퍼널)}${c[0]}`);
325
+ console.log("");
326
+ console.log(`${c.d}${마지막}${c[0]}`);
327
+ }
328
+
329
+ /* ══ 본체 ═══════════════════════════════════════════════════════ */
330
+
331
+ if (자기시험모드) {
332
+ const 나쁨 = 자기시험();
333
+ if (나쁨.length) {
334
+ console.log(`${c.r}자기시험 실패${c[0]}`);
335
+ for (const m of 나쁨) console.log(" - " + m);
336
+ process.exit(1);
337
+ }
338
+ console.log(`${c.g}자기시험 통과${c[0]}`);
339
+ process.exit(0);
340
+ }
341
+
342
+ const L = 원장읽기();
343
+ if (!L.됨) { console.log(`${c.r}✗ ${L.이유}${c[0]}`); process.exit(1); }
344
+ const 원장문제 = 원장검사(L.d);
345
+ if (원장문제.length) {
346
+ console.log(`${c.r}✗ 원장이 성하지 않다 — 깔지 않는다${c[0]}`);
347
+ for (const m of 원장문제) console.log(" - " + m);
348
+ process.exit(1);
349
+ }
350
+ const D = L.d;
351
+
352
+ console.log("");
353
+ console.log(`${c.b}LottieFiles Creator MCP${c[0]} ${c.d}— ${D.제품.한줄} (${D.확인일} 확인)${c[0]}`);
354
+
355
+ /* ★★붙이는 줄을 먼저 보여 준다. 우리한테 안 물어봐도 되게. */
356
+ console.log("");
357
+ console.log(`${c.d}붙이는 명령은 이 한 줄입니다 ${굵게("**— 우리 없이도 됩니다**")}:${c[0]}`);
358
+ console.log(` ${c.cy}${D.설치["★명령"]}${c[0]}`);
359
+ console.log(`${c.d}패키지 ${D.설치.패키지} · ${D.설치.최신판} · ${D.설치.라이선스} · 최초 공개 ${D.설치.최초공개}${c[0]}`);
360
+
361
+ const E = 환경재기();
362
+ 환경보고(E, D);
363
+
364
+ console.log("");
365
+ console.log(`${c.d}${굵게("**" + D["★상표"].고지 + "**")}${c[0]}`);
366
+
367
+ if (확인만) {
368
+ console.log(`\n${c.d}깔려면: npx --yes reborn-lottie${c[0]}\n`);
369
+ process.exit(0);
370
+ }
371
+
372
+ if (미리보기) {
373
+ console.log(`\n${c.d}할 일:${c[0]}`);
374
+ console.log(` ${스킬이름} → ${대상}`);
375
+ console.log(`${c.d}(--dry-run 이라 아무것도 안 했습니다)${c[0]}\n`);
376
+ process.exit(0);
377
+ }
378
+
379
+ const 문제 = 심기();
380
+ if (문제.length) {
381
+ console.log(`\n${c.r}✗ 심다가 막혔습니다${c[0]}`);
382
+ for (const m of 문제) console.log(" - " + m);
383
+ console.log(`${c.d}권한이나 경로 문제일 수 있습니다. --local 로 현재 폴더에 깔아 보세요.${c[0]}\n`);
384
+ process.exit(1);
385
+ }
386
+
387
+ console.log(`\n${c.g}✓${c[0]} ${c.b}${스킬이름}${c[0]} 을 깔았습니다`);
388
+ console.log(` ${c.d}${대상}${c[0]}`);
389
+ console.log("");
390
+ console.log(`${c.d}클로드 코드를 ${굵게("**다시 시작**")}하면 잡힙니다. 그 뒤 이렇게 물어 보세요:${c[0]}`);
391
+ console.log(` ${c.cy}"로티 MCP 붙이려는데 내 환경에서 되나?"${c[0]}`);
392
+ console.log("");
393
+ console.log(`${c.d}지금 상태만 다시 재려면: ${c[0]}npx --yes reborn-lottie --check`);
394
+
395
+ 꼬리();
package/package.json ADDED
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "reborn-lottie",
3
+ "version": "1.0.0",
4
+ "description": "영상에서 소개한 LottieFiles Creator MCP(클로드 코드에서 말로 시켜 Lottie 애니메이션을 짓는 브리지)를 붙이기 전에 먼저 재 주는 안내 스킬입니다. 설치 명령은 한 줄이 맞지만 그 뒤에 Creator 에서 MCP 를 켜는 일과 로그인한 탭을 열어 두는 일이 남아 있다는 것, 원격에서는 못 쓴다는 것, 그리고 약관에서 확인 못 한 것이 무엇인지를 그대로 말해 줍니다.",
5
+ "keywords": [
6
+ "claude",
7
+ "claude-code",
8
+ "agent-skills",
9
+ "skill",
10
+ "lottie",
11
+ "lottiefiles",
12
+ "mcp",
13
+ "motion-graphics",
14
+ "animation",
15
+ "after-effects",
16
+ "korean"
17
+ ],
18
+ "homepage": "https://rebornlabs.kr/lottie?utm_source=installer&utm_medium=cli&utm_campaign=lottie",
19
+ "bugs": {
20
+ "url": "https://mobility.rebornlabs.kr/cs"
21
+ },
22
+ "license": "MIT",
23
+ "author": "REBORN LABS",
24
+ "type": "module",
25
+ "bin": {
26
+ "reborn-lottie": "cli.mjs"
27
+ },
28
+ "files": [
29
+ "cli.mjs",
30
+ "tail.mjs",
31
+ "skill/",
32
+ "README.md",
33
+ "안내스킬.md"
34
+ ],
35
+ "engines": {
36
+ "node": ">=18"
37
+ },
38
+ "scripts": {
39
+ "test": "node cli.mjs --self-test",
40
+ "check": "node cli.mjs --check"
41
+ },
42
+ "publishConfig": {
43
+ "access": "public"
44
+ }
45
+ }
package/skill/SKILL.md ADDED
@@ -0,0 +1,117 @@
1
+ ---
2
+ name: lottie-guide
3
+ description: LottieFiles Creator MCP — 클로드 코드에서 말로 시켜 Lottie 애니메이션을 짓고 고치는 브리지를, **붙이기 전에** 무엇이 막는지 알려 준다. 사람들이 가장 많이 틀리는 자리를 먼저 말한다 — 명령은 한 줄이 맞지만 그 뒤에 Creator 에서 MCP 를 켜는 일과 로그인한 탭을 열어 두는 일이 남아 있고, 원격에서는 못 쓴다. "로티", "LottieFiles", "Lottie MCP", "클로드로 애니메이션", "애프터이펙트 없이 모션그래픽", "로딩 스피너 만들기", "로고 리빌 애니메이션", "MCP 붙였는데 아무 일도 안 일어남", "lottiefiles-creator" 같은 이야기가 나올 때 쓴다.
4
+ ---
5
+
6
+ # LottieFiles Creator MCP — 붙이기 전에 아는 것
7
+
8
+ 원장은 옆의 `lottie.json` 이다. **이 문서의 모든 수치·명령은 거기서 온다.**
9
+ 확인일과 확인 방법이 그 파일에 적혀 있다. 없는 것은 「확인불가」라고 적혀 있고,
10
+ 이 문서도 그렇게 말한다 — **모르는 것을 아는 척하면 이 스킬은 존재할 이유가 없다.**
11
+
12
+ ---
13
+
14
+ ## 먼저 말할 것 — 명령은 한 줄이 맞다. 그 줄이 끝은 아니다
15
+
16
+ 소개 영상들이 말하는 설치는 실제로 한 줄이다:
17
+
18
+ ```
19
+ claude mcp add lottiefiles-creator -- npx -y @lottiefiles/creator-mcp@latest
20
+ ```
21
+
22
+ **우리 없이도 된다.** 위 줄을 그대로 쓰면 붙는다.
23
+ 그런데 그 줄 뒤에 **세 가지**가 남아 있고, 이걸 모르면 붙여 놓고 아무 일도 안 일어난다.
24
+
25
+ | | 무엇 | 안 하면 |
26
+ |---|---|---|
27
+ | ① | Lottie Creator 안에서 **MCP 를 켠다** (설정 → MCP Settings → Enable MCP) | 명령은 나가는데 화면에서 아무 일도 안 일어난다 |
28
+ | ② | 로그인한 **Creator 브라우저 탭을 열어 둔다** | 탭을 닫는 순간 브리지가 끊긴다 |
29
+ | ③ | **로컬에서만 쓴다** — 호스팅 엔드포인트가 없다 | 원격 서버·CI 에서는 붙지 않는다 |
30
+
31
+ ②가 이 도구의 성격을 정한다. **이건 에디터가 아니라 브리지다.**
32
+ 애니메이션을 실제로 그리는 곳은 브라우저에서 도는 Lottie Creator 이고,
33
+ MCP 는 그 탭에 명령을 실어 나르는 로컬 통로다. 그래서 탭이 살아 있어야 한다.
34
+
35
+ ---
36
+
37
+ ## 붙이기 전에 재는 것
38
+
39
+ ```
40
+ npx --yes reborn-lottie --check
41
+ ```
42
+
43
+ 말로 「되실 겁니다」 하지 않는다. 실제로 찾는다:
44
+
45
+ - **Node 18 이상인가** — 문서가 못 박은 유일한 실행 조건이다
46
+ - 이 컴퓨터에 **MCP 클라이언트가 실제로 있나** (Claude Code · Cursor · VS Code · Codex)
47
+ - **이미 등록돼 있나** — 두 번 붙이면 헷갈린다
48
+ - **npx 가 도는가** — 설치 명령이 npx 를 탄다
49
+
50
+ 못 찾으면 「모른다」고 한다. 「된다」고 하지 않는다.
51
+
52
+ ---
53
+
54
+ ## 무엇을 시킬 수 있나
55
+
56
+ 원장의 `할수있는일` 이 전부다. 우리가 늘리지 않는다.
57
+
58
+ - **씬** — 만들기·전환·속성, Lottie JSON 내보내기, JSON/dotLottie/SVG/이미지 가져오기
59
+ - **레이어** — 표시 여부, 타이밍, 블렌드 모드, 마스크·매트, 트랜스폼
60
+ - **셰이프** — 사각형·타원·다각형·별·패스·그룹
61
+ - **채우기** — 단색, 선형·방사 그라디언트, trim path
62
+ - **애니메이션** — 키프레임, 이징(Linear · Cubic Bezier)
63
+ - **재생** — 재생·일시정지·프레임 이동
64
+
65
+ State Machines · Motion Tokens 는 문서에 **예정**으로 적혀 있다. 아직 없다.
66
+
67
+ 시키는 말은 이런 모양이다:
68
+
69
+ ```
70
+ 로고가 나타나는 로딩 스피너를 만들어 줘.
71
+ 육각형이 레이어별로 조립되면서 천천히 회전하고, 글로우가 호흡하게.
72
+ ```
73
+
74
+ ★**맨바닥에서 일러스트 셰이프부터 만들게 하면 결과가 들쭉날쭉하다**고 문서가 적어 두었다.
75
+ 이미 열어 둔 파일을 고치게 하는 쪽이 훨씬 잘 나온다 — 색·타이밍·트랜지션 바꾸기.
76
+ 그리고 **결과 품질이 쓰는 모델에 크게 좌우된다**고도 적혀 있다.
77
+
78
+ ---
79
+
80
+ ## 확인 못 한 것 — 여기서 멈춰 각자 봐야 하는 자리
81
+
82
+ 이 스킬이 아는 척하지 않는 항목이다. 원장에도 「확인불가」로 적혀 있다.
83
+
84
+ | 무엇 | 상태 | 왜 |
85
+ |---|---|---|
86
+ | **상업적 이용** | 확인불가 | 약관 원문 페이지가 403 이라 1차 출처로 못 읽었다. 검색 요약에는 무료 개인 플랜이 비상업 용도라는 말이 보인다 — **일로 쓸 거면 이걸 먼저 확인해야 한다** |
87
+ | 지역 제한 | 확인불가 | 한국을 막는 조항은 못 봤으나 약관을 못 읽었으므로 「없다」고 말하지 않는다 |
88
+ | 유료 플랜 연동 | 확인불가 | MCP 사용량이 AI 크레딧과 물리는지 1차 출처를 못 읽었다 |
89
+ | GIF·MP4 내보내기 | 확인불가 | MCP 문서에 언급이 없다. 확인된 내보내기는 **Lottie JSON** 하나다 |
90
+
91
+ 확인된 것은 이만큼이다 — **MCP 패키지 자체는 npm 공개 패키지이고 MIT 다.**
92
+ 레지스트리를 직접 호출해 확인했다.
93
+
94
+ ---
95
+
96
+ ## 헷갈리는 자리
97
+
98
+ - ★npm 에 **`mcp-server-lottiefiles`** 라는 비공식 서드파티 패키지가 따로 있다.
99
+ 커뮤니티 애니메이션을 **검색·조회만** 하는 다른 물건이고, 여기서 말하는
100
+ `lottiefiles-creator` 와 무관하다. 이름이 비슷해 잘못 깔기 쉽다.
101
+ - 공식 문서가 가리키는 GitHub 저장소는 접속하면 **404** 다.
102
+ 비공개이거나 없는 것으로 보여서, 이슈를 찾아 읽을 수 없다.
103
+
104
+ ---
105
+
106
+ ## 안 될 때 되짚는 순서
107
+
108
+ 1. `npx --yes reborn-lottie --check` — Node 판과 클라이언트를 먼저 본다
109
+ 2. Creator 설정에서 **MCP 가 켜져 있나** (①)
110
+ 3. **Creator 탭이 살아 있나** (②) — 「갑자기 안 된다」의 대부분이 이것이다
111
+ 4. 등록이 중복되지 않았나 — `claude mcp list`
112
+ 5. 클로드 코드를 **다시 시작**했나
113
+
114
+ ---
115
+
116
+ LottieFiles · Lottie 는 LottieFiles 의 상표입니다.
117
+ 이 스킬은 리본랩스가 만들었고 LottieFiles 와 무관합니다.
@@ -0,0 +1,92 @@
1
+ {
2
+ "_doc": "LottieFiles Creator MCP 사실 원장 — 릴스·착지·DM·설치기가 **전부 이 파일 하나**를 본다. 지어낸 명령·지어낸 기능이 화면에 오르는 것을 막는다.",
3
+ "확인일": "2026-09-02",
4
+ "확인방법": "공식 문서(docs.lottiefiles.com/en/creator/13_ai-tools/lottie-creator-mcp)를 읽고, npm 레지스트리 API(registry.npmjs.org/@lottiefiles/creator-mcp)를 직접 호출해 버전·최초공개일·라이선스를 확인했다. 문서가 가리키는 GitHub 저장소(LottieFiles/creator)는 실제로 404 라 공개 이슈로 교차 확인은 못 했다. lottiefiles.com 의 약관·가격 페이지는 403 이라 1차 출처로 확인하지 못했고, 그 항목은 아래에서 전부 「확인불가」로 적었다.",
5
+
6
+ "제품": {
7
+ "이름": "LottieFiles Creator MCP",
8
+ "문서": "https://docs.lottiefiles.com/en/creator/13_ai-tools/lottie-creator-mcp",
9
+ "에디터": "https://creator.lottiefiles.com",
10
+ "한줄": "클로드 코드 같은 MCP 클라이언트를 Lottie Creator 에 붙여, 말로 시키면 애니메이션을 레이어 단위로 짓고 고치게 하는 로컬 브리지.",
11
+ "회사": "LottieFiles",
12
+ "★정체": "★**에디터가 아니라 브리지다.** 애니메이션을 실제로 그리는 곳은 브라우저에서 도는 Lottie Creator 이고, MCP 는 그 탭에 명령을 실어 나르는 로컬 통로다. 이 한 줄이 아래 조건 전부의 이유다."
13
+ },
14
+
15
+ "설치": {
16
+ "★명령": "claude mcp add lottiefiles-creator -- npx -y @lottiefiles/creator-mcp@latest",
17
+ "★왜원장에두나": "릴스 자막·터미널 목업·착지 페이지·DM 이 전부 이 문자열 하나를 읽어 간다. 손으로 옮겨 적으면 어느 한 곳이 조용히 어긋난다.",
18
+ "패키지": "@lottiefiles/creator-mcp",
19
+ "최신판": "0.2.1",
20
+ "판이력": ["0.1.1", "0.1.2", "0.1.3", "0.2.0", "0.2.1"],
21
+ "최초공개": "2026-04-06",
22
+ "최신판배포": "2026-08-20",
23
+ "라이선스": "MIT",
24
+ "★npx는yes": "안내문에 쓰는 명령에는 -y 가 들어 있다. 없으면 클로드 코드 안에서 설치 확인 프롬프트를 기다리다 무음으로 멈춘다 [[npx-installer-needs-yes-flag]].",
25
+ "★공개일주의": "위 최초공개는 registry 의 time.created 다. modified 가 아니다 [[npm-registry-modified-is-not-publish-date]]."
26
+ },
27
+
28
+ "★명령하나로_안_끝난다": {
29
+ "_왜": "★★이 회차에서 우리가 참고본에 **더하는 한 줄**이다. 참고본은 「명령어 하나로 설치하고 나서 원하는 걸 설명만 하면」이라고 말한다. 설치가 한 줄인 건 사실이다 — 다만 그 뒤에 **두 가지 일**이 더 남아 있고, 그걸 모르면 깔아 놓고 안 된다.",
30
+ "①켜기": "Creator 안에서 MCP 를 **직접 켭니다** — 설정 → MCP Settings → Enable MCP. 기본으로 꺼져 있습니다.",
31
+ "②열어두기": "로그인한 **Creator 탭을 열어 둔 채로** 씁니다. 로컬 stdio 브리지가 그 탭과 통신하므로, 닫으면 끊깁니다.",
32
+ "③원격불가": "**로컬 stdio 전용**입니다. 호스팅 엔드포인트가 없어 원격 서버·CI 에서는 붙지 않습니다.",
33
+ "_참고본이_안_말한_자리": "참고본은 ①의 화면(Creator 의 MCP Settings)이 9~11초에 스쳐 지나가는데도 말로는 설명하지 않는다. ②·③은 아예 나오지 않는다. 우리가 더하는 한 줄이 여기다.",
34
+ "판정": "설치는 한 줄이 맞다. 「한 줄이면 끝」은 아니다. 이 셋을 먼저 말하는 것이 이 스킬의 존재 이유다."
35
+ },
36
+
37
+ "★공짜의범위": {
38
+ "_왜": "「무료」라고 우리 입으로 단정하지 않는다. MCP 패키지와 LottieFiles 계정·플랜은 다른 이야기이고, 후자는 1차 출처로 확인하지 못했다.",
39
+ "MCP패키지": "무료. npm 공개 패키지이고 라이선스는 MIT 다. 여기까지는 레지스트리에서 직접 확인했다.",
40
+ "계정": "★Creator 웹앱에 로그인한 탭이 있어야 브리지가 통신하므로 **사실상 LottieFiles 계정이 필요하다**. 다만 「가입 필수」라는 명문 문구는 못 찾았다 — 정황으로 적는다.",
41
+ "인증": "API 키도 OAuth 도 아니다. 로컬 stdio 브리지가 **내 브라우저 세션**을 탄다.",
42
+ "플랜조건": "★**확인불가.** 무료 워크스페이스의 파일 한도는 공개돼 있으나(공개 애니 다운로드 월 10개 · 비공개 업로드 5개, Creator 로 만든 파일은 이 한도에서 빠진다), MCP 사용량이 유료 플랜의 AI 크레딧과 연동되는지는 확인하지 못했다.",
43
+ "상업적이용": "★**확인불가 — 여기서 멈춰서 각자 확인해야 하는 자리다.** 검색 요약에는 무료 개인 플랜이 비상업 용도라는 말이 보이는데, 약관 원문(lottiefiles.com/page/terms-and-conditions)이 403 이라 1차 출처로 확인하지 못했다. 일로 쓸 거면 이걸 먼저 보라고 말한다 [[copied-reel-claims-need-license-territory-check]].",
44
+ "지역": "★확인불가. 한국을 막는 조항은 발견하지 못했으나 약관 원문을 못 읽었으므로 「없다」고 말하지 않는다.",
45
+ "비교표": [
46
+ ["MCP 패키지", "0원", "npm 공개 · MIT (레지스트리에서 직접 확인)"],
47
+ ["Creator 계정", "사실상 필요", "로그인한 탭이 있어야 브리지가 통신한다"],
48
+ ["유료 플랜 연동", "확인불가", "AI 크레딧과 물리는지 1차 출처를 못 읽었다"],
49
+ ["상업적 이용", "확인불가", "약관 원문이 403 — 일로 쓸 거면 먼저 확인"]
50
+ ]
51
+ },
52
+
53
+ "할수있는일": {
54
+ "_출처": "공식 문서의 도구 목록. 우리가 늘리지 않는다.",
55
+ "씬": "씬 생성·전환, 속성 설정, Lottie JSON 내보내기, JSON/dotLottie/SVG/이미지 가져오기",
56
+ "레이어": "표시 여부, 타이밍, 블렌드 모드, 마스크·매트, 트랜스폼",
57
+ "셰이프": "사각형·타원·다각형·별·패스·그룹",
58
+ "채우기": "단색, 선형·방사 그라디언트, trim path",
59
+ "애니메이션": "키프레임, 이징(Linear · Cubic Bezier), 애니메이터블 속성",
60
+ "재생": "재생·일시정지·프레임 이동",
61
+ "★아직없는것": "State Machines · Motion Tokens 는 문서에 예정으로 적혀 있다. 있는 것처럼 말하지 않는다."
62
+ },
63
+
64
+ "내보내기": {
65
+ "확인됨": "Lottie JSON (bodymovin)",
66
+ "가져오기": "JSON · dotLottie(.lottie) · SVG · 이미지 에셋",
67
+ "★GIF·MP4": "★확인불가. MCP 문서에 언급이 없고 Creator 앱 기능 페이지는 403 이라 못 읽었다. 「영상으로 바로 뽑힌다」고 말하지 않는다."
68
+ },
69
+
70
+ "★먼저재는것": [
71
+ "Node 18 이상인가 — 문서가 못 박은 유일한 실행 조건이다",
72
+ "이 컴퓨터에 MCP 클라이언트가 실제로 있나 (claude · cursor · code · codex)",
73
+ "이미 lottiefiles-creator 가 등록돼 있나 — 두 번 붙이면 헷갈린다",
74
+ "npx 가 도는가 — 설치 명령이 npx 를 탄다"
75
+ ],
76
+
77
+ "★함정": {
78
+ "노드": "Node.js 18 이상이 필요하다.",
79
+ "탭": "★Creator 탭을 닫으면 브리지가 끊긴다. 「갑자기 안 된다」의 대부분이 이것이다.",
80
+ "켜기": "★Creator 설정에서 MCP 를 켜지 않으면 명령은 나가는데 아무 일도 안 일어난다.",
81
+ "원격": "호스팅 엔드포인트가 없다 — 로컬 stdio 전용.",
82
+ "모델": "공식 문서가 결과 품질이 쓰는 모델에 크게 좌우된다고 적어 두었다. 좋은 모델을 권한다.",
83
+ "맨바닥생성": "아무것도 없는 상태에서 일러스트 셰이프부터 만들게 하면 결과가 들쭉날쭉하다고 문서가 적는다.",
84
+ "★다른패키지": "★npm 에 `mcp-server-lottiefiles` 라는 **비공식 서드파티** 패키지가 따로 있다. LottieFiles 커뮤니티 애니메이션을 **검색·조회만** 하는 다른 물건이고, 참고본이 쓴 `lottiefiles-creator` 와 무관하다. 이름이 비슷해 헷갈리는 자리다.",
85
+ "★저장소": "문서가 가리키는 GitHub 저장소(LottieFiles/creator)는 접속하면 404 다. 비공개이거나 없는 것으로 보인다 — 이슈를 찾아 읽을 수 없다."
86
+ },
87
+
88
+ "★상표": {
89
+ "고지": "LottieFiles · Lottie 는 LottieFiles 의 상표입니다. 이 영상과 이 패키지는 리본랩스가 만들었고 LottieFiles 와 무관합니다.",
90
+ "★왜": "릴스에서 남의 로고를 화면 가득 세운다. 귀속을 안 박으면 그 브랜드가 한 일로 읽힌다 [[reel-borrowed-logo-needs-attribution]]. 같은 화면 · 다음 컷 · 발행 캡션 세 곳에 박는다."
91
+ }
92
+ }
package/tail.mjs ADDED
@@ -0,0 +1,24 @@
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
+ lottie: {
15
+ 이음: [
16
+ "방금 한 일은 **붙이기 전에 재 본 것**입니다 — 노드 판이 되는지, 붙일 클라이언트가 있는지, 그 줄 뒤에 무엇이 더 남는지.",
17
+ "소개 영상은 명령 한 줄까지만 말합니다. 막히는 자리는 늘 **그 줄 다음**에 있습니다.",
18
+ ],
19
+ 제목: "리본랩스 스킬팩",
20
+ 한줄: "같은 방식으로 골라 담은 48종을 한 줄로. 8,900원",
21
+ },
22
+ };
23
+
24
+ export const 마지막 = "목록과 직접 까는 명령까지 그 페이지에 그대로 적어 두었습니다. 안 사셔도 됩니다.";
@@ -0,0 +1,81 @@
1
+ # 안내스킬 — `lottie-guide`
2
+
3
+ 이 패키지가 `~/.claude/skills/lottie-guide/` 에 심는 것.
4
+
5
+ | 파일 | 무엇 |
6
+ |---|---|
7
+ | `SKILL.md` | 클로드가 읽는 안내. **답하는 순서**가 여기 있다 |
8
+ | `lottie.json` | **원장.** 모든 사실의 주인. 여기 없는 기능 이름은 말하지 않는다 |
9
+
10
+ ★심는 것은 이 폴더 하나뿐이다. **공유 안내스킬에는 손대지 않는다** —
11
+ 같은 파일을 여러 설치기가 덮는 사고를 애초에 안 만든다.
12
+
13
+ ## 왜 원장을 따로 두나
14
+
15
+ 사실을 `SKILL.md` 본문에 적으면 두 곳이 서로 다른 말을 하기 시작한다.
16
+ 설치 명령·판 번호·확인 못 한 항목은 **한 곳에서만** 나온다. [[one-metric-one-owner]]
17
+
18
+ ★특히 **설치 명령 문자열**이 그렇다. 릴스 자막·터미널 목업·착지 페이지·DM 이
19
+ 전부 원장의 `설치.★명령` 하나를 읽어 간다. 손으로 옮겨 적으면 어느 한 곳이 조용히 어긋난다.
20
+
21
+ 원장에는 **확인일과 확인방법**이 반드시 있다. 없으면 설치기가 막는다.
22
+
23
+ ## ★이 킷의 존재 이유는 `★명령하나로_안_끝난다` 다
24
+
25
+ 참고본은 「명령어 하나로 설치하고 나서 원하는 걸 설명만 하면」이라고 말한다.
26
+ 틀린 말이 아니다 — 설치는 진짜로 한 줄이다. 다만 **그 줄 뒤에 두 가지가 더 남는다.**
27
+
28
+ ① Creator 안에서 MCP 를 **켜야** 하고(기본으로 꺼져 있다)
29
+ ② 로그인한 Creator **탭을 열어 둔 채로** 써야 한다(닫으면 끊긴다)
30
+ ③ 그리고 **로컬 전용**이라 원격에서는 못 쓴다
31
+
32
+ 이 칸이 비면 자기시험이 막는다. 그러면 우리는 참고본과 똑같은 말만 하는 패키지가 되기 때문이다.
33
+
34
+ ## ★모르는 것을 아는 척하지 못하게 막는 자리
35
+
36
+ 이 회차는 **확인 못 한 항목이 많은 회차**다. 약관·가격 페이지가 403 이라 못 읽었다.
37
+ 그래서 검사기가 「확인불가」가 **지워지는 것**을 막는다.
38
+
39
+ | 막는 것 | 어떻게 |
40
+ |---|---|
41
+ | 「무료 플랜에서도 상업적으로 쓸 수 있다」로 바꾸는 것 | `★공짜의범위.상업적이용` 에 「확인불가」가 없으면 실패 |
42
+ | 지역 제한이 없다고 단정하는 것 | `★공짜의범위.지역` 도 같다 |
43
+ | GIF·MP4 로 바로 뽑힌다고 말하는 것 | `내보내기.★GIF·MP4` 도 같다 |
44
+ | 예정 기능을 있는 것처럼 적는 것 | `할수있는일.★아직없는것` 이 예정임을 말해야 한다 |
45
+ | `npx` 안내에서 `-y` 를 빼는 것 | 없으면 클로드 코드 안에서 무음 정지한다 [[npx-installer-needs-yes-flag]] |
46
+ | 헷갈리는 서드파티 패키지를 안 짚는 것 | `★함정.★다른패키지` 가 `mcp-server-lottiefiles` 를 짚어야 한다 |
47
+ | 「완전 무료」·「한 줄이면 끝」·「설정 없이」 | 금칙어 검사. 단 **「그 말을 하지 마라」고 적은 문장은 면제**한다(부정문 판별) |
48
+
49
+ ★금칙 면제 규칙은 회차 ㉔에서 실제로 밟은 사고를 막는 것이다 — 검사기가 자기 규칙 문서를
50
+ 금칙어로 잡아 스스로를 막았다. **낫표(「」) 안은 인용으로 보고 벗겨 낸 뒤** 검사한다
51
+ [[forbidden-word-checker-blocks-its-own-quotes]].
52
+
53
+ ## 검사기를 양방향으로 시험한다
54
+
55
+ `--self-test` 는 원장이 통과하는지만 보지 않는다. **일부러 망가뜨린 원장 다섯**을 만들어
56
+ 그것들이 **막히는지**까지 본다 [[verifier-must-be-tested-both-ways]]:
57
+
58
+ 1. `★명령하나로_안_끝난다` 를 지운 것
59
+ 2. 확인 못 한 약관을 단정으로 바꾼 것
60
+ 3. `npx` 에서 `-y` 를 뺀 것
61
+ 4. 확인 못 한 내보내기를 단정으로 바꾼 것
62
+ 5. 헷갈리는 서드파티 패키지 항목을 비운 것
63
+
64
+ 여기에 금칙 검사도 양방향으로 본다 — 인용을 안 잡는지, 우리 단정은 잡는지.
65
+ 전건 통과나 전건 실패는 검사기가 고장 났다는 신호다.
66
+
67
+ ## 스킬이 안 뜰 때
68
+
69
+ 깐 다음 **클로드 코드를 껐다 켜세요.** 그래도 안 뜨면 이름을 직접 부르시고,
70
+ 그래도 없으면 지금 상태를 재 봅니다 — `npx --yes reborn-lottie --check`
71
+
72
+ ---
73
+
74
+ 방금 한 일은 **붙이기 전에 재 본 것**입니다 — 노드 판이 되는지,
75
+ 붙일 클라이언트가 있는지, 그 줄 뒤에 무엇이 더 남는지.
76
+ 소개 영상은 명령 한 줄까지만 말합니다. 막히는 자리는 늘 **그 줄 다음**에 있습니다.
77
+
78
+ **리본랩스 스킬팩** — 같은 방식으로 골라 담은 48종을 한 줄로. 8,900원
79
+ https://rebornlabs.kr/skillpack?utm_source=installer&utm_medium=cli&utm_campaign=lottie
80
+
81
+ 목록과 직접 까는 명령까지 그 페이지에 그대로 적어 두었습니다. 안 사셔도 됩니다.