@namch/agent-assistant 1.0.4 → 1.1.1

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