z2o-cli 0.4.1 → 0.7.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 CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  ```bash
6
6
  npm i -g z2o-cli
7
- z2o init z2o_live_... # 설정「팀 · 연결」에서 발급한 열쇠
7
+ z2o init z2o_live_... # z2o.kr 프로필 「연결 토큰」에서 발급한 열쇠
8
8
  ```
9
9
 
10
10
  `init` 이 세 가지를 한 번에 한다 — **로그인 · 워크스페이스 지정 · AI 규칙 파일에 사용법 심기.**
@@ -30,6 +30,19 @@ z2o find 계약 # 원본에서 찾기
30
30
  Claude Code·Cursor·Codex 등 **셸을 쓸 수 있는 AI라면 무엇에서든** 된다.
31
31
  MCP 와 달리 앱마다 연동 설정이 필요 없고, 토큰이 만료되지 않아 한 번 연결해 두면 계속 이어진다.
32
32
 
33
+ ## Claude Code 스킬 — `/z2o:read` · `/z2o:ingest`
34
+
35
+ `init` 은 Claude Code 가 깔려 있으면 **스킬 둘**도 `~/.claude/skills/z2o/` 에 넣는다.
36
+
37
+ | | 언제 |
38
+ |---|---|
39
+ | `/z2o:read` | 회사 맥락을 찾아 답할 때 — 슬랙·회의록·위키 |
40
+ | `/z2o:ingest` | 자료를 위키에 넣고 정리할 때 — 넣기 → 뼈대 → 관련 문서 고쳐 쓰기 |
41
+
42
+ 직접 불러도 되고, **그냥 "이거 위키에 정리해"라고 말해도** Claude 가 알아서 꺼내 쓴다.
43
+ 평소에는 설명 한 줄(약 90토큰)만 들고 있다가 쓸 때 본문을 읽는다.
44
+ 새 판으로 올린 뒤에는 `z2o skills` 로 스킬만 바꿔 끼운다.
45
+
33
46
  ## 명령
34
47
 
35
48
  | | |
@@ -47,7 +60,12 @@ MCP 와 달리 앱마다 연동 설정이 필요 없고, 토큰이 만료되지
47
60
  | `z2o recent [개수]` | **정리 전 원본** — 슬랙·메일이 들어온 그대로 |
48
61
  | `z2o find <낱말>` | 원본에서 찾기 |
49
62
  | `z2o raw <id...>` | 원본 본문 |
63
+ | `z2o rules` | 이 워크스페이스의 위키 규칙 — 쓰기 전에 먼저 |
64
+ | `z2o skills` | Claude Code 스킬 설치·갱신 |
50
65
  | `z2o push <제목> <파일\|-\>` | 자료 넣기 — **쓰기 토큰 필요** |
66
+ | `z2o build` | 원문·장부·표 만들기 (코드만, 0원) |
67
+ | `z2o pending` | 요약이 필요한 원본 |
68
+ | `z2o write <경로> <파일\|-\>` | 요약을 위키에 남기기 — **쓰기 토큰 필요** |
51
69
  | `z2o organize` | 정리 돌리기 — **쓰기 토큰 필요** |
52
70
 
53
71
  `-c <id>` 로 워크스페이스를 그때만 바꿀 수 있다.
package/index.js CHANGED
@@ -14,9 +14,10 @@
14
14
  * 이쪽 설치가 무거우면 만든 이유가 없어진다.
15
15
  */
16
16
 
17
- import { readFileSync, writeFileSync, mkdirSync, chmodSync, existsSync } from 'node:fs';
17
+ import { readFileSync, writeFileSync, mkdirSync, chmodSync, existsSync, cpSync, rmSync } from 'node:fs';
18
18
  import { homedir } from 'node:os';
19
- import { join } from 'node:path';
19
+ import { join, dirname } from 'node:path';
20
+ import { fileURLToPath } from 'node:url';
20
21
 
21
22
  const DEFAULT_API = 'https://z2o.kr/_/backend';
22
23
  // 발급되는 토큰의 모양. `z2o_live_` + base64url.
@@ -147,6 +148,36 @@ function needCompany(flags) {
147
148
 
148
149
  // 🌍 **도구마다 「모든 폴더에 적용되는」 규칙 파일 자리가 따로 있다.**
149
150
  // 여기 한 번 심으면 폴더마다 `init` 을 돌릴 필요가 없다.
151
+ // 🧩 **Claude Code 에는 스킬로도 심는다** — `/z2o:read` · `/z2o:ingest`.
152
+ // 규칙 파일 블록은 **모든 대화에 항상** 실리지만, 스킬은 한 줄 설명(~90토큰)만 늘 들고
153
+ // 본문은 **부를 때만** 읽힌다. 그래서 절차를 길고 정확하게 적을 수 있다.
154
+ // `~/.claude/skills/<이름>/` 에 두면 마켓플레이스 없이 다음 세션부터 `z2o@skills-dir` 로 뜬다.
155
+ // ⚠️ 규격은 서버(`z2o rules`), **순서는 스킬** — 회사마다 다른 것을 패키지에 박지 않는다.
156
+ const PLUGIN_SRC = join(dirname(fileURLToPath(import.meta.url)), 'plugin');
157
+
158
+ function installPlugin() {
159
+ const home = join(homedir(), '.claude');
160
+ if (!existsSync(home) || !existsSync(PLUGIN_SRC)) return null;
161
+ const dest = join(home, 'skills', 'z2o');
162
+ const mine = join(dest, '.claude-plugin', 'plugin.json');
163
+ if (existsSync(dest)) {
164
+ // 같은 이름의 **남의 것**은 덮지 않는다.
165
+ let ours = false;
166
+ try { ours = JSON.parse(readFileSync(mine, 'utf8')).name === 'z2o'; } catch { /* 없음 */ }
167
+ if (!ours) return { dest, state: '건너뜀 — 같은 이름의 다른 폴더가 있어요' };
168
+ rmSync(dest, { recursive: true, force: true }); // 옛 판의 지운 스킬이 남지 않게
169
+ }
170
+ mkdirSync(join(home, 'skills'), { recursive: true });
171
+ cpSync(PLUGIN_SRC, dest, { recursive: true });
172
+ return { dest, state: '설치' };
173
+ }
174
+
175
+ function reportPlugin(r = installPlugin()) {
176
+ if (!r) return;
177
+ console.log(`~/.claude/skills/z2o — ${r.state}`);
178
+ if (r.state === '설치') console.log(' Claude Code 스킬 /z2o:read · /z2o:ingest (다음 세션부터, 지금은 /reload-plugins)');
179
+ }
180
+
150
181
  const GLOBAL_RULES = [
151
182
  ['.claude', 'CLAUDE.md'],
152
183
  ['.codex', 'AGENTS.md'],
@@ -164,27 +195,20 @@ const BLOCK = `${MARK_START}
164
195
 
165
196
  슬랙·회의록·위키를 \`z2o\` 명령으로 꺼낸다. **사람에게 복사해 달라고 하지 않는다.**
166
197
 
167
- | 정리 전 원본 | |
168
- |---|---|
169
- | \`z2o recent\` | 최근 들어온 것 (슬랙·메일) |
170
- | \`z2o find <낱말>\` | 원본에서 찾기 |
171
- | \`z2o raw <id>\` | 원본 본문 |
172
-
173
- | 정리된 위키 | |
174
- |---|---|
175
- | \`z2o search <낱말>\` | 본문 검색 |
176
- | \`z2o read <경로>\` | 문서 본문 |
177
- | \`z2o list [접두어]\` | 문서 목록 |
198
+ | 정리 전 원본 | | 정리된 위키 | |
199
+ |---|---|---|---|
200
+ | \`z2o recent\` | 최근 들어온 것 | \`z2o search <낱말>\` | 본문 검색 |
201
+ | \`z2o find <낱말>\` | 원본에서 찾기 | \`z2o read <경로>\` | 문서 본문 |
202
+ | \`z2o raw <id>\` | 원본 본문 | \`z2o list [접두어]\` | 문서 목록 |
178
203
 
179
204
  **정리를 부탁받으면 내가 한다** — Z2O 의 AI 에게 맡기지 않는다.
180
205
 
181
- | | |
182
- |---|---|
183
- | \`z2o push <제목> <파일>\` | 원본 넣기. 장부·표는 코드가 알아서 만든다 |
184
- | \`z2o pending\` | 요약이 필요한 원본 |
185
- | \`z2o write <경로> <파일>\` | 관련 문서를 읽고 고쳐 쓴 요약을 남긴다 |
206
+ 🔑 **위키에 무엇을 쓰기 전에 \`z2o rules\` 를 먼저 읽고 그대로 따른다.**
207
+ 축 구성·문서 형식·건드리지 않을 곳·정리 순서가 거기 있다. **회사마다 다르고
208
+ 사용자가 고쳐 두었을 있으므로, 블록의 기억에 의존하지 않는다.**
186
209
 
187
- 자세한 것은 \`z2o --help\`.
210
+ Claude Code 에서는 스킬 \`/z2o:read\` · \`/z2o:ingest\` 가 순서를 담고 있다.
211
+ 자세한 명령은 \`z2o --help\`.
188
212
  ${MARK_END}`;
189
213
 
190
214
  /** 규칙 파일에 블록을 심는다. **두 번 해도 하나만 남는다.** */
@@ -250,7 +274,10 @@ const HELP = `z2o — 회사 온톨로지를 내가 쓰는 AI에서 꺼내 쓴
250
274
  z2o raw <id...> 원본 본문 (id 는 recent·find 가 준 것)
251
275
 
252
276
  ── 정리를 내 AI 가 한다 ── (쓰기 토큰 필요)
253
- z2o push <제목> <파일|-> 원본 넣기장부·표는 코드가 알아서 만든다
277
+ z2o rules 이 워크스페이스의 위키 규칙**쓰기 전에 먼저**
278
+ z2o skills Claude Code 스킬 설치·갱신 (/z2o:read · /z2o:ingest)
279
+ z2o push <제목> <파일|-> 원본 넣기
280
+ z2o build 원문·장부·표 만들기 (코드만, 0원)
254
281
  z2o pending 요약이 필요한 원본
255
282
  z2o write <경로> <파일|-> 요약을 위키에 남기기 (예: topics/물류.md)
256
283
  z2o organize Z2O 의 AI 에게 정리를 맡긴다 (직접 안 쓸 때)
@@ -334,6 +361,7 @@ const COMMANDS = {
334
361
  console.log(`~/${d}/${f} — ${r.state}`);
335
362
  }
336
363
  console.log(' (모든 폴더에서 통합니다)');
364
+ reportPlugin();
337
365
  console.log('\n이제 AI 에게 그냥 물어보세요:');
338
366
  console.log(' "최근 슬랙에서 나온 얘기 정리해줘"');
339
367
  if (needPick) {
@@ -357,6 +385,7 @@ const COMMANDS = {
357
385
  console.log(
358
386
  ' (다른 도구를 쓰면 그 도구의 규칙 파일을 만들어 두고 `z2o init` 을 다시 돌리세요)',
359
387
  );
388
+ reportPlugin();
360
389
 
361
390
  // ⚠️ **다 된 것처럼 끝내지 않는다.** 워크스페이스를 못 정했으면 아직 아무것도 안 된다 —
362
391
  // 여기서 "이제 물어보세요" 라고 하면 사람은 됐다고 믿고 넘어간다.
@@ -371,6 +400,13 @@ const COMMANDS = {
371
400
  void flags;
372
401
  },
373
402
 
403
+ // 스킬만 깔거나 새 판으로 바꾼다 — 토큰이 없어도 된다. `npm i -g z2o-cli` 로 올린 뒤에 한 번.
404
+ async skills() {
405
+ const r = installPlugin();
406
+ if (!r) die('Claude Code 가 안 보여요(~/.claude 없음). Claude Code 를 한 번 실행한 뒤 다시 해 주세요.');
407
+ reportPlugin(r);
408
+ },
409
+
374
410
  async logout() {
375
411
  const conf = loadConf();
376
412
  delete conf.token;
@@ -504,6 +540,24 @@ const COMMANDS = {
504
540
  );
505
541
  },
506
542
 
543
+ /** 이 워크스페이스의 규칙. **위키에 무엇을 쓰기 전에 먼저 본다.**
544
+ *
545
+ * 🔑 규칙을 규칙 파일에 통째로 적지 않는 이유 — 사용자가 지워도 아무도 모르고,
546
+ * 무엇보다 **회사마다 다를 수 없다.** 정본은 서버의 위키 문서 한 장이다.
547
+ */
548
+ async rules(_args, flags) {
549
+ console.log(await callTool('get_rules', { company_id: needCompany(flags) }));
550
+ },
551
+
552
+ /** 코드가 만드는 것만 — 원문·장부·거래처·표. **LLM 을 안 쓴다.**
553
+ *
554
+ * 🔑 `push` 뒤에 이걸 불러야 `docs/` 원문 문서가 생긴다. 안 부르면 요약에 건
555
+ * 링크가 깨진 채로 남는다.
556
+ */
557
+ async build(_args, flags) {
558
+ console.log(await callTool('build_skeleton', { company_id: needCompany(flags) }));
559
+ },
560
+
507
561
  async organize(_args, flags) {
508
562
  console.log(await callTool('organize', { company_id: needCompany(flags) }));
509
563
  },
@@ -511,6 +565,12 @@ const COMMANDS = {
511
565
 
512
566
  // ── 진입점 ──────────────────────────────────────────────
513
567
 
568
+ if (['--version', '-v', 'version'].includes(process.argv[2])) {
569
+ const pkg = JSON.parse(readFileSync(join(dirname(fileURLToPath(import.meta.url)), 'package.json'), 'utf8'));
570
+ console.log(pkg.version);
571
+ process.exit(0);
572
+ }
573
+
514
574
  const { flags, rest } = parseArgs(process.argv.slice(2));
515
575
  const [cmd, ...args] = rest;
516
576
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "z2o-cli",
3
- "version": "0.4.1",
3
+ "version": "0.7.0",
4
4
  "description": "제로투원 — 회사 온톨로지와 슬랙 맥락을 내가 쓰는 AI에서 꺼내 쓴다",
5
5
  "keywords": [
6
6
  "z2o",
@@ -24,7 +24,8 @@
24
24
  },
25
25
  "files": [
26
26
  "index.js",
27
- "README.md"
27
+ "README.md",
28
+ "plugin/"
28
29
  ],
29
30
  "engines": {
30
31
  "node": ">=18"
@@ -0,0 +1,11 @@
1
+ {
2
+ "$schema": "https://anthropic.com/claude-code/plugin.schema.json",
3
+ "name": "z2o",
4
+ "version": "0.7.0",
5
+ "description": "제로투원 — 회사 위키·슬랙·회의록을 읽고(/z2o:read) 위키에 정리해 넣는다(/z2o:ingest). z2o CLI 를 감싼다.",
6
+ "author": {
7
+ "name": "Lindy Operation"
8
+ },
9
+ "homepage": "https://z2o.kr",
10
+ "keywords": ["z2o", "zerotoone", "wiki", "ontology", "slack"]
11
+ }
@@ -0,0 +1,95 @@
1
+ ---
2
+ name: ingest
3
+ description: 자료를 제로투원 위키에 넣고 정리할 때 쓴다 — "이거 위키에 올려", "회의록 z2o 에 정리해", "pending 정리해", "온톨로지 정리해", "슬랙 들어온 거 요약해 둬". 원본을 넣고, 관련 문서를 찾아 읽고, 고쳐 쓴 요약을 남긴다. Z2O 의 AI(organize)에 맡기지 않고 내가 한다.
4
+ allowed-tools:
5
+ - Bash(z2o *)
6
+ - Bash(mktemp *)
7
+ - Read
8
+ - Write
9
+ ---
10
+
11
+ # /z2o:ingest — 위키에 정리해 넣기
12
+
13
+ **정리는 내가 한다.** `z2o organize`(Z2O 의 AI)는 사람이 그렇게 해 달라고 할 때만 부른다.
14
+
15
+ 요청: `$ARGUMENTS`
16
+
17
+ ## 0. 규칙부터 — 매번
18
+
19
+ ```
20
+ z2o rules
21
+ ```
22
+
23
+ 축 구성·문서 형식·건드리지 않을 곳이 거기 있다. **회사마다 다르고 사람이 고쳐 두었을 수 있다.**
24
+ 이 스킬은 **순서**를, `z2o rules` 는 **규격**을 맡는다. 둘이 어긋나면 **`z2o rules` 를 따른다.**
25
+
26
+ ## 1. 넣기 — 넣을 원본이 있을 때만
27
+
28
+ ```
29
+ z2o find <제목의 핵심 낱말> 이미 들어와 있나 먼저 본다
30
+ z2o push "<제목>" <파일> 없을 때만
31
+ ```
32
+
33
+ - ⚠️ **슬랙·티로·캘린더는 매시 자동 수집된다.** 회의록을 손으로 또 넣으면 **같은 회의가 두 벌**이 된다.
34
+ `find` 로 찾아지면 넣지 않는다. 방금 끝난 회의면 한 시간 뒤 다시 본다.
35
+ - 원본은 **한 글자도 고치지 않고** 넣는다. 요약은 넣지 않는다 — 요약은 5단계에서 위키에 쓴다.
36
+ - 비밀번호·토큰·계좌번호가 보이면 **넣기 전에 사람에게 묻는다.**
37
+
38
+ ## 2. 뼈대 — 한 번
39
+
40
+ ```
41
+ z2o build
42
+ ```
43
+
44
+ 원문(`docs/`)·장부·표를 **코드가** 만든다(0원). 이게 없으면 요약에 건 링크가 깨진다.
45
+ **두 번 부르지 않는다.**
46
+
47
+ ## 3. 할 일 보기
48
+
49
+ ```
50
+ z2o pending 요약이 필요한 원본
51
+ z2o raw <id> <id> ... 한 번에 여러 개 읽는다
52
+ ```
53
+
54
+ 잡담뿐인 원본도 있다. **남길 사실만** 추린다 — 누가·무엇을·언제·숫자.
55
+
56
+ ## 4. 붙일 자리 찾기 — 건너뛰지 않는다
57
+
58
+ ```
59
+ z2o list topics/
60
+ z2o search <낱말>
61
+ z2o read topics/<후보>.md
62
+ ```
63
+
64
+ **새 문서는 맞는 주제가 정말 없을 때만** 만든다. 새 문서만 늘리면 위키가 누적되지 않고 흩어진다.
65
+ 원문 문서의 경로는 `z2o list docs/` 로 확인한다 — **2단계가 만든 경로를 그대로** 쓴다.
66
+
67
+ ## 5. 고쳐 쓰기
68
+
69
+ 주제 문서는 두 층이다(자세한 모양은 `z2o rules`).
70
+
71
+ - **산문** — 새 자료를 반영해 **다시 쓴다.** 이어 붙이지 말고 한 덩어리로.
72
+ - **`## 문서` 줄** — 기존 줄은 **한 글자도 지우거나 고치지 않는다.** 새 원본 줄만 덧붙인다:
73
+ `- [[docs/<경로>|<제목>]] — 한 줄 설명`
74
+
75
+ 파일은 임시로 쓰고 올린다.
76
+
77
+ ```
78
+ z2o write topics/<주제>.md <임시파일>
79
+ ```
80
+
81
+ - 문서 머리(`type`·`tags`·`updated`)가 없으면 서버가 틀을 보여 주며 거절한다 — 그 틀대로 고친다.
82
+ - **쓰면 안 되는 곳**: `ledger/` `entities/` `tables/` `docs/` `calendar/` `meetings/` `index.md` `log.md` `overview.md` — 코드가 만든다. 서버도 거절한다.
83
+
84
+ ## 6. 확인
85
+
86
+ ```
87
+ z2o pending
88
+ ```
89
+
90
+ 요약이 원문 문서를 링크하면 그 원본은 **pending 에서 빠진다.** 안 빠졌으면 **링크 경로가 틀린 것**이다 —
91
+ `z2o list docs/` 와 대조해 고친다.
92
+
93
+ ## 보고
94
+
95
+ 사람에게 짧게: 넣은 원본 · 고친/새로 만든 문서 · 남은 pending 수 · **원본끼리 어긋난 것**(날짜·숫자·사람).
@@ -0,0 +1,45 @@
1
+ ---
2
+ name: read
3
+ description: 회사(제로투원) 맥락이 필요할 때 쓴다 — 슬랙·회의록·메일·위키에서 찾아 답한다. "슬랙에서 뭐라고 했지", "지난 회의에서 정한 거", "우리 회사 ~ 어떻게 됐어", "z2o 에서 찾아줘", "최근 얘기 정리해줘" 같은 요청. 사람에게 복사해 달라고 하지 않고 z2o 로 직접 꺼낸다.
4
+ allowed-tools:
5
+ - Bash(z2o *)
6
+ ---
7
+
8
+ # /z2o:read — 회사 맥락 꺼내기
9
+
10
+ 회사의 슬랙·회의록·메일·정리된 위키는 전부 `z2o` 명령으로 꺼낸다.
11
+ **사람에게 "복사해서 붙여 주세요"라고 하지 않는다.** 이 스킬은 읽기만 한다 — 쓰기는 `/z2o:ingest`.
12
+
13
+ 요청: `$ARGUMENTS`
14
+
15
+ ## 어디서 찾나 — 둘로 나뉜다
16
+
17
+ | | 무엇 | 명령 |
18
+ |---|---|---|
19
+ | **원본** | 들어온 그대로. 슬랙·메일·티로. **가장 최신** | `z2o recent [개수]` · `z2o find <낱말>` · `z2o raw <id...>` |
20
+ | **위키** | 정리된 지식. 주제·개체·장부 | `z2o list [접두어]` · `z2o search <낱말>` · `z2o read <경로...>` · `z2o graph` |
21
+
22
+ - **오늘·이번 주·"슬랙에서"** 같은 요청 → 원본부터. `recent` 로 훑고 `raw` 로 읽는다.
23
+ - **"~가 뭐였지", "~ 현황"** 같은 요청 → 위키부터.
24
+ - 둘 다 본 뒤 **어긋나면 둘 다 말한다.** 원본이 더 최신이다 — 위키는 정리된 시점에 멈춰 있다.
25
+
26
+ ## 위키 찾는 법
27
+
28
+ 1. `z2o read index.md overview.md` — 목차와 종합. 어디를 볼지 여기서 정한다.
29
+ 2. `z2o list topics/` 처럼 **접두어로 목록**을 본다. 위키가 100장 안팎이면
30
+ **목록을 보고 관련 문서를 통째로 읽는 편이 검색보다 낫다.**
31
+ 3. `z2o search` 는 **낱말을 그대로 포함한 것만** 찾는다(최대 30건, 뜻으로 찾지 않는다).
32
+ 동의어·다른 표기로 **여러 번** 찾는다. 예: `타임원`·`TimeOne`·`외주`
33
+ 4. `z2o read a.md b.md c.md` — **여러 장을 한 번에**(한 번에 40장·12만 자까지).
34
+ 5. 주제 문서의 `## 문서` 줄은 원문(`docs/`)을 가리킨다. 산문이 모호하면 원문을 읽는다.
35
+
36
+ ## 답할 때
37
+
38
+ - **출처를 붙인다** — 문서 경로(`topics/물류.md`)나 원본 id(`d213b634`).
39
+ - 못 찾았으면 **못 찾았다고 한다.** 짐작으로 메우지 않는다.
40
+ - 워크스페이스가 여럿이면 `-c <id>` 로 고른다. 모르겠으면 `z2o companies`.
41
+
42
+ ## 막히면
43
+
44
+ - `토큰이 없어요` → 사람에게 `z2o init` 을 안내한다. **토큰을 대화로 받지 않는다** — 사람이 직접 넣는다.
45
+ - `워크스페이스를 정하세요` → `z2o companies` 로 보여 주고 사람이 `z2o use` 로 고르게 한다.