vibe-collab 0.7.0 → 0.8.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
@@ -76,10 +76,26 @@ vibe start
76
76
  | `vibe auth login` | GitHub OAuth 로그인 |
77
77
  | `vibe auth logout` | 로그아웃 |
78
78
  | `vibe auth status` | 로그인 상태 및 만료일 확인 |
79
- | `vibe init` | 프로젝트 초기화 (CHARTER, state.json, MCP 설정 생성) |
79
+ | `vibe init` | 프로젝트 초기화 (CHARTER, state.json 생성 + MCP 자동 감지) |
80
+ | `vibe connect` | 프로젝트 내 AI 도구 자동 감지 후 MCP 설정 추가 |
81
+ | `vibe connect --ai <tool>` | 특정 AI 도구에 MCP 설정 강제 추가 |
80
82
  | `vibe start` | 작업 시작 또는 이어서 진행 |
81
83
  | `vibe status` | 팀 현황 출력 |
82
84
  | `vibe serve` | MCP 서버 시작 (AI 도구에서 자동 실행됨) |
85
+ | `vibe update` | vibe-collab을 최신 버전으로 업데이트 |
86
+
87
+ ### `vibe connect --ai` 지원 도구
88
+
89
+ ```bash
90
+ vibe connect --ai claude # Claude Code → .claude/settings.json
91
+ vibe connect --ai cursor # Cursor → .cursor/mcp.json
92
+ vibe connect --ai vscode # VS Code → .vscode/mcp.json
93
+ vibe connect --ai windsurf # Windsurf → .windsurf/mcp.json
94
+ vibe connect --ai gemini # Gemini CLI → .gemini/settings.json
95
+ vibe connect --ai kiro # Kiro → .kiro/mcp.json
96
+ vibe connect --ai copilot # Copilot → .vscode/mcp.json
97
+ vibe connect --ai all # 위 전체 설정
98
+ ```
83
99
 
84
100
  ---
85
101
 
@@ -149,7 +149,6 @@ export async function authCommand(action) {
149
149
  }
150
150
  case 'logout': {
151
151
  const data = readAuthData();
152
- deleteAuthData();
153
152
  if (data) {
154
153
  try {
155
154
  await fetch(`${PROXY_URL}/api/auth/cli-token`, {
@@ -160,6 +159,7 @@ export async function authCommand(action) {
160
159
  catch {
161
160
  // 서버 호출 실패해도 로컬 삭제는 완료
162
161
  }
162
+ deleteAuthData();
163
163
  console.log(chalk.green(`👋 @${data.user.login} 로그아웃 완료.`));
164
164
  }
165
165
  else {
@@ -1 +1 @@
1
- export declare function connectCommand(cwd: string): Promise<void>;
1
+ export declare function connectCommand(cwd: string, aiFlag?: string): Promise<void>;
@@ -1,26 +1,27 @@
1
1
  import fs from 'fs';
2
2
  import path from 'path';
3
- import { execSync } from 'child_process';
4
3
  import chalk from 'chalk';
5
4
  const STANDARD_MCP_ENTRY = {
6
5
  command: 'npx',
7
- args: ['vibe-orchestrator', 'serve'],
6
+ args: ['vibe-collab', 'serve'],
8
7
  env: {},
9
8
  };
10
9
  const VSCODE_MCP_ENTRY = {
11
10
  type: 'stdio',
12
11
  command: 'npx',
13
- args: ['vibe-orchestrator', 'serve'],
12
+ args: ['vibe-collab', 'serve'],
14
13
  };
15
- function hasBinary(name) {
16
- try {
17
- const cmd = process.platform === 'win32' ? `where ${name}` : `which ${name}`;
18
- execSync(cmd, { stdio: 'pipe' });
19
- return true;
20
- }
21
- catch {
22
- return false;
23
- }
14
+ function getToolDefs(cwd) {
15
+ return {
16
+ claude: { label: 'Claude Code', configDir: '.claude', configFile: 'settings.json', format: 'standard' },
17
+ cursor: { label: 'Cursor', configDir: '.cursor', configFile: 'mcp.json', format: 'standard' },
18
+ vscode: { label: 'VS Code', configDir: '.vscode', configFile: 'mcp.json', format: 'vscode' },
19
+ copilot: { label: 'Copilot', configDir: '.vscode', configFile: 'mcp.json', format: 'vscode' },
20
+ windsurf: { label: 'Windsurf', configDir: '.windsurf', configFile: 'mcp.json', format: 'standard' },
21
+ gemini: { label: 'Gemini CLI', configDir: '.gemini', configFile: 'settings.json', format: 'standard' },
22
+ kiro: { label: 'Kiro', configDir: '.kiro', configFile: 'mcp.json', format: 'standard' },
23
+ };
24
+ void cwd;
24
25
  }
25
26
  function hasDir(dir) {
26
27
  return fs.existsSync(dir);
@@ -66,74 +67,46 @@ function addVSCodeEntry(existing, serverKey) {
66
67
  },
67
68
  };
68
69
  }
69
- async function configureClaudeCode(cwd) {
70
- const tool = 'Claude Code';
71
- const claudeDir = path.join(cwd, '.claude');
72
- const detected = hasDir(claudeDir) || hasBinary('claude');
73
- if (!detected) {
74
- return { tool, configPath: '', status: 'skipped' };
70
+ function configureTool(cwd, def, force) {
71
+ const dir = path.join(cwd, def.configDir);
72
+ if (!force && !hasDir(dir)) {
73
+ return { tool: def.label, configPath: '', status: 'skipped' };
75
74
  }
76
- const configPath = path.join(claudeDir, 'settings.json');
75
+ const configPath = path.join(dir, def.configFile);
77
76
  const existing = readJsonSafe(configPath);
78
77
  if (isAlreadyConfigured(existing, 'vibe-orchestrator')) {
79
- return { tool, configPath, status: 'already' };
78
+ return { tool: def.label, configPath, status: 'already' };
80
79
  }
81
- writeJson(configPath, addStandardEntry(existing, 'vibe-orchestrator'));
82
- return { tool, configPath, status: 'added' };
80
+ const updated = def.format === 'vscode'
81
+ ? addVSCodeEntry(existing, 'vibe-orchestrator')
82
+ : addStandardEntry(existing, 'vibe-orchestrator');
83
+ writeJson(configPath, updated);
84
+ return { tool: def.label, configPath, status: 'added' };
83
85
  }
84
- async function configureCursor(cwd) {
85
- const tool = 'Cursor';
86
- const cursorDir = path.join(cwd, '.cursor');
87
- const detected = hasDir(cursorDir) || hasBinary('cursor');
88
- if (!detected) {
89
- return { tool, configPath: '', status: 'skipped' };
90
- }
91
- const configPath = path.join(cursorDir, 'mcp.json');
92
- const existing = readJsonSafe(configPath);
93
- if (isAlreadyConfigured(existing, 'vibe-orchestrator')) {
94
- return { tool, configPath, status: 'already' };
95
- }
96
- writeJson(configPath, addStandardEntry(existing, 'vibe-orchestrator'));
97
- return { tool, configPath, status: 'added' };
98
- }
99
- async function configureVSCode(cwd) {
100
- const tool = 'VS Code';
101
- const vscodeDir = path.join(cwd, '.vscode');
102
- const detected = hasDir(vscodeDir) || hasBinary('code');
103
- if (!detected) {
104
- return { tool, configPath: '', status: 'skipped' };
86
+ export async function connectCommand(cwd, aiFlag) {
87
+ const toolDefs = getToolDefs(cwd);
88
+ let targets;
89
+ if (aiFlag) {
90
+ const key = aiFlag.toLowerCase();
91
+ if (key === 'all') {
92
+ targets = Object.values(toolDefs).map(def => ({ def, force: true }));
93
+ }
94
+ else if (toolDefs[key]) {
95
+ targets = [{ def: toolDefs[key], force: true }];
96
+ }
97
+ else {
98
+ console.log(chalk.red(`알 수 없는 AI 도구: ${aiFlag}`));
99
+ console.log(chalk.gray(`지원 목록: ${Object.keys(toolDefs).join(', ')}, all`));
100
+ return;
101
+ }
102
+ console.log(chalk.cyan(`\n🔌 ${aiFlag === 'all' ? '전체' : toolDefs[aiFlag.toLowerCase()]?.label} MCP 설정 중...\n`));
105
103
  }
106
- const configPath = path.join(vscodeDir, 'mcp.json');
107
- const existing = readJsonSafe(configPath);
108
- if (isAlreadyConfigured(existing, 'vibe-orchestrator')) {
109
- return { tool, configPath, status: 'already' };
104
+ else {
105
+ // 자동 감지: 프로젝트 디렉토리가 있는 것만
106
+ targets = Object.values(toolDefs).map(def => ({ def, force: false }));
107
+ console.log(chalk.cyan('\n🔌 AI 도구 자동 감지 중...\n'));
110
108
  }
111
- writeJson(configPath, addVSCodeEntry(existing, 'vibe-orchestrator'));
112
- return { tool, configPath, status: 'added' };
113
- }
114
- // Windsurf도 글로벌 설정(~/.codeium/)이므로 자동 설정 제외
115
- async function configureWindsurf() {
116
- return { tool: 'Windsurf', configPath: '', status: 'skipped' };
117
- }
118
- // Claude Desktop과 Gemini CLI는 글로벌 설정 파일을 수정하므로
119
- // vibe init 시 자동 설정하지 않습니다.
120
- // 원하면 vibe connect --global 로 별도 실행하세요. (미구현)
121
- async function configureClaudeDesktop() {
122
- return { tool: 'Claude Desktop', configPath: '', status: 'skipped' };
123
- }
124
- async function configureGeminiCLI() {
125
- return { tool: 'Gemini CLI', configPath: '', status: 'skipped' };
126
- }
127
- export async function connectCommand(cwd) {
128
- console.log(chalk.cyan('\n🔌 AI 도구 자동 설정 중...\n'));
129
- const results = await Promise.all([
130
- configureClaudeCode(cwd),
131
- configureCursor(cwd),
132
- configureVSCode(cwd),
133
- configureWindsurf(),
134
- configureClaudeDesktop(),
135
- configureGeminiCLI(),
136
- ]);
109
+ const results = targets.map(({ def, force }) => configureTool(cwd, def, force));
137
110
  let addedCount = 0;
138
111
  let alreadyCount = 0;
139
112
  let skippedCount = 0;
@@ -167,5 +140,16 @@ export async function connectCommand(cwd) {
167
140
  console.log(chalk.green(`✨ ${parts.join(', ')}`));
168
141
  console.log(chalk.gray(' AI 도구를 재시작하면 vibe-orchestrator MCP가 활성화됩니다.\n'));
169
142
  }
143
+ console.log(chalk.cyan('─── 수동 설정 (다른 MCP 지원 도구에 직접 추가) ───\n'));
144
+ console.log(chalk.white('Claude Code / Cursor / 기타:'));
145
+ console.log(chalk.gray(JSON.stringify({
146
+ mcpServers: { 'vibe-orchestrator': STANDARD_MCP_ENTRY },
147
+ }, null, 2)));
148
+ console.log('');
149
+ console.log(chalk.white('VS Code:'));
150
+ console.log(chalk.gray(JSON.stringify({
151
+ servers: { 'vibe-orchestrator': VSCODE_MCP_ENTRY },
152
+ }, null, 2)));
153
+ console.log('');
170
154
  }
171
155
  //# sourceMappingURL=connect.js.map
@@ -0,0 +1 @@
1
+ export declare function updateCommand(): Promise<void>;
@@ -0,0 +1,52 @@
1
+ import { execSync, spawnSync } from 'child_process';
2
+ import chalk from 'chalk';
3
+ const PACKAGE_NAME = 'vibe-collab';
4
+ function getCurrentVersion() {
5
+ try {
6
+ const result = execSync(`npm list -g --depth=0 ${PACKAGE_NAME} --json`, { encoding: 'utf-8', stdio: 'pipe' });
7
+ const json = JSON.parse(result);
8
+ return json.dependencies?.[PACKAGE_NAME]?.version ?? 'unknown';
9
+ }
10
+ catch {
11
+ return 'unknown';
12
+ }
13
+ }
14
+ function getLatestVersion() {
15
+ try {
16
+ return execSync(`npm view ${PACKAGE_NAME} version`, { encoding: 'utf-8', stdio: 'pipe' }).trim();
17
+ }
18
+ catch {
19
+ throw new Error('npm 레지스트리에서 버전 정보를 가져올 수 없습니다.');
20
+ }
21
+ }
22
+ export async function updateCommand() {
23
+ console.log(chalk.cyan('\n🔄 vibe-collab 업데이트 확인 중...\n'));
24
+ const current = getCurrentVersion();
25
+ let latest;
26
+ try {
27
+ latest = getLatestVersion();
28
+ }
29
+ catch (e) {
30
+ console.log(chalk.red(e.message));
31
+ return;
32
+ }
33
+ console.log(chalk.gray(` 현재 버전: ${current}`));
34
+ console.log(chalk.gray(` 최신 버전: ${latest}\n`));
35
+ if (current === latest) {
36
+ console.log(chalk.green('✅ 이미 최신 버전입니다.'));
37
+ return;
38
+ }
39
+ console.log(chalk.cyan(`📦 ${current} → ${latest} 업데이트 중...\n`));
40
+ const result = spawnSync('npm', ['install', '-g', `${PACKAGE_NAME}@latest`], {
41
+ stdio: 'inherit',
42
+ shell: true,
43
+ });
44
+ if (result.status === 0) {
45
+ console.log(chalk.green(`\n✅ ${latest}로 업데이트 완료!`));
46
+ }
47
+ else {
48
+ console.log(chalk.red('\n업데이트 실패. 직접 실행해보세요:'));
49
+ console.log(chalk.gray(` npm install -g ${PACKAGE_NAME}@latest`));
50
+ }
51
+ }
52
+ //# sourceMappingURL=update.js.map
package/dist/cli/index.js CHANGED
@@ -7,6 +7,7 @@ import { startCommand } from './commands/start.js';
7
7
  import { serveCommand } from './commands/serve.js';
8
8
  import { connectCommand } from './commands/connect.js';
9
9
  import { authCommand } from './commands/auth.js';
10
+ import { updateCommand } from './commands/update.js';
10
11
  const program = new Command();
11
12
  program
12
13
  .name('vibe')
@@ -40,9 +41,10 @@ program
40
41
  });
41
42
  program
42
43
  .command('connect')
43
- .description('설치된 AI 도구(Cursor, VS Code, Claude Code 등)에 자동으로 MCP 설정을 추가합니다')
44
- .action(async () => {
45
- await connectCommand(process.cwd());
44
+ .description('AI 도구에 MCP 설정을 추가합니다')
45
+ .option('--ai <tool>', 'AI 도구 지정 (claude|cursor|vscode|windsurf|gemini|kiro|copilot|all)')
46
+ .action(async (options) => {
47
+ await connectCommand(process.cwd(), options.ai);
46
48
  });
47
49
  program
48
50
  .command('auth')
@@ -51,5 +53,11 @@ program
51
53
  .action(async (action) => {
52
54
  await authCommand(action);
53
55
  });
56
+ program
57
+ .command('update')
58
+ .description('vibe-collab을 최신 버전으로 업데이트합니다')
59
+ .action(async () => {
60
+ await updateCommand();
61
+ });
54
62
  program.parse();
55
63
  //# sourceMappingURL=index.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vibe-collab",
3
- "version": "0.7.0",
3
+ "version": "0.8.0",
4
4
  "description": "누가 어떤 AI를 써도, 항상 한 팀처럼 작동하는 바이브 코딩 협업 도구",
5
5
  "type": "module",
6
6
  "bin": {