@nclamvn/vibecode-cli 2.0.0 → 2.2.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/.vibecode/learning/fixes.json +1 -0
- package/.vibecode/learning/preferences.json +1 -0
- package/README.md +310 -49
- package/SESSION_NOTES.md +154 -0
- package/bin/vibecode.js +235 -2
- package/package.json +5 -2
- package/src/agent/decomposition.js +476 -0
- package/src/agent/index.js +391 -0
- package/src/agent/memory.js +542 -0
- package/src/agent/orchestrator.js +917 -0
- package/src/agent/self-healing.js +516 -0
- package/src/commands/agent.js +349 -0
- package/src/commands/ask.js +230 -0
- package/src/commands/assist.js +413 -0
- package/src/commands/build.js +345 -4
- package/src/commands/debug.js +565 -0
- package/src/commands/docs.js +167 -0
- package/src/commands/git.js +1024 -0
- package/src/commands/go.js +635 -0
- package/src/commands/learn.js +294 -0
- package/src/commands/migrate.js +341 -0
- package/src/commands/plan.js +8 -2
- package/src/commands/refactor.js +205 -0
- package/src/commands/review.js +126 -1
- package/src/commands/security.js +229 -0
- package/src/commands/shell.js +486 -0
- package/src/commands/templates.js +397 -0
- package/src/commands/test.js +194 -0
- package/src/commands/undo.js +281 -0
- package/src/commands/watch.js +556 -0
- package/src/commands/wizard.js +322 -0
- package/src/config/constants.js +5 -1
- package/src/config/templates.js +146 -15
- package/src/core/backup.js +325 -0
- package/src/core/error-analyzer.js +237 -0
- package/src/core/fix-generator.js +195 -0
- package/src/core/iteration.js +226 -0
- package/src/core/learning.js +295 -0
- package/src/core/session.js +18 -2
- package/src/core/test-runner.js +281 -0
- package/src/debug/analyzer.js +329 -0
- package/src/debug/evidence.js +228 -0
- package/src/debug/fixer.js +348 -0
- package/src/debug/image-analyzer.js +304 -0
- package/src/debug/index.js +378 -0
- package/src/debug/verifier.js +346 -0
- package/src/index.js +102 -0
- package/src/providers/claude-code.js +12 -7
- package/src/templates/index.js +724 -0
- package/src/ui/__tests__/error-translator.test.js +390 -0
- package/src/ui/dashboard.js +364 -0
- package/src/ui/error-translator.js +775 -0
- package/src/utils/image.js +222 -0
|
@@ -0,0 +1,486 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shell Mode for Vibecode CLI
|
|
3
|
+
* Interactive command shell with vibecode context and AI assistance
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import readline from 'readline';
|
|
7
|
+
import chalk from 'chalk';
|
|
8
|
+
import { exec, spawn } from 'child_process';
|
|
9
|
+
import { promisify } from 'util';
|
|
10
|
+
import path from 'path';
|
|
11
|
+
import fs from 'fs/promises';
|
|
12
|
+
|
|
13
|
+
const execAsync = promisify(exec);
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Main shell command handler
|
|
17
|
+
*/
|
|
18
|
+
export async function shellCommand(options) {
|
|
19
|
+
const cwd = process.cwd();
|
|
20
|
+
const projectInfo = await getProjectInfo(cwd);
|
|
21
|
+
const history = [];
|
|
22
|
+
let historyIndex = -1;
|
|
23
|
+
|
|
24
|
+
// Render header
|
|
25
|
+
console.log(renderHeader(projectInfo));
|
|
26
|
+
|
|
27
|
+
// Setup readline with custom prompt
|
|
28
|
+
const rl = readline.createInterface({
|
|
29
|
+
input: process.stdin,
|
|
30
|
+
output: process.stdout,
|
|
31
|
+
prompt: chalk.green('vibe$ '),
|
|
32
|
+
historySize: 100,
|
|
33
|
+
terminal: true
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
// Custom completer
|
|
37
|
+
rl.on('line', async (line) => {
|
|
38
|
+
const input = line.trim();
|
|
39
|
+
|
|
40
|
+
if (!input) {
|
|
41
|
+
rl.prompt();
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Add to history
|
|
46
|
+
history.push(input);
|
|
47
|
+
historyIndex = history.length;
|
|
48
|
+
|
|
49
|
+
try {
|
|
50
|
+
const shouldContinue = await processCommand(input, cwd, projectInfo, history, rl);
|
|
51
|
+
if (shouldContinue === false) {
|
|
52
|
+
return; // Exit was called
|
|
53
|
+
}
|
|
54
|
+
} catch (error) {
|
|
55
|
+
console.log(chalk.red(`\n Error: ${error.message}\n`));
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
rl.prompt();
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
rl.on('close', () => {
|
|
62
|
+
console.log(chalk.cyan('\n Shell closed.\n'));
|
|
63
|
+
process.exit(0);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
// Handle SIGINT (Ctrl+C)
|
|
67
|
+
rl.on('SIGINT', () => {
|
|
68
|
+
console.log(chalk.gray('\n (Use "exit" to quit)\n'));
|
|
69
|
+
rl.prompt();
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
rl.prompt();
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Get project information for context
|
|
77
|
+
*/
|
|
78
|
+
async function getProjectInfo(cwd) {
|
|
79
|
+
const info = {
|
|
80
|
+
name: path.basename(cwd),
|
|
81
|
+
type: 'Unknown',
|
|
82
|
+
framework: null,
|
|
83
|
+
hasGit: false,
|
|
84
|
+
branch: null,
|
|
85
|
+
hasVibecode: false
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
try {
|
|
89
|
+
// Check package.json
|
|
90
|
+
const pkgPath = path.join(cwd, 'package.json');
|
|
91
|
+
const pkg = JSON.parse(await fs.readFile(pkgPath, 'utf-8'));
|
|
92
|
+
|
|
93
|
+
info.name = pkg.name || info.name;
|
|
94
|
+
|
|
95
|
+
// Detect framework/type
|
|
96
|
+
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
97
|
+
|
|
98
|
+
if (deps.next) {
|
|
99
|
+
info.type = 'Next.js';
|
|
100
|
+
info.framework = 'next';
|
|
101
|
+
} else if (deps.react) {
|
|
102
|
+
info.type = 'React';
|
|
103
|
+
info.framework = 'react';
|
|
104
|
+
} else if (deps.vue) {
|
|
105
|
+
info.type = 'Vue';
|
|
106
|
+
info.framework = 'vue';
|
|
107
|
+
} else if (deps.express) {
|
|
108
|
+
info.type = 'Express';
|
|
109
|
+
info.framework = 'express';
|
|
110
|
+
} else if (deps.fastify) {
|
|
111
|
+
info.type = 'Fastify';
|
|
112
|
+
info.framework = 'fastify';
|
|
113
|
+
} else if (deps.typescript) {
|
|
114
|
+
info.type = 'TypeScript';
|
|
115
|
+
} else if (pkg.main || pkg.bin) {
|
|
116
|
+
info.type = 'Node.js';
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Add prisma indicator
|
|
120
|
+
if (deps['@prisma/client'] || deps.prisma) {
|
|
121
|
+
info.type += ' + Prisma';
|
|
122
|
+
}
|
|
123
|
+
} catch {
|
|
124
|
+
// No package.json
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
try {
|
|
128
|
+
// Check git
|
|
129
|
+
await execAsync('git rev-parse --git-dir', { cwd });
|
|
130
|
+
info.hasGit = true;
|
|
131
|
+
|
|
132
|
+
const { stdout } = await execAsync('git branch --show-current', { cwd });
|
|
133
|
+
info.branch = stdout.trim() || 'HEAD';
|
|
134
|
+
} catch {
|
|
135
|
+
// Not a git repo
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
try {
|
|
139
|
+
// Check vibecode
|
|
140
|
+
await fs.stat(path.join(cwd, '.vibecode'));
|
|
141
|
+
info.hasVibecode = true;
|
|
142
|
+
} catch {
|
|
143
|
+
// No vibecode
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return info;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Render the shell header
|
|
151
|
+
*/
|
|
152
|
+
function renderHeader(projectInfo) {
|
|
153
|
+
const gitInfo = projectInfo.hasGit
|
|
154
|
+
? chalk.gray(` [${projectInfo.branch}]`)
|
|
155
|
+
: '';
|
|
156
|
+
|
|
157
|
+
const vibeInfo = projectInfo.hasVibecode
|
|
158
|
+
? chalk.green(' [vibecode]')
|
|
159
|
+
: '';
|
|
160
|
+
|
|
161
|
+
return chalk.cyan(`
|
|
162
|
+
+----------------------------------------------------------------------+
|
|
163
|
+
| VIBECODE SHELL |
|
|
164
|
+
| |
|
|
165
|
+
| Project: ${chalk.white(projectInfo.name.padEnd(52))}|${gitInfo}${vibeInfo}
|
|
166
|
+
| Type: ${chalk.white(projectInfo.type.padEnd(55))}|
|
|
167
|
+
| |
|
|
168
|
+
| ${chalk.gray('Prefixes:')} |
|
|
169
|
+
| ${chalk.yellow('@')}${chalk.gray('<cmd>')} ${chalk.gray('Vibecode command (e.g., @status, @git)')} |
|
|
170
|
+
| ${chalk.yellow('?')}${chalk.gray('<query>')} ${chalk.gray('Ask AI (e.g., ?explain auth)')} |
|
|
171
|
+
| ${chalk.yellow('!')}${chalk.gray('<cmd>')} ${chalk.gray('Force raw execution')} |
|
|
172
|
+
| ${chalk.yellow('!!')} ${chalk.gray('Repeat last command')} |
|
|
173
|
+
| |
|
|
174
|
+
+----------------------------------------------------------------------+
|
|
175
|
+
`);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Process a command input
|
|
180
|
+
*/
|
|
181
|
+
async function processCommand(input, cwd, projectInfo, history, rl) {
|
|
182
|
+
// Built-in commands
|
|
183
|
+
if (input === 'exit' || input === 'quit' || input === 'q') {
|
|
184
|
+
rl.close();
|
|
185
|
+
return false;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
if (input === 'clear' || input === 'cls') {
|
|
189
|
+
console.clear();
|
|
190
|
+
console.log(renderHeader(projectInfo));
|
|
191
|
+
return true;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
if (input === 'history' || input === 'hist') {
|
|
195
|
+
console.log(chalk.cyan('\n Command history:\n'));
|
|
196
|
+
const start = Math.max(0, history.length - 20);
|
|
197
|
+
history.slice(start, -1).forEach((cmd, i) => {
|
|
198
|
+
console.log(chalk.gray(` ${start + i + 1}. ${cmd}`));
|
|
199
|
+
});
|
|
200
|
+
console.log('');
|
|
201
|
+
return true;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
if (input === 'help' || input === 'h') {
|
|
205
|
+
showHelp();
|
|
206
|
+
return true;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
if (input === 'pwd') {
|
|
210
|
+
console.log(chalk.white(`\n ${cwd}\n`));
|
|
211
|
+
return true;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
if (input === 'info') {
|
|
215
|
+
showProjectInfo(projectInfo, cwd);
|
|
216
|
+
return true;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// Repeat last command (!!)
|
|
220
|
+
if (input === '!!') {
|
|
221
|
+
if (history.length < 2) {
|
|
222
|
+
console.log(chalk.yellow('\n No previous command.\n'));
|
|
223
|
+
return true;
|
|
224
|
+
}
|
|
225
|
+
const lastCmd = history[history.length - 2];
|
|
226
|
+
console.log(chalk.gray(` Repeating: ${lastCmd}\n`));
|
|
227
|
+
return processCommand(lastCmd, cwd, projectInfo, history, rl);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// History expansion (!n)
|
|
231
|
+
const histMatch = input.match(/^!(\d+)$/);
|
|
232
|
+
if (histMatch) {
|
|
233
|
+
const index = parseInt(histMatch[1]) - 1;
|
|
234
|
+
if (index >= 0 && index < history.length - 1) {
|
|
235
|
+
const cmd = history[index];
|
|
236
|
+
console.log(chalk.gray(` Repeating: ${cmd}\n`));
|
|
237
|
+
return processCommand(cmd, cwd, projectInfo, history, rl);
|
|
238
|
+
}
|
|
239
|
+
console.log(chalk.yellow('\n Invalid history index.\n'));
|
|
240
|
+
return true;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// Vibecode commands (@)
|
|
244
|
+
if (input.startsWith('@')) {
|
|
245
|
+
await runVibecodeCommand(input.slice(1), cwd);
|
|
246
|
+
return true;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// AI queries (?)
|
|
250
|
+
if (input.startsWith('?')) {
|
|
251
|
+
await runAIQuery(input.slice(1), cwd, projectInfo);
|
|
252
|
+
return true;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// Force raw execution (!)
|
|
256
|
+
if (input.startsWith('!') && !input.startsWith('!!')) {
|
|
257
|
+
await runRawCommand(input.slice(1), cwd);
|
|
258
|
+
return true;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// cd command (special handling)
|
|
262
|
+
if (input.startsWith('cd ')) {
|
|
263
|
+
const dir = input.slice(3).trim();
|
|
264
|
+
try {
|
|
265
|
+
const newPath = path.resolve(cwd, dir);
|
|
266
|
+
await fs.stat(newPath);
|
|
267
|
+
process.chdir(newPath);
|
|
268
|
+
console.log(chalk.gray(`\n Changed to: ${newPath}\n`));
|
|
269
|
+
} catch {
|
|
270
|
+
console.log(chalk.red(`\n Directory not found: ${dir}\n`));
|
|
271
|
+
}
|
|
272
|
+
return true;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
// Normal shell command
|
|
276
|
+
await runShellCommand(input, cwd);
|
|
277
|
+
return true;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* Run a vibecode command
|
|
282
|
+
*/
|
|
283
|
+
async function runVibecodeCommand(cmd, cwd) {
|
|
284
|
+
const parts = cmd.trim().split(/\s+/);
|
|
285
|
+
const command = parts[0];
|
|
286
|
+
const args = parts.slice(1);
|
|
287
|
+
|
|
288
|
+
if (!command) {
|
|
289
|
+
console.log(chalk.yellow('\n Usage: @<command> [args]\n'));
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
console.log(chalk.cyan(`\n Running: vibecode ${cmd}\n`));
|
|
294
|
+
|
|
295
|
+
// Map aliases
|
|
296
|
+
const aliases = {
|
|
297
|
+
's': 'status',
|
|
298
|
+
'g': 'git',
|
|
299
|
+
'd': 'debug',
|
|
300
|
+
'b': 'build',
|
|
301
|
+
'w': 'watch',
|
|
302
|
+
'a': 'assist'
|
|
303
|
+
};
|
|
304
|
+
|
|
305
|
+
const vibeCmd = aliases[command] || command;
|
|
306
|
+
|
|
307
|
+
return new Promise((resolve) => {
|
|
308
|
+
const child = spawn('vibecode', [vibeCmd, ...args], {
|
|
309
|
+
cwd,
|
|
310
|
+
stdio: 'inherit',
|
|
311
|
+
shell: true
|
|
312
|
+
});
|
|
313
|
+
|
|
314
|
+
child.on('close', (code) => {
|
|
315
|
+
console.log('');
|
|
316
|
+
resolve();
|
|
317
|
+
});
|
|
318
|
+
|
|
319
|
+
child.on('error', (error) => {
|
|
320
|
+
console.log(chalk.red(`\n Error: ${error.message}\n`));
|
|
321
|
+
resolve();
|
|
322
|
+
});
|
|
323
|
+
});
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* Run an AI query using Claude
|
|
328
|
+
*/
|
|
329
|
+
async function runAIQuery(query, cwd, projectInfo) {
|
|
330
|
+
if (!query.trim()) {
|
|
331
|
+
console.log(chalk.yellow('\n Usage: ?<your question>\n'));
|
|
332
|
+
return;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
console.log(chalk.cyan(`\n AI Query: "${query}"\n`));
|
|
336
|
+
|
|
337
|
+
// Build context
|
|
338
|
+
const context = `Project: ${projectInfo.name} (${projectInfo.type})
|
|
339
|
+
Directory: ${cwd}
|
|
340
|
+
Question: ${query}
|
|
341
|
+
|
|
342
|
+
Please provide a helpful, concise answer.`;
|
|
343
|
+
|
|
344
|
+
return new Promise((resolve) => {
|
|
345
|
+
// Try using claude CLI directly
|
|
346
|
+
const child = spawn('claude', ['-p', context], {
|
|
347
|
+
cwd,
|
|
348
|
+
stdio: 'inherit',
|
|
349
|
+
shell: true
|
|
350
|
+
});
|
|
351
|
+
|
|
352
|
+
child.on('close', (code) => {
|
|
353
|
+
console.log('');
|
|
354
|
+
resolve();
|
|
355
|
+
});
|
|
356
|
+
|
|
357
|
+
child.on('error', () => {
|
|
358
|
+
// Fallback: suggest using vibecode assist
|
|
359
|
+
console.log(chalk.yellow(' Claude CLI not available.'));
|
|
360
|
+
console.log(chalk.gray(' Try: vibecode assist "' + query + '"\n'));
|
|
361
|
+
resolve();
|
|
362
|
+
});
|
|
363
|
+
});
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
/**
|
|
367
|
+
* Run a raw shell command (force mode)
|
|
368
|
+
*/
|
|
369
|
+
async function runRawCommand(cmd, cwd) {
|
|
370
|
+
if (!cmd.trim()) {
|
|
371
|
+
console.log(chalk.yellow('\n Usage: !<command>\n'));
|
|
372
|
+
return;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
return new Promise((resolve) => {
|
|
376
|
+
console.log('');
|
|
377
|
+
|
|
378
|
+
const child = spawn(cmd, [], {
|
|
379
|
+
cwd,
|
|
380
|
+
stdio: 'inherit',
|
|
381
|
+
shell: true
|
|
382
|
+
});
|
|
383
|
+
|
|
384
|
+
child.on('close', (code) => {
|
|
385
|
+
console.log('');
|
|
386
|
+
resolve();
|
|
387
|
+
});
|
|
388
|
+
|
|
389
|
+
child.on('error', (error) => {
|
|
390
|
+
console.log(chalk.red(`\n Error: ${error.message}\n`));
|
|
391
|
+
resolve();
|
|
392
|
+
});
|
|
393
|
+
});
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
/**
|
|
397
|
+
* Run a normal shell command
|
|
398
|
+
*/
|
|
399
|
+
async function runShellCommand(cmd, cwd) {
|
|
400
|
+
return new Promise((resolve) => {
|
|
401
|
+
console.log('');
|
|
402
|
+
|
|
403
|
+
const child = spawn(cmd, [], {
|
|
404
|
+
cwd,
|
|
405
|
+
stdio: 'inherit',
|
|
406
|
+
shell: true
|
|
407
|
+
});
|
|
408
|
+
|
|
409
|
+
child.on('close', (code) => {
|
|
410
|
+
if (code !== 0 && code !== null) {
|
|
411
|
+
console.log(chalk.gray(` Exit code: ${code}`));
|
|
412
|
+
}
|
|
413
|
+
console.log('');
|
|
414
|
+
resolve();
|
|
415
|
+
});
|
|
416
|
+
|
|
417
|
+
child.on('error', (error) => {
|
|
418
|
+
// Command not found
|
|
419
|
+
const cmdName = cmd.split(' ')[0];
|
|
420
|
+
console.log(chalk.red(`\n Command not found: ${cmdName}`));
|
|
421
|
+
console.log(chalk.gray(` Did you mean: @${cmdName}?\n`));
|
|
422
|
+
resolve();
|
|
423
|
+
});
|
|
424
|
+
});
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
/**
|
|
428
|
+
* Show help message
|
|
429
|
+
*/
|
|
430
|
+
function showHelp() {
|
|
431
|
+
console.log(chalk.white(`
|
|
432
|
+
VIBECODE SHELL HELP
|
|
433
|
+
|
|
434
|
+
${chalk.cyan('Built-in Commands:')}
|
|
435
|
+
exit, quit, q Exit shell
|
|
436
|
+
clear, cls Clear screen
|
|
437
|
+
history, hist Show command history
|
|
438
|
+
help, h Show this help
|
|
439
|
+
pwd Print working directory
|
|
440
|
+
info Show project info
|
|
441
|
+
cd <dir> Change directory
|
|
442
|
+
|
|
443
|
+
${chalk.cyan('Prefixes:')}
|
|
444
|
+
${chalk.yellow('@')}<command> Run vibecode command
|
|
445
|
+
e.g., @status, @git status, @debug
|
|
446
|
+
|
|
447
|
+
${chalk.yellow('?')}<query> Ask AI a question
|
|
448
|
+
e.g., ?explain this code, ?fix the error
|
|
449
|
+
|
|
450
|
+
${chalk.yellow('!')}<command> Force raw shell execution
|
|
451
|
+
e.g., !npm run dev
|
|
452
|
+
|
|
453
|
+
${chalk.yellow('!!')} Repeat last command
|
|
454
|
+
${chalk.yellow('!')}<n> Repeat command #n from history
|
|
455
|
+
|
|
456
|
+
${chalk.cyan('Examples:')}
|
|
457
|
+
vibe$ npm test Run npm test
|
|
458
|
+
vibe$ @git commit Git commit via vibecode
|
|
459
|
+
vibe$ @s Vibecode status (alias)
|
|
460
|
+
vibe$ ?what is useState Ask AI about useState
|
|
461
|
+
vibe$ !node server.js Run node directly
|
|
462
|
+
vibe$ !! Repeat last command
|
|
463
|
+
|
|
464
|
+
${chalk.cyan('Aliases:')}
|
|
465
|
+
@s -> @status @g -> @git
|
|
466
|
+
@d -> @debug @b -> @build
|
|
467
|
+
@w -> @watch @a -> @assist
|
|
468
|
+
`));
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
/**
|
|
472
|
+
* Show project information
|
|
473
|
+
*/
|
|
474
|
+
function showProjectInfo(projectInfo, cwd) {
|
|
475
|
+
console.log(chalk.cyan(`
|
|
476
|
+
PROJECT INFO
|
|
477
|
+
|
|
478
|
+
Name: ${chalk.white(projectInfo.name)}
|
|
479
|
+
Type: ${chalk.white(projectInfo.type)}
|
|
480
|
+
Directory: ${chalk.white(cwd)}
|
|
481
|
+
Git: ${projectInfo.hasGit ? chalk.green('Yes') + chalk.gray(` (${projectInfo.branch})`) : chalk.gray('No')}
|
|
482
|
+
Vibecode: ${projectInfo.hasVibecode ? chalk.green('Yes') : chalk.gray('No')}
|
|
483
|
+
`));
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
export default shellCommand;
|