@namch/agent-assistant 1.0.3 → 1.1.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.
Files changed (86) hide show
  1. package/CHANGELOG.md +78 -0
  2. package/README.md +1 -1
  3. package/agents/planner.md +59 -11
  4. package/agents/reporter.md +1 -1
  5. package/cli/install.js +514 -169
  6. package/code-assistants/antigravity-assistant/AntigravityGlobal.agent.md +38 -135
  7. package/code-assistants/antigravity-assistant/GEMINI.md +37 -137
  8. package/code-assistants/claude-assistant/CLAUDE.md +60 -38
  9. package/code-assistants/copilot-assistant/agent-assistant.agent.md +44 -125
  10. package/code-assistants/cursor-assistant/.cursorrules +42 -84
  11. package/code-assistants/cursor-assistant/rules/agent-assistant.mdc +37 -135
  12. package/commands/ask/fast.md +6 -4
  13. package/commands/ask/hard.md +6 -4
  14. package/commands/ask.md +3 -3
  15. package/commands/auto.md +3 -3
  16. package/commands/brainstorm/fast.md +6 -4
  17. package/commands/brainstorm/hard.md +6 -4
  18. package/commands/brainstorm.md +3 -3
  19. package/commands/code/fast.md +6 -4
  20. package/commands/code/focus.md +42 -46
  21. package/commands/code/hard.md +43 -48
  22. package/commands/code.md +6 -3
  23. package/commands/cook/fast.md +5 -3
  24. package/commands/cook/focus.md +22 -51
  25. package/commands/cook/hard.md +23 -55
  26. package/commands/cook.md +3 -3
  27. package/commands/debug/fast.md +5 -3
  28. package/commands/debug/focus.md +35 -40
  29. package/commands/debug/hard.md +38 -16
  30. package/commands/debug.md +3 -3
  31. package/commands/deploy/check.md +4 -4
  32. package/commands/deploy/preview.md +4 -4
  33. package/commands/deploy/production.md +4 -4
  34. package/commands/deploy/rollback.md +4 -4
  35. package/commands/deploy.md +3 -3
  36. package/commands/design/fast.md +6 -4
  37. package/commands/design/focus.md +28 -44
  38. package/commands/design/hard.md +53 -17
  39. package/commands/design.md +3 -3
  40. package/commands/docs/audit.md +5 -5
  41. package/commands/docs/business.md +5 -5
  42. package/commands/docs/core.md +5 -5
  43. package/commands/docs.md +3 -3
  44. package/commands/fix/fast.md +5 -3
  45. package/commands/fix/focus.md +36 -44
  46. package/commands/fix/hard.md +23 -37
  47. package/commands/fix.md +3 -3
  48. package/commands/plan/fast.md +6 -4
  49. package/commands/plan/focus.md +6 -4
  50. package/commands/plan/hard.md +6 -4
  51. package/commands/plan.md +3 -3
  52. package/commands/report/fast.md +6 -4
  53. package/commands/report/focus.md +6 -4
  54. package/commands/report/hard.md +6 -4
  55. package/commands/report.md +3 -3
  56. package/commands/review/fast.md +5 -3
  57. package/commands/review/hard.md +5 -3
  58. package/commands/review.md +3 -3
  59. package/commands/test/fast.md +5 -3
  60. package/commands/test/focus.md +24 -43
  61. package/commands/test/hard.md +24 -16
  62. package/commands/test.md +3 -3
  63. package/documents/HSOL-ASSESSMENT.md +121 -0
  64. package/documents/SMART-SKILL-ORCHESTRATION-BLUEPRINT.md +1341 -0
  65. package/documents/business/business-glossary.md +6 -6
  66. package/documents/knowledge-architecture.md +81 -1
  67. package/documents/knowledge-domain.md +4 -3
  68. package/documents/knowledge-overview.md +1 -1
  69. package/documents/knowledge-source-base.md +15 -10
  70. package/package.json +5 -3
  71. package/rules/AGENTS.md +187 -0
  72. package/rules/CONTEXT-GATE.md +362 -0
  73. package/rules/CORE.md +175 -0
  74. package/rules/ERRORS.md +127 -0
  75. package/rules/PHASES.md +156 -0
  76. package/rules/REFERENCE.md +179 -0
  77. package/rules/SKILLS.md +167 -0
  78. package/skills/find-skills/SKILL.md +137 -0
  79. package/rules/ADAPTIVE-EXECUTION.md +0 -271
  80. package/rules/AGENT-RULES.md +0 -285
  81. package/rules/BOOTSTRAP.md +0 -301
  82. package/rules/ERROR-RECOVERY.md +0 -201
  83. package/rules/EXECUTION-PROTOCOL.md +0 -485
  84. package/rules/ORCHESTRATION-LAWS.md +0 -218
  85. package/rules/QUICK-REFERENCE.md +0 -204
  86. package/rules/SKILL-DISCOVERY.md +0 -370
package/cli/install.js CHANGED
@@ -7,12 +7,19 @@
7
7
  * - Cursor
8
8
  * - GitHub Copilot
9
9
  * - Antigravity (Gemini)
10
+ * - Claude Code
10
11
  *
11
12
  * Usage:
12
13
  * npx agent-assistant install [tool]
13
14
  * npx agent-assistant install --all
14
15
  * npx agent-assistant uninstall [tool]
15
16
  * npx agent-assistant list
17
+ *
18
+ * Features:
19
+ * - Real-time progress bar with file count
20
+ * - Verification phase to ensure all files are written
21
+ * - Proper file system sync for reliability
22
+ * - Summary report with statistics
16
23
  */
17
24
 
18
25
  const fs = require('node:fs');
@@ -162,13 +169,144 @@ const BUNDLED_AGENTS = [
162
169
  // Utility Functions
163
170
  // ============================================================================
164
171
 
172
+ /**
173
+ * Progress tracking state
174
+ */
175
+ const progressState = {
176
+ total: 0,
177
+ current: 0,
178
+ phase: '',
179
+ errors: [],
180
+ startTime: 0,
181
+ copiedFiles: [],
182
+ removedPaths: [],
183
+ lastDraw: 0, // Throttle draws
184
+ lastPercent: -1 // Track last drawn percent
185
+ };
186
+
187
+ // Check if stdout is a TTY (interactive terminal)
188
+ const isTTY = process.stdout.isTTY;
189
+
190
+ /**
191
+ * Reset progress state for new operation
192
+ */
193
+ function resetProgress() {
194
+ progressState.total = 0;
195
+ progressState.current = 0;
196
+ progressState.phase = '';
197
+ progressState.errors = [];
198
+ progressState.startTime = Date.now();
199
+ progressState.copiedFiles = [];
200
+ progressState.removedPaths = [];
201
+ progressState.lastDraw = 0;
202
+ progressState.lastPercent = -1;
203
+ }
204
+
205
+ /**
206
+ * Count total files in a directory (for progress estimation)
207
+ */
208
+ function countFiles(dir) {
209
+ if (!fs.existsSync(dir)) return 0;
210
+ let count = 0;
211
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
212
+ for (const entry of entries) {
213
+ if (entry.name.startsWith('.') || entry.name === 'node_modules') continue;
214
+ if (entry.isSymbolicLink()) continue;
215
+ const fullPath = path.join(dir, entry.name);
216
+ if (entry.isDirectory()) {
217
+ count += countFiles(fullPath);
218
+ } else {
219
+ count++;
220
+ }
221
+ }
222
+ return count;
223
+ }
224
+
225
+ /**
226
+ * Draw progress bar in terminal (real-time single line update)
227
+ * @param {number} current - Current progress
228
+ * @param {number} total - Total items
229
+ * @param {boolean} force - Force draw regardless of throttle
230
+ */
231
+ function drawProgress(current, total, force = false) {
232
+ if (total === 0) return;
233
+
234
+ const percent = Math.min(100, Math.round((current / total) * 100));
235
+ const now = Date.now();
236
+
237
+ // Throttle: only draw every 50ms OR when percent changes OR forced
238
+ if (!force && percent === progressState.lastPercent && (now - progressState.lastDraw) < 50) {
239
+ return;
240
+ }
241
+
242
+ progressState.lastDraw = now;
243
+ progressState.lastPercent = percent;
244
+
245
+ const width = 40;
246
+ const filled = Math.round((percent / 100) * width);
247
+ const empty = width - filled;
248
+
249
+ // Unicode progress bar characters
250
+ const filledChar = '█';
251
+ const emptyChar = '░';
252
+
253
+ const bar = filledChar.repeat(filled) + emptyChar.repeat(empty);
254
+ const stats = `${current.toLocaleString()}/${total.toLocaleString()}`;
255
+ const elapsed = ((now - progressState.startTime) / 1000).toFixed(1);
256
+
257
+ const line = ` ${bar} ${percent}% (${stats}) ${elapsed}s`;
258
+
259
+ if (isTTY) {
260
+ // Real TTY: clear line and rewrite on same line
261
+ process.stdout.clearLine(0);
262
+ process.stdout.cursorTo(0);
263
+ process.stdout.write(line);
264
+ } else {
265
+ // Non-TTY (piped): only print on percent milestones
266
+ if (percent % 10 === 0 && percent !== progressState.lastPercent) {
267
+ console.log(line);
268
+ }
269
+ }
270
+ }
271
+
272
+ /**
273
+ * Update progress counter (no draw - for batch updates)
274
+ */
275
+ function updateProgress(phase) {
276
+ progressState.current++;
277
+ progressState.phase = phase;
278
+ drawProgress(progressState.current, progressState.total);
279
+ }
280
+
281
+ /**
282
+ * Complete progress bar and move to next line
283
+ */
284
+ function completeProgress() {
285
+ if (progressState.total > 0) {
286
+ drawProgress(progressState.total, progressState.total, true);
287
+ console.log(''); // New line after progress bar
288
+ }
289
+ }
290
+
291
+ /**
292
+ * Log error to progress state
293
+ */
294
+ function logError(operation, path, error) {
295
+ progressState.errors.push({
296
+ operation,
297
+ path,
298
+ error: error.message || String(error),
299
+ timestamp: new Date().toISOString()
300
+ });
301
+ }
302
+
165
303
  function ensureDir(dir) {
166
304
  if (!fs.existsSync(dir)) {
167
305
  fs.mkdirSync(dir, { recursive: true });
168
306
  }
169
307
  }
170
308
 
171
- function copyWithReplace(src, dest, replacements = {}) {
309
+ function copyWithReplace(src, dest, replacements = {}, trackProgress = true) {
172
310
  if (!fs.existsSync(src)) return 0;
173
311
  ensureDir(dest);
174
312
  let count = 0;
@@ -180,7 +318,9 @@ function copyWithReplace(src, dest, replacements = {}) {
180
318
 
181
319
  // Skip symbolic links for security (prevents path traversal attacks)
182
320
  if (entry.isSymbolicLink()) {
183
- console.log(` ⚠️ Skipping symlink: ${entry.name}`);
321
+ if (process.env.DEBUG) {
322
+ console.log(` ⚠️ Skipping symlink: ${entry.name}`);
323
+ }
184
324
  continue;
185
325
  }
186
326
 
@@ -188,55 +328,118 @@ function copyWithReplace(src, dest, replacements = {}) {
188
328
  const destPath = path.join(dest, entry.name);
189
329
 
190
330
  if (entry.isDirectory()) {
191
- count += copyWithReplace(srcPath, destPath, replacements);
331
+ count += copyWithReplace(srcPath, destPath, replacements, trackProgress);
192
332
  } else {
193
- // Apply replacements for text files
194
- const textExtensions = ['.md', '.txt', '.json', '.mdc', '.yaml', '.yml'];
195
- const ext = path.extname(entry.name).toLowerCase();
333
+ try {
334
+ // Apply replacements for text files
335
+ const textExtensions = ['.md', '.txt', '.json', '.mdc', '.yaml', '.yml'];
336
+ const ext = path.extname(entry.name).toLowerCase();
196
337
 
197
- if (textExtensions.includes(ext)) {
198
- try {
338
+ if (textExtensions.includes(ext)) {
199
339
  let content = fs.readFileSync(srcPath, 'utf8');
200
340
  // Sort keys by length (longer first) to prevent partial replacements
201
341
  const keys = Object.keys(replacements).sort((a, b) => b.length - a.length);
202
342
  for (const search of keys) {
203
343
  content = content.replaceAll(search, replacements[search]);
204
344
  }
205
- fs.writeFileSync(destPath, content);
206
- } catch (e) {
207
- // Log warning but continue with binary copy as fallback
208
- if (process.env.DEBUG) {
209
- console.warn(` ⚠️ Could not process ${entry.name} as text, copying as binary`);
210
- }
345
+ // Write with fsync for reliability
346
+ const fd = fs.openSync(destPath, 'w');
347
+ fs.writeSync(fd, content);
348
+ fs.fsyncSync(fd);
349
+ fs.closeSync(fd);
350
+ } else {
211
351
  fs.copyFileSync(srcPath, destPath);
212
352
  }
213
- } else {
214
- fs.copyFileSync(srcPath, destPath);
353
+
354
+ // Track copied file for verification
355
+ progressState.copiedFiles.push(destPath);
356
+
357
+ // Update progress
358
+ if (trackProgress) {
359
+ updateProgress(entry.name);
360
+ }
361
+
362
+ count++;
363
+ } catch (e) {
364
+ logError('copy', srcPath, e);
365
+ if (process.env.DEBUG) {
366
+ console.warn(`\n ⚠️ Could not copy ${entry.name}: ${e.message}`);
367
+ }
215
368
  }
216
- count++;
217
369
  }
218
370
  }
219
371
  return count;
220
372
  }
221
373
 
222
- function copyFileWithReplace(src, dest, replacements = {}) {
374
+ function copyFileWithReplace(src, dest, replacements = {}, trackProgress = true) {
223
375
  if (!fs.existsSync(src)) return false;
224
376
 
225
377
  ensureDir(path.dirname(dest));
226
378
 
227
- let content = fs.readFileSync(src, 'utf8');
228
- const keys = Object.keys(replacements).sort((a, b) => b.length - a.length);
229
- for (const search of keys) {
230
- content = content.replaceAll(search, replacements[search]);
379
+ try {
380
+ let content = fs.readFileSync(src, 'utf8');
381
+ const keys = Object.keys(replacements).sort((a, b) => b.length - a.length);
382
+ for (const search of keys) {
383
+ content = content.replaceAll(search, replacements[search]);
384
+ }
385
+
386
+ // Write with fsync for reliability
387
+ const fd = fs.openSync(dest, 'w');
388
+ fs.writeSync(fd, content);
389
+ fs.fsyncSync(fd);
390
+ fs.closeSync(fd);
391
+
392
+ // Track copied file for verification
393
+ progressState.copiedFiles.push(dest);
394
+
395
+ // Update progress
396
+ if (trackProgress) {
397
+ updateProgress(path.basename(dest));
398
+ }
399
+
400
+ return true;
401
+ } catch (e) {
402
+ logError('copy', src, e);
403
+ if (process.env.DEBUG) {
404
+ console.warn(`\n ⚠️ Could not copy ${path.basename(src)}: ${e.message}`);
405
+ }
406
+ return false;
231
407
  }
232
- fs.writeFileSync(dest, content);
233
- return true;
234
408
  }
235
409
 
236
- function removeDir(dir) {
410
+ function removeDir(dir, trackProgress = true) {
237
411
  if (fs.existsSync(dir)) {
238
- fs.rmSync(dir, { recursive: true, force: true });
239
- return true;
412
+ try {
413
+ fs.rmSync(dir, { recursive: true, force: true });
414
+ progressState.removedPaths.push(dir);
415
+ if (trackProgress) {
416
+ updateProgress(`Removed ${path.basename(dir)}`);
417
+ }
418
+ return true;
419
+ } catch (e) {
420
+ logError('remove', dir, e);
421
+ return false;
422
+ }
423
+ }
424
+ return false;
425
+ }
426
+
427
+ /**
428
+ * Remove a single file with tracking
429
+ */
430
+ function removeFile(filePath, trackProgress = true) {
431
+ if (fs.existsSync(filePath)) {
432
+ try {
433
+ fs.unlinkSync(filePath);
434
+ progressState.removedPaths.push(filePath);
435
+ if (trackProgress) {
436
+ updateProgress(`Removed ${path.basename(filePath)}`);
437
+ }
438
+ return true;
439
+ } catch (e) {
440
+ logError('remove', filePath, e);
441
+ return false;
442
+ }
240
443
  }
241
444
  return false;
242
445
  }
@@ -245,29 +448,145 @@ function formatNumber(num) {
245
448
  return num.toLocaleString();
246
449
  }
247
450
 
451
+ /**
452
+ * Estimate total files for installation
453
+ */
454
+ function estimateInstallFiles() {
455
+ let total = 0;
456
+
457
+ // Count files in core directories
458
+ for (const dir of CORE_DIRS) {
459
+ const srcDir = path.join(ROOT, dir);
460
+ total += countFiles(srcDir);
461
+ }
462
+
463
+ // Count skills
464
+ const skillsDir = path.join(ROOT, 'skills');
465
+ total += countFiles(skillsDir);
466
+
467
+ // Count agents
468
+ const agentsDir = path.join(ROOT, 'agents');
469
+ total += countFiles(agentsDir);
470
+
471
+ // Commands (copied twice - once to commands, once to workflows for backward compat)
472
+ const commandsDir = path.join(ROOT, 'commands');
473
+ total += countFiles(commandsDir) * 2;
474
+
475
+ // Root files
476
+ total += ROOT_FILES.length;
477
+
478
+ // Config files (estimate)
479
+ total += 5;
480
+
481
+ return total;
482
+ }
483
+
484
+ /**
485
+ * Verify installation by checking copied files exist
486
+ * @returns {Object} Verification result
487
+ */
488
+ function verifyInstallation() {
489
+ const verified = [];
490
+ const failed = [];
491
+
492
+ for (const filePath of progressState.copiedFiles) {
493
+ if (fs.existsSync(filePath)) {
494
+ verified.push(filePath);
495
+ } else {
496
+ failed.push(filePath);
497
+ }
498
+ }
499
+
500
+ return {
501
+ total: progressState.copiedFiles.length,
502
+ verified: verified.length,
503
+ failed: failed.length,
504
+ failedPaths: failed,
505
+ success: failed.length === 0
506
+ };
507
+ }
508
+
509
+ /**
510
+ * Print summary report
511
+ */
512
+ function printSummary(toolName, operation = 'install') {
513
+ const duration = ((Date.now() - progressState.startTime) / 1000).toFixed(2);
514
+ const verification = operation === 'install' ? verifyInstallation() : null;
515
+
516
+ console.log('\n' + '─'.repeat(60));
517
+ console.log(`📊 ${operation === 'install' ? 'Installation' : 'Uninstallation'} Summary`);
518
+ console.log('─'.repeat(60));
519
+
520
+ if (operation === 'install') {
521
+ console.log(` Tool: ${toolName}`);
522
+ console.log(` Files: ${formatNumber(progressState.copiedFiles.length)} copied`);
523
+ console.log(` Duration: ${duration}s`);
524
+
525
+ if (verification) {
526
+ console.log(` Verified: ${verification.verified}/${verification.total} files`);
527
+ if (verification.failed > 0) {
528
+ console.log(` ⚠️ Failed: ${verification.failed} files`);
529
+ verification.failedPaths.slice(0, 5).forEach(p => {
530
+ console.log(` - ${p}`);
531
+ });
532
+ if (verification.failedPaths.length > 5) {
533
+ console.log(` ... and ${verification.failedPaths.length - 5} more`);
534
+ }
535
+ }
536
+ }
537
+ } else {
538
+ console.log(` Tool: ${toolName}`);
539
+ console.log(` Removed: ${formatNumber(progressState.removedPaths.length)} paths`);
540
+ console.log(` Duration: ${duration}s`);
541
+ }
542
+
543
+ if (progressState.errors.length > 0) {
544
+ console.log(` ⚠️ Errors: ${progressState.errors.length}`);
545
+ progressState.errors.slice(0, 3).forEach(e => {
546
+ console.log(` - ${e.operation}: ${path.basename(e.path)} (${e.error})`);
547
+ });
548
+ if (progressState.errors.length > 3) {
549
+ console.log(` ... and ${progressState.errors.length - 3} more`);
550
+ }
551
+ }
552
+
553
+ console.log('─'.repeat(60));
554
+
555
+ if (operation === 'install' && verification && verification.success && progressState.errors.length === 0) {
556
+ console.log('✅ Installation completed successfully!');
557
+ } else if (operation === 'uninstall' && progressState.errors.length === 0) {
558
+ console.log('✅ Uninstallation completed successfully!');
559
+ } else {
560
+ console.log('⚠️ Operation completed with warnings. Check errors above.');
561
+ }
562
+ }
563
+
248
564
  // ============================================================================
249
565
  // Installation Functions
250
566
  // ============================================================================
251
567
 
252
568
  function installCursor() {
253
569
  const tool = TOOLS.cursor;
254
- console.log(`\n📦 Installing Agent Assistant for ${tool.name}...\n`);
570
+
571
+ // Reset and estimate progress
572
+ resetProgress();
573
+ progressState.total = estimateInstallFiles();
574
+
575
+ console.log(`\n📦 Installing Agent Assistant for ${tool.name}...`);
576
+ console.log(` Estimated files: ~${formatNumber(progressState.total)}\n`);
255
577
 
256
578
  let total = 0;
257
579
 
258
580
  // --- 1. INSTALL EDITOR CONFIG (~/.cursor) ---
259
581
  // 1.1 Global MDCs (Rules)
260
- console.log(' 1. Installing global rules (MDC files)...');
261
582
  if (tool.assets.rules && fs.existsSync(tool.assets.rules)) {
262
583
  total += copyWithReplace(tool.assets.rules, tool.paths.rules, tool.replacements);
263
584
  }
264
585
 
265
586
  // 1.2 Global Commands (Suggestions)
266
- console.log(' 2. Installing global commands...');
267
587
  total += copyWithReplace(path.join(ROOT, 'commands'), tool.paths.commands, tool.replacements);
268
588
 
269
589
  // --- 1.2 Global Config Files (CURSOR.md, AGENT.md, CLAUDE.md) ---
270
- console.log(' 2.1 Installing global config files...');
271
590
  // We want CURSOR.md, AGENT.md, CLAUDE.md in ~/.cursor/
272
591
  // .cursorrules from extension becomes CURSOR.md
273
592
  if (tool.assets.cursorRules && fs.existsSync(tool.assets.cursorRules)) {
@@ -286,8 +605,6 @@ function installCursor() {
286
605
  }
287
606
 
288
607
  // --- 2. INSTALL EXTENSION BRAIN (~/.cursor/skills/agent-assistant) ---
289
- console.log(' 3. Installing core framework...');
290
-
291
608
  // Clean install - remove old framework
292
609
  if (fs.existsSync(tool.paths.agentAssistant)) {
293
610
  fs.rmSync(tool.paths.agentAssistant, { recursive: true, force: true });
@@ -319,44 +636,51 @@ function installCursor() {
319
636
  }
320
637
 
321
638
  // --- 3. INSTALL USER SKILLS (~/.cursor/skills/) ---
322
- console.log(' 4. Installing skills...');
323
639
  total += copyWithReplace(path.join(ROOT, 'skills'), tool.paths.skills, tool.replacements);
324
640
 
325
641
  // --- 4. NATIVE SUBAGENT SUPPORT (~/.cursor/agents/) ---
326
- console.log(' 5. Installing native agents...');
327
642
  // Only copy bundled agents (merge/update)
328
643
  total += copyWithReplace(path.join(ROOT, 'agents'), tool.paths.agents, tool.replacements);
329
644
 
330
- console.log(`\n✅ ${tool.name}: ${formatNumber(total)} files installed`);
331
- console.log(` Rules: ${tool.paths.rules}`);
332
- console.log(` Commands: ${tool.paths.commands}`);
333
- console.log(` Core Framework: ${tool.paths.agentAssistant}`);
334
- console.log(` Skills: ${tool.paths.skills}`);
335
- console.log(` Native Agents: ${tool.paths.agents}`);
645
+ // Complete progress bar
646
+ completeProgress();
647
+
648
+ // Print summary with verification
649
+ printSummary(tool.name, 'install');
650
+
651
+ console.log(`\n 📁 Paths:`);
652
+ console.log(` Rules: ${tool.paths.rules}`);
653
+ console.log(` Commands: ${tool.paths.commands}`);
654
+ console.log(` Core Framework: ${tool.paths.agentAssistant}`);
655
+ console.log(` Skills: ${tool.paths.skills}`);
656
+ console.log(` Native Agents: ${tool.paths.agents}`);
336
657
 
337
658
  return total;
338
659
  }
339
660
 
340
661
  function installCopilot() {
341
662
  const tool = TOOLS.copilot;
342
- console.log(`\n📦 Installing Agent Assistant for ${tool.name}...\n`);
663
+
664
+ // Reset and estimate progress
665
+ resetProgress();
666
+ progressState.total = estimateInstallFiles();
667
+
668
+ console.log(`\n📦 Installing Agent Assistant for ${tool.name}...`);
669
+ console.log(` Estimated files: ~${formatNumber(progressState.total)}\n`);
343
670
 
344
671
  let total = 0;
345
672
 
346
673
  // --- 1. INSTALL TO VS CODE PROMPTS & GLOBAL CONFIG ---
347
- console.log(' 1. Installing agent definitions...');
348
674
  if (tool.assets.agentFile && fs.existsSync(tool.assets.agentFile)) {
349
675
  // 1.1 Custom Prompt (VS Code) -> agent-assistant.agent.md
350
676
  ensureDir(tool.paths.vsCodePrompts);
351
677
  const promptDest = path.join(tool.paths.vsCodePrompts, 'agent-assistant.agent.md');
352
678
  if (copyFileWithReplace(tool.assets.agentFile, promptDest, tool.replacements)) {
353
679
  total++;
354
- console.log(` → Custom Prompt: ${promptDest}`);
355
680
  }
356
681
  }
357
682
 
358
683
  // --- 1.2 Global Config Files (COPILOT.md, AGENT.md, CLAUDE.md) ---
359
- console.log(' 1.2 Installing global config files...');
360
684
  ensureDir(tool.paths.home);
361
685
  const globalFiles = ['COPILOT.md', 'AGENT.md', 'CLAUDE.md'];
362
686
  for (const file of globalFiles) {
@@ -365,14 +689,11 @@ function installCopilot() {
365
689
  if (fs.existsSync(src)) {
366
690
  if (copyFileWithReplace(src, dest, tool.replacements)) {
367
691
  total++;
368
- console.log(` → ${file}: ${dest}`);
369
692
  }
370
693
  }
371
694
  }
372
695
 
373
696
  // --- 2. INSTALL CORE FRAMEWORK (~/.copilot/skills/agent-assistant) ---
374
- console.log(' 2. Installing core framework...');
375
-
376
697
  // Clean install - remove old framework
377
698
  if (fs.existsSync(tool.paths.agentAssistant)) {
378
699
  fs.rmSync(tool.paths.agentAssistant, { recursive: true, force: true });
@@ -388,7 +709,6 @@ function installCopilot() {
388
709
  }
389
710
 
390
711
  // Install commands to ~/.copilot/commands
391
- console.log(' 2.1 Installing commands...');
392
712
  if (fs.existsSync(path.join(ROOT, 'commands'))) {
393
713
  ensureDir(tool.paths.commands);
394
714
  total += copyWithReplace(path.join(ROOT, 'commands'), tool.paths.commands, tool.replacements);
@@ -411,38 +731,42 @@ function installCopilot() {
411
731
  }
412
732
 
413
733
  // --- 3. INSTALL USER SKILLS (~/.copilot/skills/) ---
414
- console.log(' 3. Installing skills...');
415
734
  total += copyWithReplace(path.join(ROOT, 'skills'), tool.paths.skills, tool.replacements);
416
735
 
417
736
  // --- 4. NATIVE SUBAGENT SUPPORT (~/.copilot/agents/) ---
418
- console.log(' 4. Installing native agents...');
419
- // We overwrite/update user agents on install as per user request (sync logic)
420
- // But typically we'd just ensure dir.
421
- // The previous logic for other tools was just copy.
422
- // For copilot, we want agents in ~/.copilot/agents
423
737
  ensureDir(tool.paths.agents);
424
738
  total += copyWithReplace(path.join(ROOT, 'agents'), tool.paths.agents, tool.replacements);
425
739
 
426
- console.log(`\n✅ ${tool.name}: ${formatNumber(total)} files installed`);
427
- console.log(` VS Code Prompts: ${tool.paths.vsCodePrompts}`);
428
- console.log(` Global Config: ${tool.paths.home}`);
429
- console.log(` Commands: ${tool.paths.commands}`);
430
- console.log(` Core Framework: ${tool.paths.agentAssistant}`);
431
- console.log(` Skills: ${tool.paths.skills}`);
432
- console.log(` Native Agents: ${tool.paths.agents}`);
740
+ // Complete progress bar
741
+ completeProgress();
742
+
743
+ // Print summary with verification
744
+ printSummary(tool.name, 'install');
745
+
746
+ console.log(`\n 📁 Paths:`);
747
+ console.log(` VS Code Prompts: ${tool.paths.vsCodePrompts}`);
748
+ console.log(` Global Config: ${tool.paths.home}`);
749
+ console.log(` Commands: ${tool.paths.commands}`);
750
+ console.log(` Core Framework: ${tool.paths.agentAssistant}`);
751
+ console.log(` Skills: ${tool.paths.skills}`);
752
+ console.log(` Native Agents: ${tool.paths.agents}`);
433
753
 
434
754
  return total;
435
755
  }
436
756
 
437
757
  function installAntigravity() {
438
758
  const tool = TOOLS.antigravity;
439
- console.log(`\n📦 Installing Agent Assistant for ${tool.name}...\n`);
759
+
760
+ // Reset and estimate progress
761
+ resetProgress();
762
+ progressState.total = estimateInstallFiles() * 1.5; // Antigravity has more destinations
763
+
764
+ console.log(`\n📦 Installing Agent Assistant for ${tool.name}...`);
765
+ console.log(` Estimated files: ~${formatNumber(Math.round(progressState.total))}\n`);
440
766
 
441
767
  let total = 0;
442
768
 
443
769
  // --- 1. INSTALL EDITOR CONFIG (~/.antigravity) ---
444
- console.log(' 1. Installing editor config (~/.antigravity)...');
445
-
446
770
  // 1.1 Workflows (from commands) -> ~/.antigravity/workflows
447
771
  ensureDir(tool.paths.workflows);
448
772
  total += copyWithReplace(path.join(ROOT, 'commands'), tool.paths.workflows, tool.replacements);
@@ -453,7 +777,6 @@ function installAntigravity() {
453
777
 
454
778
 
455
779
  // --- 2. INSTALL PLATFORM CONFIG (~/.gemini) ---
456
- console.log(' 2. Installing platform config (~/.gemini)...');
457
780
  ensureDir(tool.paths.gemini);
458
781
 
459
782
  // 2.1 GEMINI.md
@@ -475,11 +798,19 @@ function installAntigravity() {
475
798
 
476
799
  if (existingContent.includes(MARKER_START)) {
477
800
  const regex = new RegExp(`${MARKER_START}[\\s\\S]*?${MARKER_END}`, 'g');
478
- fs.writeFileSync(destFile, existingContent.replace(regex, wrappedContent));
801
+ const fd = fs.openSync(destFile, 'w');
802
+ fs.writeSync(fd, existingContent.replace(regex, wrappedContent));
803
+ fs.fsyncSync(fd);
804
+ fs.closeSync(fd);
479
805
  } else {
480
806
  const separator = existingContent.trim() === '' ? '' : '\n\n';
481
- fs.writeFileSync(destFile, existingContent + separator + wrappedContent);
807
+ const fd = fs.openSync(destFile, 'w');
808
+ fs.writeSync(fd, existingContent + separator + wrappedContent);
809
+ fs.fsyncSync(fd);
810
+ fs.closeSync(fd);
482
811
  }
812
+ progressState.copiedFiles.push(destFile);
813
+ updateProgress('GEMINI.md');
483
814
  total++;
484
815
  }
485
816
 
@@ -494,7 +825,6 @@ function installAntigravity() {
494
825
  }
495
826
 
496
827
  // 2.3 Global Agents (~/.gemini/agents)
497
- console.log(' 2.3 Installing global agents...');
498
828
  ensureDir(tool.paths.globalAgents);
499
829
 
500
830
  // AntigravityGlobal.agent.md
@@ -508,14 +838,11 @@ function installAntigravity() {
508
838
 
509
839
 
510
840
  // --- 3. INSTALL EXTENSION BRAIN (~/.gemini/antigravity) ---
511
- console.log(' 3. Installing extension brain...');
512
-
513
841
  // 3.1 Global Workflows (~/.gemini/antigravity/global_workflows)
514
842
  ensureDir(tool.paths.globalWorkflows);
515
843
  total += copyWithReplace(path.join(ROOT, 'commands'), tool.paths.globalWorkflows, tool.replacements);
516
844
 
517
845
  // 3.2 Core Framework (~/.gemini/antigravity/skills/agent-assistant)
518
- console.log(' 3.2 Installing core framework...');
519
846
  if (fs.existsSync(tool.paths.agentAssistant)) {
520
847
  fs.rmSync(tool.paths.agentAssistant, { recursive: true, force: true });
521
848
  }
@@ -542,25 +869,35 @@ function installAntigravity() {
542
869
  }
543
870
 
544
871
  // 3.3 Skills (~/.gemini/antigravity/skills)
545
- console.log(' 3.3 Installing skills...');
546
872
  total += copyWithReplace(path.join(ROOT, 'skills'), tool.paths.skills, tool.replacements);
547
873
 
548
- console.log(`\n✅ ${tool.name}: ${formatNumber(total)} files installed`);
549
- console.log(` Editor Config: ${tool.paths.editorHome}`);
550
- console.log(` Platform Config: ${tool.paths.gemini}`);
551
- console.log(` Extension Brain: ${tool.paths.antigravity}`);
874
+ // Complete progress bar
875
+ completeProgress();
876
+
877
+ // Print summary with verification
878
+ printSummary(tool.name, 'install');
879
+
880
+ console.log(`\n 📁 Paths:`);
881
+ console.log(` Editor Config: ${tool.paths.editorHome}`);
882
+ console.log(` Platform Config: ${tool.paths.gemini}`);
883
+ console.log(` Extension Brain: ${tool.paths.antigravity}`);
552
884
 
553
885
  return total;
554
886
  }
555
887
 
556
888
  function installClaude() {
557
889
  const tool = TOOLS.claude;
558
- console.log(`\n📦 Installing Agent Assistant for ${tool.name}...\n`);
890
+
891
+ // Reset and estimate progress
892
+ resetProgress();
893
+ progressState.total = estimateInstallFiles();
894
+
895
+ console.log(`\n📦 Installing Agent Assistant for ${tool.name}...`);
896
+ console.log(` Estimated files: ~${formatNumber(progressState.total)}\n`);
559
897
 
560
898
  let total = 0;
561
899
 
562
900
  // --- 1. INSTALL GLOBAL CONFIG (~/.claude) ---
563
- console.log(' 1. Installing global config...');
564
901
  ensureDir(tool.paths.home);
565
902
 
566
903
  // 1.1 CLAUDE.md (Global Instructions)
@@ -570,17 +907,14 @@ function installClaude() {
570
907
  }
571
908
 
572
909
  // 1.2 Commands (~/.claude/commands)
573
- console.log(' 1.2 Installing commands...');
574
910
  ensureDir(tool.paths.commands);
575
911
  total += copyWithReplace(path.join(ROOT, 'commands'), tool.paths.commands, tool.replacements);
576
912
 
577
913
  // 1.3 Native Agents (~/.claude/agents)
578
- console.log(' 1.3 Installing native agents...');
579
914
  ensureDir(tool.paths.agents);
580
915
  total += copyWithReplace(path.join(ROOT, 'agents'), tool.paths.agents, tool.replacements);
581
916
 
582
917
  // --- 2. INSTALL CORE FRAMEWORK (~/.claude/skills/agent-assistant) ---
583
- console.log(' 2. Installing core framework...');
584
918
  if (fs.existsSync(tool.paths.agentAssistant)) {
585
919
  fs.rmSync(tool.paths.agentAssistant, { recursive: true, force: true });
586
920
  }
@@ -608,13 +942,18 @@ function installClaude() {
608
942
  }
609
943
 
610
944
  // --- 3. INSTALL SKILLS (~/.claude/skills) ---
611
- console.log(' 3. Installing skills...');
612
945
  total += copyWithReplace(path.join(ROOT, 'skills'), tool.paths.skills, tool.replacements);
613
946
 
614
- console.log(`\n✅ ${tool.name}: ${formatNumber(total)} files installed`);
615
- console.log(` Home: ${tool.paths.home}`);
616
- console.log(` Commands: ${tool.paths.commands}`);
617
- console.log(` Skills: ${tool.paths.skills}`);
947
+ // Complete progress bar
948
+ completeProgress();
949
+
950
+ // Print summary with verification
951
+ printSummary(tool.name, 'install');
952
+
953
+ console.log(`\n 📁 Paths:`);
954
+ console.log(` Home: ${tool.paths.home}`);
955
+ console.log(` Commands: ${tool.paths.commands}`);
956
+ console.log(` Skills: ${tool.paths.skills}`);
618
957
 
619
958
  return total;
620
959
  }
@@ -630,12 +969,8 @@ function removeBundledAgents(agentsDir) {
630
969
  for (const agentFile of BUNDLED_AGENTS) {
631
970
  const agentPath = path.join(agentsDir, agentFile);
632
971
  if (fs.existsSync(agentPath)) {
633
- try {
634
- fs.unlinkSync(agentPath);
635
- console.log(` ✓ Removed bundled agent: ${agentFile}`);
972
+ if (removeFile(agentPath)) {
636
973
  removed++;
637
- } catch (e) {
638
- console.error(` ✗ Failed to remove: ${agentPath}`);
639
974
  }
640
975
  }
641
976
  }
@@ -644,10 +979,7 @@ function removeBundledAgents(agentsDir) {
644
979
  try {
645
980
  const remaining = fs.readdirSync(agentsDir);
646
981
  if (remaining.length === 0) {
647
- fs.rmdirSync(agentsDir);
648
- console.log(` ✓ Removed empty agents folder`);
649
- } else {
650
- console.log(` ℹ Kept ${remaining.length} user-custom agents`);
982
+ removeDir(agentsDir, false);
651
983
  }
652
984
  } catch (e) {
653
985
  // Ignore
@@ -658,12 +990,17 @@ function removeBundledAgents(agentsDir) {
658
990
 
659
991
  function uninstallCursor() {
660
992
  const tool = TOOLS.cursor;
661
- console.log(`\n🗑️ Uninstalling Agent Assistant from ${tool.name}...\n`);
993
+
994
+ // Reset progress - estimate items to remove
995
+ resetProgress();
996
+ progressState.total = 10; // Approximate count of remove operations
997
+
998
+ console.log(`\n🗑️ Uninstalling Agent Assistant from ${tool.name}...`);
999
+ console.log(` This will remove the framework while preserving user skills.\n`);
662
1000
 
663
1001
  let removed = 0;
664
1002
 
665
1003
  // 1. Remove Rules & Global Configs
666
- console.log(' 1. Removing rules and global configs...');
667
1004
  const filesToRemove = [
668
1005
  path.join(tool.paths.rules, 'agent-assistant.mdc'),
669
1006
  path.join(tool.paths.editorHome, 'CURSOR.md'),
@@ -672,199 +1009,192 @@ function uninstallCursor() {
672
1009
  ];
673
1010
 
674
1011
  for (const file of filesToRemove) {
675
- if (fs.existsSync(file)) {
676
- try {
677
- fs.unlinkSync(file);
678
- console.log(` ✓ Removed: ${file}`);
679
- removed++;
680
- } catch (e) {
681
- console.error(` ✗ Failed to remove: ${file}`, e);
682
- }
1012
+ if (removeFile(file)) {
1013
+ removed++;
683
1014
  }
684
1015
  }
685
1016
 
686
1017
  // 2. Remove Commands (Entire folder)
687
- console.log(' 2. Removing commands...');
688
1018
  if (removeDir(tool.paths.commands)) {
689
- console.log(` ✓ Removed: ${tool.paths.commands}`);
690
1019
  removed++;
691
1020
  }
692
1021
 
693
1022
  // 3. Remove Core Framework
694
- console.log(' 3. Removing core framework...');
695
1023
  if (removeDir(tool.paths.agentAssistant)) {
696
- console.log(` ✓ Removed: ${tool.paths.agentAssistant}`);
697
1024
  removed++;
698
1025
  }
699
1026
 
700
1027
  // 4. Remove Native Agents (Entire folder)
701
- console.log(' 4. Removing native agents...');
702
1028
  if (removeDir(tool.paths.agents)) {
703
- console.log(` ✓ Removed: ${tool.paths.agents}`);
704
1029
  removed++;
705
1030
  }
706
1031
 
707
- // Note: User skills are preserved
1032
+ // Complete progress bar
1033
+ completeProgress();
1034
+
1035
+ // Print summary
1036
+ printSummary(tool.name, 'uninstall');
1037
+
1038
+ console.log(`\n ℹ️ User skills preserved at: ${tool.paths.skills}`);
708
1039
 
709
- console.log(`\n✅ ${tool.name}: Uninstalled (user skills preserved, everything else removed)`);
710
1040
  return removed;
711
1041
  }
712
1042
 
713
1043
  function uninstallCopilot() {
714
1044
  const tool = TOOLS.copilot;
715
- console.log(`\n🗑️ Uninstalling Agent Assistant from ${tool.name}...\n`);
1045
+
1046
+ // Reset progress
1047
+ resetProgress();
1048
+ progressState.total = 10;
1049
+
1050
+ console.log(`\n🗑️ Uninstalling Agent Assistant from ${tool.name}...`);
1051
+ console.log(` This will remove the framework while preserving user skills.\n`);
716
1052
 
717
1053
  let removed = 0;
718
1054
 
719
1055
  // 1. Remove from VS Code Prompts
720
- console.log(' 1. Removing from VS Code Prompts...');
721
1056
  const promptFile = path.join(tool.paths.vsCodePrompts, 'agent-assistant.agent.md');
722
- if (fs.existsSync(promptFile)) {
723
- fs.unlinkSync(promptFile);
724
- console.log(` ✓ Removed: ${promptFile}`);
1057
+ if (removeFile(promptFile)) {
725
1058
  removed++;
726
1059
  }
727
1060
 
728
1061
  // 2. Remove core framework
729
- console.log(' 2. Removing core framework...');
730
1062
  if (removeDir(tool.paths.agentAssistant)) {
731
- console.log(` ✓ Removed: ${tool.paths.agentAssistant}`);
732
1063
  removed++;
733
1064
  }
734
1065
 
735
1066
  // 3. Remove commands
736
- console.log(' 3. Removing commands...');
737
1067
  if (removeDir(tool.paths.commands)) {
738
- console.log(` ✓ Removed: ${tool.paths.commands}`);
739
1068
  removed++;
740
1069
  }
741
1070
 
742
1071
  // 4. Remove Global Config Files
743
- console.log(' 4. Removing global config files...');
744
1072
  const globalFiles = ['AGENT.md', 'COPILOT.md', 'CLAUDE.md'];
745
1073
  for (const file of globalFiles) {
746
1074
  const filePath = path.join(tool.paths.home, file);
747
- if (fs.existsSync(filePath)) {
748
- fs.unlinkSync(filePath);
749
- console.log(` ✓ Removed: ${filePath}`);
1075
+ if (removeFile(filePath)) {
750
1076
  removed++;
751
1077
  }
752
1078
  }
753
1079
 
754
1080
  // 5. Remove native agents (Entire folder)
755
- console.log(' 5. Removing native agents...');
756
1081
  if (removeDir(tool.paths.agents)) {
757
- console.log(` ✓ Removed: ${tool.paths.agents}`);
758
1082
  removed++;
759
1083
  }
760
1084
 
761
- // Note: Skills are preserved (user may have custom ones)
1085
+ // Complete progress bar
1086
+ completeProgress();
1087
+
1088
+ // Print summary
1089
+ printSummary(tool.name, 'uninstall');
1090
+
1091
+ console.log(`\n ℹ️ User skills preserved at: ${tool.paths.skills}`);
762
1092
 
763
- console.log(`\n✅ ${tool.name}: Uninstalled (skills preserved, everything else removed)`);
764
1093
  return removed;
765
1094
  }
766
1095
 
767
1096
  function uninstallAntigravity() {
768
1097
  const tool = TOOLS.antigravity;
769
- console.log(`\n🗑️ Uninstalling Agent Assistant from ${tool.name}...\n`);
1098
+
1099
+ // Reset progress
1100
+ resetProgress();
1101
+ progressState.total = 12;
1102
+
1103
+ console.log(`\n🗑️ Uninstalling Agent Assistant from ${tool.name}...`);
1104
+ console.log(` This will remove the framework while preserving user skills.\n`);
770
1105
 
771
1106
  let removed = 0;
772
1107
 
773
1108
  // 1. Remove Editor Config (~/.antigravity)
774
- console.log(' 1. Removing editor config...');
775
-
776
1109
  // 1.1 Remove Workflows (~/.antigravity/workflows/)
777
1110
  if (removeDir(tool.paths.workflows)) {
778
- console.log(` ✓ Removed: ${tool.paths.workflows}`);
779
1111
  removed++;
780
1112
  }
781
1113
 
782
1114
  // 1.2 Remove Agents (~/.antigravity/agents/)
783
1115
  if (removeDir(tool.paths.agents)) {
784
- console.log(` ✓ Removed: ${tool.paths.agents}`);
785
1116
  removed++;
786
1117
  }
787
1118
 
788
1119
 
789
1120
  // 2. Remove Platform Config (~/.gemini)
790
- console.log(' 2. Removing platform config...');
791
-
792
1121
  // 2.1 Remove GEMINI.md, AGENT.md, CLAUDE.md
793
1122
  const globalFiles = ["GEMINI.md", "AGENT.md", "CLAUDE.md"];
794
1123
  for (const file of globalFiles) {
795
1124
  const filePath = path.join(tool.paths.gemini, file);
796
- if (fs.existsSync(filePath)) {
797
- try { fs.unlinkSync(filePath); removed++; } catch (e) { }
798
- console.log(` ✓ Removed: ${filePath}`);
1125
+ if (removeFile(filePath)) {
1126
+ removed++;
799
1127
  }
800
1128
  }
801
1129
 
802
1130
  // 2.2 Remove Global Agents Folder (~/.gemini/agents/)
803
1131
  if (removeDir(tool.paths.globalAgents)) {
804
- console.log(` ✓ Removed: ${tool.paths.globalAgents}`);
805
1132
  removed++;
806
1133
  }
807
1134
 
808
1135
  // 3. Remove Extension Brain (~/.gemini/antigravity)
809
- console.log(' 3. Removing extension brain...');
810
-
811
1136
  // 3.1 Remove Global Workflows (~/.gemini/antigravity/global_workflows)
812
1137
  if (removeDir(tool.paths.globalWorkflows)) {
813
- console.log(` ✓ Removed: ${tool.paths.globalWorkflows}`);
814
1138
  removed++;
815
1139
  }
816
1140
 
817
1141
  // 3.2 Remove Core Framework (~/.gemini/antigravity/skills/agent-assistant)
818
- console.log(' - Removing core framework...');
819
1142
  if (removeDir(tool.paths.agentAssistant)) {
820
- console.log(` ✓ Removed: ${tool.paths.agentAssistant}`);
821
1143
  removed++;
822
1144
  }
823
1145
 
824
- // Note: Skills in ~/.gemini/antigravity/skills are preserved (except agent-assistant)
1146
+ // Complete progress bar
1147
+ completeProgress();
1148
+
1149
+ // Print summary
1150
+ printSummary(tool.name, 'uninstall');
1151
+
1152
+ console.log(`\n ℹ️ User skills preserved at: ${tool.paths.skills}`);
825
1153
 
826
- console.log(`\n✅ ${tool.name}: Uninstalled (skills preserved, everything else removed)`);
827
1154
  return removed;
828
1155
  }
829
1156
 
830
1157
  function uninstallClaude() {
831
1158
  const tool = TOOLS.claude;
832
- console.log(`\n🗑️ Uninstalling Agent Assistant from ${tool.name}...\n`);
1159
+
1160
+ // Reset progress
1161
+ resetProgress();
1162
+ progressState.total = 6;
1163
+
1164
+ console.log(`\n🗑️ Uninstalling Agent Assistant from ${tool.name}...`);
1165
+ console.log(` This will remove the framework while preserving user skills.\n`);
833
1166
 
834
1167
  let removed = 0;
835
1168
 
836
1169
  // 1. Remove Global Config
837
- console.log(' 1. Removing global config...');
838
1170
  const claudeMd = path.join(tool.paths.home, 'CLAUDE.md');
839
- if (fs.existsSync(claudeMd)) {
840
- try { fs.unlinkSync(claudeMd); removed++; } catch (e) { }
841
- console.log(` ✓ Removed: ${claudeMd}`);
1171
+ if (removeFile(claudeMd)) {
1172
+ removed++;
842
1173
  }
843
1174
 
844
1175
  // 2. Remove Commands
845
- console.log(' 2. Removing commands...');
846
1176
  if (removeDir(tool.paths.commands)) {
847
- console.log(` ✓ Removed: ${tool.paths.commands}`);
848
1177
  removed++;
849
1178
  }
850
1179
 
851
1180
  // 3. Remove Native Agents
852
- console.log(' 3. Removing native agents...');
853
1181
  if (removeDir(tool.paths.agents)) {
854
- console.log(` ✓ Removed: ${tool.paths.agents}`);
855
1182
  removed++;
856
1183
  }
857
1184
 
858
1185
  // 4. Remove Core Framework
859
- console.log(' 4. Removing core framework...');
860
1186
  if (removeDir(tool.paths.agentAssistant)) {
861
- console.log(` ✓ Removed: ${tool.paths.agentAssistant}`);
862
1187
  removed++;
863
1188
  }
864
1189
 
865
- // Note: Skills in ~/.claude/skills are preserved (except agent-assistant)
1190
+ // Complete progress bar
1191
+ completeProgress();
1192
+
1193
+ // Print summary
1194
+ printSummary(tool.name, 'uninstall');
1195
+
1196
+ console.log(`\n ℹ️ User skills preserved at: ${tool.paths.skills}`);
866
1197
 
867
- console.log(`\n✅ ${tool.name}: Uninstalled (skills preserved, everything else removed)`);
868
1198
  return removed;
869
1199
  }
870
1200
 
@@ -1016,15 +1346,25 @@ async function main() {
1016
1346
  return;
1017
1347
  }
1018
1348
 
1349
+ const startTime = Date.now();
1350
+ let totalFiles = 0;
1351
+
1019
1352
  switch (command) {
1020
1353
  case 'install':
1021
1354
  if (target === '--all' || target === 'all') {
1022
1355
  console.log('🚀 Installing for all supported tools...');
1023
- installCursor();
1024
- installCopilot();
1025
- installAntigravity();
1026
- installClaude();
1027
- console.log('\n🎉 All installations complete!\n');
1356
+ console.log(' This may take a moment. Progress will be shown for each tool.\n');
1357
+ totalFiles += installCursor();
1358
+ totalFiles += installCopilot();
1359
+ totalFiles += installAntigravity();
1360
+ totalFiles += installClaude();
1361
+
1362
+ const duration = ((Date.now() - startTime) / 1000).toFixed(2);
1363
+ console.log('\n' + '═'.repeat(60));
1364
+ console.log('🎉 All installations complete!');
1365
+ console.log(` Total files: ${formatNumber(totalFiles)}`);
1366
+ console.log(` Total time: ${duration}s`);
1367
+ console.log('═'.repeat(60) + '\n');
1028
1368
  } else if (target === 'cursor') {
1029
1369
  installCursor();
1030
1370
  } else if (target === 'copilot') {
@@ -1043,12 +1383,17 @@ async function main() {
1043
1383
 
1044
1384
  case 'uninstall':
1045
1385
  if (target === '--all' || target === 'all') {
1046
- console.log('🗑️ Uninstalling from all tools...');
1386
+ console.log('🗑️ Uninstalling from all tools...\n');
1047
1387
  uninstallCursor();
1048
1388
  uninstallCopilot();
1049
1389
  uninstallAntigravity();
1050
1390
  uninstallClaude();
1051
- console.log('\n✅ All uninstallations complete!\n');
1391
+
1392
+ const duration = ((Date.now() - startTime) / 1000).toFixed(2);
1393
+ console.log('\n' + '═'.repeat(60));
1394
+ console.log('✅ All uninstallations complete!');
1395
+ console.log(` Total time: ${duration}s`);
1396
+ console.log('═'.repeat(60) + '\n');
1052
1397
  } else if (target === 'cursor') {
1053
1398
  uninstallCursor();
1054
1399
  } else if (target === 'copilot') {