proagents 1.6.12 → 1.6.13

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.
@@ -1,5 +1,6 @@
1
1
  import { existsSync, readFileSync } from 'fs';
2
2
  import { join } from 'path';
3
+ import { execSync } from 'child_process';
3
4
  import chalk from 'chalk';
4
5
  import yaml from 'js-yaml';
5
6
 
@@ -98,7 +99,9 @@ function checkPlatformSync(targetDir) {
98
99
  const content = readFileSync(configPath, 'utf-8');
99
100
  const config = yaml.load(content);
100
101
  configPlatforms = config?.platforms || config?.ai_platforms || [];
101
- } catch { }
102
+ } catch {
103
+ // Config file unreadable - will be caught by other checks
104
+ }
102
105
  }
103
106
 
104
107
  // Check each platform file
@@ -134,7 +137,7 @@ function checkPlatformSync(targetDir) {
134
137
  * Check for lock file
135
138
  */
136
139
  function checkLockFile(targetDir) {
137
- const lockPath = join(targetDir, 'proagents', '.lock');
140
+ const lockPath = join(targetDir, '.proagents', '.lock');
138
141
  const checks = [];
139
142
 
140
143
  if (existsSync(lockPath)) {
@@ -163,18 +166,187 @@ function checkLockFile(targetDir) {
163
166
  }
164
167
 
165
168
  /**
166
- * Check version
169
+ * Extended checks for --full mode
167
170
  */
168
- async function checkVersion() {
171
+ function checkExtended(targetDir) {
169
172
  const checks = [];
170
173
 
174
+ // Check changelog size
175
+ const recentPath = join(targetDir, '.proagents', 'changelog', '_recent.md');
176
+ if (existsSync(recentPath)) {
177
+ try {
178
+ const content = readFileSync(recentPath, 'utf-8');
179
+ const entries = (content.match(/^### /gm) || []).length;
180
+ if (entries > 50) {
181
+ checks.push({ name: 'Changelog size', status: 'warning', message: `${entries} entries (consider archiving)` });
182
+ } else {
183
+ checks.push({ name: 'Changelog size', status: 'ok', message: `${entries} entries` });
184
+ }
185
+ } catch {
186
+ checks.push({ name: 'Changelog size', status: 'skip', message: 'Could not read' });
187
+ }
188
+ } else {
189
+ checks.push({ name: 'Changelog', status: 'info', message: 'No recent changelog' });
190
+ }
191
+
192
+ // Check activity log freshness
193
+ const activityPath = join(targetDir, '.proagents', 'activity.log');
194
+ if (existsSync(activityPath)) {
195
+ try {
196
+ const content = readFileSync(activityPath, 'utf-8');
197
+ const lines = content.trim().split('\n').filter(l => l && !l.startsWith('#') && !l.includes('Activity Log'));
198
+ if (lines.length > 0) {
199
+ const lastLine = lines[lines.length - 1];
200
+ const dateMatch = lastLine.match(/^\[?(\d{4}-\d{2}-\d{2})/);
201
+ if (dateMatch) {
202
+ const lastDate = new Date(dateMatch[1]);
203
+ const daysAgo = Math.floor((Date.now() - lastDate.getTime()) / (1000 * 60 * 60 * 24));
204
+ if (daysAgo > 7) {
205
+ checks.push({ name: 'Activity log', status: 'warning', message: `Last entry ${daysAgo} days ago` });
206
+ } else if (daysAgo > 0) {
207
+ checks.push({ name: 'Activity log', status: 'ok', message: `Last entry ${daysAgo} day(s) ago` });
208
+ } else {
209
+ checks.push({ name: 'Activity log', status: 'ok', message: 'Activity today' });
210
+ }
211
+ } else {
212
+ checks.push({ name: 'Activity log', status: 'ok', message: `${lines.length} entries` });
213
+ }
214
+ } else {
215
+ checks.push({ name: 'Activity log', status: 'info', message: 'No entries yet' });
216
+ }
217
+ } catch {
218
+ checks.push({ name: 'Activity log', status: 'skip', message: 'Could not read' });
219
+ }
220
+ } else {
221
+ checks.push({ name: 'Activity log', status: 'info', message: 'No activity log' });
222
+ }
223
+
224
+ // Check for stale feature branches
171
225
  try {
172
- // Get current version from package.json
226
+ const branches = execSync('git branch --list "feature/*" 2>/dev/null', { encoding: 'utf-8' }).trim();
227
+ if (branches) {
228
+ const branchCount = branches.split('\n').filter(b => b.trim()).length;
229
+ if (branchCount > 5) {
230
+ checks.push({ name: 'Feature branches', status: 'warning', message: `${branchCount} branches (consider cleanup)` });
231
+ } else if (branchCount > 0) {
232
+ checks.push({ name: 'Feature branches', status: 'ok', message: `${branchCount} active` });
233
+ }
234
+ } else {
235
+ checks.push({ name: 'Feature branches', status: 'ok', message: 'None' });
236
+ }
237
+ } catch {
238
+ checks.push({ name: 'Feature branches', status: 'skip', message: 'Not a git repo or no feature branches' });
239
+ }
240
+
241
+ // Check active features
242
+ const featuresPath = join(targetDir, '.proagents', 'active-features', '_index.json');
243
+ if (existsSync(featuresPath)) {
244
+ try {
245
+ const content = readFileSync(featuresPath, 'utf-8');
246
+ const index = JSON.parse(content);
247
+ const activeCount = index.active_features?.length || 0;
248
+ const completedCount = index.completed_features?.length || 0;
249
+
250
+ if (activeCount > 0) {
251
+ checks.push({ name: 'Active features', status: 'ok', message: `${activeCount} active, ${completedCount} completed` });
252
+ } else {
253
+ checks.push({ name: 'Active features', status: 'info', message: `None active, ${completedCount} completed` });
254
+ }
255
+ } catch {
256
+ checks.push({ name: 'Active features', status: 'skip', message: 'Could not read index' });
257
+ }
258
+ } else {
259
+ checks.push({ name: 'Active features', status: 'info', message: 'No features tracked' });
260
+ }
261
+
262
+ // Check worklog context
263
+ const contextPath = join(targetDir, '.proagents', 'worklog', '_context.md');
264
+ if (existsSync(contextPath)) {
265
+ checks.push({ name: 'Worklog context', status: 'ok', message: 'Present' });
266
+ } else {
267
+ checks.push({ name: 'Worklog context', status: 'warning', message: 'Missing (cross-AI sync may be affected)' });
268
+ }
269
+
270
+ // Check for required folders
271
+ const requiredFolders = [
272
+ { path: '.proagents/prompts', name: 'Prompts folder' },
273
+ { path: '.proagents/templates', name: 'Templates folder' },
274
+ { path: '.proagents/changelog', name: 'Changelog folder' },
275
+ { path: '.proagents/worklog', name: 'Worklog folder' }
276
+ ];
277
+
278
+ for (const folder of requiredFolders) {
279
+ if (existsSync(join(targetDir, folder.path))) {
280
+ checks.push({ name: folder.name, status: 'ok', message: 'Present' });
281
+ } else {
282
+ checks.push({ name: folder.name, status: 'warning', message: 'Missing' });
283
+ }
284
+ }
285
+
286
+ return checks;
287
+ }
288
+
289
+ /**
290
+ * Compare semantic versions
291
+ * Returns: -1 if v1 < v2, 0 if equal, 1 if v1 > v2
292
+ */
293
+ function compareVersions(v1, v2) {
294
+ const parts1 = v1.split('.').map(Number);
295
+ const parts2 = v2.split('.').map(Number);
296
+
297
+ for (let i = 0; i < 3; i++) {
298
+ const p1 = parts1[i] || 0;
299
+ const p2 = parts2[i] || 0;
300
+ if (p1 < p2) return -1;
301
+ if (p1 > p2) return 1;
302
+ }
303
+ return 0;
304
+ }
305
+
306
+ /**
307
+ * Check version (CLI, project, and npm)
308
+ */
309
+ async function checkVersion(targetDir) {
310
+ const checks = [];
311
+ const recommendations = [];
312
+
313
+ try {
314
+ // Get CLI version from package.json
173
315
  const packagePath = new URL('../../package.json', import.meta.url);
174
316
  const packageJson = JSON.parse(readFileSync(packagePath, 'utf-8'));
175
- const currentVersion = packageJson.version;
176
-
177
- checks.push({ name: 'Installed version', status: 'info', message: `v${currentVersion}` });
317
+ const cliVersion = packageJson.version;
318
+
319
+ checks.push({ name: 'CLI version', status: 'info', message: `v${cliVersion}` });
320
+
321
+ // Get project version from .proagents/.version
322
+ const projectVersionPath = join(targetDir, '.proagents', '.version');
323
+ let projectVersion = null;
324
+
325
+ if (existsSync(projectVersionPath)) {
326
+ try {
327
+ projectVersion = readFileSync(projectVersionPath, 'utf-8').trim();
328
+
329
+ if (projectVersion === cliVersion) {
330
+ checks.push({ name: 'Project version', status: 'ok', message: `v${projectVersion} (synced with CLI)` });
331
+ } else if (compareVersions(projectVersion, cliVersion) < 0) {
332
+ checks.push({ name: 'Project version', status: 'warning', message: `v${projectVersion} (outdated)` });
333
+ recommendations.push({
334
+ issue: 'Project framework is outdated',
335
+ action: 'Run `npx proagents init` to update framework files'
336
+ });
337
+ } else {
338
+ checks.push({ name: 'Project version', status: 'info', message: `v${projectVersion}` });
339
+ }
340
+ } catch {
341
+ checks.push({ name: 'Project version', status: 'warning', message: 'Could not read version file' });
342
+ }
343
+ } else {
344
+ checks.push({ name: 'Project version', status: 'warning', message: 'No version marker (older installation)' });
345
+ recommendations.push({
346
+ issue: 'No version tracking',
347
+ action: 'Run `npx proagents init` to update and add version tracking'
348
+ });
349
+ }
178
350
 
179
351
  // Try to fetch latest version from npm (with timeout)
180
352
  try {
@@ -190,20 +362,24 @@ async function checkVersion() {
190
362
  const data = await response.json();
191
363
  const latestVersion = data.version;
192
364
 
193
- if (currentVersion === latestVersion) {
194
- checks.push({ name: 'Latest version', status: 'ok', message: 'Up to date' });
365
+ if (compareVersions(cliVersion, latestVersion) >= 0) {
366
+ checks.push({ name: 'npm registry', status: 'ok', message: `v${latestVersion} (up to date)` });
195
367
  } else {
196
- checks.push({ name: 'Latest version', status: 'warning', message: `v${latestVersion} available. Run: npm update -g proagents` });
368
+ checks.push({ name: 'npm registry', status: 'warning', message: `v${latestVersion} available` });
369
+ recommendations.push({
370
+ issue: 'CLI update available',
371
+ action: 'Run `npm update -g proagents` to update CLI'
372
+ });
197
373
  }
198
374
  }
199
375
  } catch {
200
- checks.push({ name: 'Version check', status: 'skip', message: 'Could not check npm registry' });
376
+ checks.push({ name: 'npm registry', status: 'skip', message: 'Could not check (offline?)' });
201
377
  }
202
- } catch {
203
- checks.push({ name: 'Version', status: 'error', message: 'Could not read version' });
378
+ } catch (error) {
379
+ checks.push({ name: 'Version', status: 'error', message: `Could not read version: ${error.message}` });
204
380
  }
205
381
 
206
- return checks;
382
+ return { checks, recommendations };
207
383
  }
208
384
 
209
385
  /**
@@ -248,16 +424,14 @@ function printChecks(title, checks) {
248
424
  /**
249
425
  * Doctor command - check health of ProAgents installation
250
426
  */
251
- export async function doctorCommand() {
427
+ export async function doctorCommand(options = {}) {
252
428
  const targetDir = process.cwd();
429
+ const isFullMode = options.full || false;
253
430
 
254
- console.log(chalk.bold('\nProAgents Doctor'));
255
- console.log(chalk.gray('================'));
431
+ console.log(chalk.bold('\nProAgents Doctor' + (isFullMode ? ' (Full)' : '')));
432
+ console.log(chalk.gray(''.repeat(40)));
256
433
  console.log(chalk.gray(`Checking: ${targetDir}\n`));
257
434
 
258
- let hasErrors = false;
259
- let hasWarnings = false;
260
-
261
435
  // Run all checks
262
436
  const installChecks = checkInstallation(targetDir);
263
437
  printChecks('Installation', installChecks);
@@ -271,14 +445,32 @@ export async function doctorCommand() {
271
445
  const lockChecks = checkLockFile(targetDir);
272
446
  printChecks('Lock Status', lockChecks);
273
447
 
274
- const versionChecks = await checkVersion();
275
- printChecks('Version', versionChecks);
448
+ const versionResult = await checkVersion(targetDir);
449
+ printChecks('Version', versionResult.checks);
450
+
451
+ // Extended checks for --full mode
452
+ let extendedChecks = [];
453
+ if (isFullMode) {
454
+ extendedChecks = checkExtended(targetDir);
455
+ printChecks('Extended Health Checks', extendedChecks);
456
+ }
276
457
 
277
458
  // Count issues
278
- const allChecks = [...installChecks, ...configChecks, ...platformChecks, ...lockChecks, ...versionChecks];
459
+ const allChecks = [...installChecks, ...configChecks, ...platformChecks, ...lockChecks, ...versionResult.checks, ...extendedChecks];
279
460
  const errors = allChecks.filter(c => c.status === 'error').length;
280
461
  const warnings = allChecks.filter(c => c.status === 'warning').length;
281
462
 
463
+ // Recommendations section (if any)
464
+ if (versionResult.recommendations && versionResult.recommendations.length > 0) {
465
+ console.log(chalk.bold('\nRecommendations'));
466
+ console.log(chalk.gray('─'.repeat(40)));
467
+
468
+ for (const rec of versionResult.recommendations) {
469
+ console.log(chalk.yellow(` ⚡ ${rec.issue}`));
470
+ console.log(chalk.cyan(` → ${rec.action}`));
471
+ }
472
+ }
473
+
282
474
  // Summary
283
475
  console.log(chalk.bold('\nSummary'));
284
476
  console.log(chalk.gray('─'.repeat(40)));
@@ -298,8 +490,13 @@ export async function doctorCommand() {
298
490
  console.log(chalk.gray('Run `npx proagents init` to fix installation issues.'));
299
491
  }
300
492
  if (platformChecks.some(c => c.status === 'warning')) {
301
- console.log(chalk.gray('Run `pa:ai-sync` to fix platform sync issues.'));
493
+ console.log(chalk.gray('Run `npx proagents ai add` to fix platform sync issues.'));
302
494
  }
303
495
  console.log('');
304
496
  }
497
+
498
+ // Hint for full mode
499
+ if (!isFullMode) {
500
+ console.log(chalk.gray('Run `proagents doctor --full` for extended health checks.\n'));
501
+ }
305
502
  }
@@ -53,10 +53,30 @@ export async function helpCommand() {
53
53
  console.log(chalk.bold.white('Status & Info'));
54
54
  console.log(chalk.gray('─'.repeat(40)));
55
55
  console.log(chalk.cyan('proagents status') + ' Show ProAgents status');
56
+ console.log(chalk.cyan('proagents version') + ' Show detailed version info');
57
+ console.log(chalk.cyan('proagents doctor') + ' Health check installation');
56
58
  console.log(chalk.cyan('proagents docs') + ' Open documentation');
57
59
  console.log(chalk.cyan('proagents commands') + ' Show this help');
58
- console.log(chalk.cyan('proagents uninstall') + ' Remove ProAgents from project');
59
- console.log(chalk.cyan('proagents --version') + ' Show version');
60
+ console.log('');
61
+
62
+ // Release & Maintenance
63
+ console.log(chalk.bold.white('Release & Maintenance'));
64
+ console.log(chalk.gray('─'.repeat(40)));
65
+ console.log(chalk.cyan('proagents release') + ' Interactive release notes');
66
+ console.log(chalk.gray(' Types: -t detailed | short | client | developer | hotfix | prerelease'));
67
+ console.log(chalk.gray(' Filters:'));
68
+ console.log(chalk.cyan(' --include fixes') + ' Only include bug fixes');
69
+ console.log(chalk.cyan(' --include features') + ' Only include features');
70
+ console.log(chalk.cyan(' --exclude docs,deps') + ' Exclude docs and deps');
71
+ console.log(chalk.cyan(' --module auth') + ' Filter by module name');
72
+ console.log(chalk.cyan(' --path src/lib') + ' Filter by file path');
73
+ console.log(chalk.gray(' Options:'));
74
+ console.log(chalk.cyan(' --append') + ' Append to existing notes');
75
+ console.log(chalk.cyan(' --bump') + ' Suggest version bump');
76
+ console.log(chalk.cyan(' --prerelease beta') + ' Mark as beta/rc/alpha');
77
+ console.log(chalk.cyan(' --since v1.0.0') + ' From specific tag');
78
+ console.log(chalk.cyan('proagents upgrade') + ' Upgrade .proagents folder');
79
+ console.log(chalk.cyan('proagents uninstall') + ' Remove ProAgents from project');
60
80
  console.log('');
61
81
 
62
82
  // Commands for AI Assistants
@@ -14,6 +14,8 @@ const PRESERVE_PATHS = [
14
14
  'active-features', // User's work in progress
15
15
  '.learning', // Learned patterns
16
16
  'cache', // Cached analysis
17
+ 'changelog', // Change history (user data)
18
+ 'worklog', // Work context (user data)
17
19
  ];
18
20
 
19
21
  // Config file is handled specially - merged not preserved
@@ -41,7 +43,6 @@ const FRAMEWORK_FOLDERS = [
41
43
  'api-versioning',
42
44
  'approval-workflows',
43
45
  'automation',
44
- 'changelog',
45
46
  'cicd',
46
47
  'collaboration',
47
48
  'compliance',
@@ -0,0 +1,188 @@
1
+ import { existsSync } from 'fs';
2
+ import { join } from 'path';
3
+ import { execSync } from 'child_process';
4
+ import chalk from 'chalk';
5
+
6
+ // File shortcuts mapping
7
+ const FILE_SHORTCUTS = {
8
+ // Main config
9
+ 'config': 'proagents.config.yaml',
10
+ 'cfg': 'proagents.config.yaml',
11
+
12
+ // Changelog files
13
+ 'changelog': '.proagents/changelog/_recent.md',
14
+ 'changes': '.proagents/changelog/_recent.md',
15
+ 'recent': '.proagents/changelog/_recent.md',
16
+
17
+ // Activity and logs
18
+ 'activity': '.proagents/activity.log',
19
+ 'log': '.proagents/activity.log',
20
+ 'logs': '.proagents/activity.log',
21
+
22
+ // Context and worklog
23
+ 'context': '.proagents/worklog/_context.md',
24
+ 'ctx': '.proagents/worklog/_context.md',
25
+ 'worklog': '.proagents/worklog/',
26
+
27
+ // AI instructions
28
+ 'instructions': '.proagents/AI_INSTRUCTIONS.md',
29
+ 'ai': '.proagents/AI_INSTRUCTIONS.md',
30
+
31
+ // Learning and feedback
32
+ 'feedback': '.proagents/feedback.md',
33
+ 'errors': '.proagents/errors.md',
34
+ 'decisions': '.proagents/decisions.md',
35
+
36
+ // Watchlist
37
+ 'watchlist': '.proagents/watchlist.yaml',
38
+ 'watch': '.proagents/watchlist.yaml',
39
+
40
+ // Handoff
41
+ 'handoff': '.proagents/handoff.md',
42
+
43
+ // Features
44
+ 'features': '.proagents/active-features/',
45
+
46
+ // Standards and rules
47
+ 'standards': '.proagents/config/standards/',
48
+ 'rules': '.proagents/config/rules/',
49
+ 'integrations': '.proagents/config/integrations/',
50
+
51
+ // Quick reference
52
+ 'commands': '.proagents/PROAGENTS.md',
53
+ 'help': '.proagents/PROAGENTS.md',
54
+ 'workflow': '.proagents/WORKFLOW.md',
55
+ };
56
+
57
+ /**
58
+ * Get the editor command based on environment
59
+ */
60
+ function getEditorCommand() {
61
+ // Check for common environment variables
62
+ const editor = process.env.EDITOR || process.env.VISUAL;
63
+ if (editor) return editor;
64
+
65
+ // Platform-specific defaults
66
+ const platform = process.platform;
67
+ if (platform === 'darwin') {
68
+ // macOS - try code, then open
69
+ try {
70
+ execSync('which code', { stdio: 'ignore' });
71
+ return 'code';
72
+ } catch {
73
+ return 'open';
74
+ }
75
+ } else if (platform === 'win32') {
76
+ return 'notepad';
77
+ } else {
78
+ // Linux - try code, vim, nano
79
+ try {
80
+ execSync('which code', { stdio: 'ignore' });
81
+ return 'code';
82
+ } catch {
83
+ try {
84
+ execSync('which vim', { stdio: 'ignore' });
85
+ return 'vim';
86
+ } catch {
87
+ return 'nano';
88
+ }
89
+ }
90
+ }
91
+ }
92
+
93
+ /**
94
+ * Open a file or directory in the default editor
95
+ */
96
+ function openInEditor(path) {
97
+ const editor = getEditorCommand();
98
+
99
+ try {
100
+ if (editor === 'open') {
101
+ // macOS open command
102
+ execSync(`open "${path}"`, { stdio: 'inherit' });
103
+ } else if (editor === 'code') {
104
+ // VS Code
105
+ execSync(`code "${path}"`, { stdio: 'inherit' });
106
+ } else {
107
+ // Other editors
108
+ execSync(`${editor} "${path}"`, { stdio: 'inherit' });
109
+ }
110
+ return true;
111
+ } catch (error) {
112
+ return false;
113
+ }
114
+ }
115
+
116
+ /**
117
+ * Command: proagents open <shortcut|path>
118
+ * Open ProAgents files quickly
119
+ */
120
+ export function openCommand(target, options = {}) {
121
+ const targetDir = process.cwd();
122
+
123
+ // If no target, show available shortcuts
124
+ if (!target) {
125
+ console.log(chalk.bold('\nProAgents Open - Quick File Access'));
126
+ console.log(chalk.gray('══════════════════════════════════════════════════════════\n'));
127
+
128
+ console.log(chalk.cyan('Usage:'));
129
+ console.log(chalk.white(' proagents open <shortcut>'));
130
+ console.log(chalk.white(' proagents open <file-path>\n'));
131
+
132
+ console.log(chalk.cyan('Shortcuts:'));
133
+ console.log(chalk.gray('─────────────────────────────────────────────────'));
134
+
135
+ const categories = {
136
+ 'Configuration': ['config', 'watchlist', 'standards', 'rules'],
137
+ 'Changelog & Logs': ['changelog', 'activity', 'context'],
138
+ 'AI & Workflow': ['instructions', 'commands', 'workflow'],
139
+ 'Learning': ['feedback', 'errors', 'decisions'],
140
+ 'Collaboration': ['handoff', 'features', 'worklog'],
141
+ };
142
+
143
+ for (const [category, shortcuts] of Object.entries(categories)) {
144
+ console.log(chalk.yellow(`\n ${category}:`));
145
+ for (const shortcut of shortcuts) {
146
+ const path = FILE_SHORTCUTS[shortcut];
147
+ if (path) {
148
+ const exists = existsSync(join(targetDir, path));
149
+ const status = exists ? chalk.green('✓') : chalk.gray('○');
150
+ console.log(` ${status} ${chalk.white(shortcut.padEnd(15))} → ${chalk.gray(path)}`);
151
+ }
152
+ }
153
+ }
154
+
155
+ console.log(chalk.gray('\n─────────────────────────────────────────────────'));
156
+ console.log(chalk.gray('Legend: ') + chalk.green('✓ exists ') + chalk.gray('○ not created yet\n'));
157
+ return;
158
+ }
159
+
160
+ // Check if target is a shortcut
161
+ let filePath = FILE_SHORTCUTS[target.toLowerCase()];
162
+
163
+ if (filePath) {
164
+ filePath = join(targetDir, filePath);
165
+ } else {
166
+ // Treat as direct path
167
+ filePath = target.startsWith('/') ? target : join(targetDir, target);
168
+ }
169
+
170
+ // Check if file/directory exists
171
+ if (!existsSync(filePath)) {
172
+ console.log(chalk.red(`\nFile not found: ${filePath}`));
173
+ console.log(chalk.gray('Run "proagents open" to see available shortcuts.\n'));
174
+ return;
175
+ }
176
+
177
+ // Open the file
178
+ console.log(chalk.cyan(`\nOpening: ${filePath}`));
179
+
180
+ const success = openInEditor(filePath);
181
+
182
+ if (success) {
183
+ console.log(chalk.green('✓ Opened in editor\n'));
184
+ } else {
185
+ console.log(chalk.yellow(`\nCould not open automatically.`));
186
+ console.log(chalk.gray(`Path: ${filePath}\n`));
187
+ }
188
+ }