reborn-claudian 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 +36 -0
- package/cli.mjs +205 -0
- package/package.json +16 -0
- package/skill/SKILL.md +50 -0
- package/skill/claudian-ko/SKILL.md +47 -0
- package/skill/claudian-ko/claudian.mjs +90 -0
- package/skill/claudian.json +43 -0
- package/tail.mjs +24 -0
package/README.md
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# reborn-claudian — 옵시디언 볼트에 클로드를
|
|
2
|
+
|
|
3
|
+
```
|
|
4
|
+
npx --yes reborn-claudian
|
|
5
|
+
```
|
|
6
|
+
|
|
7
|
+
클로드 코드 스킬 폴더(`~/.claude/skills/`)에 한국어 스킬 둘을 놓습니다.
|
|
8
|
+
|
|
9
|
+
| 스킬 | 하는 일 |
|
|
10
|
+
|---|---|
|
|
11
|
+
| `claudian-ko` | 이 컴퓨터에 Claude Code CLI 가 있고 **로그인돼 있는지** 재서, 옵시디언 커뮤니티 플러그인 「Claudian」을 설치·연결하는 순서를 안내합니다 |
|
|
12
|
+
| `claudian-ko-guide` | Claudian 이 무엇이고 무엇이 필요한지, 왜 모바일은 안 되는지, 큰 번들 경고가 왜 정상인지 안내합니다 |
|
|
13
|
+
|
|
14
|
+
## 먼저 알아 두실 것
|
|
15
|
+
- **Claudian**(github.com/YishenTu/claudian · MIT · 무료 오픈소스)은 Claude Code/Codex 등 로컬 에이전트를 옵시디언 볼트에 AI 협업자로 심는 플러그인입니다.
|
|
16
|
+
- **이 패키지에는 Claudian 플러그인 자체가 들어 있지 않습니다.** 옵시디언 안에서 Community plugins → 「Claudian」으로 직접 설치해야 합니다. 저희는 그 순서를 안내하는 스킬만 놓습니다.
|
|
17
|
+
- Claude Code CLI 는 **이미 쓰는 구독 로그인**으로 그대로 됩니다 — 별도 API 키가 필요 없습니다.
|
|
18
|
+
- **데스크톱 전용**입니다(macOS·Linux·Windows) — 옵시디언 모바일 앱에서는 안 됩니다.
|
|
19
|
+
- 번들이 5MB 를 넘어 옵시디언이 「대형 플러그인」 경고를 띄울 수 있습니다 — 저장소 README 가 명시한 정상 상태입니다.
|
|
20
|
+
|
|
21
|
+
## 쓰는 법
|
|
22
|
+
```
|
|
23
|
+
npx --yes reborn-claudian --check 깔지 않고 Claude Code CLI 유무·로그인 상태·갈 길만 봅니다
|
|
24
|
+
npx --yes reborn-claudian --dry-run 무엇이 어디로 갈지 보여 주기만 합니다
|
|
25
|
+
npx --yes reborn-claudian --local 현재 폴더(.claude/skills)에 놓습니다
|
|
26
|
+
npx --yes reborn-claudian --force 이미 있어도 덮어씁니다
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
깐 뒤 클로드 코드를 다시 켜고 이렇게 말하세요:
|
|
30
|
+
```
|
|
31
|
+
옵시디언에 클로드 붙이는 법 알려줘
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## 라이선스
|
|
35
|
+
REBORN LABS. 개인·회사 안에서 자유롭게 쓰실 수 있고, 다시 파는 것은 안 됩니다.
|
|
36
|
+
Claudian 은 YishenTu 의 MIT 오픈소스 프로젝트이고, Obsidian 은 Dynalist Inc.의 제품입니다 — 이 패키지는 어느 쪽과도 제휴하지 않았습니다.
|
package/cli.mjs
ADDED
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* claudian 설치기 — **옵시디언 볼트에 클로드를 심는 무료 오픈소스 플러그인 Claudian 을 한국어로 안내한다.**
|
|
4
|
+
*
|
|
5
|
+
* npx --yes reborn-claudian 스킬 claudian-ko + claudian-ko-guide + 한국어 안내
|
|
6
|
+
* npx --yes reborn-claudian --check ★깔지 않고 Claude Code CLI 유무·로그인 상태·갈 길만 본다
|
|
7
|
+
* npx --yes reborn-claudian --dry-run 무엇이 어디로 갈지 보여주기만 한다
|
|
8
|
+
* npx --yes reborn-claudian --local 현재 폴더(.claude/skills)에 놓는다
|
|
9
|
+
* npx --yes reborn-claudian --force 이미 있어도 덮어쓴다
|
|
10
|
+
* npx --yes reborn-claudian --self-test 자기시험 (네트워크 안 씀)
|
|
11
|
+
*
|
|
12
|
+
* ★우리가 만든 것만 싣는다 — Claudian 플러그인 자체는 옵시디언 안에서 사람이 직접 설치한다.
|
|
13
|
+
* ★명령의 exit 0 을 믿지 않는다 — 스킬 폴더의 파일을 깔기 전·후로 세어 **새 파일이 생겼을 때만** 「붙었다」고 말하고,
|
|
14
|
+
* 마지막에 깐 claudian.mjs 를 실제로 import 해 판정이 도는지 본다.
|
|
15
|
+
* ★끝내는 법 — process.exit() 를 부르지 않는다. exitCode 만 세우고 자연 종료한다.
|
|
16
|
+
*/
|
|
17
|
+
import { cpSync, existsSync, mkdirSync, readdirSync, readFileSync, statSync } from "node:fs";
|
|
18
|
+
import { homedir } from "node:os";
|
|
19
|
+
import { dirname, join } from "node:path";
|
|
20
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
21
|
+
import { TAIL, 링크, 마지막 } from "./tail.mjs";
|
|
22
|
+
|
|
23
|
+
const HOME = homedir();
|
|
24
|
+
const CFG = process.env.CLAUDE_CONFIG_DIR || join(HOME, ".claude");
|
|
25
|
+
const 여기 = dirname(fileURLToPath(import.meta.url));
|
|
26
|
+
const 원본 = join(여기, "skill");
|
|
27
|
+
const 인자 = process.argv.slice(2);
|
|
28
|
+
const 확인만 = 인자.includes("--check");
|
|
29
|
+
const 미리보기 = 인자.includes("--dry-run");
|
|
30
|
+
const 여기에 = 인자.includes("--local");
|
|
31
|
+
const 덮기 = 인자.includes("--force");
|
|
32
|
+
const 자기시험모드 = 인자.includes("--self-test");
|
|
33
|
+
|
|
34
|
+
const c = { g: "\x1b[32m", r: "\x1b[31m", y: "\x1b[33m", d: "\x1b[90m", cy: "\x1b[36m", b: "\x1b[1m", 0: "\x1b[0m" };
|
|
35
|
+
const 굵게 = (t) => String(t).replace(/\*\*(.+?)\*\*/g, `${c[0]}${c.b}$1${c[0]}${c.d}`);
|
|
36
|
+
const 퍼널 = "claudian";
|
|
37
|
+
|
|
38
|
+
function 원장읽기() {
|
|
39
|
+
const p = join(원본, "claudian.json");
|
|
40
|
+
if (!existsSync(p)) return { 됨: false, 이유: "skill/claudian.json 이 없다 — 설치기가 무엇을 까는지 모르는 상태다" };
|
|
41
|
+
try { return { 됨: true, d: JSON.parse(readFileSync(p, "utf8")) }; }
|
|
42
|
+
catch (e) { return { 됨: false, 이유: `skill/claudian.json 을 못 읽는다 — ${e.message}` }; }
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const 금칙 = [/완전\s*무료/, /무제한/, /평생/, /100\s*%\s*보장/, /누구나\s*바로/, /무조건/,
|
|
46
|
+
/모바일에서도\s*된다/, /무료로\s*붙/, /반드시\s*성공/, /실패\s*없/, /전부\s*공짜/];
|
|
47
|
+
const 금칙면제 = /(하지\s*않는다|말하지\s*마라|쓰지\s*않는다|아니다|금칙|안\s*된다|하지\s*마라|말하지\s*않는다|잰\s*적이\s*없다|않는다|마라|아닙니다|없다|까지다|말이다|않습니다)/;
|
|
48
|
+
|
|
49
|
+
const 스킬방 = () => (여기에 ? join(process.cwd(), ".claude", "skills") : join(CFG, "skills"));
|
|
50
|
+
|
|
51
|
+
function 자리들() {
|
|
52
|
+
const 방 = 스킬방();
|
|
53
|
+
return [
|
|
54
|
+
{ 이름: "claudian-ko", 짐: join(원본, "claudian-ko"), 갈곳: join(방, "claudian-ko") },
|
|
55
|
+
{ 이름: "claudian-ko-guide", 짐: null, 갈곳: join(방, "claudian-ko-guide") },
|
|
56
|
+
];
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function 파일수(p) {
|
|
60
|
+
if (!existsSync(p)) return 0;
|
|
61
|
+
let n = 0;
|
|
62
|
+
const 걷기 = (d) => { for (const f of readdirSync(d)) { const q = join(d, f); if (statSync(q).isDirectory()) 걷기(q); else n++; } };
|
|
63
|
+
걷기(p);
|
|
64
|
+
return n;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
async function 자기시험() {
|
|
68
|
+
const 관문 = [];
|
|
69
|
+
const 본다 = (이름, 됨, 말) => 관문.push({ 이름, 됨, 말 });
|
|
70
|
+
|
|
71
|
+
const L = 원장읽기();
|
|
72
|
+
본다("원장이 읽힌다", L.됨, L.됨 ? "" : L.이유);
|
|
73
|
+
if (L.됨) {
|
|
74
|
+
const d = L.d;
|
|
75
|
+
본다("까는 것이 2종 적혀 있다", (d.까는것 || []).length === 2, `${(d.까는것 || []).length}종`);
|
|
76
|
+
본다("사실마다 출처가 있다", Object.values(d.사실 || {}).every((v) => v && v.출처 && v.확인), "출처·확인날짜 없는 칸이 있다");
|
|
77
|
+
본다("★말하지_않는_것 이 비어 있지 않다", Object.keys(d["★말하지_않는_것"] || {}).length >= 3, "");
|
|
78
|
+
}
|
|
79
|
+
for (const s of ["claudian-ko/SKILL.md", "claudian-ko/claudian.mjs", "SKILL.md", "claudian.json"]) {
|
|
80
|
+
본다(`짐에 ${s} 가 있다`, existsSync(join(원본, s)), "");
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
try {
|
|
84
|
+
const m = await import(pathToFileURL(join(원본, "claudian-ko", "claudian.mjs")).href);
|
|
85
|
+
const 길 = (있다, 로그인됨) => m.길정하기({ 클로드: { 있다, 버전: "2.1.0" }, 로그인: { 안다: 로그인됨 != null, 로그인됨 } }).길;
|
|
86
|
+
본다("클로드 없음 → 클로드없음", 길(false, null) === "클로드없음", "");
|
|
87
|
+
본다("클로드 있고 로그인 안 됨 → 로그인필요", 길(true, false) === "로그인필요", "");
|
|
88
|
+
본다("클로드 있고 로그인 됨 → 됨", 길(true, true) === "됨", "");
|
|
89
|
+
본다("로그인 모름 → 됨(모르면 낙관적으로 안내만)", 길(true, null) === "됨", "");
|
|
90
|
+
const 클로드없음길 = m.길정하기({ 클로드: { 있다: false, 버전: null }, 로그인: { 안다: false, 로그인됨: null } });
|
|
91
|
+
본다("클로드없음은 설치 명령을 말한다", /claude-code/.test(클로드없음길.할일.join(" ")), "");
|
|
92
|
+
const 점 = m.점검(() => { throw new Error("no claude"); });
|
|
93
|
+
본다("이 컴퓨터 점검이 안 죽는다(claude 없는 환경)", 점.길.길 === "클로드없음", JSON.stringify(점.길).slice(0, 60));
|
|
94
|
+
const skill = readFileSync(join(원본, "claudian-ko", "SKILL.md"), "utf8");
|
|
95
|
+
본다("SKILL.md 가 --점검 을 먼저 하라고 말한다", /--점검/.test(skill), "");
|
|
96
|
+
본다("SKILL.md 가 데스크톱 전용을 말한다", /데스크톱/.test(skill), "");
|
|
97
|
+
본다("SKILL.md 가 대행 설치를 안 한다고 말한다", /대신\s*설치하지\s*않는다/.test(skill), "");
|
|
98
|
+
} catch (e) { 본다("claudian.mjs 가 로드된다", false, String(e.message).slice(0, 70)); }
|
|
99
|
+
|
|
100
|
+
const 글들 = [];
|
|
101
|
+
const 훑기 = (d) => { for (const f of readdirSync(d)) { const q = join(d, f); if (statSync(q).isDirectory()) 훑기(q); else if (/\.(md|json)$/.test(f)) 글들.push([q, readFileSync(q, "utf8")]); } };
|
|
102
|
+
훑기(원본);
|
|
103
|
+
글들.push([join(여기, "README.md"), existsSync(join(여기, "README.md")) ? readFileSync(join(여기, "README.md"), "utf8") : ""]);
|
|
104
|
+
const 걸린것 = [];
|
|
105
|
+
for (const [p, 글] of 글들) for (const 줄 of 글.split(/\r?\n/)) {
|
|
106
|
+
if (금칙면제.test(줄)) continue;
|
|
107
|
+
for (const re of 금칙) if (re.test(줄)) 걸린것.push(`${p.split(/[\\/]/).pop()}: ${줄.trim().slice(0, 50)}`);
|
|
108
|
+
}
|
|
109
|
+
본다("조건 없이 단정하는 말이 없다", 걸린것.length === 0, 걸린것.slice(0, 3).join(" | "));
|
|
110
|
+
|
|
111
|
+
본다("끝 한 칸에 우리 퍼널이 있다", !!TAIL[퍼널], "");
|
|
112
|
+
본다("끝 한 칸 링크에 utm 이 붙는다", 링크(퍼널).includes("utm_campaign=" + 퍼널), 링크(퍼널));
|
|
113
|
+
본다("끝 한 칸이 스킬팩만 말한다", !JSON.stringify(TAIL[퍼널]).includes("클로드킷") && !JSON.stringify(TAIL[퍼널]).includes("풀스택"), "");
|
|
114
|
+
|
|
115
|
+
const 진 = 관문.filter((x) => !x.됨);
|
|
116
|
+
console.log(`\n${c.b}자기시험${c[0]} ${관문.length}건`);
|
|
117
|
+
for (const x of 관문) console.log(` ${x.됨 ? c.g + "✓" : c.r + "✗"}${c[0]} ${x.이름}${x.됨 || !x.말 ? "" : c.d + " — " + x.말 + c[0]}`);
|
|
118
|
+
console.log(진.length ? `\n${c.r}${진.length}건 실패${c[0]}` : `\n${c.g}전부 통과${c[0]}`);
|
|
119
|
+
process.exitCode = 진.length ? 1 : 0;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function 점검찍기(점) {
|
|
123
|
+
console.log(`${c.b}이 컴퓨터${c[0]}`);
|
|
124
|
+
console.log(` Claude Code CLI ${점.클로드.있다 ? c.g + "있다 · " + (점.클로드.버전 || "") : c.d + "없다"}${c[0]}`);
|
|
125
|
+
console.log(` 로그인 ${점.로그인.안다 ? (점.로그인.로그인됨 ? c.g + "됨" : c.y + "안 됨") : c.d + "모른다(claude 실행해서 직접 확인)"}${c[0]}`);
|
|
126
|
+
console.log(`\n${c.b}▶ ${점.길.제목}${c[0]}`);
|
|
127
|
+
점.길.할일.forEach((x, i) => console.log(` ${i + 1}. ${굵게(x)}${c[0]}`));
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
async function 본체() {
|
|
131
|
+
if (자기시험모드) return 자기시험();
|
|
132
|
+
|
|
133
|
+
const L = 원장읽기();
|
|
134
|
+
if (!L.됨) { console.error(`${c.r}${L.이유}${c[0]}`); process.exitCode = 1; return; }
|
|
135
|
+
const 원 = L.d;
|
|
136
|
+
const 방 = 스킬방();
|
|
137
|
+
|
|
138
|
+
console.log(`\n${c.b}${원.이름}${c[0]}`);
|
|
139
|
+
console.log(`${c.d}Claude Code CLI 유무·로그인을 재서 갈 길을 정하고, 옵시디언 「Claudian」 설치 순서를 한국어로 안내하는 스킬 하나 + 안내 하나${c[0]}\n`);
|
|
140
|
+
|
|
141
|
+
let 점 = null;
|
|
142
|
+
try { const m = await import(pathToFileURL(join(원본, "claudian-ko", "claudian.mjs")).href); 점 = m.점검(); } catch { /* 아래에서 잡힌다 */ }
|
|
143
|
+
if (점) 점검찍기(점);
|
|
144
|
+
|
|
145
|
+
console.log(`\n${c.b}깔 것${c[0]} ${c.d}${방}${c[0]}`);
|
|
146
|
+
for (const x of 원.까는것) console.log(` ${c.cy}${x.이름}${c[0]} ${c.d}${x.하는일}${c[0]}`);
|
|
147
|
+
|
|
148
|
+
if (확인만 || 미리보기) {
|
|
149
|
+
console.log(`\n${c.b}지금 상태${c[0]}`);
|
|
150
|
+
for (const s of 자리들()) console.log(` ${existsSync(s.갈곳) ? c.g + "있다" : c.d + "없다"}${c[0]} ${s.이름} ${c.d}${existsSync(s.갈곳) ? 파일수(s.갈곳) + "개 파일" : ""}${c[0]}`);
|
|
151
|
+
console.log(`\n${c.d}${확인만 ? "보기만 했습니다 — 아무것도 깔지 않았습니다." : "보여주기만 했습니다."} 깔려면 플래그 없이 다시 부르세요.${c[0]}`);
|
|
152
|
+
process.exitCode = 0; return;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
const 자리 = 자리들();
|
|
156
|
+
const 전 = 자리.map((s) => 파일수(s.갈곳));
|
|
157
|
+
mkdirSync(방, { recursive: true });
|
|
158
|
+
const 건너뛴것 = [];
|
|
159
|
+
for (const s of 자리) {
|
|
160
|
+
if (existsSync(s.갈곳) && !덮기) { 건너뛴것.push(s.이름); continue; }
|
|
161
|
+
mkdirSync(s.갈곳, { recursive: true });
|
|
162
|
+
if (s.짐) cpSync(s.짐, s.갈곳, { recursive: true });
|
|
163
|
+
else cpSync(join(원본, "SKILL.md"), join(s.갈곳, "SKILL.md"));
|
|
164
|
+
}
|
|
165
|
+
const 후 = 자리.map((s) => 파일수(s.갈곳));
|
|
166
|
+
|
|
167
|
+
console.log(`\n${c.b}놓은 결과${c[0]}`);
|
|
168
|
+
let 붙은것 = 0;
|
|
169
|
+
자리.forEach((s, i) => {
|
|
170
|
+
const 늘 = 후[i] - 전[i];
|
|
171
|
+
const 이미 = 건너뛴것.includes(s.이름);
|
|
172
|
+
if (이미) { console.log(` ${c.d}그대로${c[0]} ${s.이름} ${c.d}이미 있습니다 (--force 로 덮습니다)${c[0]}`); 붙은것 += 후[i] > 0 ? 1 : 0; }
|
|
173
|
+
else if (늘 > 0) { console.log(` ${c.g}붙었습니다${c[0]} ${s.이름} ${c.d}파일 ${늘}개${c[0]}`); 붙은것++; }
|
|
174
|
+
else console.log(` ${c.r}안 붙었습니다${c[0]} ${s.이름} ${c.d}파일이 늘지 않았습니다${c[0]}`);
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
if (!붙은것) {
|
|
178
|
+
console.log(`\n${c.r}아무것도 깔리지 않았습니다.${c[0]} ${c.d}${방} 에 쓸 수 있는 권한이 있는지 보세요.${c[0]}`);
|
|
179
|
+
process.exitCode = 1; return;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
let 돈다 = false, 이유 = "";
|
|
183
|
+
try {
|
|
184
|
+
const m = await import(pathToFileURL(join(방, "claudian-ko", "claudian.mjs")).href + "?t=" + Date.now());
|
|
185
|
+
돈다 = m.길정하기({ 클로드: { 있다: false, 버전: null }, 로그인: { 안다: false, 로그인됨: null } }).길 === "클로드없음";
|
|
186
|
+
if (!돈다) 이유 = "판정이 제대로 안 나온다 — 파일이 잘렸을 수 있습니다";
|
|
187
|
+
} catch (e) { 이유 = String(e.message).slice(0, 70); }
|
|
188
|
+
console.log(` ${돈다 ? c.g + "돌아갑니다" : c.y + "확인 못 했습니다"}${c[0]} ${c.d}${돈다 ? "깐 파일을 실제로 불러 판정을 돌려 봤습니다" : 이유}${c[0]}`);
|
|
189
|
+
|
|
190
|
+
console.log(`\n${c.b}이렇게 씁니다${c[0]} ${c.d}(클로드 코드에 그대로 말하세요)${c[0]}`);
|
|
191
|
+
console.log(` 옵시디언에 클로드 붙이는 법 알려줘`);
|
|
192
|
+
console.log(` Claudian 이 지금 이 컴퓨터에서 될 준비가 됐는지 점검해줘`);
|
|
193
|
+
console.log(`${c.d} ※ 새 스킬은 클로드 코드를 한 번 다시 켜야 잡힙니다.${c[0]}`);
|
|
194
|
+
|
|
195
|
+
const 이음 = TAIL[퍼널];
|
|
196
|
+
if (이음) {
|
|
197
|
+
console.log("");
|
|
198
|
+
for (const 줄 of 이음.이음) console.log(`${c.d}${줄}${c[0]}`);
|
|
199
|
+
console.log(`\n${c.b}${이음.제목}${c[0]} ${c.d}— ${이음.한줄}${c[0]}`);
|
|
200
|
+
console.log(`${c.cy}${링크(퍼널)}${c[0]}`);
|
|
201
|
+
console.log(`${c.d}${마지막}${c[0]}`);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
await 본체();
|
package/package.json
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "reborn-claudian",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "옵시디언 볼트에 클로드를 심는 무료 오픈소스 플러그인 Claudian(github.com/YishenTu/claudian · MIT)을 위해, 이 컴퓨터의 Claude Code CLI 유무·로그인 상태를 재서 갈 길을 정하고, 설치·연결 순서를 한국어 스킬로 놓습니다.",
|
|
5
|
+
"keywords": ["claude", "claude-code", "skills", "obsidian", "claudian", "vault", "ai-agent", "korean"],
|
|
6
|
+
"homepage": "https://rebornlabs.kr/claudian?utm_source=installer&utm_medium=cli&utm_campaign=claudian",
|
|
7
|
+
"bugs": { "url": "https://mobility.rebornlabs.kr/cs" },
|
|
8
|
+
"license": "SEE LICENSE IN README.md",
|
|
9
|
+
"author": "REBORN LABS",
|
|
10
|
+
"type": "module",
|
|
11
|
+
"bin": { "reborn-claudian": "cli.mjs" },
|
|
12
|
+
"files": ["cli.mjs", "tail.mjs", "skill/", "README.md"],
|
|
13
|
+
"engines": { "node": ">=18" },
|
|
14
|
+
"scripts": { "test": "node cli.mjs --self-test", "check": "node cli.mjs --check" },
|
|
15
|
+
"publishConfig": { "access": "public" }
|
|
16
|
+
}
|
package/skill/SKILL.md
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: claudian-ko-guide
|
|
3
|
+
description: >
|
|
4
|
+
Claudian(옵시디언에 클로드를 심는 무료 오픈소스 플러그인)과 claudian-ko 스킬을 한국어로 안내한다 —
|
|
5
|
+
Claudian 이 무엇이고 무엇이 필요한가, 왜 무료·오픈소스인가, 왜 모바일은 안 되는가,
|
|
6
|
+
큰 번들 경고가 왜 정상인가, 무엇을 하지 않나.
|
|
7
|
+
"클로디안이 뭐야", "옵시디언 플러그인 뭐 깔았어", "대형 플러그인 경고 떠", "옵시디언 모바일에서도 돼?",
|
|
8
|
+
"claudian 이 뭐야" 라고 물으면 쓴다.
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Claudian × 클로드 — 한국어 안내 (2026-09-24 확인)
|
|
12
|
+
|
|
13
|
+
## Claudian 이 무엇인가
|
|
14
|
+
`github.com/YishenTu/claudian` — Claude Code · Codex · Grok Build · OpenCode · Pi 를 옵시디언
|
|
15
|
+
볼트 안에 AI 협업자로 심는 **무료 오픈소스**(MIT) 옵시디언 플러그인. 2026-09-24 API 실측
|
|
16
|
+
스타 15,481 · 포크 1,041. 켜면 볼트가 통째로 에이전트의 **작업 디렉터리**가 된다 — 파일
|
|
17
|
+
읽기·쓰기·검색·다단계 작업이 그 자리에서 된다.
|
|
18
|
+
|
|
19
|
+
## 무엇이 필요한가 — 이게 제일 중요하다
|
|
20
|
+
| | |
|
|
21
|
+
|---|---|
|
|
22
|
+
| 에이전트 CLI | Claude Code · Codex · Grok Build · OpenCode · Pi 중 최소 하나 |
|
|
23
|
+
| 인증 | 그 CLI 자신의 구독/API. **Claude Code CLI 는 기존 구독 로그인 그대로** 된다 |
|
|
24
|
+
| Obsidian | v1.13.0 이상 |
|
|
25
|
+
| 기기 | **데스크톱 전용**(macOS·Linux·Windows) — **모바일 앱에서는 안 된다** |
|
|
26
|
+
|
|
27
|
+
★「무료 오픈소스」는 반만 보는 말이다. 소스는 MIT 로 완전히 열려 있지만, **실행하려면 위 CLI 중
|
|
28
|
+
하나가 있어야** 한다. Claude Code CLI 를 고르면 지금 쓰는 구독이 그대로 값이 되어 추가 결제가
|
|
29
|
+
없다는 뜻이고, OpenCode 처럼 모델을 직접 고르는 백엔드는 OpenRouter·Kimi·GLM·DeepSeek 같은
|
|
30
|
+
별도 공급자가 필요하다.
|
|
31
|
+
|
|
32
|
+
## 「대형 플러그인」 경고가 뜨는 이유
|
|
33
|
+
Claudian 이 최신 Claude Agent SDK 를 번들에 넣느라 크기가 5MB 를 넘는다 — 저장소 README 가
|
|
34
|
+
직접 명시한 **정상 상태**다. 악성이거나 잘못 설치된 게 아니다.
|
|
35
|
+
|
|
36
|
+
## claudian-ko 스킬이 하는 일
|
|
37
|
+
1. `node ~/.claude/skills/claudian-ko/claudian.mjs --점검` — Claude Code CLI 유무·로그인 상태를 재서 갈 길을 정한다
|
|
38
|
+
2. Obsidian Community plugins 에서 「Claudian」을 설치하는 순서를 보여준다
|
|
39
|
+
3. 볼트를 작업 디렉터리로 여는 법 · Provider 를 Claude Code 로 고르는 법을 안내한다
|
|
40
|
+
|
|
41
|
+
## Kimi 스폰서
|
|
42
|
+
README 「## Sponsorship」 절에 Kimi(Moonshot AI)가 「Open Source Friend」로 올라 있다. 신규
|
|
43
|
+
가입 API 크레딧 보너스는 README 원문 기준 2026-09-30 종료 예정이라고 적혀 있다 — 안내 시점에
|
|
44
|
+
다시 확인해야 한다(README 가 바뀔 수 있다).
|
|
45
|
+
|
|
46
|
+
## 하지 않는 것
|
|
47
|
+
- Obsidian·Claudian 플러그인을 대신 설치하지 않는다
|
|
48
|
+
- 모바일에서 된다고 말하지 않는다
|
|
49
|
+
- 「전부 공짜」라고 말하지 않는다 — CLI 를 무엇으로 고르느냐에 따라 갈린다
|
|
50
|
+
- Claudian 이 이 패키지에 동봉돼 있다고 말하지 않는다 — 옵시디언 안에서 직접 설치해야 한다
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: claudian-ko
|
|
3
|
+
description: >
|
|
4
|
+
옵시디언 볼트에 클로드를 심는 무료 오픈소스 플러그인 「Claudian」을 한국어로 점검·안내한다.
|
|
5
|
+
이 컴퓨터에 Claude Code CLI 가 있고 로그인돼 있는지 재고, 옵시디언 커뮤니티 플러그인에서
|
|
6
|
+
「Claudian」을 설치하는 순서와 볼트를 작업 디렉터리로 여는 법을 안내한다.
|
|
7
|
+
"클로디안 뭐야", "옵시디언에 클로드 붙이고 싶어", "볼트를 작업폴더로", "Claudian 설치",
|
|
8
|
+
"옵시디언 플러그인으로 클로드 코드" 라고 물으면 쓴다.
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Claudian — 옵시디언 볼트에 클로드 (2026-09-24 확인)
|
|
12
|
+
|
|
13
|
+
## 무엇인가
|
|
14
|
+
`github.com/YishenTu/claudian` — Claude Code · Codex · Grok Build · OpenCode · Pi 같은 로컬
|
|
15
|
+
에이전트를 옵시디언 볼트 안에 AI 협업자로 심는 **무료 오픈소스**(MIT) 플러그인이다.
|
|
16
|
+
켜면 볼트 전체가 에이전트의 **작업 디렉터리**가 된다 — 파일 읽기·쓰기·검색·여러 단계 작업이
|
|
17
|
+
전부 그 자리에서 된다.
|
|
18
|
+
|
|
19
|
+
## 무엇이 필요한가
|
|
20
|
+
| | |
|
|
21
|
+
|---|---|
|
|
22
|
+
| 에이전트 CLI | Claude Code · Codex · Grok Build · OpenCode · Pi 중 **최소 하나**(이 스킬은 Claude Code 기준) |
|
|
23
|
+
| 그 CLI 의 인증 | Claude Code CLI 는 **이미 쓰는 구독 로그인**으로 그대로 된다 — 별도 API 키 필요 없음 |
|
|
24
|
+
| Obsidian | v1.13.0 이상 |
|
|
25
|
+
| 기기 | **데스크톱 전용**(macOS·Linux·Windows) — 모바일 앱에서는 안 된다 |
|
|
26
|
+
|
|
27
|
+
## 설치 순서
|
|
28
|
+
1. `node ~/.claude/skills/claudian-ko/claudian.mjs --점검` — Claude Code CLI 유무·로그인 상태를 잰다
|
|
29
|
+
2. Obsidian 설정 → **Community plugins** → 「Claudian」 검색 → 설치 → 활성화
|
|
30
|
+
3. ★번들이 5MB 를 넘어 「대형 플러그인」 경고가 뜰 수 있다 — README 가 명시한 **정상 상태**다
|
|
31
|
+
4. 리본 아이콘이나 명령 팔레트로 사이드바를 열고 Provider 를 **Claude Code** 로 고른다
|
|
32
|
+
5. 이제부터 이 볼트가 통째로 작업 디렉터리 — 노트를 읽고 쓰고 검색한다
|
|
33
|
+
|
|
34
|
+
## 왜 무료인가
|
|
35
|
+
소스 코드는 MIT 라이선스로 완전히 열려 있다. 다만 **실행하려면 위 CLI 중 하나와 그 CLI 의
|
|
36
|
+
구독/API 가 있어야** 한다 — Claude Code CLI 를 고르면 지금 쓰는 구독이 곧 그 값이라 추가 결제가
|
|
37
|
+
없고, OpenCode 처럼 모델을 직접 고르는 백엔드를 쓰면 OpenRouter·Kimi·GLM·DeepSeek 같은 별도
|
|
38
|
+
공급자가 필요하다.
|
|
39
|
+
|
|
40
|
+
## 스폰서
|
|
41
|
+
Kimi(Moonshot AI)가 README 에 「Open Source Friend」로 올라 있고, 신규 가입 API 크레딧
|
|
42
|
+
보너스를 안내한다(README 원문 기준 2026-09-30 종료 예정 — 안내 시점에 다시 확인할 것).
|
|
43
|
+
|
|
44
|
+
## 하지 않는 것
|
|
45
|
+
- Obsidian 이나 Claudian 플러그인을 대신 설치하지 않는다 — 순서를 보여줄 뿐이다
|
|
46
|
+
- 모바일에서 된다고 말하지 않는다
|
|
47
|
+
- 「전부 공짜」라고 말하지 않는다 — CLI 를 무엇으로 고르느냐에 따라 갈린다
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* claudian-ko 점검기 — **이 컴퓨터에 Claude Code CLI 가 있고 로그인돼 있는지 재고, 갈 길을 정한다.**
|
|
3
|
+
*
|
|
4
|
+
* node claudian.mjs --점검 Claude Code CLI 유무 · 버전 · 로그인 상태 · 다음 할 일
|
|
5
|
+
* node claudian.mjs --json 같은 것을 JSON 으로
|
|
6
|
+
*
|
|
7
|
+
* ★재지 못한 것은 「모른다」로 둔다 — 옵시디언 설치 여부는 표준 CLI가 없어 재지 않는다(짐작 금지).
|
|
8
|
+
* ★아무것도 설치하지 않는다 — Claudian 플러그인은 옵시디언 안에서 사람이 직접 켠다.
|
|
9
|
+
* ★끝내는 법 — process.exit() 를 부르지 않는다.
|
|
10
|
+
*
|
|
11
|
+
* 사실(2026-09-24 확인 · 출처는 claudian.json):
|
|
12
|
+
* - Claudian(github.com/YishenTu/claudian · MIT)은 Claude Code/Codex 등 로컬 에이전트를 옵시디언 볼트에 심는다
|
|
13
|
+
* - 필요한 것: 저 중 하나(우리는 Claude Code CLI 기준으로 안내) + Obsidian v1.13.0+ + 데스크톱
|
|
14
|
+
* - Claude Code CLI 는 이미 있는 구독 로그인으로 그대로 된다 — 별도 API 키가 필요 없다
|
|
15
|
+
*/
|
|
16
|
+
import { execFileSync } from "node:child_process";
|
|
17
|
+
|
|
18
|
+
/** claude --version 실행 결과 → { 있다, 버전 } */
|
|
19
|
+
export function 클로드시디재기(실행 = execFileSync) {
|
|
20
|
+
try {
|
|
21
|
+
const out = String(실행("claude", ["--version"], { stdio: ["ignore", "pipe", "ignore"] }));
|
|
22
|
+
const m = out.match(/(\d+\.\d+\.\d+)/);
|
|
23
|
+
return { 있다: true, 버전: m ? m[1] : out.trim().slice(0, 40) };
|
|
24
|
+
} catch (e) {
|
|
25
|
+
return { 있다: false, 버전: null };
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* 로그인 상태 재기 — `claude` 가 있어도 로그인 안 됐을 수 있다.
|
|
31
|
+
* `claude --print --model haiku "ok"` 같은 실호출은 과금·부작용이 있어 쓰지 않는다.
|
|
32
|
+
* 대신 `claude auth status`(있으면) 를 시도하고, 명령이 없으면 「모른다」로 둔다.
|
|
33
|
+
*/
|
|
34
|
+
export function 로그인재기(실행 = execFileSync) {
|
|
35
|
+
try {
|
|
36
|
+
const out = String(실행("claude", ["auth", "status"], { stdio: ["ignore", "pipe", "ignore"] }));
|
|
37
|
+
const 로그인됨 = /logged in|authenticated|로그인/i.test(out) && !/not logged in|로그인.*안/i.test(out);
|
|
38
|
+
return { 안다: true, 로그인됨 };
|
|
39
|
+
} catch (e) {
|
|
40
|
+
return { 안다: false, 로그인됨: null };
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** 판정 — 순수 함수. 잰 값만 받아 갈 길 하나를 돌려준다. */
|
|
45
|
+
export function 길정하기(점) {
|
|
46
|
+
if (!점.클로드.있다) return {
|
|
47
|
+
길: "클로드없음",
|
|
48
|
+
제목: "Claude Code CLI 가 이 컴퓨터에 없습니다",
|
|
49
|
+
할일: [
|
|
50
|
+
"npm i -g @anthropic-ai/claude-code 로 먼저 깝니다(또는 claude.com/code 안내를 따릅니다)",
|
|
51
|
+
"설치 뒤 claude 를 한 번 실행해 기존 구독으로 로그인합니다 — 별도 API 키는 필요 없습니다",
|
|
52
|
+
"그 다음 Obsidian → Community plugins → 「Claudian」을 설치합니다",
|
|
53
|
+
],
|
|
54
|
+
};
|
|
55
|
+
if (점.로그인.안다 && 점.로그인.로그인됨 === false) return {
|
|
56
|
+
길: "로그인필요",
|
|
57
|
+
제목: `Claude Code CLI ${점.클로드.버전 || ""} 는 있는데 로그인이 안 돼 있습니다`,
|
|
58
|
+
할일: ["터미널에서 claude 를 한 번 실행해 로그인합니다(기존 Pro/Max 구독 그대로 됩니다)",
|
|
59
|
+
"로그인 뒤 Obsidian → Community plugins → 「Claudian」을 설치·활성화합니다",
|
|
60
|
+
"Claudian 설정에서 Provider 를 Claude Code 로 고릅니다 — 별도 키 입력 칸이 없어야 정상입니다"],
|
|
61
|
+
};
|
|
62
|
+
return {
|
|
63
|
+
길: "됨",
|
|
64
|
+
제목: `Claude Code CLI ${점.클로드.버전 || ""} — 준비됐습니다`,
|
|
65
|
+
할일: ["Obsidian → 설정 → Community plugins → 「Claudian」 검색 → 설치 → 활성화",
|
|
66
|
+
"번들이 5MB 를 넘어 「대형 플러그인」 경고가 뜰 수 있습니다 — 정상입니다(README 명시)",
|
|
67
|
+
"리본 아이콘이나 명령 팔레트로 Claudian 사이드바를 열고, Provider 를 Claude Code 로 고릅니다",
|
|
68
|
+
"이제 이 볼트가 통째로 작업 디렉터리입니다 — 노트를 읽고 쓰고 검색합니다"],
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export function 점검(실행 = execFileSync) {
|
|
73
|
+
const 클로드 = 클로드시디재기(실행);
|
|
74
|
+
const 로그인 = 클로드.있다 ? 로그인재기(실행) : { 안다: false, 로그인됨: null };
|
|
75
|
+
const 길 = 길정하기({ 클로드, 로그인 });
|
|
76
|
+
return { 클로드, 로그인, 길 };
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const 인자 = process.argv.slice(2);
|
|
80
|
+
if (인자.includes("--점검") || 인자.includes("--json")) {
|
|
81
|
+
const r = 점검();
|
|
82
|
+
if (인자.includes("--json")) {
|
|
83
|
+
console.log(JSON.stringify(r, null, 2));
|
|
84
|
+
} else {
|
|
85
|
+
console.log(`Claude Code CLI: ${r.클로드.있다 ? "있음 · " + r.클로드.버전 : "없음"}`);
|
|
86
|
+
console.log(`로그인: ${r.로그인.안다 ? (r.로그인.로그인됨 ? "됨" : "안 됨") : "모름(claude auth status 없음 — claude 실행해서 직접 확인하세요)"}`);
|
|
87
|
+
console.log(`\n${r.길.제목}`);
|
|
88
|
+
r.길.할일.forEach((s, i) => console.log(` ${i + 1}. ${s}`));
|
|
89
|
+
}
|
|
90
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"퍼널": "claudian",
|
|
3
|
+
"이름": "옵시디언 볼트에 클로드를 — claudian-ko 스킬",
|
|
4
|
+
"잰날": "2026-09-24",
|
|
5
|
+
"까는것": [
|
|
6
|
+
{ "이름": "claudian-ko", "자리": "~/.claude/skills/claudian-ko/", "하는일": "이 컴퓨터에 Claude Code CLI 가 있고 로그인돼 있는지 재고, 옵시디언 커뮤니티 플러그인 「Claudian」 설치 순서와 볼트를 작업 디렉터리로 여는 법을 한국어로 안내한다", "필요": [] },
|
|
7
|
+
{ "이름": "claudian-ko-guide", "자리": "~/.claude/skills/claudian-ko-guide/", "하는일": "한국어 안내 — Claudian 이 무엇이고 무엇이 필요한가 · 무료·오픈소스인 이유 · 데스크톱 전용이라 모바일은 안 되는 이유 · 큰 번들 경고가 정상인 이유 · 하지 않는 것", "필요": [] }
|
|
8
|
+
],
|
|
9
|
+
"사실": {
|
|
10
|
+
"저장소": {
|
|
11
|
+
"값": "github.com/YishenTu/claudian — 「An Obsidian plugin that embeds Claude Code/Codex and other local Agents as AI collaborators in your vault」. MIT 라이선스. 2026-09-24 API 실측 stargazers_count=15,481 · forks_count=1,041",
|
|
12
|
+
"출처": "https://api.github.com/repos/YishenTu/claudian",
|
|
13
|
+
"확인": "2026-09-24"
|
|
14
|
+
},
|
|
15
|
+
"요구사항": {
|
|
16
|
+
"값": "Claude Code CLI · Codex CLI · Grok Build · OpenCode · Pi 중 최소 하나 + 그 도구 자신의 구독/API(Claude Code CLI 는 기존 구독 로그인으로 됨) · Obsidian v1.13.0 이상 · 데스크톱 전용(macOS·Linux·Windows, 모바일 불가)",
|
|
17
|
+
"출처": "README.md 「Requirements」 절 원문",
|
|
18
|
+
"확인": "2026-09-24"
|
|
19
|
+
},
|
|
20
|
+
"설치": {
|
|
21
|
+
"값": "Obsidian 설정 → Community plugins → 「Claudian」 검색 → 설치. 최신 Claude Agent SDK 를 쓰느라 번들이 5MB 를 넘어 Obsidian 이 「대형 플러그인」 경고를 띄울 수 있다 — README 가 명시한 정상 상태",
|
|
22
|
+
"출처": "README.md",
|
|
23
|
+
"확인": "2026-09-24"
|
|
24
|
+
},
|
|
25
|
+
"커뮤니티스토어": {
|
|
26
|
+
"값": "community.obsidian.md/plugins/realclaudian — 작성자 Yishen Tu · 2.2M downloads · 카테고리 AI · Developers · Files",
|
|
27
|
+
"출처": "community.obsidian.md/plugins/realclaudian (WebFetch 실측)",
|
|
28
|
+
"확인": "2026-09-24"
|
|
29
|
+
},
|
|
30
|
+
"Kimi스폰서": {
|
|
31
|
+
"값": "README 「## Sponsorship / ### Kimi (Moonshot AI)」 — 「Open Source Friend」로 명시. 신규 가입 API 크레딧 보너스는 2026-09-30 종료 예정이라고 README 가 못박음(우리가 안내 시점에 다시 확인 필요)",
|
|
32
|
+
"출처": "https://raw.githubusercontent.com/YishenTu/claudian/main/README.md",
|
|
33
|
+
"확인": "2026-09-24"
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
"★말하지_않는_것": {
|
|
37
|
+
"모바일": "Obsidian 모바일 앱에서 된다고 말하지 않는다 — README 가 데스크톱 전용이라고 명시한다.",
|
|
38
|
+
"무료API": "Claude Code CLI 자체는 기존 구독으로 되지만, OpenCode 등 다른 백엔드를 고르면 OpenRouter·Kimi·GLM·DeepSeek 같은 별도 API 키/구독이 필요하다고 그대로 말한다 — 「전부 공짜」라고 말하지 않는다.",
|
|
39
|
+
"동봉": "이 설치기는 Claudian 플러그인 자체를 담지 않는다 — Obsidian 안에서 직접 설치해야 한다. 우리는 판단·안내 스킬만 놓는다.",
|
|
40
|
+
"설치대행": "옵시디언 플러그인 설치를 이 스킬이 대신 눌러주지 않는다 — 순서를 보여줄 뿐이다."
|
|
41
|
+
},
|
|
42
|
+
"고치는곳": "claudekit/claudiankit/"
|
|
43
|
+
}
|
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
|
+
const 랜딩경로 = "/skillpack";
|
|
11
|
+
export const 링크 = (퍼널) => `https://rebornlabs.kr${랜딩경로}?utm_source=installer&utm_medium=cli&utm_campaign=${퍼널}`;
|
|
12
|
+
|
|
13
|
+
export const TAIL = {
|
|
14
|
+
claudian: {
|
|
15
|
+
이음: [
|
|
16
|
+
"방금 한 일은 **이 컴퓨터에 Claude Code CLI 가 있고 로그인돼 있는지 재고, 옵시디언 「Claudian」 플러그인을 설치·연결하는 순서를 한국어 스킬로 스킬 폴더에 놓고, 파일이 실제로 늘었는지 다시 센 것**입니다.",
|
|
17
|
+
"Claudian 자체(옵시디언 플러그인 본체)는 옵시디언 안에서 직접 설치해야 합니다 — 이 설치기는 그 순서를 안내하는 스킬만 놓습니다.",
|
|
18
|
+
],
|
|
19
|
+
제목: "리본랩스 스킬팩",
|
|
20
|
+
한줄: "같은 방식으로 골라 담은 48종을 한 줄로. 8,900원",
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export const 마지막 = "목록과 직접 까는 명령까지 그 페이지에 그대로 적어 두었습니다. 안 사셔도 됩니다.";
|