@team-semicolon/semo-cli 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,118 @@
1
+ # @team-semicolon/semo-cli
2
+
3
+ > SEMO CLI - AI Agent Orchestration Framework Installer
4
+
5
+ ## 개요
6
+
7
+ Gemini의 하이브리드 전략에 따라 SEMO를 자동 설치하는 CLI 도구입니다.
8
+
9
+ ```bash
10
+ npx @team-semicolon/semo-cli init
11
+ ```
12
+
13
+ ## 동작 방식
14
+
15
+ `semo init` 명령어는 다음을 자동으로 수행합니다:
16
+
17
+ ### 1. White Box 설정 (Git Subtree)
18
+
19
+ 에이전트가 **읽고 학습**해야 하는 지식 베이스:
20
+
21
+ ```
22
+ semo-system/
23
+ ├── semo-core/ # Layer 0: 원칙, 오케스트레이션
24
+ └── semo-skills/ # Layer 1: coder, tester, planner
25
+ ```
26
+
27
+ ### 2. Black Box 설정 (MCP Server)
28
+
29
+ 토큰이 격리된 **외부 연동 도구**:
30
+
31
+ ```json
32
+ // .claude/settings.json
33
+ {
34
+ "mcpServers": {
35
+ "semo-integrations": {
36
+ "command": "npx",
37
+ "args": ["-y", "@team-semicolon/semo-mcp"]
38
+ }
39
+ }
40
+ }
41
+ ```
42
+
43
+ ### 3. Context Mesh 초기화
44
+
45
+ 세션 간 **컨텍스트 영속화**:
46
+
47
+ ```
48
+ .claude/memory/
49
+ ├── context.md # 프로젝트 상태
50
+ ├── decisions.md # 아키텍처 결정
51
+ └── rules/ # 프로젝트별 규칙
52
+ ```
53
+
54
+ ## 명령어
55
+
56
+ ### init
57
+
58
+ 현재 프로젝트에 SEMO를 설치합니다.
59
+
60
+ ```bash
61
+ semo init # 기본 설치
62
+ semo init --force # 기존 설정 덮어쓰기
63
+ semo init --skip-mcp # MCP 설정 생략
64
+ semo init --skip-subtree # Git Subtree 생략
65
+ ```
66
+
67
+ ### status
68
+
69
+ SEMO 설치 상태를 확인합니다.
70
+
71
+ ```bash
72
+ semo status
73
+ ```
74
+
75
+ ### update
76
+
77
+ SEMO를 최신 버전으로 업데이트합니다.
78
+
79
+ ```bash
80
+ semo update
81
+ ```
82
+
83
+ ## 설치 후 구조
84
+
85
+ ```
86
+ your-project/
87
+ ├── .claude/
88
+ │ ├── CLAUDE.md # 프로젝트 설정
89
+ │ ├── settings.json # MCP 서버 설정
90
+ │ ├── memory/ # Context Mesh
91
+ │ ├── agents → semo-system/semo-core/agents
92
+ │ └── skills → semo-system/semo-skills
93
+
94
+ └── semo-system/ # White Box (읽기 전용)
95
+ ├── semo-core/
96
+ └── semo-skills/
97
+ ```
98
+
99
+ ## 환경변수
100
+
101
+ MCP 연동을 위해 다음 환경변수를 설정하세요:
102
+
103
+ | 변수 | 설명 |
104
+ |------|------|
105
+ | `GITHUB_TOKEN` | GitHub API 토큰 |
106
+ | `SLACK_BOT_TOKEN` | Slack Bot 토큰 |
107
+ | `SUPABASE_URL` | Supabase 프로젝트 URL |
108
+ | `SUPABASE_KEY` | Supabase 서비스 키 |
109
+
110
+ ## 참조
111
+
112
+ - [SEMO 레포지토리](https://github.com/semicolon-devteam/semo)
113
+ - [SEMO MCP Server](../mcp-server/README.md)
114
+ - [Gemini 하이브리드 전략](../../docs/SEMO_ARCHITECTURE_REVIEW.md)
115
+
116
+ ## 라이선스
117
+
118
+ MIT
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * SEMO CLI
4
+ *
5
+ * Gemini 하이브리드 전략에 따른 SEMO 설치 자동화 도구
6
+ *
7
+ * 사용법:
8
+ * npx @team-semicolon/semo-cli init
9
+ *
10
+ * 동작:
11
+ * 1. White Box (semo-core, semo-skills) → Git Subtree로 주입
12
+ * 2. Black Box (semo-integrations) → MCP 설정 파일 생성
13
+ * 3. Context Mesh (.claude/memory/) 초기화
14
+ */
15
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,410 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ /**
4
+ * SEMO CLI
5
+ *
6
+ * Gemini 하이브리드 전략에 따른 SEMO 설치 자동화 도구
7
+ *
8
+ * 사용법:
9
+ * npx @team-semicolon/semo-cli init
10
+ *
11
+ * 동작:
12
+ * 1. White Box (semo-core, semo-skills) → Git Subtree로 주입
13
+ * 2. Black Box (semo-integrations) → MCP 설정 파일 생성
14
+ * 3. Context Mesh (.claude/memory/) 초기화
15
+ */
16
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
17
+ if (k2 === undefined) k2 = k;
18
+ var desc = Object.getOwnPropertyDescriptor(m, k);
19
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
20
+ desc = { enumerable: true, get: function() { return m[k]; } };
21
+ }
22
+ Object.defineProperty(o, k2, desc);
23
+ }) : (function(o, m, k, k2) {
24
+ if (k2 === undefined) k2 = k;
25
+ o[k2] = m[k];
26
+ }));
27
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
28
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
29
+ }) : function(o, v) {
30
+ o["default"] = v;
31
+ });
32
+ var __importStar = (this && this.__importStar) || (function () {
33
+ var ownKeys = function(o) {
34
+ ownKeys = Object.getOwnPropertyNames || function (o) {
35
+ var ar = [];
36
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
37
+ return ar;
38
+ };
39
+ return ownKeys(o);
40
+ };
41
+ return function (mod) {
42
+ if (mod && mod.__esModule) return mod;
43
+ var result = {};
44
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
45
+ __setModuleDefault(result, mod);
46
+ return result;
47
+ };
48
+ })();
49
+ var __importDefault = (this && this.__importDefault) || function (mod) {
50
+ return (mod && mod.__esModule) ? mod : { "default": mod };
51
+ };
52
+ Object.defineProperty(exports, "__esModule", { value: true });
53
+ const commander_1 = require("commander");
54
+ const chalk_1 = __importDefault(require("chalk"));
55
+ const ora_1 = __importDefault(require("ora"));
56
+ const child_process_1 = require("child_process");
57
+ const fs = __importStar(require("fs"));
58
+ const path = __importStar(require("path"));
59
+ const VERSION = "1.0.0";
60
+ const SEMO_REPO = "https://github.com/semicolon-devteam/semo.git";
61
+ const program = new commander_1.Command();
62
+ program
63
+ .name("semo")
64
+ .description("SEMO CLI - AI Agent Orchestration Framework")
65
+ .version(VERSION);
66
+ // === init 명령어 ===
67
+ program
68
+ .command("init")
69
+ .description("현재 프로젝트에 SEMO를 설치합니다 (Gemini 하이브리드 전략)")
70
+ .option("-f, --force", "기존 설정 덮어쓰기")
71
+ .option("--skip-mcp", "MCP 설정 생략")
72
+ .option("--skip-subtree", "Git Subtree 생략 (MCP만 설정)")
73
+ .action(async (options) => {
74
+ console.log(chalk_1.default.cyan.bold("\n🚀 SEMO 설치 시작\n"));
75
+ console.log(chalk_1.default.gray("Gemini 하이브리드 전략: White Box + Black Box\n"));
76
+ const cwd = process.cwd();
77
+ // 1. Git 레포지토리 확인
78
+ const spinner = (0, ora_1.default)("Git 레포지토리 확인 중...").start();
79
+ try {
80
+ (0, child_process_1.execSync)("git rev-parse --git-dir", { cwd, stdio: "pipe" });
81
+ spinner.succeed("Git 레포지토리 확인됨");
82
+ }
83
+ catch {
84
+ spinner.fail("Git 레포지토리가 아닙니다. 'git init'을 먼저 실행하세요.");
85
+ process.exit(1);
86
+ }
87
+ // 2. .claude 디렉토리 생성
88
+ const claudeDir = path.join(cwd, ".claude");
89
+ if (!fs.existsSync(claudeDir)) {
90
+ fs.mkdirSync(claudeDir, { recursive: true });
91
+ console.log(chalk_1.default.green("✓ .claude/ 디렉토리 생성됨"));
92
+ }
93
+ // 3. White Box: Git Subtree로 semo-core, semo-skills 주입
94
+ if (!options.skipSubtree) {
95
+ await setupWhiteBox(cwd, options.force);
96
+ }
97
+ // 4. Black Box: MCP 설정 파일 생성
98
+ if (!options.skipMcp) {
99
+ await setupBlackBox(cwd, options.force);
100
+ }
101
+ // 5. Context Mesh 초기화
102
+ await setupContextMesh(cwd);
103
+ // 6. CLAUDE.md 생성
104
+ await setupClaudeMd(cwd, options.force);
105
+ console.log(chalk_1.default.green.bold("\n✅ SEMO 설치 완료!\n"));
106
+ console.log(chalk_1.default.cyan("다음 단계:"));
107
+ console.log(chalk_1.default.gray(" 1. Claude Code에서 프로젝트 열기"));
108
+ console.log(chalk_1.default.gray(" 2. 자연어로 요청하기 (예: \"댓글 기능 구현해줘\")"));
109
+ console.log(chalk_1.default.gray(" 3. /SEMO:help로 도움말 확인\n"));
110
+ });
111
+ // === White Box 설정 (Git Subtree) ===
112
+ async function setupWhiteBox(cwd, force) {
113
+ const semoSystemDir = path.join(cwd, "semo-system");
114
+ console.log(chalk_1.default.cyan("\n📚 White Box 설정 (Git Subtree)"));
115
+ console.log(chalk_1.default.gray(" 에이전트가 읽고 학습할 지식 베이스\n"));
116
+ // semo-system 디렉토리 확인
117
+ if (fs.existsSync(semoSystemDir) && !force) {
118
+ console.log(chalk_1.default.yellow("⚠ semo-system/ 이미 존재. --force로 덮어쓰기 가능"));
119
+ return;
120
+ }
121
+ const spinner = (0, ora_1.default)("semo-core, semo-skills 다운로드 중...").start();
122
+ try {
123
+ // Git Subtree로 semo-core 추가
124
+ if (!fs.existsSync(path.join(semoSystemDir, "semo-core"))) {
125
+ (0, child_process_1.execSync)(`git subtree add --prefix=semo-system/semo-core ${SEMO_REPO} main --squash 2>/dev/null || true`, { cwd, stdio: "pipe" });
126
+ }
127
+ // semo-skills 추가 (같은 레포에서)
128
+ if (!fs.existsSync(path.join(semoSystemDir, "semo-skills"))) {
129
+ // subtree split으로 특정 폴더만 가져오기는 복잡하므로 전체 clone 후 복사
130
+ const tempDir = path.join(cwd, ".semo-temp");
131
+ if (!fs.existsSync(tempDir)) {
132
+ (0, child_process_1.execSync)(`git clone --depth 1 ${SEMO_REPO} ${tempDir}`, { stdio: "pipe" });
133
+ }
134
+ // semo-core와 semo-skills 복사
135
+ fs.mkdirSync(semoSystemDir, { recursive: true });
136
+ if (fs.existsSync(path.join(tempDir, "semo-core"))) {
137
+ (0, child_process_1.execSync)(`cp -r ${tempDir}/semo-core ${semoSystemDir}/`, { stdio: "pipe" });
138
+ }
139
+ if (fs.existsSync(path.join(tempDir, "semo-skills"))) {
140
+ (0, child_process_1.execSync)(`cp -r ${tempDir}/semo-skills ${semoSystemDir}/`, { stdio: "pipe" });
141
+ }
142
+ // 임시 디렉토리 삭제
143
+ (0, child_process_1.execSync)(`rm -rf ${tempDir}`, { stdio: "pipe" });
144
+ }
145
+ spinner.succeed("White Box 설정 완료 (semo-core, semo-skills)");
146
+ // .claude 심볼릭 링크 생성
147
+ const claudeDir = path.join(cwd, ".claude");
148
+ const agentsLink = path.join(claudeDir, "agents");
149
+ const skillsLink = path.join(claudeDir, "skills");
150
+ if (!fs.existsSync(agentsLink)) {
151
+ fs.symlinkSync("../semo-system/semo-core/agents", agentsLink);
152
+ console.log(chalk_1.default.green(" ✓ .claude/agents → semo-system/semo-core/agents"));
153
+ }
154
+ if (!fs.existsSync(skillsLink)) {
155
+ fs.symlinkSync("../semo-system/semo-skills", skillsLink);
156
+ console.log(chalk_1.default.green(" ✓ .claude/skills → semo-system/semo-skills"));
157
+ }
158
+ }
159
+ catch (error) {
160
+ spinner.fail("White Box 설정 실패");
161
+ console.error(chalk_1.default.red(` ${error}`));
162
+ }
163
+ }
164
+ // === Black Box 설정 (MCP) ===
165
+ async function setupBlackBox(cwd, force) {
166
+ console.log(chalk_1.default.cyan("\n🔧 Black Box 설정 (MCP Server)"));
167
+ console.log(chalk_1.default.gray(" 토큰이 격리된 외부 연동 도구\n"));
168
+ const settingsPath = path.join(cwd, ".claude", "settings.json");
169
+ if (fs.existsSync(settingsPath) && !force) {
170
+ console.log(chalk_1.default.yellow("⚠ .claude/settings.json 이미 존재. --force로 덮어쓰기 가능"));
171
+ return;
172
+ }
173
+ const settings = {
174
+ mcpServers: {
175
+ "semo-integrations": {
176
+ command: "npx",
177
+ args: ["-y", "@team-semicolon/semo-mcp"],
178
+ env: {
179
+ GITHUB_TOKEN: "${GITHUB_TOKEN}",
180
+ SLACK_BOT_TOKEN: "${SLACK_BOT_TOKEN}",
181
+ SUPABASE_URL: "${SUPABASE_URL}",
182
+ SUPABASE_KEY: "${SUPABASE_KEY}",
183
+ },
184
+ },
185
+ },
186
+ };
187
+ fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2));
188
+ console.log(chalk_1.default.green("✓ .claude/settings.json 생성됨 (MCP 설정)"));
189
+ console.log(chalk_1.default.gray(" → semo-integrations: github, slack, supabase"));
190
+ }
191
+ // === Context Mesh 초기화 ===
192
+ async function setupContextMesh(cwd) {
193
+ console.log(chalk_1.default.cyan("\n🧠 Context Mesh 초기화"));
194
+ console.log(chalk_1.default.gray(" 세션 간 컨텍스트 영속화\n"));
195
+ const memoryDir = path.join(cwd, ".claude", "memory");
196
+ fs.mkdirSync(memoryDir, { recursive: true });
197
+ // context.md
198
+ const contextPath = path.join(memoryDir, "context.md");
199
+ if (!fs.existsSync(contextPath)) {
200
+ const contextContent = `# Project Context
201
+
202
+ > 세션 간 영속화되는 프로젝트 컨텍스트
203
+
204
+ ---
205
+
206
+ ## 프로젝트 정보
207
+
208
+ | 항목 | 값 |
209
+ |------|-----|
210
+ | **이름** | ${path.basename(cwd)} |
211
+ | **SEMO 버전** | 2.0.0 |
212
+ | **설치일** | ${new Date().toISOString().split("T")[0]} |
213
+
214
+ ---
215
+
216
+ ## 현재 작업 상태
217
+
218
+ _아직 작업 기록이 없습니다._
219
+
220
+ ---
221
+
222
+ *마지막 업데이트: ${new Date().toISOString().split("T")[0]}*
223
+ `;
224
+ fs.writeFileSync(contextPath, contextContent);
225
+ console.log(chalk_1.default.green("✓ .claude/memory/context.md 생성됨"));
226
+ }
227
+ // decisions.md
228
+ const decisionsPath = path.join(memoryDir, "decisions.md");
229
+ if (!fs.existsSync(decisionsPath)) {
230
+ const decisionsContent = `# Architecture Decisions
231
+
232
+ > 프로젝트 아키텍처 결정 기록 (ADR)
233
+
234
+ ---
235
+
236
+ ## 결정 목록
237
+
238
+ _아직 기록된 결정이 없습니다._
239
+
240
+ ---
241
+
242
+ ## 템플릿
243
+
244
+ \`\`\`markdown
245
+ ### ADR-XXX: 결정 제목
246
+
247
+ **날짜**: YYYY-MM-DD
248
+ **상태**: Proposed | Accepted | Deprecated
249
+
250
+ #### 배경
251
+ 결정이 필요한 이유
252
+
253
+ #### 결정
254
+ 선택한 방안
255
+
256
+ #### 근거
257
+ 선택 이유
258
+ \`\`\`
259
+ `;
260
+ fs.writeFileSync(decisionsPath, decisionsContent);
261
+ console.log(chalk_1.default.green("✓ .claude/memory/decisions.md 생성됨"));
262
+ }
263
+ // rules 디렉토리
264
+ const rulesDir = path.join(memoryDir, "rules");
265
+ fs.mkdirSync(rulesDir, { recursive: true });
266
+ const rulesPath = path.join(rulesDir, "project-specific.md");
267
+ if (!fs.existsSync(rulesPath)) {
268
+ const rulesContent = `# Project-Specific Rules
269
+
270
+ > 이 프로젝트에만 적용되는 규칙
271
+
272
+ ---
273
+
274
+ ## 코딩 규칙
275
+
276
+ _프로젝트별 코딩 규칙을 여기에 추가하세요._
277
+
278
+ ---
279
+
280
+ ## 예외 사항
281
+
282
+ _SEMO 기본 규칙의 예외 사항을 여기에 추가하세요._
283
+ `;
284
+ fs.writeFileSync(rulesPath, rulesContent);
285
+ console.log(chalk_1.default.green("✓ .claude/memory/rules/project-specific.md 생성됨"));
286
+ }
287
+ }
288
+ // === CLAUDE.md 생성 ===
289
+ async function setupClaudeMd(cwd, force) {
290
+ console.log(chalk_1.default.cyan("\n📄 CLAUDE.md 설정"));
291
+ const claudeMdPath = path.join(cwd, ".claude", "CLAUDE.md");
292
+ if (fs.existsSync(claudeMdPath) && !force) {
293
+ console.log(chalk_1.default.yellow("⚠ CLAUDE.md 이미 존재. --force로 덮어쓰기 가능"));
294
+ return;
295
+ }
296
+ const claudeMdContent = `# SEMO Project Configuration
297
+
298
+ > SEMO (Semicolon Orchestrate) - AI Agent Orchestration Framework
299
+
300
+ ## 구조
301
+
302
+ \`\`\`
303
+ .claude/
304
+ ├── settings.json # MCP 서버 설정 (Black Box)
305
+ ├── memory/ # Context Mesh
306
+ │ ├── context.md # 프로젝트 상태
307
+ │ ├── decisions.md # 아키텍처 결정
308
+ │ └── rules/ # 프로젝트별 규칙
309
+ ├── agents → semo-system/semo-core/agents
310
+ └── skills → semo-system/semo-skills
311
+
312
+ semo-system/ # White Box (읽기 전용)
313
+ ├── semo-core/ # Layer 0: 원칙, 오케스트레이션
314
+ └── semo-skills/ # Layer 1: coder, tester, planner
315
+ \`\`\`
316
+
317
+ ## 사용 가능한 커맨드
318
+
319
+ | 커맨드 | 설명 |
320
+ |--------|------|
321
+ | \`/SEMO:help\` | 도움말 |
322
+ | \`/SEMO:slack\` | Slack 메시지 전송 |
323
+ | \`/SEMO:feedback\` | 피드백 제출 |
324
+ | \`/SEMO:health\` | 환경 검증 |
325
+
326
+ ## 플랫폼 자동 감지
327
+
328
+ SEMO는 프로젝트 파일을 분석하여 플랫폼을 자동 감지합니다:
329
+
330
+ | 파일 | 플랫폼 |
331
+ |------|--------|
332
+ | \`next.config.js\` | Next.js |
333
+ | \`pom.xml\` | Spring |
334
+ | \`docker-compose.yml\` | Microservice |
335
+ | 기타 | MVP |
336
+
337
+ ## References
338
+
339
+ - [SEMO Principles](semo-system/semo-core/principles/PRINCIPLES.md)
340
+ - [SEMO Skills](semo-system/semo-skills/)
341
+ `;
342
+ fs.writeFileSync(claudeMdPath, claudeMdContent);
343
+ console.log(chalk_1.default.green("✓ .claude/CLAUDE.md 생성됨"));
344
+ }
345
+ // === status 명령어 ===
346
+ program
347
+ .command("status")
348
+ .description("SEMO 설치 상태를 확인합니다")
349
+ .action(() => {
350
+ console.log(chalk_1.default.cyan.bold("\n📊 SEMO 설치 상태\n"));
351
+ const cwd = process.cwd();
352
+ const checks = [
353
+ { name: ".claude/", path: path.join(cwd, ".claude"), type: "dir" },
354
+ { name: ".claude/settings.json", path: path.join(cwd, ".claude", "settings.json"), type: "file" },
355
+ { name: ".claude/memory/", path: path.join(cwd, ".claude", "memory"), type: "dir" },
356
+ { name: "semo-system/semo-core/", path: path.join(cwd, "semo-system", "semo-core"), type: "dir" },
357
+ { name: "semo-system/semo-skills/", path: path.join(cwd, "semo-system", "semo-skills"), type: "dir" },
358
+ ];
359
+ let allPassed = true;
360
+ for (const check of checks) {
361
+ const exists = fs.existsSync(check.path);
362
+ if (exists) {
363
+ console.log(chalk_1.default.green(`✓ ${check.name}`));
364
+ }
365
+ else {
366
+ console.log(chalk_1.default.red(`✗ ${check.name}`));
367
+ allPassed = false;
368
+ }
369
+ }
370
+ console.log();
371
+ if (allPassed) {
372
+ console.log(chalk_1.default.green.bold("SEMO가 정상적으로 설치되어 있습니다."));
373
+ }
374
+ else {
375
+ console.log(chalk_1.default.yellow("일부 구성 요소가 누락되었습니다. 'semo init'을 실행하세요."));
376
+ }
377
+ console.log();
378
+ });
379
+ // === update 명령어 ===
380
+ program
381
+ .command("update")
382
+ .description("SEMO를 최신 버전으로 업데이트합니다")
383
+ .action(() => {
384
+ console.log(chalk_1.default.cyan.bold("\n🔄 SEMO 업데이트\n"));
385
+ const cwd = process.cwd();
386
+ const semoSystemDir = path.join(cwd, "semo-system");
387
+ if (!fs.existsSync(semoSystemDir)) {
388
+ console.log(chalk_1.default.red("SEMO가 설치되어 있지 않습니다. 'semo init'을 먼저 실행하세요."));
389
+ process.exit(1);
390
+ }
391
+ const spinner = (0, ora_1.default)("최신 버전 다운로드 중...").start();
392
+ try {
393
+ // 임시 디렉토리에 최신 버전 clone
394
+ const tempDir = path.join(cwd, ".semo-temp");
395
+ (0, child_process_1.execSync)(`rm -rf ${tempDir}`, { stdio: "pipe" });
396
+ (0, child_process_1.execSync)(`git clone --depth 1 ${SEMO_REPO} ${tempDir}`, { stdio: "pipe" });
397
+ // semo-core, semo-skills 업데이트
398
+ (0, child_process_1.execSync)(`rm -rf ${semoSystemDir}/semo-core ${semoSystemDir}/semo-skills`, { stdio: "pipe" });
399
+ (0, child_process_1.execSync)(`cp -r ${tempDir}/semo-core ${semoSystemDir}/`, { stdio: "pipe" });
400
+ (0, child_process_1.execSync)(`cp -r ${tempDir}/semo-skills ${semoSystemDir}/`, { stdio: "pipe" });
401
+ // 임시 디렉토리 삭제
402
+ (0, child_process_1.execSync)(`rm -rf ${tempDir}`, { stdio: "pipe" });
403
+ spinner.succeed("SEMO 업데이트 완료");
404
+ }
405
+ catch (error) {
406
+ spinner.fail("업데이트 실패");
407
+ console.error(chalk_1.default.red(`${error}`));
408
+ }
409
+ });
410
+ program.parse();
package/package.json ADDED
@@ -0,0 +1,48 @@
1
+ {
2
+ "name": "@team-semicolon/semo-cli",
3
+ "version": "1.0.0",
4
+ "description": "SEMO CLI - AI Agent Orchestration Framework Installer",
5
+ "main": "dist/index.js",
6
+ "bin": {
7
+ "semo": "./dist/index.js",
8
+ "semo-cli": "./dist/index.js"
9
+ },
10
+ "scripts": {
11
+ "build": "tsc",
12
+ "start": "node dist/index.js",
13
+ "dev": "ts-node src/index.ts"
14
+ },
15
+ "keywords": [
16
+ "semo",
17
+ "cli",
18
+ "ai-agent",
19
+ "claude",
20
+ "semicolon"
21
+ ],
22
+ "author": "Semicolon DevTeam",
23
+ "license": "MIT",
24
+ "repository": {
25
+ "type": "git",
26
+ "url": "https://github.com/semicolon-devteam/semo.git",
27
+ "directory": "packages/cli"
28
+ },
29
+ "dependencies": {
30
+ "chalk": "^5.3.0",
31
+ "commander": "^12.0.0",
32
+ "ora": "^8.0.0",
33
+ "inquirer": "^9.2.0"
34
+ },
35
+ "devDependencies": {
36
+ "@types/node": "^20.0.0",
37
+ "@types/inquirer": "^9.0.0",
38
+ "typescript": "^5.0.0",
39
+ "ts-node": "^10.0.0"
40
+ },
41
+ "engines": {
42
+ "node": ">=18.0.0"
43
+ },
44
+ "files": [
45
+ "dist",
46
+ "README.md"
47
+ ]
48
+ }