reborn-ruflo 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 +91 -0
- package/cli.mjs +276 -0
- package/package.json +44 -0
- package/skill/SKILL.md +83 -0
- package/skill/ruflo.json +64 -0
- package/tail.mjs +24 -0
- package//354/225/210/353/202/264/354/212/244/355/202/254.md +67 -0
package/README.md
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# reborn-ruflo
|
|
2
|
+
|
|
3
|
+
**ruflo(옛 claude-flow)를 깔기 전에, 이 컴퓨터가 되는지 재 드립니다.**
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
npx --yes reborn-ruflo --check 이 컴퓨터를 실제로 잰다 (깔지 않는다)
|
|
7
|
+
npx --yes reborn-ruflo 안내 스킬을 깐다
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## 이건 저희가 만든 게 아닙니다
|
|
13
|
+
|
|
14
|
+
[ruflo](https://github.com/ruvnet/ruflo) 는 **ruvnet** 의 **MIT** 오픈소스이고,
|
|
15
|
+
Anthropic 과도 무관한 독립 프로젝트입니다.
|
|
16
|
+
저희는 **재배포하지 않습니다** — 코드를 담지도, 대신 설치하지도 않습니다. 안내만 합니다.
|
|
17
|
+
|
|
18
|
+
> 2026년 1월에 상표 문제로 이름이 `claude-flow` → `ruflo` 로 바뀌었습니다.
|
|
19
|
+
> 옛 이름으로 쓴 글이 아직 많은데, 같은 프로젝트입니다.
|
|
20
|
+
|
|
21
|
+
## 무엇을 하는 도구인가요
|
|
22
|
+
|
|
23
|
+
클로드 코드가 「한 사람」이라면, ruflo 는 그 위에 **팀**을 얹습니다.
|
|
24
|
+
퀸 에이전트가 일을 갈라 맡기고 → 역할별 에이전트가 나눠 처리하고 →
|
|
25
|
+
결과를 합치고 → 그 과정에서 나온 규칙을 기억에 남깁니다.
|
|
26
|
+
|
|
27
|
+
CLI 로 깔면 **에이전트 98종 · 커맨드 60개 이상 · 스킬 30종 · MCP 서버 · 훅 · 데몬**이 옵니다.
|
|
28
|
+
(저장소 설치 경로 표에 그렇게 적혀 있습니다.)
|
|
29
|
+
|
|
30
|
+
## ★막히는 자리는 셋입니다
|
|
31
|
+
|
|
32
|
+
**① 노드 20 이상**
|
|
33
|
+
`engines` 가 `node >=20.0.0` 입니다. 18 에서는 **깔리는 것처럼 보이다 실행에서 죽습니다.**
|
|
34
|
+
|
|
35
|
+
**② 설치 경로 — 가장 많이 틀리는 자리**
|
|
36
|
+
|
|
37
|
+
| | 플러그인 | CLI 설치 (`npx ruflo@latest init`) |
|
|
38
|
+
|---|---|---|
|
|
39
|
+
| 오는 것 | 슬래시 명령 + 에이전트 정의 | 전체 loop |
|
|
40
|
+
| 훅 | **안 온다** | 온다 |
|
|
41
|
+
| MCP 서버 | 대부분 안 온다 | 온다 |
|
|
42
|
+
|
|
43
|
+
「문서대로 안 된다」는 말의 대부분이 **플러그인만 깔고 CLI 문서를 보고 있는 것**입니다.
|
|
44
|
+
|
|
45
|
+
**③ 모델 값은 따로 듭니다**
|
|
46
|
+
도구는 MIT 무료입니다. 그런데 에이전트가 부르는 건 **모델**이고, 그 값은 쓰시는 분이 냅니다.
|
|
47
|
+
|
|
48
|
+
## 무엇을 재 주나요
|
|
49
|
+
|
|
50
|
+
```
|
|
51
|
+
노드 20 이상 있음 — v24.16.0
|
|
52
|
+
클로드 코드 있음
|
|
53
|
+
설치 경로 이 폴더에는 아직 없다
|
|
54
|
+
MCP 등록 목록에 없다 — claude mcp add ruflo -- npx ruflo@latest mcp start
|
|
55
|
+
모델 값 도구는 MIT 무료 · 모델 값은 따로
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
**못 재면 「못 쟀다」고 합니다 — 「있다」고 하지 않습니다.**
|
|
59
|
+
|
|
60
|
+
## 까는 순서
|
|
61
|
+
|
|
62
|
+
```
|
|
63
|
+
node -v
|
|
64
|
+
npx ruflo@latest init
|
|
65
|
+
claude mcp add ruflo -- npx ruflo@latest mcp start
|
|
66
|
+
claude mcp list
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## 저희가 말하지 않는 것
|
|
70
|
+
|
|
71
|
+
- **「토큰을 몇 퍼센트 아낀다」** — 저장소 어디에도 그 수치가 없습니다.
|
|
72
|
+
라우팅과 비용 추적이 **있다**는 것까지가 사실입니다.
|
|
73
|
+
- **「깔면 코딩이 끝난다」** — 하네스이지 모델이 아닙니다.
|
|
74
|
+
- **「우리가 만들었다」** — ruvnet 의 오픈소스입니다.
|
|
75
|
+
|
|
76
|
+
## 옵션
|
|
77
|
+
|
|
78
|
+
```
|
|
79
|
+
--check 깔지 않고 이 컴퓨터를 잰다
|
|
80
|
+
--dry-run 무엇을 할지 보여주기만 한다
|
|
81
|
+
--local 홈이 아니라 현재 폴더(.claude/skills)에 깐다
|
|
82
|
+
--self-test 자기시험 (네트워크 안 씀)
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
같은 방식으로 골라 담은 **리본랩스 스킬팩** 48종을 한 줄로 —
|
|
88
|
+
<https://rebornlabs.kr/skillpack?utm_source=installer&utm_medium=cli&utm_campaign=ruflo> · 8,900원
|
|
89
|
+
목록과 직접 까는 명령까지 그 페이지에 그대로 적어 두었습니다. 안 사셔도 됩니다.
|
|
90
|
+
|
|
91
|
+
REBORN LABS · 안내 스킬은 MIT
|
package/cli.mjs
ADDED
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* ruflo 안내 설치기 — **깔기 전에 이 컴퓨터가 되는지 재 주고**, 안내 스킬을 깐다.
|
|
4
|
+
*
|
|
5
|
+
* npx --yes reborn-ruflo 안내 스킬을 깐다 (이게 전부다)
|
|
6
|
+
* npx --yes reborn-ruflo --check ★깔지 않고 **이 컴퓨터를 실제로 잰다**
|
|
7
|
+
* npx --yes reborn-ruflo --dry-run 무엇을 할지 보여주기만 한다
|
|
8
|
+
* npx --yes reborn-ruflo --local 홈이 아니라 현재 폴더에 깐다
|
|
9
|
+
* npx --yes reborn-ruflo --self-test 자기시험 (네트워크 안 씀)
|
|
10
|
+
*
|
|
11
|
+
* ★★우리가 만든 저장소가 아니다.
|
|
12
|
+
* ruflo(옛 claude-flow)는 ruvnet 의 MIT 오픈소스이고, Anthropic 과도 무관한 독립 프로젝트다.
|
|
13
|
+
* 우리는 **재배포하지 않는다** — 코드를 담지도, 대신 설치하지도 않는다. 안내만 한다.
|
|
14
|
+
*
|
|
15
|
+
* ★★--check 가 이 설치기의 존재 이유다
|
|
16
|
+
* 저장소는 「npx ruflo init 한 줄」로 읽힌다. 그런데 실제로 막히는 자리는 셋이다:
|
|
17
|
+
* ① **노드 20 이상** — 18 에서는 깔리는 듯하다 실행에서 죽는다(engines: node >=20).
|
|
18
|
+
* ② **설치 경로** — 플러그인으로 깔면 슬래시 명령만 오고 **훅·MCP·데몬이 안 온다.**
|
|
19
|
+
* 「문서대로 안 된다」는 말의 대부분이 이 자리다.
|
|
20
|
+
* ③ **모델 값** — 도구는 MIT 무료지만 에이전트가 부르는 것은 모델이다. 그건 사용자가 낸다.
|
|
21
|
+
* 그래서 말로 「준비물이 있습니다」 하지 않고, **지금 이 컴퓨터에서 다섯 개를 직접 재 준다.**
|
|
22
|
+
* 못 재면 「못 쟀다」고 한다 — 「있다」고 하지 않는다.
|
|
23
|
+
*/
|
|
24
|
+
import { existsSync, readFileSync, mkdirSync, cpSync, readdirSync } from "node:fs";
|
|
25
|
+
import { homedir, platform } from "node:os";
|
|
26
|
+
import { dirname, join } from "node:path";
|
|
27
|
+
import { fileURLToPath } from "node:url";
|
|
28
|
+
import { execFileSync } from "node:child_process";
|
|
29
|
+
import { TAIL, 링크, 마지막 } from "./tail.mjs";
|
|
30
|
+
|
|
31
|
+
const HOME = homedir();
|
|
32
|
+
const 여기 = dirname(fileURLToPath(import.meta.url));
|
|
33
|
+
const 인자 = process.argv.slice(2);
|
|
34
|
+
const 확인만 = 인자.includes("--check");
|
|
35
|
+
const 미리보기 = 인자.includes("--dry-run");
|
|
36
|
+
const 여기에 = 인자.includes("--local");
|
|
37
|
+
const 자기시험모드 = 인자.includes("--self-test");
|
|
38
|
+
|
|
39
|
+
const c = { g: "\x1b[32m", r: "\x1b[31m", y: "\x1b[33m", d: "\x1b[90m", cy: "\x1b[36m", b: "\x1b[1m", 0: "\x1b[0m" };
|
|
40
|
+
const 굵게 = (t) => String(t).replace(/\*\*(.+?)\*\*/g, `${c[0]}${c.b}$1${c[0]}${c.d}`);
|
|
41
|
+
|
|
42
|
+
const 퍼널 = "ruflo";
|
|
43
|
+
const 스킬이름 = "ruflo-guide";
|
|
44
|
+
const 원본 = join(여기, "skill");
|
|
45
|
+
const 대상뿌리 = 여기에 ? join(process.cwd(), ".claude", "skills") : join(HOME, ".claude", "skills");
|
|
46
|
+
const 대상 = join(대상뿌리, 스킬이름);
|
|
47
|
+
|
|
48
|
+
/* ══ 원장 ═══════════════════════════════════════════════════════════ */
|
|
49
|
+
|
|
50
|
+
function 원장읽기() {
|
|
51
|
+
const p = join(원본, "ruflo.json");
|
|
52
|
+
if (!existsSync(p)) return { 됨: false, 이유: `원장이 없다 — ${p}` };
|
|
53
|
+
try { return { 됨: true, d: JSON.parse(readFileSync(p, "utf8")) }; }
|
|
54
|
+
catch (e) { return { 됨: false, 이유: `원장을 못 읽었다 — ${e.message}` }; }
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** ★조건 없이 단정하는 말 [[kmong-no-unbounded-guarantee]] */
|
|
58
|
+
const 금칙 = [/완전\s*무료/, /무제한/, /평생/, /100\s*%\s*보장/, /누구나\s*바로/, /무조건/,
|
|
59
|
+
/반드시\s*빨라/, /비용\s*걱정\s*없/, /토큰을\s*절반/];
|
|
60
|
+
const 금칙면제 = /(하지\s*않는다|말하지\s*마라|쓰지\s*않는다|아니다|틀리다|금칙|안\s*된다|하지\s*마라|말하지\s*않는다|은\s*아니다|되지\s*않는다|마라|않는다|다른\s*이야기)/;
|
|
61
|
+
/** ★검사기가 자기 인용을 막지 않게 낫표 안은 벗기고 잰다 [[forbidden-word-checker-blocks-its-own-quotes]] */
|
|
62
|
+
const 인용벗기기 = (s) => String(s).replace(/「[^」]*」/g, "○");
|
|
63
|
+
|
|
64
|
+
function 금칙검사(텍스트, 어디) {
|
|
65
|
+
const 문제 = [];
|
|
66
|
+
for (const 줄 of String(텍스트).split("\n")) {
|
|
67
|
+
const 벗긴 = 인용벗기기(줄);
|
|
68
|
+
if (금칙면제.test(벗긴)) continue;
|
|
69
|
+
for (const re of 금칙) if (re.test(벗긴)) 문제.push(`${어디}: 조건 없이 단정하는 말 — ${줄.trim().slice(0, 60)}`);
|
|
70
|
+
}
|
|
71
|
+
return 문제;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function 원장검사(d) {
|
|
75
|
+
const 문제 = [];
|
|
76
|
+
if (!/^https:\/\/github\.com\//.test(String(d?.저장소?.주소 || ""))) 문제.push("저장소 주소가 GitHub 이 아니다");
|
|
77
|
+
if (d?.저장소?.라이선스 !== "MIT") 문제.push("라이선스 칸이 MIT 이 아니다 — 확인 없이 안내하지 않는다");
|
|
78
|
+
if (!String(d?.저장소?.["★면책"] || "").includes("우리가 만든 것이 아니다"))
|
|
79
|
+
문제.push("★면책이 사라졌다 — 남의 저장소를 크게 세우면 귀속을 반드시 박는다");
|
|
80
|
+
const 관문 = Array.isArray(d?.관문) ? d.관문 : [];
|
|
81
|
+
if (관문.length < 5) 문제.push(`관문이 ${관문.length}개다 — 다섯 가지를 재기로 한 설치기다`);
|
|
82
|
+
for (const [i, g] of 관문.entries()) {
|
|
83
|
+
if (!g?.이름 || !g?.왜 || !g?.어떻게) 문제.push(`관문 ${i + 1}: 이름·왜·어떻게 중 빈 칸이 있다`);
|
|
84
|
+
}
|
|
85
|
+
if (!Array.isArray(d?.["★말하지_않는_것"]) || d["★말하지_않는_것"].length < 3)
|
|
86
|
+
문제.push("★말하지 않는 것이 3개 미만이다 — 안내가 광고가 된다");
|
|
87
|
+
if (!String(d?.["★말하지_않는_것"]?.join(" ") || "").includes("퍼센트"))
|
|
88
|
+
문제.push("퍼센트 절감 이야기를 막는 줄이 없다 — 참고본의 목업 값이 그대로 옮겨 간다");
|
|
89
|
+
return 문제;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/* ══ 재기 ═══════════════════════════════════════════════════════════ */
|
|
93
|
+
|
|
94
|
+
const 실행 = (cmd, args, ms = 8000) => {
|
|
95
|
+
try {
|
|
96
|
+
return { 됨: true, out: String(execFileSync(cmd, args, { encoding: "utf8", timeout: ms, stdio: ["ignore", "pipe", "pipe"], shell: process.platform === "win32" })).trim() };
|
|
97
|
+
} catch (e) { return { 됨: false, 이유: String(e?.message || e).split("\n")[0].slice(0, 90) }; }
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
/** ★「못 쟀다」와 「없다」를 구분한다. 못 쟀는데 「없다」고 하면 그게 틀린 진단이다. */
|
|
101
|
+
function 재기(d) {
|
|
102
|
+
const 결과 = [];
|
|
103
|
+
|
|
104
|
+
/* ① 노드 판 */
|
|
105
|
+
const 최소 = Number(d.값.노드최소);
|
|
106
|
+
const 지금 = Number(String(process.versions.node).split(".")[0]);
|
|
107
|
+
결과.push({
|
|
108
|
+
이름: `노드 ${최소} 이상`,
|
|
109
|
+
상태: 지금 >= 최소 ? "ok" : "no",
|
|
110
|
+
값: `v${process.versions.node}`,
|
|
111
|
+
말: 지금 >= 최소 ? "" : `노드를 먼저 올려야 한다 — engines 가 node >=${최소}.0.0 이다. 18 에서는 깔리는 듯하다 실행에서 죽는다`,
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
/* ② 클로드 코드 — ruflo 는 하네스다. 모델을 부르는 도구가 따로 있어야 한다 */
|
|
115
|
+
const cc = 실행("claude", ["--version"]);
|
|
116
|
+
결과.push({
|
|
117
|
+
이름: "클로드 코드",
|
|
118
|
+
상태: cc.됨 ? "ok" : "no",
|
|
119
|
+
값: cc.됨 ? cc.out.split("\n")[0].slice(0, 40) : "PATH 에서 못 찾음",
|
|
120
|
+
말: cc.됨 ? "" : "ruflo 는 하네스다 — 혼자서는 아무 일도 하지 않는다. 클로드 코드(또는 코덱스)가 먼저 있어야 한다",
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
/* ③ 설치 경로 — ★가장 많이 틀리는 자리 */
|
|
124
|
+
const mcp파일 = [join(process.cwd(), ".mcp.json"), join(HOME, ".claude.json")].filter(existsSync);
|
|
125
|
+
const 훅있나 = (() => {
|
|
126
|
+
const p = join(process.cwd(), ".claude", "settings.json");
|
|
127
|
+
if (!existsSync(p)) return null;
|
|
128
|
+
try { const s = JSON.parse(readFileSync(p, "utf8")); return !!(s.hooks && Object.keys(s.hooks).length); }
|
|
129
|
+
catch { return null; }
|
|
130
|
+
})();
|
|
131
|
+
const 깔림 = existsSync(join(process.cwd(), ".claude-flow")) || existsSync(join(process.cwd(), ".swarm"))
|
|
132
|
+
|| existsSync(join(process.cwd(), ".ruflo"));
|
|
133
|
+
결과.push({
|
|
134
|
+
이름: "설치 경로",
|
|
135
|
+
상태: 깔림 ? (훅있나 ? "ok" : "warn") : "info",
|
|
136
|
+
값: 깔림 ? (훅있나 ? "CLI 설치 흔적 + 훅 있음" : "설치 흔적은 있는데 훅이 안 보인다") : "이 폴더에는 아직 없다",
|
|
137
|
+
말: 깔림 && !훅있나
|
|
138
|
+
? "플러그인만 깐 상태일 수 있다 — 그러면 슬래시 명령만 오고 훅·MCP·데몬이 안 온다. 문서대로 다 돌게 하려면 CLI 설치다"
|
|
139
|
+
: (깔림 ? "" : `이 폴더에서 깔려면: ${d.명령.설치}`),
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
/* ④ MCP 등록 */
|
|
143
|
+
const ml = 실행("claude", ["mcp", "list"], 12000);
|
|
144
|
+
결과.push({
|
|
145
|
+
이름: "MCP 등록",
|
|
146
|
+
상태: ml.됨 ? (/ruflo|claude-flow/i.test(ml.out) ? "ok" : "no") : "unknown",
|
|
147
|
+
값: ml.됨 ? (/ruflo|claude-flow/i.test(ml.out) ? "등록돼 있다" : "목록에 없다") : "못 쟀다",
|
|
148
|
+
말: ml.됨
|
|
149
|
+
? (/ruflo|claude-flow/i.test(ml.out) ? "" : `등록하려면: ${d.명령.MCP등록}`)
|
|
150
|
+
: "claude mcp list 를 못 불렀다 — 클로드 코드가 없거나 PATH 밖이다. 「없다」가 아니라 「못 쟀다」다",
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
/* ⑤ 모델 값 — 재는 게 아니라 **말해 주는** 칸이다 */
|
|
154
|
+
결과.push({
|
|
155
|
+
이름: "모델 값",
|
|
156
|
+
상태: "info",
|
|
157
|
+
값: "도구는 MIT 무료 · 모델 값은 따로",
|
|
158
|
+
말: `에이전트 ${d.값.에이전트}종이 부르는 것은 모델이다. 스웜을 크게 띄우면 그만큼 청구된다 — `
|
|
159
|
+
+ "작은 작업으로 먼저 재 보고 ruflo-cost-tracker 로 예산과 알림을 건다",
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
return 결과;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
function 재기찍기(결과) {
|
|
166
|
+
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]}` };
|
|
167
|
+
console.log(`\n ${c.b}이 컴퓨터에서 ruflo 가 되는지${c[0]} ${c.d}(${platform()})${c[0]}\n`);
|
|
168
|
+
for (const r of 결과) {
|
|
169
|
+
console.log(` ${표[r.상태]} ${c.b}${r.이름}${c[0]} ${c.d}${r.값}${c[0]}`);
|
|
170
|
+
if (r.말) console.log(` ${c.d}${굵게(r.말)}${c[0]}`);
|
|
171
|
+
}
|
|
172
|
+
const 막힘 = 결과.filter((r) => r.상태 === "no").length;
|
|
173
|
+
console.log(`\n ${막힘 ? `${c.y}막히는 자리 ${막힘}개${c[0]}` : `${c.g}막히는 자리 없음${c[0]}`}`
|
|
174
|
+
+ ` ${c.d}· 못 잰 칸은 「없다」가 아니라 「못 쟀다」입니다${c[0]}\n`);
|
|
175
|
+
return 막힘;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/* ══ 끝난 뒤 한 칸 ═══════════════════════════════════════════════════ */
|
|
179
|
+
function 꼬리(깔았나) {
|
|
180
|
+
if (!깔았나) return; /* ★못 깔았으면 안 띄운다 */
|
|
181
|
+
const t = TAIL[퍼널];
|
|
182
|
+
console.log("");
|
|
183
|
+
for (const l of t.이음) console.log(` ${c.d}${굵게(l)}${c[0]}`);
|
|
184
|
+
console.log(`\n ${c.b}${t.제목}${c[0]} ${c.d}— ${t.한줄}${c[0]}`);
|
|
185
|
+
console.log(` ${c.cy}${링크(퍼널)}${c[0]}`);
|
|
186
|
+
console.log(` ${c.d}${마지막}${c[0]}\n`);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/* ══ 깔기 ═══════════════════════════════════════════════════════════ */
|
|
190
|
+
function 깔기() {
|
|
191
|
+
mkdirSync(대상뿌리, { recursive: true });
|
|
192
|
+
cpSync(원본, 대상, { recursive: true });
|
|
193
|
+
return readdirSync(대상);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/* ══ 자기시험 — ★양방향 ════════════════════════════════════════════ */
|
|
197
|
+
function 자기시험() {
|
|
198
|
+
const 나쁨 = [];
|
|
199
|
+
const L = 원장읽기();
|
|
200
|
+
if (!L.됨) { console.error(`✗ ${L.이유}`); process.exit(1); }
|
|
201
|
+
나쁨.push(...원장검사(L.d));
|
|
202
|
+
|
|
203
|
+
const skill = join(원본, "SKILL.md");
|
|
204
|
+
if (!existsSync(skill)) 나쁨.push("skill/SKILL.md 가 없다");
|
|
205
|
+
else {
|
|
206
|
+
const t = readFileSync(skill, "utf8");
|
|
207
|
+
나쁨.push(...금칙검사(t, "SKILL.md"));
|
|
208
|
+
if (!t.includes("ruvnet")) 나쁨.push("SKILL.md 가 만든이를 안 밝힌다");
|
|
209
|
+
if (!t.includes("MIT")) 나쁨.push("SKILL.md 가 라이선스를 안 밝힌다");
|
|
210
|
+
if (!/name:\s*ruflo-guide/.test(t)) 나쁨.push("SKILL.md 의 name 이 ruflo-guide 가 아니다 — 스킬이 안 불린다");
|
|
211
|
+
}
|
|
212
|
+
나쁨.push(...금칙검사(JSON.stringify(L.d), "원장"));
|
|
213
|
+
|
|
214
|
+
/* ★꼬리 규율 — 클로드킷·풀스택은 스킬팩 구매 이후다 */
|
|
215
|
+
const 꼬리글 = JSON.stringify(TAIL[퍼널]) + 링크(퍼널) + 마지막;
|
|
216
|
+
for (const 금지 of ["클로드킷", "자비스", "58,000", "158,000", "일감 진단"]) {
|
|
217
|
+
if (꼬리글.includes(금지)) 나쁨.push(`꼬리에 「${금지}」 가 있다 — 스킬팩 한 칸만 말한다`);
|
|
218
|
+
}
|
|
219
|
+
if (!링크(퍼널).includes(`utm_campaign=${퍼널}`)) 나쁨.push("꼬리 링크에 utm_campaign 이 없다 — 어느 릴스가 만들었는지 못 센다");
|
|
220
|
+
|
|
221
|
+
/* ★미탐 시험 — 검사기가 실제로 잡는가 */
|
|
222
|
+
if (!금칙검사("이건 완전 무료입니다", "시험").length) 나쁨.push("금칙 검사가 「완전 무료」를 못 잡는다");
|
|
223
|
+
if (금칙검사("「완전 무료」라고 말하지 않는다", "시험").length) 나쁨.push("금칙 검사가 자기 인용을 오탐한다");
|
|
224
|
+
if (!원장검사({ ...L.d, 저장소: { ...L.d.저장소, 라이선스: "GPL" } }).length) 나쁨.push("원장 검사가 라이선스 어긋남을 못 잡는다");
|
|
225
|
+
if (!원장검사({ ...L.d, 관문: L.d.관문.slice(0, 2) }).length) 나쁨.push("원장 검사가 관문 수 부족을 못 잡는다");
|
|
226
|
+
|
|
227
|
+
/* ★재기가 던지지 않는가 (네트워크·외부 명령이 없어도 돌아야 한다) */
|
|
228
|
+
let 결과 = null;
|
|
229
|
+
try { 결과 = 재기(L.d); } catch (e) { 나쁨.push(`재기가 던졌다: ${e.message}`); }
|
|
230
|
+
if (결과 && 결과.length !== L.d.관문.length)
|
|
231
|
+
나쁨.push(`재는 칸이 ${결과.length}개인데 원장의 관문은 ${L.d.관문.length}개다 — 원장에 적고 안 재는 칸이 생긴다`);
|
|
232
|
+
if (결과 && 결과.some((r) => !r.이름 || !r.상태)) 나쁨.push("재기 결과에 빈 칸이 있다");
|
|
233
|
+
|
|
234
|
+
if (나쁨.length) { console.error("✗ 자기시험 실패\n - " + 나쁨.join("\n - ")); process.exit(1); }
|
|
235
|
+
console.log(`✓ 자기시험 통과 — 원장 관문 ${L.d.관문.length}개 · 재는 칸 ${결과.length}개 · 금칙 검사 양방향 · 꼬리 규율`);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/* ══ 본문 ═══════════════════════════════════════════════════════════ */
|
|
239
|
+
if (자기시험모드) { 자기시험(); process.exit(0); }
|
|
240
|
+
|
|
241
|
+
const L = 원장읽기();
|
|
242
|
+
if (!L.됨) { console.error(`✗ ${L.이유}`); process.exit(1); }
|
|
243
|
+
const D = L.d;
|
|
244
|
+
|
|
245
|
+
console.log(`\n ${c.b}ruflo${c[0]} ${c.d}— ${D.저장소.만든이} 의 ${D.저장소.라이선스} 오픈소스`
|
|
246
|
+
+ ` (옛 이름 ${D.저장소.옛이름})${c[0]}`);
|
|
247
|
+
console.log(` ${c.d}${D.저장소.주소}${c[0]}`);
|
|
248
|
+
|
|
249
|
+
const 결과 = 재기(D);
|
|
250
|
+
const 막힘 = 재기찍기(결과);
|
|
251
|
+
|
|
252
|
+
if (확인만) {
|
|
253
|
+
console.log(` ${c.d}안내 스킬을 깔려면: ${c.cy}npx --yes reborn-ruflo${c[0]}\n`);
|
|
254
|
+
process.exit(0);
|
|
255
|
+
}
|
|
256
|
+
if (미리보기) {
|
|
257
|
+
console.log(` ${c.d}깔 자리: ${대상}${c[0]}`);
|
|
258
|
+
console.log(` ${c.d}담을 것: ${readdirSync(원본).join(" · ")}${c[0]}\n`);
|
|
259
|
+
process.exit(0);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
let 깔았나 = false;
|
|
263
|
+
try {
|
|
264
|
+
const 담긴 = 깔기();
|
|
265
|
+
깔았나 = true;
|
|
266
|
+
console.log(` ${c.g}안내 스킬을 깔았습니다${c[0]} ${c.d}→ ${대상}${c[0]}`);
|
|
267
|
+
console.log(` ${c.d}담긴 것: ${담긴.join(" · ")}${c[0]}`);
|
|
268
|
+
console.log(`\n 클로드 코드를 다시 열고 ${c.b}「루플로 깔아줘」${c[0]} 라고 하면 스킬이 이어서 안내합니다.`);
|
|
269
|
+
if (막힘) console.log(` ${c.y}막히는 자리 ${막힘}개는 위에 적어 두었습니다 — 그것부터 풉니다.${c[0]}`);
|
|
270
|
+
} catch (e) {
|
|
271
|
+
console.error(`\n ${c.r}못 깔았습니다${c[0]} — ${String(e.message).slice(0, 120)}`);
|
|
272
|
+
console.error(` ${c.d}권한 문제면 --local 로 현재 폴더에 깔 수 있습니다.${c[0]}\n`);
|
|
273
|
+
process.exit(1);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
꼬리(깔았나);
|
package/package.json
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "reborn-ruflo",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "ruflo(옛 claude-flow · ruvnet · MIT · 별 71.7k)를 쓰기 전에 무엇이 막는지 알려 주는 안내 스킬입니다. --check 가 이 컴퓨터에서 다섯 가지(노드 20+ · 클로드 코드 · 설치 경로 · MCP 등록 · 모델 값)를 실제로 재 줍니다. 가장 많이 틀리는 자리는 설치 경로입니다 — 플러그인으로 깔면 슬래시 명령만 오고 훅·MCP·데몬이 안 옵니다. 저장소 코드는 담지 않습니다.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"claude",
|
|
7
|
+
"claude-code",
|
|
8
|
+
"ruflo",
|
|
9
|
+
"claude-flow",
|
|
10
|
+
"agent-swarm",
|
|
11
|
+
"multi-agent",
|
|
12
|
+
"orchestration",
|
|
13
|
+
"mcp",
|
|
14
|
+
"agent-harness",
|
|
15
|
+
"korean"
|
|
16
|
+
],
|
|
17
|
+
"homepage": "https://rebornlabs.kr/ruflo?utm_source=installer&utm_medium=cli&utm_campaign=ruflo",
|
|
18
|
+
"bugs": {
|
|
19
|
+
"url": "https://mobility.rebornlabs.kr/cs"
|
|
20
|
+
},
|
|
21
|
+
"license": "MIT",
|
|
22
|
+
"author": "REBORN LABS",
|
|
23
|
+
"type": "module",
|
|
24
|
+
"bin": {
|
|
25
|
+
"reborn-ruflo": "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,83 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ruflo-guide
|
|
3
|
+
description: ruflo(옛 claude-flow) — 클로드 코드·코덱스 위에 얹는 에이전트 메타하네스를 **깔기 전에** 무엇이 막는지 알려 준다. 노드 20 미만이면 깔리는 듯하다 실행에서 죽는다는 것, 플러그인으로 깔면 훅·MCP·데몬이 안 온다는 것(「문서대로 안 된다」의 대부분이 이 자리다), 도구는 MIT 무료지만 에이전트가 부르는 모델 값은 사용자가 낸다는 것을 먼저 말한다. "ruflo", "루플로", "claude-flow", "클로드 플로우", "에이전트 스웜", "멀티 에이전트", "퀸 에이전트", "에이전트 여러 개 동시에", "클로드 코드에 에이전트 붙이기", "npx ruflo init", "MCP 서버 등록", "에이전트 오케스트레이션" 같은 이야기가 나올 때 쓴다.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# ruflo — 깔기 전에 알아야 하는 것
|
|
7
|
+
|
|
8
|
+
> **우리가 만든 것이 아니다.** ruflo 는 [ruvnet](https://github.com/ruvnet) 의 MIT 오픈소스이고,
|
|
9
|
+
> Anthropic 과도 무관한 독립 프로젝트다. 이 스킬은 **안내만** 한다 — 코드를 담지도,
|
|
10
|
+
> 대신 설치하지도 않는다.
|
|
11
|
+
>
|
|
12
|
+
> 사실 원장은 이 폴더의 `ruflo.json` 이다. **여기 없는 수치는 말하지 않는다.**
|
|
13
|
+
|
|
14
|
+
## 0. 한 줄로
|
|
15
|
+
|
|
16
|
+
클로드 코드가 「한 사람」이라면, ruflo 는 그 위에 **팀**을 얹는다 —
|
|
17
|
+
퀸 에이전트가 일을 갈라 맡기고, 결과를 합치고, 그 과정에서 나온 규칙을 기억에 남긴다.
|
|
18
|
+
|
|
19
|
+
* 저장소: <https://github.com/ruvnet/ruflo> · 라이선스 **MIT**
|
|
20
|
+
* 옛 이름 **claude-flow** (2026-01 에 상표 문제로 개명 — 옛 이름으로 된 글이 아직 많다)
|
|
21
|
+
|
|
22
|
+
## 1. ★먼저 재라 — 말로 준비물을 늘어놓지 않는다
|
|
23
|
+
|
|
24
|
+
```
|
|
25
|
+
npx --yes reborn-ruflo --check
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
이 컴퓨터에서 **다섯 가지를 실제로 잰다.** 못 재는 칸은 「없다」가 아니라 **「못 쟀다」**로 말한다.
|
|
29
|
+
|
|
30
|
+
## 2. 막히는 자리 셋 (거의 전부가 여기다)
|
|
31
|
+
|
|
32
|
+
### ① 노드 20 이상
|
|
33
|
+
`engines` 가 `node >=20.0.0` 이다. **18 에서는 깔리는 듯하다 실행에서 죽는다** —
|
|
34
|
+
설치 로그만 보고 「됐다」고 넘어가면 나중에 엉뚱한 곳에서 실패한다. 노드를 먼저 올린다.
|
|
35
|
+
|
|
36
|
+
### ② ★설치 경로를 고르는 일 — 가장 많이 틀린다
|
|
37
|
+
두 갈래가 있고 **주는 것이 다르다.**
|
|
38
|
+
|
|
39
|
+
| | 클로드 코드 플러그인 | CLI 설치 (`npx ruflo@latest init`) |
|
|
40
|
+
|---|---|---|
|
|
41
|
+
| 오는 것 | 슬래시 명령 + 에이전트 정의 | 에이전트 98종 · 커맨드 60+ · 스킬 30 · MCP 서버 · 훅 · 데몬 |
|
|
42
|
+
| 훅 | **안 온다** | 온다 |
|
|
43
|
+
| MCP 서버 | 대부분 안 온다 | 온다 |
|
|
44
|
+
|
|
45
|
+
「문서대로 안 된다」는 말의 대부분이 **플러그인만 깔고 CLI 문서를 보고 있는 것**이다.
|
|
46
|
+
문서대로 다 돌게 하려면 CLI 설치다.
|
|
47
|
+
|
|
48
|
+
### ③ 모델 값은 따로 든다
|
|
49
|
+
도구는 MIT 무료다. 그런데 **에이전트 98종이 부르는 것은 모델**이고, 그 값은 사용자가 낸다.
|
|
50
|
+
스웜을 크게 띄우면 그만큼 청구된다 — 작은 작업으로 먼저 재 보고,
|
|
51
|
+
`ruflo-cost-tracker` 로 예산과 알림을 건다.
|
|
52
|
+
|
|
53
|
+
## 3. 까는 순서
|
|
54
|
+
|
|
55
|
+
```
|
|
56
|
+
node -v # 20 이상인지 먼저
|
|
57
|
+
npx ruflo@latest init # CLI 설치 (전체 loop)
|
|
58
|
+
claude mcp add ruflo -- npx ruflo@latest mcp start # MCP 등록
|
|
59
|
+
claude mcp list # ruflo 가 목록에 있나
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
`init wizard` 를 쓰면 대화형으로 고르며 깐다.
|
|
63
|
+
깔고 나면 **평소처럼 클로드 코드를 쓰면 된다** — 훅이 알아서 일을 라우팅한다.
|
|
64
|
+
314개 MCP 도구와 26개 CLI 명령을 외울 필요가 없다(README 가 직접 그렇게 적는다).
|
|
65
|
+
|
|
66
|
+
## 4. 무엇이 좋아지나 (확인된 것까지만)
|
|
67
|
+
|
|
68
|
+
* **일감을 갈라 맡긴다** — 퀸이 계획하고, 역할별 에이전트가 나눠 처리하고, 결과를 합친다
|
|
69
|
+
* **기억이 남는다** — AgentDB(벡터 메모리)에 결정과 규칙이 쌓여 세션을 넘어 이어진다
|
|
70
|
+
* **난이도에 따라 모델이 갈린다** — 쉬운 일과 어려운 일을 같은 모델로 태우지 않는다
|
|
71
|
+
* **비용이 보인다** — `ruflo-cost-tracker` 로 사용량·예산·알림
|
|
72
|
+
|
|
73
|
+
## 5. ★말하지 않는 것
|
|
74
|
+
|
|
75
|
+
* **「토큰을 몇 퍼센트 아낀다」** — 저장소 어디에도 그런 수치가 없다.
|
|
76
|
+
라우팅과 비용 추적이 **있다**는 것까지가 사실이다. 퍼센트는 소개 영상들의 목업 값이다.
|
|
77
|
+
* **「깔면 코딩이 끝난다」** — 하네스이지 모델이 아니다.
|
|
78
|
+
* **「우리가 만들었다」** — ruvnet 의 오픈소스다. 우리는 설치와 설정을 정리했을 뿐이다.
|
|
79
|
+
|
|
80
|
+
## 6. 되돌리기
|
|
81
|
+
|
|
82
|
+
`init` 이 만든 것은 프로젝트 폴더 안이다(`.claude/`, `.mcp.json`, `.swarm/` 등).
|
|
83
|
+
지우면 원래대로 돌아간다. MCP 등록은 `claude mcp remove ruflo`.
|
package/skill/ruflo.json
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_doc": "reborn-ruflo 안내 스킬의 사실 원장. 스킬이 말하는 값은 전부 여기서만 온다.",
|
|
3
|
+
"_잰날": "2026-09-09",
|
|
4
|
+
|
|
5
|
+
"저장소": {
|
|
6
|
+
"이름": "ruflo",
|
|
7
|
+
"옛이름": "claude-flow",
|
|
8
|
+
"주소": "https://github.com/ruvnet/ruflo",
|
|
9
|
+
"만든이": "ruvnet (rUv)",
|
|
10
|
+
"라이선스": "MIT",
|
|
11
|
+
"★면책": "우리가 만든 것이 아니다. ruflo 는 ruvnet 의 오픈소스이고, Anthropic 과도 무관한 독립 프로젝트다. 우리는 재배포하지 않는다 — 코드를 담지도, 대신 클론하지도 않는다. 안내만 한다.",
|
|
12
|
+
"★개명": "2026-01 에 상표 문제로 claude-flow 에서 ruflo 로 바뀌었다. 옛 이름으로 찾는 글이 아직 많다."
|
|
13
|
+
},
|
|
14
|
+
|
|
15
|
+
"값": {
|
|
16
|
+
"버전": "3.39.0",
|
|
17
|
+
"에이전트": "98",
|
|
18
|
+
"커맨드": "60+",
|
|
19
|
+
"스킬": "30",
|
|
20
|
+
"MCP도구": "314",
|
|
21
|
+
"노드최소": "20",
|
|
22
|
+
"_출처": "npm registry(버전·engines) + README 설치경로 표(에이전트·커맨드·스킬) + README 본문(MCP 도구)"
|
|
23
|
+
},
|
|
24
|
+
|
|
25
|
+
"명령": {
|
|
26
|
+
"설치": "npx ruflo@latest init",
|
|
27
|
+
"마법사": "npx ruflo@latest init wizard",
|
|
28
|
+
"MCP등록": "claude mcp add ruflo -- npx ruflo@latest mcp start"
|
|
29
|
+
},
|
|
30
|
+
|
|
31
|
+
"관문": [
|
|
32
|
+
{
|
|
33
|
+
"이름": "노드 20 이상",
|
|
34
|
+
"왜": "package.json 의 engines 가 node >=20.0.0 이다. 18 에서는 설치가 되는 것처럼 보이다가 실행에서 죽는다.",
|
|
35
|
+
"어떻게": "node -v 로 재고, 낮으면 노드를 먼저 올린다."
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"이름": "클로드 코드(또는 코덱스)",
|
|
39
|
+
"왜": "ruflo 는 **하네스**다 — 모델을 부르는 도구가 따로 있어야 한다. 혼자서는 아무 일도 하지 않는다.",
|
|
40
|
+
"어떻게": "claude --version 이 답하는지 본다."
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"이름": "설치 경로를 고르는 일",
|
|
44
|
+
"왜": "★가장 많이 틀리는 자리다. 플러그인으로 깔면 슬래시 명령과 에이전트 정의만 오고, **훅·MCP·데몬이 안 온다.** 문서대로 다 돌게 하려면 CLI 설치(npx ruflo init)다.",
|
|
45
|
+
"어떻게": "무엇을 깔았는지 확인한다 — .claude/settings.json 의 훅과 .mcp.json 을 본다."
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
"이름": "MCP 등록",
|
|
49
|
+
"왜": "CLI 로 깔아도 MCP 서버를 따로 등록해야 클로드가 도구를 본다.",
|
|
50
|
+
"어떻게": "claude mcp list 에 ruflo 가 있는지 본다."
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
"이름": "모델 값은 따로 든다",
|
|
54
|
+
"왜": "★도구는 MIT 무료지만, 에이전트 98종이 부르는 것은 **모델**이다. 스웜을 크게 띄우면 그만큼 청구된다 — 도구가 공짜인 것과 쓰는 값이 공짜인 것은 다른 이야기다.",
|
|
55
|
+
"어떻게": "먼저 작은 작업으로 재 보고, ruflo-cost-tracker 로 예산과 알림을 건다."
|
|
56
|
+
}
|
|
57
|
+
],
|
|
58
|
+
|
|
59
|
+
"★말하지_않는_것": [
|
|
60
|
+
"「토큰을 몇 퍼센트 아낀다」 — 저장소 어디에도 그런 수치가 없다. 라우팅과 비용 추적이 있다는 것까지가 사실이다.",
|
|
61
|
+
"「깔면 코딩이 끝난다」 — 하네스이지 모델이 아니다.",
|
|
62
|
+
"「우리가 만들었다」 — ruvnet 의 오픈소스다. 우리는 설치와 설정을 정리했을 뿐이다."
|
|
63
|
+
]
|
|
64
|
+
}
|
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
|
+
ruflo: {
|
|
15
|
+
이음: [
|
|
16
|
+
"방금 한 일은 **이 컴퓨터가 되는지 실제로 재 본 것**입니다 — 다섯 가지 중 무엇이 있고 무엇이 없는지.",
|
|
17
|
+
"저장소는 ruvnet 이 공개해 둔 것입니다. 막히는 자리는 **심는 것이 아니라 고르는 것**입니다 — 어느 설치 경로로 깔았는지.",
|
|
18
|
+
],
|
|
19
|
+
제목: "리본랩스 스킬팩",
|
|
20
|
+
한줄: "같은 방식으로 골라 담은 48종을 한 줄로. 8,900원",
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export const 마지막 = "목록과 직접 까는 명령까지 그 페이지에 그대로 적어 두었습니다. 안 사셔도 됩니다.";
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# reborn-ruflo — 안내 설치기 규격 (내부 문서)
|
|
2
|
+
|
|
3
|
+
> 이 파일은 **고객에게 깔리지 않는다.** `skill/SKILL.md` 가 깔리는 것이고,
|
|
4
|
+
> 이 문서는 그 스킬이 무엇을 지켜야 하는지를 적어 둔 규격이다.
|
|
5
|
+
|
|
6
|
+
## 무엇을 파는가
|
|
7
|
+
|
|
8
|
+
**저장소가 아니다.** ruflo 는 ruvnet 의 MIT 오픈소스이고 공개돼 있다.
|
|
9
|
+
우리가 파는 것은 **「깔기 전에 이 컴퓨터에서 뭐가 막히는지 재 주는 것」** 하나다.
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
npx --yes reborn-ruflo --check
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## 재는 다섯 (원장 `skill/ruflo.json` 의 `관문`)
|
|
16
|
+
|
|
17
|
+
| # | 무엇 | 왜 |
|
|
18
|
+
|---|---|---|
|
|
19
|
+
| 1 | 노드 20 이상 | engines 가 `node >=20.0.0`. **18 에서는 깔리는 듯하다 실행에서 죽는다** |
|
|
20
|
+
| 2 | 클로드 코드 | ruflo 는 하네스다 — 모델을 부르는 도구가 없으면 아무 일도 안 한다 |
|
|
21
|
+
| 3 | **설치 경로** | ★가장 많이 틀린다. 플러그인은 슬래시 명령만 오고 훅·MCP·데몬이 안 온다 |
|
|
22
|
+
| 4 | MCP 등록 | CLI 로 깔아도 따로 등록해야 클로드가 도구를 본다 |
|
|
23
|
+
| 5 | 모델 값 | 도구는 무료지만 에이전트가 부르는 모델 값은 사용자가 낸다 |
|
|
24
|
+
|
|
25
|
+
★**「못 쟀다」와 「없다」를 구분한다.** `claude mcp list` 를 못 부르면 「없다」가 아니라
|
|
26
|
+
「못 쟀다」로 말한다. 틀린 진단은 침묵과 같다 [[wrong-diagnosis-is-a-silent-failure]].
|
|
27
|
+
|
|
28
|
+
★**재는 칸 수 = 원장의 관문 수.** `--self-test` 가 그 둘을 대조한다 —
|
|
29
|
+
원장에 적어 놓고 안 재는 칸이 생기면 그 자리가 조용히 빈다.
|
|
30
|
+
|
|
31
|
+
## ★끝 한 칸 — 스킬팩
|
|
32
|
+
|
|
33
|
+
설치가 **끝난 뒤 딱 한 칸.** 정본 문안은 `tail.mjs` 에 있고 `skillpack/tail_copy.mjs` 가 상위 정본이다.
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
리본랩스 스킬팩 — 같은 방식으로 골라 담은 48종을 한 줄로. 8,900원
|
|
37
|
+
https://rebornlabs.kr/skillpack?utm_source=installer&utm_medium=cli&utm_campaign=ruflo
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
규율 다섯:
|
|
41
|
+
|
|
42
|
+
1. **끝난 뒤 딱 한 칸**
|
|
43
|
+
2. **아무것도 못 깔았으면 안 띄운다** — `꼬리(깔았나)` 가 그 자리에서 막는다
|
|
44
|
+
3. **파일을 안 남긴다** — 지나가는 글자다
|
|
45
|
+
4. **고지 블록 금지**
|
|
46
|
+
5. **첫 줄은 방금 한 일에서 이어져야 한다** — 「방금 이 컴퓨터를 재 봤습니다」에서 시작한다
|
|
47
|
+
|
|
48
|
+
★스킬팩 위의 상품들은 **여기서 말하지 않는다.** 그 안내는 스킬팩 구매 이후 자리다(2026-08-24 전략).
|
|
49
|
+
0원 다음 칸이 곧바로 십오만 원대면 사람은 종종 **둘 다 안 고른다.**
|
|
50
|
+
이 문서에도 그 상품 이름을 적지 않는다 — 관문이 문자열로 본다.
|
|
51
|
+
|
|
52
|
+
★마지막 줄은 언제나 이것이다 — **「목록과 직접 까는 명령까지 그 페이지에 그대로 적어
|
|
53
|
+
두었습니다. 안 사셔도 됩니다.」** 저장소가 공개돼 있다는 사실을 숨기지 않는다.
|
|
54
|
+
|
|
55
|
+
## 안 하는 말
|
|
56
|
+
|
|
57
|
+
`cli.mjs` 의 `안하는말`·`금칙` 에 박아 뒀고, `--self-test` 가 금칙어를 **양방향으로** 시험한다.
|
|
58
|
+
|
|
59
|
+
- 「깔면 끝」 — 깔리는 것과 도는 것은 다르다
|
|
60
|
+
- 「토큰을 몇 퍼센트 아낀다」 — **저장소 어디에도 없는 수치다.** 소개 영상들의 목업 값이다
|
|
61
|
+
- 「ruvnet 과 제휴했다」 — 우리는 공개된 오픈소스를 안내할 뿐이다
|
|
62
|
+
- 「우리가 만들었다」 — ruvnet 의 MIT 오픈소스다
|
|
63
|
+
- 성과를 보장한다는 말 — 우리가 잴 수 있는 값이 아니다
|
|
64
|
+
|
|
65
|
+
## 되돌리기
|
|
66
|
+
|
|
67
|
+
깔린 스킬은 `~/.claude/skills/ruflo-guide/` 다. 지우고 클로드 코드를 다시 켜면 목록에서 빠진다.
|