claude-code-templates 1.15.0 → 1.15.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 (101) hide show
  1. package/README.md +7 -7
  2. package/bin/create-claude-config.js +15 -8
  3. package/package.json +2 -3
  4. package/src/analytics/core/AgentAnalyzer.js +17 -3
  5. package/src/analytics/core/ProcessDetector.js +23 -7
  6. package/src/analytics/core/StateCalculator.js +102 -33
  7. package/src/analytics/data/DataCache.js +7 -7
  8. package/src/analytics-web/chats_mobile.html +2590 -0
  9. package/src/analytics-web/components/App.js +10 -10
  10. package/src/analytics-web/components/SessionTimer.js +1 -1
  11. package/src/analytics-web/components/Sidebar.js +5 -14
  12. package/src/analytics-web/index.html +932 -78
  13. package/src/analytics.js +263 -5
  14. package/src/chats-mobile.js +682 -0
  15. package/src/claude-api-proxy.js +460 -0
  16. package/src/file-operations.js +422 -83
  17. package/src/health-check.js +310 -0
  18. package/src/index.js +944 -56
  19. package/src/tracking-service.js +31 -34
  20. package/components/agents/api-security-audit.md +0 -92
  21. package/components/agents/database-optimization.md +0 -94
  22. package/components/agents/react-performance-optimization.md +0 -64
  23. package/components/commands/check-file.md +0 -53
  24. package/components/commands/generate-tests.md +0 -68
  25. package/components/mcps/deepgraph-nextjs.json +0 -12
  26. package/components/mcps/deepgraph-react.json +0 -12
  27. package/components/mcps/deepgraph-typescript.json +0 -12
  28. package/components/mcps/deepgraph-vue.json +0 -12
  29. package/components/mcps/filesystem-access.json +0 -12
  30. package/components/mcps/github-integration.json +0 -11
  31. package/components/mcps/memory-integration.json +0 -8
  32. package/components/mcps/mysql-integration.json +0 -11
  33. package/components/mcps/postgresql-integration.json +0 -11
  34. package/components/mcps/web-fetch.json +0 -8
  35. package/src/analytics-web/components/AgentsPage.js +0 -4761
  36. package/templates/common/.claude/commands/git-workflow.md +0 -239
  37. package/templates/common/.claude/commands/project-setup.md +0 -316
  38. package/templates/common/.mcp.json +0 -41
  39. package/templates/common/CLAUDE.md +0 -109
  40. package/templates/common/README.md +0 -96
  41. package/templates/go/.mcp.json +0 -78
  42. package/templates/go/README.md +0 -25
  43. package/templates/javascript-typescript/.claude/commands/api-endpoint.md +0 -51
  44. package/templates/javascript-typescript/.claude/commands/debug.md +0 -52
  45. package/templates/javascript-typescript/.claude/commands/lint.md +0 -48
  46. package/templates/javascript-typescript/.claude/commands/npm-scripts.md +0 -48
  47. package/templates/javascript-typescript/.claude/commands/refactor.md +0 -55
  48. package/templates/javascript-typescript/.claude/commands/test.md +0 -61
  49. package/templates/javascript-typescript/.claude/commands/typescript-migrate.md +0 -51
  50. package/templates/javascript-typescript/.claude/settings.json +0 -142
  51. package/templates/javascript-typescript/.mcp.json +0 -80
  52. package/templates/javascript-typescript/CLAUDE.md +0 -185
  53. package/templates/javascript-typescript/README.md +0 -259
  54. package/templates/javascript-typescript/examples/angular-app/.claude/commands/components.md +0 -63
  55. package/templates/javascript-typescript/examples/angular-app/.claude/commands/services.md +0 -62
  56. package/templates/javascript-typescript/examples/node-api/.claude/commands/api-endpoint.md +0 -46
  57. package/templates/javascript-typescript/examples/node-api/.claude/commands/database.md +0 -56
  58. package/templates/javascript-typescript/examples/node-api/.claude/commands/middleware.md +0 -61
  59. package/templates/javascript-typescript/examples/node-api/.claude/commands/route.md +0 -57
  60. package/templates/javascript-typescript/examples/node-api/CLAUDE.md +0 -102
  61. package/templates/javascript-typescript/examples/react-app/.claude/commands/component.md +0 -29
  62. package/templates/javascript-typescript/examples/react-app/.claude/commands/hooks.md +0 -44
  63. package/templates/javascript-typescript/examples/react-app/.claude/commands/state-management.md +0 -45
  64. package/templates/javascript-typescript/examples/react-app/CLAUDE.md +0 -81
  65. package/templates/javascript-typescript/examples/react-app/agents/react-performance-optimization.md +0 -530
  66. package/templates/javascript-typescript/examples/react-app/agents/react-state-management.md +0 -295
  67. package/templates/javascript-typescript/examples/vue-app/.claude/commands/components.md +0 -46
  68. package/templates/javascript-typescript/examples/vue-app/.claude/commands/composables.md +0 -51
  69. package/templates/python/.claude/commands/lint.md +0 -111
  70. package/templates/python/.claude/commands/test.md +0 -73
  71. package/templates/python/.claude/settings.json +0 -153
  72. package/templates/python/.mcp.json +0 -78
  73. package/templates/python/CLAUDE.md +0 -276
  74. package/templates/python/examples/django-app/.claude/commands/admin.md +0 -264
  75. package/templates/python/examples/django-app/.claude/commands/django-model.md +0 -124
  76. package/templates/python/examples/django-app/.claude/commands/views.md +0 -222
  77. package/templates/python/examples/django-app/CLAUDE.md +0 -313
  78. package/templates/python/examples/django-app/agents/django-api-security.md +0 -642
  79. package/templates/python/examples/django-app/agents/django-database-optimization.md +0 -752
  80. package/templates/python/examples/fastapi-app/.claude/commands/api-endpoints.md +0 -513
  81. package/templates/python/examples/fastapi-app/.claude/commands/auth.md +0 -775
  82. package/templates/python/examples/fastapi-app/.claude/commands/database.md +0 -657
  83. package/templates/python/examples/fastapi-app/.claude/commands/deployment.md +0 -160
  84. package/templates/python/examples/fastapi-app/.claude/commands/testing.md +0 -927
  85. package/templates/python/examples/fastapi-app/CLAUDE.md +0 -229
  86. package/templates/python/examples/flask-app/.claude/commands/app-factory.md +0 -384
  87. package/templates/python/examples/flask-app/.claude/commands/blueprint.md +0 -243
  88. package/templates/python/examples/flask-app/.claude/commands/database.md +0 -410
  89. package/templates/python/examples/flask-app/.claude/commands/deployment.md +0 -620
  90. package/templates/python/examples/flask-app/.claude/commands/flask-route.md +0 -217
  91. package/templates/python/examples/flask-app/.claude/commands/testing.md +0 -559
  92. package/templates/python/examples/flask-app/CLAUDE.md +0 -391
  93. package/templates/ruby/.claude/commands/model.md +0 -360
  94. package/templates/ruby/.claude/commands/test.md +0 -480
  95. package/templates/ruby/.claude/settings.json +0 -146
  96. package/templates/ruby/.mcp.json +0 -83
  97. package/templates/ruby/CLAUDE.md +0 -284
  98. package/templates/ruby/examples/rails-app/.claude/commands/authentication.md +0 -490
  99. package/templates/ruby/examples/rails-app/CLAUDE.md +0 -376
  100. package/templates/rust/.mcp.json +0 -78
  101. package/templates/rust/README.md +0 -26
package/src/index.js CHANGED
@@ -13,6 +13,7 @@ const { runCommandStats } = require('./command-stats');
13
13
  const { runHookStats } = require('./hook-stats');
14
14
  const { runMCPStats } = require('./mcp-stats');
15
15
  const { runAnalytics } = require('./analytics');
16
+ const { startChatsMobile } = require('./chats-mobile');
16
17
  const { runHealthCheck } = require('./health-check');
17
18
  const { trackingService } = require('./tracking-service');
18
19
 
@@ -30,9 +31,14 @@ async function showMainMenu() {
30
31
  short: 'Analytics Dashboard'
31
32
  },
32
33
  {
33
- name: '💬 Chats Dashboard - View and analyze your Claude conversations',
34
+ name: '💬 Chats Mobile - AI-first mobile interface for conversations',
34
35
  value: 'chats',
35
- short: 'Chats Dashboard'
36
+ short: 'Chats Mobile'
37
+ },
38
+ {
39
+ name: '🤖 Agents Dashboard - View and analyze Claude conversations with agent tools',
40
+ value: 'agents',
41
+ short: 'Agents Dashboard'
36
42
  },
37
43
  {
38
44
  name: '⚙️ Project Setup - Configure Claude Code for your project',
@@ -56,12 +62,20 @@ async function showMainMenu() {
56
62
  }
57
63
 
58
64
  if (initialChoice.action === 'chats') {
59
- console.log(chalk.blue('💬 Launching Claude Code Chats Dashboard...'));
65
+ console.log(chalk.blue('💬 Launching Claude Code Mobile Chats...'));
66
+ trackingService.trackAnalyticsDashboard({ page: 'chats-mobile', source: 'interactive_menu' });
67
+ await startChatsMobile({});
68
+ return;
69
+ }
70
+
71
+ if (initialChoice.action === 'agents') {
72
+ console.log(chalk.blue('🤖 Launching Claude Code Agents Dashboard...'));
60
73
  trackingService.trackAnalyticsDashboard({ page: 'agents', source: 'interactive_menu' });
61
74
  await runAnalytics({ openTo: 'agents' });
62
75
  return;
63
76
  }
64
77
 
78
+
65
79
  if (initialChoice.action === 'health') {
66
80
  console.log(chalk.blue('🔍 Running Health Check...'));
67
81
  const healthResult = await runHealthCheck();
@@ -90,19 +104,29 @@ async function showMainMenu() {
90
104
  async function createClaudeConfig(options = {}) {
91
105
  const targetDir = options.directory || process.cwd();
92
106
 
93
- // Handle individual component installation
94
- if (options.agent) {
95
- await installIndividualAgent(options.agent, targetDir, options);
107
+ // Validate --tunnel usage
108
+ if (options.tunnel && !options.analytics && !options.chats && !options.agents && !options.chatsMobile) {
109
+ console.log(chalk.red('❌ Error: --tunnel can only be used with --analytics, --chats, or --chats-mobile'));
110
+ console.log(chalk.yellow('💡 Examples:'));
111
+ console.log(chalk.gray(' cct --analytics --tunnel'));
112
+ console.log(chalk.gray(' cct --chats --tunnel'));
113
+ console.log(chalk.gray(' cct --chats-mobile'));
96
114
  return;
97
115
  }
98
116
 
99
- if (options.command) {
100
- await installIndividualCommand(options.command, targetDir, options);
117
+ // Handle multiple components installation (new approach)
118
+ if (options.agent || options.command || options.mcp) {
119
+ // If --workflow is used with components, treat it as YAML
120
+ if (options.workflow) {
121
+ options.yaml = options.workflow;
122
+ }
123
+ await installMultipleComponents(options, targetDir);
101
124
  return;
102
125
  }
103
126
 
104
- if (options.mcp) {
105
- await installIndividualMCP(options.mcp, targetDir, options);
127
+ // Handle workflow installation (hash-based)
128
+ if (options.workflow) {
129
+ await installWorkflow(options.workflow, targetDir, options);
106
130
  return;
107
131
  }
108
132
 
@@ -131,13 +155,27 @@ async function createClaudeConfig(options = {}) {
131
155
  return;
132
156
  }
133
157
 
134
- // Handle chats/agents dashboard
135
- if (options.chats || options.agents) {
158
+ // Handle chats dashboard (now points to mobile chats interface)
159
+ if (options.chats) {
160
+ trackingService.trackAnalyticsDashboard({ page: 'chats-mobile', source: 'command_line' });
161
+ await startChatsMobile(options);
162
+ return;
163
+ }
164
+
165
+ // Handle agents dashboard (separate from chats)
166
+ if (options.agents) {
136
167
  trackingService.trackAnalyticsDashboard({ page: 'agents', source: 'command_line' });
137
168
  await runAnalytics({ ...options, openTo: 'agents' });
138
169
  return;
139
170
  }
140
171
 
172
+ // Handle mobile chats interface
173
+ if (options.chatsMobile) {
174
+ trackingService.trackAnalyticsDashboard({ page: 'chats-mobile', source: 'command_line' });
175
+ await startChatsMobile(options);
176
+ return;
177
+ }
178
+
141
179
  // Handle health check
142
180
  let shouldRunSetup = false;
143
181
  if (options.healthCheck || options.health || options.check || options.verify) {
@@ -175,8 +213,8 @@ async function createClaudeConfig(options = {}) {
175
213
 
176
214
  let config;
177
215
  if (options.yes) {
178
- // Use defaults
179
- const selectedLanguage = options.language || projectInfo.detectedLanguage || 'common';
216
+ // Use defaults - prioritize --template over --language for backward compatibility
217
+ const selectedLanguage = options.template || options.language || projectInfo.detectedLanguage || 'common';
180
218
 
181
219
  // Check if selected language is coming soon
182
220
  if (selectedLanguage && TEMPLATES_CONFIG[selectedLanguage] && TEMPLATES_CONFIG[selectedLanguage].comingSoon) {
@@ -265,7 +303,7 @@ async function createClaudeConfig(options = {}) {
265
303
  console.log(chalk.white(' 3. Start using Claude Code with: claude'));
266
304
  console.log('');
267
305
  console.log(chalk.blue('🌐 View all available templates at: https://aitmpl.com/'));
268
- console.log(chalk.blue('📖 Read the complete documentation at: https://aitmpl.com/docu/'));
306
+ console.log(chalk.blue('📖 Read the complete documentation at: https://docs.aitmpl.com/'));
269
307
 
270
308
  if (config.language !== 'common') {
271
309
  console.log(chalk.yellow(`💡 Language-specific features for ${config.language} have been configured`));
@@ -298,6 +336,11 @@ async function createClaudeConfig(options = {}) {
298
336
  if (!options.dryRun) {
299
337
  await runPostInstallationValidation(targetDir, templateConfig);
300
338
  }
339
+
340
+ // Handle prompt execution if provided
341
+ if (options.prompt) {
342
+ await handlePromptExecution(options.prompt, targetDir);
343
+ }
301
344
  }
302
345
 
303
346
  // Individual component installation functions
@@ -305,15 +348,23 @@ async function installIndividualAgent(agentName, targetDir, options) {
305
348
  console.log(chalk.blue(`🤖 Installing agent: ${agentName}`));
306
349
 
307
350
  try {
308
- // Download agent directly from GitHub
309
- const githubUrl = `https://raw.githubusercontent.com/davila7/claude-code-templates/main/cli-tool/components/agents/${agentName}.md`;
351
+ // Support both category/agent-name and direct agent-name formats
352
+ let githubUrl;
353
+ if (agentName.includes('/')) {
354
+ // Category/agent format: deep-research-team/academic-researcher
355
+ githubUrl = `https://raw.githubusercontent.com/davila7/claude-code-templates/main/cli-tool/components/agents/${agentName}.md`;
356
+ } else {
357
+ // Direct agent format: api-security-audit
358
+ githubUrl = `https://raw.githubusercontent.com/davila7/claude-code-templates/main/cli-tool/components/agents/${agentName}.md`;
359
+ }
360
+
310
361
  console.log(chalk.gray(`📥 Downloading from GitHub (main branch)...`));
311
362
 
312
363
  const response = await fetch(githubUrl);
313
364
  if (!response.ok) {
314
365
  if (response.status === 404) {
315
366
  console.log(chalk.red(`❌ Agent "${agentName}" not found`));
316
- console.log(chalk.yellow('Available agents: api-security-audit, database-optimization, react-performance-optimization'));
367
+ await showAvailableAgents();
317
368
  return;
318
369
  }
319
370
  throw new Error(`HTTP ${response.status}: ${response.statusText}`);
@@ -321,35 +372,32 @@ async function installIndividualAgent(agentName, targetDir, options) {
321
372
 
322
373
  const agentContent = await response.text();
323
374
 
324
- // For agents, they are typically part of templates, so we need to determine
325
- // the appropriate language/framework and install the complete template
326
- const language = extractLanguageFromAgent(agentContent, agentName);
327
- const framework = extractFrameworkFromAgent(agentContent, agentName);
328
-
329
- console.log(chalk.yellow(`📝 Agent "${agentName}" is part of ${language}/${framework} template`));
330
- console.log(chalk.blue('🚀 Installing complete template with this agent...'));
331
-
332
- // Install the template that contains this agent (avoid recursion)
333
- const setupOptions = {
334
- ...options,
335
- language,
336
- framework,
337
- yes: true,
338
- targetDirectory: targetDir,
339
- agent: null // Remove agent to avoid recursion
340
- };
341
- delete setupOptions.agent;
342
- await createClaudeConfig(setupOptions);
375
+ // Create .claude/agents directory if it doesn't exist
376
+ const agentsDir = path.join(targetDir, '.claude', 'agents');
377
+ await fs.ensureDir(agentsDir);
343
378
 
344
- console.log(chalk.green(`✅ Agent "${agentName}" installed successfully!`));
345
- console.log(chalk.cyan(`📦 Downloaded from: ${githubUrl}`));
379
+ // Write the agent file - always to flat .claude/agents directory
380
+ let fileName;
381
+ if (agentName.includes('/')) {
382
+ const [category, filename] = agentName.split('/');
383
+ fileName = filename; // Extract just the filename, ignore category for installation
384
+ } else {
385
+ fileName = agentName;
386
+ }
387
+
388
+ const targetFile = path.join(agentsDir, `${fileName}.md`);
389
+ await fs.writeFile(targetFile, agentContent, 'utf8');
390
+
391
+ if (!options.silent) {
392
+ console.log(chalk.green(`✅ Agent "${agentName}" installed successfully!`));
393
+ console.log(chalk.cyan(`📁 Installed to: ${path.relative(targetDir, targetFile)}`));
394
+ console.log(chalk.cyan(`📦 Downloaded from: ${githubUrl}`));
395
+ }
346
396
 
347
397
  // Track successful agent installation
348
398
  trackingService.trackDownload('agent', agentName, {
349
- language: language,
350
- framework: framework,
351
- installation_type: 'individual_agent',
352
- template_installed: true,
399
+ installation_type: 'individual_component',
400
+ target_directory: path.relative(process.cwd(), targetDir),
353
401
  source: 'github_main'
354
402
  });
355
403
 
@@ -362,8 +410,16 @@ async function installIndividualCommand(commandName, targetDir, options) {
362
410
  console.log(chalk.blue(`⚡ Installing command: ${commandName}`));
363
411
 
364
412
  try {
365
- // Download command directly from GitHub
366
- const githubUrl = `https://raw.githubusercontent.com/davila7/claude-code-templates/main/cli-tool/components/commands/${commandName}.md`;
413
+ // Support both category/command-name and direct command-name formats
414
+ let githubUrl;
415
+ if (commandName.includes('/')) {
416
+ // Category/command format: security/vulnerability-scan
417
+ githubUrl = `https://raw.githubusercontent.com/davila7/claude-code-templates/main/cli-tool/components/commands/${commandName}.md`;
418
+ } else {
419
+ // Direct command format: check-file
420
+ githubUrl = `https://raw.githubusercontent.com/davila7/claude-code-templates/main/cli-tool/components/commands/${commandName}.md`;
421
+ }
422
+
367
423
  console.log(chalk.gray(`📥 Downloading from GitHub (main branch)...`));
368
424
 
369
425
  const response = await fetch(githubUrl);
@@ -382,13 +438,24 @@ async function installIndividualCommand(commandName, targetDir, options) {
382
438
  const commandsDir = path.join(targetDir, '.claude', 'commands');
383
439
  await fs.ensureDir(commandsDir);
384
440
 
385
- // Write the command file
386
- const targetFile = path.join(commandsDir, `${commandName}.md`);
441
+ // Write the command file - always to flat .claude/commands directory
442
+ let fileName;
443
+ if (commandName.includes('/')) {
444
+ const [category, filename] = commandName.split('/');
445
+ fileName = filename; // Extract just the filename, ignore category for installation
446
+ } else {
447
+ fileName = commandName;
448
+ }
449
+
450
+ const targetFile = path.join(commandsDir, `${fileName}.md`);
451
+
387
452
  await fs.writeFile(targetFile, commandContent, 'utf8');
388
453
 
389
- console.log(chalk.green(`✅ Command "${commandName}" installed successfully!`));
390
- console.log(chalk.cyan(`📁 Installed to: ${path.relative(targetDir, targetFile)}`));
391
- console.log(chalk.cyan(`📦 Downloaded from: ${githubUrl}`));
454
+ if (!options.silent) {
455
+ console.log(chalk.green(`✅ Command "${commandName}" installed successfully!`));
456
+ console.log(chalk.cyan(`📁 Installed to: ${path.relative(targetDir, targetFile)}`));
457
+ console.log(chalk.cyan(`📦 Downloaded from: ${githubUrl}`));
458
+ }
392
459
 
393
460
  // Track successful command installation
394
461
  trackingService.trackDownload('command', commandName, {
@@ -406,8 +473,16 @@ async function installIndividualMCP(mcpName, targetDir, options) {
406
473
  console.log(chalk.blue(`🔌 Installing MCP: ${mcpName}`));
407
474
 
408
475
  try {
409
- // Download MCP directly from GitHub
410
- const githubUrl = `https://raw.githubusercontent.com/davila7/claude-code-templates/main/cli-tool/components/mcps/${mcpName}.json`;
476
+ // Support both category/mcp-name and direct mcp-name formats
477
+ let githubUrl;
478
+ if (mcpName.includes('/')) {
479
+ // Category/mcp format: database/mysql-integration
480
+ githubUrl = `https://raw.githubusercontent.com/davila7/claude-code-templates/main/cli-tool/components/mcps/${mcpName}.json`;
481
+ } else {
482
+ // Direct mcp format: web-fetch
483
+ githubUrl = `https://raw.githubusercontent.com/davila7/claude-code-templates/main/cli-tool/components/mcps/${mcpName}.json`;
484
+ }
485
+
411
486
  console.log(chalk.gray(`📥 Downloading from GitHub (main branch)...`));
412
487
 
413
488
  const response = await fetch(githubUrl);
@@ -422,6 +497,15 @@ async function installIndividualMCP(mcpName, targetDir, options) {
422
497
 
423
498
  const mcpConfigText = await response.text();
424
499
  const mcpConfig = JSON.parse(mcpConfigText);
500
+
501
+ // Remove description field from each MCP server before merging
502
+ if (mcpConfig.mcpServers) {
503
+ for (const serverName in mcpConfig.mcpServers) {
504
+ if (mcpConfig.mcpServers[serverName] && typeof mcpConfig.mcpServers[serverName] === 'object') {
505
+ delete mcpConfig.mcpServers[serverName].description;
506
+ }
507
+ }
508
+ }
425
509
 
426
510
  // Check if .mcp.json exists in target directory
427
511
  const targetMcpFile = path.join(targetDir, '.mcp.json');
@@ -432,18 +516,28 @@ async function installIndividualMCP(mcpName, targetDir, options) {
432
516
  console.log(chalk.yellow('📝 Existing .mcp.json found, merging configurations...'));
433
517
  }
434
518
 
435
- // Merge configurations
519
+ // Merge configurations with deep merge for mcpServers
436
520
  const mergedConfig = {
437
521
  ...existingConfig,
438
522
  ...mcpConfig
439
523
  };
440
524
 
525
+ // Deep merge mcpServers specifically to avoid overwriting existing servers
526
+ if (existingConfig.mcpServers && mcpConfig.mcpServers) {
527
+ mergedConfig.mcpServers = {
528
+ ...existingConfig.mcpServers,
529
+ ...mcpConfig.mcpServers
530
+ };
531
+ }
532
+
441
533
  // Write the merged configuration
442
534
  await fs.writeJson(targetMcpFile, mergedConfig, { spaces: 2 });
443
535
 
444
- console.log(chalk.green(`✅ MCP "${mcpName}" installed successfully!`));
445
- console.log(chalk.cyan(`📁 Configuration merged into: ${path.relative(targetDir, targetMcpFile)}`));
446
- console.log(chalk.cyan(`📦 Downloaded from: ${githubUrl}`));
536
+ if (!options.silent) {
537
+ console.log(chalk.green(`✅ MCP "${mcpName}" installed successfully!`));
538
+ console.log(chalk.cyan(`📁 Configuration merged into: ${path.relative(targetDir, targetMcpFile)}`));
539
+ console.log(chalk.cyan(`📦 Downloaded from: ${githubUrl}`));
540
+ }
447
541
 
448
542
  // Track successful MCP installation
449
543
  trackingService.trackDownload('mcp', mcpName, {
@@ -485,4 +579,798 @@ function extractFrameworkFromAgent(content, agentName) {
485
579
  return 'none';
486
580
  }
487
581
 
582
+ /**
583
+ * Fetch available agents dynamically from GitHub repository
584
+ */
585
+ async function getAvailableAgentsFromGitHub() {
586
+ try {
587
+ const response = await fetch('https://api.github.com/repos/davila7/claude-code-templates/contents/cli-tool/components/agents');
588
+ if (!response.ok) {
589
+ throw new Error(`GitHub API error: ${response.status}`);
590
+ }
591
+
592
+ const contents = await response.json();
593
+ const agents = [];
594
+
595
+ for (const item of contents) {
596
+ if (item.type === 'file' && item.name.endsWith('.md')) {
597
+ // Direct agent file
598
+ agents.push({
599
+ name: item.name.replace('.md', ''),
600
+ path: item.name.replace('.md', ''),
601
+ category: 'root'
602
+ });
603
+ } else if (item.type === 'dir') {
604
+ // Category directory, fetch its contents
605
+ try {
606
+ const categoryResponse = await fetch(`https://api.github.com/repos/davila7/claude-code-templates/contents/cli-tool/components/agents/${item.name}`);
607
+ if (categoryResponse.ok) {
608
+ const categoryContents = await categoryResponse.json();
609
+ for (const categoryItem of categoryContents) {
610
+ if (categoryItem.type === 'file' && categoryItem.name.endsWith('.md')) {
611
+ agents.push({
612
+ name: categoryItem.name.replace('.md', ''),
613
+ path: `${item.name}/${categoryItem.name.replace('.md', '')}`,
614
+ category: item.name
615
+ });
616
+ }
617
+ }
618
+ }
619
+ } catch (error) {
620
+ console.warn(`Warning: Could not fetch category ${item.name}:`, error.message);
621
+ }
622
+ }
623
+ }
624
+
625
+ return agents;
626
+ } catch (error) {
627
+ console.warn('Warning: Could not fetch agents from GitHub, using fallback list');
628
+ // Fallback to basic list if GitHub API fails
629
+ return [
630
+ { name: 'api-security-audit', path: 'api-security-audit', category: 'root' },
631
+ { name: 'database-optimization', path: 'database-optimization', category: 'root' },
632
+ { name: 'react-performance-optimization', path: 'react-performance-optimization', category: 'root' }
633
+ ];
634
+ }
635
+ }
636
+
637
+ /**
638
+ * Install multiple components with optional YAML workflow
639
+ */
640
+ async function installMultipleComponents(options, targetDir) {
641
+ console.log(chalk.blue('🔧 Installing multiple components...'));
642
+
643
+ try {
644
+ const components = {
645
+ agents: [],
646
+ commands: [],
647
+ mcps: []
648
+ };
649
+
650
+ // Parse comma-separated values for each component type
651
+ if (options.agent) {
652
+ const agentsInput = Array.isArray(options.agent) ? options.agent.join(',') : options.agent;
653
+ components.agents = agentsInput.split(',').map(a => a.trim()).filter(a => a);
654
+ }
655
+
656
+ if (options.command) {
657
+ const commandsInput = Array.isArray(options.command) ? options.command.join(',') : options.command;
658
+ components.commands = commandsInput.split(',').map(c => c.trim()).filter(c => c);
659
+ }
660
+
661
+ if (options.mcp) {
662
+ const mcpsInput = Array.isArray(options.mcp) ? options.mcp.join(',') : options.mcp;
663
+ components.mcps = mcpsInput.split(',').map(m => m.trim()).filter(m => m);
664
+ }
665
+
666
+ const totalComponents = components.agents.length + components.commands.length + components.mcps.length;
667
+
668
+ if (totalComponents === 0) {
669
+ console.log(chalk.yellow('⚠️ No components specified to install.'));
670
+ return;
671
+ }
672
+
673
+ console.log(chalk.cyan(`📦 Installing ${totalComponents} components:`));
674
+ console.log(chalk.gray(` Agents: ${components.agents.length}`));
675
+ console.log(chalk.gray(` Commands: ${components.commands.length}`));
676
+ console.log(chalk.gray(` MCPs: ${components.mcps.length}`));
677
+
678
+ // Install agents
679
+ for (const agent of components.agents) {
680
+ console.log(chalk.gray(` Installing agent: ${agent}`));
681
+ await installIndividualAgent(agent, targetDir, { ...options, silent: true });
682
+ }
683
+
684
+ // Install commands
685
+ for (const command of components.commands) {
686
+ console.log(chalk.gray(` Installing command: ${command}`));
687
+ await installIndividualCommand(command, targetDir, { ...options, silent: true });
688
+ }
689
+
690
+ // Install MCPs
691
+ for (const mcp of components.mcps) {
692
+ console.log(chalk.gray(` Installing MCP: ${mcp}`));
693
+ await installIndividualMCP(mcp, targetDir, { ...options, silent: true });
694
+ }
695
+
696
+ // Handle YAML workflow if provided
697
+ if (options.yaml) {
698
+ console.log(chalk.blue('\n📄 Processing workflow YAML...'));
699
+
700
+ try {
701
+ // Decode the YAML from base64
702
+ const yamlContent = Buffer.from(options.yaml, 'base64').toString('utf8');
703
+
704
+ // Parse workflow name from YAML (try to extract from name: field)
705
+ let workflowName = 'custom-workflow';
706
+ const nameMatch = yamlContent.match(/name:\s*["']?([^"'\n]+)["']?/);
707
+ if (nameMatch) {
708
+ workflowName = nameMatch[1].trim().replace(/[^a-z0-9]/gi, '_').toLowerCase();
709
+ }
710
+
711
+ // Save YAML to workflows directory
712
+ const workflowsDir = path.join(targetDir, '.claude', 'workflows');
713
+ const workflowFile = path.join(workflowsDir, `${workflowName}.yaml`);
714
+
715
+ await fs.ensureDir(workflowsDir);
716
+ await fs.writeFile(workflowFile, yamlContent, 'utf8');
717
+
718
+ console.log(chalk.green(`✅ Workflow YAML saved: ${path.relative(targetDir, workflowFile)}`));
719
+
720
+ } catch (yamlError) {
721
+ console.log(chalk.red(`❌ Error processing YAML: ${yamlError.message}`));
722
+ }
723
+ }
724
+
725
+ console.log(chalk.green(`\n✅ Successfully installed ${totalComponents} components!`));
726
+ console.log(chalk.cyan(`📁 Components installed to: .claude/`));
727
+
728
+ if (options.yaml) {
729
+ console.log(chalk.cyan(`📄 Workflow file created in: .claude/workflows/`));
730
+ console.log(chalk.cyan(`🚀 Use the workflow file with Claude Code to execute the complete setup`));
731
+ }
732
+
733
+ // Track installation
734
+ trackingService.trackDownload('multi-component', 'batch', {
735
+ installation_type: 'multi-component',
736
+ agents_count: components.agents.length,
737
+ commands_count: components.commands.length,
738
+ mcps_count: components.mcps.length,
739
+ has_yaml: !!options.yaml,
740
+ target_directory: path.relative(process.cwd(), targetDir)
741
+ });
742
+
743
+ // Handle prompt execution if provided
744
+ if (options.prompt) {
745
+ await handlePromptExecution(options.prompt, targetDir);
746
+ }
747
+
748
+ } catch (error) {
749
+ console.log(chalk.red(`❌ Error installing components: ${error.message}`));
750
+ }
751
+ }
752
+
753
+ /**
754
+ * Show available agents organized by category
755
+ */
756
+ async function showAvailableAgents() {
757
+ console.log(chalk.yellow('\n📋 Available Agents:'));
758
+ console.log(chalk.gray('Use format: category/agent-name or just agent-name for root level\n'));
759
+ console.log(chalk.gray('⏳ Fetching latest agents from GitHub...\n'));
760
+
761
+ const agents = await getAvailableAgentsFromGitHub();
762
+
763
+ // Group agents by category
764
+ const groupedAgents = agents.reduce((acc, agent) => {
765
+ const category = agent.category === 'root' ? '🤖 General Agents' : `📁 ${agent.category}`;
766
+ if (!acc[category]) acc[category] = [];
767
+ acc[category].push(agent);
768
+ return acc;
769
+ }, {});
770
+
771
+ // Display agents by category
772
+ Object.entries(groupedAgents).forEach(([category, categoryAgents]) => {
773
+ console.log(chalk.cyan(category));
774
+ categoryAgents.forEach(agent => {
775
+ console.log(chalk.gray(` • ${agent.path}`));
776
+ });
777
+ console.log('');
778
+ });
779
+
780
+ console.log(chalk.blue('Examples:'));
781
+ console.log(chalk.gray(' cct --agent api-security-audit'));
782
+ console.log(chalk.gray(' cct --agent deep-research-team/academic-researcher'));
783
+ console.log('');
784
+ }
785
+
786
+ /**
787
+ * Install workflow from hash
788
+ */
789
+ async function installWorkflow(workflowHash, targetDir, options) {
790
+ console.log(chalk.blue(`🔧 Installing workflow from hash: ${workflowHash}`));
791
+
792
+ try {
793
+ // Extract hash from format #hash
794
+ const hash = workflowHash.startsWith('#') ? workflowHash.substring(1) : workflowHash;
795
+
796
+ if (!hash || hash.length < 3) {
797
+ throw new Error('Invalid workflow hash format. Expected format: #hash');
798
+ }
799
+
800
+ console.log(chalk.gray(`📥 Fetching workflow configuration...`));
801
+
802
+ // Fetch workflow configuration from a remote service
803
+ // For now, we'll simulate this by using a local storage approach
804
+ // In production, this would fetch from a workflow registry
805
+ const workflowData = await fetchWorkflowData(hash);
806
+
807
+ if (!workflowData) {
808
+ throw new Error(`Workflow with hash "${hash}" not found. Please check the hash and try again.`);
809
+ }
810
+
811
+ console.log(chalk.green(`✅ Workflow found: ${workflowData.name}`));
812
+ console.log(chalk.cyan(`📝 Description: ${workflowData.description}`));
813
+ console.log(chalk.cyan(`🏷️ Tags: ${workflowData.tags.join(', ')}`));
814
+ console.log(chalk.cyan(`📊 Steps: ${workflowData.steps.length}`));
815
+
816
+ // Install all required components
817
+ const installPromises = [];
818
+
819
+ // Group components by type
820
+ const agents = workflowData.steps.filter(step => step.type === 'agent');
821
+ const commands = workflowData.steps.filter(step => step.type === 'command');
822
+ const mcps = workflowData.steps.filter(step => step.type === 'mcp');
823
+
824
+ console.log(chalk.blue(`\n📦 Installing workflow components...`));
825
+ console.log(chalk.gray(` Agents: ${agents.length}`));
826
+ console.log(chalk.gray(` Commands: ${commands.length}`));
827
+ console.log(chalk.gray(` MCPs: ${mcps.length}`));
828
+
829
+ // Install components from workflow data (not from GitHub)
830
+ if (workflowData.components) {
831
+ console.log(chalk.blue(`📦 Installing components from workflow package...`));
832
+
833
+ // Install agents
834
+ if (workflowData.components.agent) {
835
+ for (const agent of workflowData.components.agent) {
836
+ console.log(chalk.gray(` Installing agent: ${agent.name}`));
837
+ await installComponentFromWorkflow(agent, 'agent', targetDir, options);
838
+ }
839
+ }
840
+
841
+ // Install commands
842
+ if (workflowData.components.command) {
843
+ for (const command of workflowData.components.command) {
844
+ console.log(chalk.gray(` Installing command: ${command.name}`));
845
+ await installComponentFromWorkflow(command, 'command', targetDir, options);
846
+ }
847
+ }
848
+
849
+ // Install MCPs
850
+ if (workflowData.components.mcp) {
851
+ for (const mcp of workflowData.components.mcp) {
852
+ console.log(chalk.gray(` Installing MCP: ${mcp.name}`));
853
+ await installComponentFromWorkflow(mcp, 'mcp', targetDir, options);
854
+ }
855
+ }
856
+ } else {
857
+ // Fallback to old method for legacy workflows
858
+ console.log(chalk.yellow(`⚠️ Using legacy component installation method...`));
859
+
860
+ // Install agents
861
+ for (const agent of agents) {
862
+ console.log(chalk.gray(` Installing agent: ${agent.name}`));
863
+ await installIndividualAgent(agent.path, targetDir, { ...options, silent: true });
864
+ }
865
+
866
+ // Install commands
867
+ for (const command of commands) {
868
+ console.log(chalk.gray(` Installing command: ${command.name}`));
869
+ await installIndividualCommand(command.path, targetDir, { ...options, silent: true });
870
+ }
871
+ }
872
+
873
+ // Install MCPs
874
+ for (const mcp of mcps) {
875
+ console.log(chalk.gray(` Installing MCP: ${mcp.name}`));
876
+ await installIndividualMCP(mcp.path, targetDir, { ...options, silent: true });
877
+ }
878
+
879
+ // Generate and save workflow YAML
880
+ let yamlContent;
881
+ if (workflowData.yaml) {
882
+ // Use YAML from workflow package
883
+ yamlContent = workflowData.yaml;
884
+ } else {
885
+ // Generate YAML (legacy)
886
+ yamlContent = generateWorkflowYAML(workflowData);
887
+ }
888
+
889
+ const workflowsDir = path.join(targetDir, '.claude', 'workflows');
890
+ const workflowFile = path.join(workflowsDir, `${workflowData.name.replace(/[^a-z0-9]/gi, '_').toLowerCase()}.yaml`);
891
+
892
+ // Ensure .claude/workflows directory exists
893
+ await fs.ensureDir(workflowsDir);
894
+ await fs.writeFile(workflowFile, yamlContent, 'utf8');
895
+
896
+ console.log(chalk.green(`\n✅ Workflow "${workflowData.name}" installed successfully!`));
897
+ console.log(chalk.cyan(`📁 Components installed to: .claude/`));
898
+ console.log(chalk.cyan(`📄 Workflow file: ${path.relative(targetDir, workflowFile)}`));
899
+ console.log(chalk.cyan(`🚀 Use the workflow file with Claude Code to execute the complete workflow`));
900
+
901
+ // Track successful workflow installation
902
+ trackingService.trackDownload('workflow', hash, {
903
+ installation_type: 'workflow',
904
+ workflow_name: workflowData.name,
905
+ components_count: workflowData.steps.length,
906
+ agents_count: agents.length,
907
+ commands_count: commands.length,
908
+ mcps_count: mcps.length,
909
+ target_directory: path.relative(process.cwd(), targetDir)
910
+ });
911
+
912
+ // Handle prompt execution if provided
913
+ if (options.prompt) {
914
+ await handlePromptExecution(options.prompt, targetDir);
915
+ }
916
+
917
+ } catch (error) {
918
+ console.log(chalk.red(`❌ Error installing workflow: ${error.message}`));
919
+
920
+ if (error.message.includes('not found')) {
921
+ console.log(chalk.yellow('\n💡 Possible solutions:'));
922
+ console.log(chalk.gray(' • Check that the workflow hash is correct'));
923
+ console.log(chalk.gray(' • Verify the workflow was generated successfully'));
924
+ console.log(chalk.gray(' • Try generating a new workflow from the builder'));
925
+ }
926
+ }
927
+ }
928
+
929
+ /**
930
+ * Decompress string with Unicode support
931
+ */
932
+ function decompressString(compressed) {
933
+ try {
934
+ // Simple Base64 decoding with Unicode support
935
+ const decoded = Buffer.from(compressed, 'base64').toString('utf8');
936
+ // Convert URI encoded characters back
937
+ return decodeURIComponent(decoded.replace(/(.)/g, function(m, p) {
938
+ let code = p.charCodeAt(0).toString(16).toUpperCase();
939
+ if (code.length < 2) code = '0' + code;
940
+ return '%' + code;
941
+ }));
942
+ } catch (error) {
943
+ throw new Error(`Decompression failed: ${error.message}`);
944
+ }
945
+ }
946
+
947
+ /**
948
+ * Fetch workflow data from hash
949
+ * In production, this would fetch from a remote workflow registry
950
+ * For now, we'll simulate this functionality
951
+ */
952
+ async function fetchWorkflowData(hash) {
953
+ try {
954
+ // Check if hash contains encoded data (new format: shortHash_encodedData)
955
+ if (hash.includes('_')) {
956
+ console.log(chalk.green('🔓 Decoding workflow from hash...'));
957
+
958
+ const [shortHash, encodedData] = hash.split('_', 2);
959
+
960
+ if (!encodedData) {
961
+ throw new Error('Invalid hash format: missing encoded data');
962
+ }
963
+
964
+ // Decode compressed data
965
+ let decodedData;
966
+ try {
967
+ // First try to decompress the data (new compressed format)
968
+ const decompressedString = decompressString(encodedData);
969
+ decodedData = JSON.parse(decompressedString);
970
+ } catch (decompressError) {
971
+ // Fallback to old Base64 format for compatibility
972
+ try {
973
+ const decodedString = decodeURIComponent(escape(atob(encodedData)));
974
+ decodedData = JSON.parse(decodedString);
975
+ } catch (base64Error) {
976
+ throw new Error('Failed to decode workflow data from hash');
977
+ }
978
+ }
979
+
980
+ // Validate decoded data structure
981
+ if (!decodedData.metadata || !decodedData.steps || !decodedData.components) {
982
+ throw new Error('Invalid workflow data structure in hash');
983
+ }
984
+
985
+ console.log(chalk.green('✅ Workflow decoded successfully!'));
986
+ console.log(chalk.gray(` Short hash: ${shortHash}`));
987
+ console.log(chalk.gray(` Timestamp: ${decodedData.timestamp}`));
988
+ console.log(chalk.gray(` Version: ${decodedData.version}`));
989
+
990
+ // Convert to expected format
991
+ return {
992
+ name: decodedData.metadata.name,
993
+ description: decodedData.metadata.description,
994
+ tags: decodedData.metadata.tags || [],
995
+ version: decodedData.version,
996
+ hash: shortHash,
997
+ steps: decodedData.steps,
998
+ components: decodedData.components,
999
+ yaml: decodedData.yaml,
1000
+ timestamp: decodedData.timestamp
1001
+ };
1002
+ }
1003
+
1004
+ // Legacy demo workflows for testing
1005
+ if (hash === 'demo123' || hash === 'abc123test') {
1006
+ console.log(chalk.green('🎯 Demo workflow found! Using sample configuration...'));
1007
+ return {
1008
+ name: 'Full Stack Development Workflow',
1009
+ description: 'Complete workflow for setting up a full-stack development environment with React frontend, Node.js backend, and security auditing',
1010
+ tags: ['development', 'fullstack', 'react', 'security'],
1011
+ version: '1.0.0',
1012
+ hash: hash,
1013
+ steps: [
1014
+ {
1015
+ type: 'agent',
1016
+ name: 'frontend-developer',
1017
+ path: 'development-team/frontend-developer',
1018
+ category: 'development-team',
1019
+ description: 'Setup React frontend development environment'
1020
+ },
1021
+ {
1022
+ type: 'agent',
1023
+ name: 'backend-architect',
1024
+ path: 'development-team/backend-architect',
1025
+ category: 'development-team',
1026
+ description: 'Configure Node.js backend architecture'
1027
+ },
1028
+ {
1029
+ type: 'command',
1030
+ name: 'generate-tests',
1031
+ path: 'testing/generate-tests',
1032
+ category: 'testing',
1033
+ description: 'Generate comprehensive test suite'
1034
+ },
1035
+ {
1036
+ type: 'agent',
1037
+ name: 'api-security-audit',
1038
+ path: 'security/api-security-audit',
1039
+ category: 'security',
1040
+ description: 'Perform security audit on APIs'
1041
+ },
1042
+ {
1043
+ type: 'mcp',
1044
+ name: 'github-integration',
1045
+ path: 'integration/github-integration',
1046
+ category: 'integration',
1047
+ description: 'Setup GitHub integration for repository management'
1048
+ }
1049
+ ]
1050
+ };
1051
+ }
1052
+
1053
+ // This is where we would integrate with a workflow registry API
1054
+ // For now, return null to indicate workflow not found for other hashes
1055
+ console.log(chalk.yellow('\n⚠️ Workflow registry not yet implemented.'));
1056
+ console.log(chalk.gray('To test with demo workflow, use hash: demo123'));
1057
+ console.log(chalk.gray('Example: --workflow "#demo123"'));
1058
+
1059
+ return null;
1060
+
1061
+ } catch (error) {
1062
+ console.error(chalk.red(`❌ Error fetching workflow data: ${error.message}`));
1063
+ return null;
1064
+ }
1065
+ }
1066
+
1067
+ /**
1068
+ * Install component from workflow package data
1069
+ */
1070
+ async function installComponentFromWorkflow(componentData, type, targetDir, options) {
1071
+ try {
1072
+ let targetPath;
1073
+ let fileName = componentData.name;
1074
+
1075
+ if (type === 'agent') {
1076
+ // Create .claude/agents directory if it doesn't exist
1077
+ const agentsDir = path.join(targetDir, '.claude', 'agents');
1078
+ await fs.ensureDir(agentsDir);
1079
+
1080
+ // For agents, handle category subdirectories
1081
+ if (componentData.category && componentData.category !== 'general') {
1082
+ const categoryDir = path.join(agentsDir, componentData.category);
1083
+ await fs.ensureDir(categoryDir);
1084
+ targetPath = path.join(categoryDir, `${fileName}.md`);
1085
+ } else {
1086
+ targetPath = path.join(agentsDir, `${fileName}.md`);
1087
+ }
1088
+
1089
+ } else if (type === 'command') {
1090
+ // Create .claude/commands directory if it doesn't exist
1091
+ const commandsDir = path.join(targetDir, '.claude', 'commands');
1092
+ await fs.ensureDir(commandsDir);
1093
+ targetPath = path.join(commandsDir, `${fileName}.md`);
1094
+
1095
+ } else if (type === 'mcp') {
1096
+ // For MCPs, merge with existing .mcp.json
1097
+ const targetMcpFile = path.join(targetDir, '.mcp.json');
1098
+ let existingConfig = {};
1099
+
1100
+ if (await fs.pathExists(targetMcpFile)) {
1101
+ existingConfig = await fs.readJson(targetMcpFile);
1102
+ }
1103
+
1104
+ // Parse MCP content and merge
1105
+ let mcpConfig;
1106
+ try {
1107
+ mcpConfig = JSON.parse(componentData.content);
1108
+ } catch (error) {
1109
+ throw new Error(`Failed to parse MCP content for ${componentData.name}: ${error.message}`);
1110
+ }
1111
+
1112
+ // Remove description field before merging (CLI processing)
1113
+ if (mcpConfig.mcpServers) {
1114
+ for (const serverName in mcpConfig.mcpServers) {
1115
+ if (mcpConfig.mcpServers[serverName] && typeof mcpConfig.mcpServers[serverName] === 'object') {
1116
+ delete mcpConfig.mcpServers[serverName].description;
1117
+ }
1118
+ }
1119
+ }
1120
+
1121
+ // Merge configurations
1122
+ const mergedConfig = {
1123
+ ...existingConfig,
1124
+ ...mcpConfig
1125
+ };
1126
+
1127
+ // Deep merge mcpServers
1128
+ if (existingConfig.mcpServers && mcpConfig.mcpServers) {
1129
+ mergedConfig.mcpServers = {
1130
+ ...existingConfig.mcpServers,
1131
+ ...mcpConfig.mcpServers
1132
+ };
1133
+ }
1134
+
1135
+ await fs.writeJson(targetMcpFile, mergedConfig, { spaces: 2 });
1136
+ return;
1137
+ }
1138
+
1139
+ // Write content for agents and commands
1140
+ if (targetPath) {
1141
+ await fs.writeFile(targetPath, componentData.content, 'utf8');
1142
+ }
1143
+
1144
+ } catch (error) {
1145
+ console.error(chalk.red(`❌ Error installing ${type} "${componentData.name}": ${error.message}`));
1146
+ throw error;
1147
+ }
1148
+ }
1149
+
1150
+ /**
1151
+ * Generate workflow YAML from workflow data
1152
+ */
1153
+ function generateWorkflowYAML(workflowData) {
1154
+ const yaml = `#═══════════════════════════════════════════════════════════════════════════════
1155
+ # 🤖 CLAUDE CODE WORKFLOW CONFIGURATION
1156
+ #═══════════════════════════════════════════════════════════════════════════════
1157
+ #
1158
+ # WORKFLOW: ${workflowData.name}
1159
+ # DESCRIPTION: ${workflowData.description}
1160
+ # GENERATED: ${new Date().toISOString()}
1161
+ # HASH: ${workflowData.hash || 'generated'}
1162
+ #
1163
+ #═══════════════════════════════════════════════════════════════════════════════
1164
+ # 📋 INSTRUCTIONS FOR CLAUDE CODE
1165
+ #═══════════════════════════════════════════════════════════════════════════════
1166
+ #
1167
+ # This is a WORKFLOW EXECUTION FILE for Claude Code. When you encounter this file,
1168
+ # you should execute it as a complete automated workflow. Here's how:
1169
+ #
1170
+ # 🎯 EXECUTION BEHAVIOR:
1171
+ # 1. READ this entire YAML file to understand the workflow structure
1172
+ # 2. EXECUTE each step in the exact order listed below (sequential mode)
1173
+ # 3. For AGENTS: Use the agent specified to perform the task described
1174
+ # 4. For COMMANDS: Execute the Claude Code command as specified
1175
+ # 5. For MCPs: Ensure the MCP server is available and use it as needed
1176
+ # 6. STOP if any step fails (on_error: stop)
1177
+ # 7. PROVIDE progress updates after each step completion
1178
+ #
1179
+ # 🔧 STEP EXECUTION PATTERN:
1180
+ # - Announce: "Executing Step X: [step.name]"
1181
+ # - Action: Perform the task using the specified component
1182
+ # - Confirm: "✅ Step X completed successfully"
1183
+ # - Continue to next step
1184
+ #
1185
+ # 💡 IMPORTANT NOTES:
1186
+ # - All components are already installed in .claude/ directories
1187
+ # - Each step builds upon the previous ones
1188
+ # - Follow the descriptions exactly as specified
1189
+ # - Use confirmation_required: true for user approval before starting
1190
+ # - Maintain context and outputs between steps for workflow continuity
1191
+ #
1192
+ #═══════════════════════════════════════════════════════════════════════════════
1193
+
1194
+ name: "${workflowData.name}"
1195
+ description: "${workflowData.description}"
1196
+ tags: [${workflowData.tags.map(tag => `"${tag}"`).join(', ')}]
1197
+ version: "${workflowData.version || '1.0.0'}"
1198
+
1199
+ #═══════════════════════════════════════════════════════════════════════════════
1200
+ # 🚀 WORKFLOW STEPS - EXECUTE IN ORDER
1201
+ #═══════════════════════════════════════════════════════════════════════════════
1202
+
1203
+ steps:
1204
+ ${workflowData.steps.map((step, index) => ` - step: ${index + 1}
1205
+ type: ${step.type}
1206
+ name: "${step.name}"
1207
+ path: "${step.path}"
1208
+ category: "${step.category}"
1209
+ description: "${step.description}"
1210
+
1211
+ # CLAUDE CODE INSTRUCTIONS FOR THIS STEP:
1212
+ claude_instructions: |
1213
+ Execute this step using the ${step.type} located at .claude/${step.type}s/${step.name}.${step.type === 'mcp' ? 'json' : 'md'}
1214
+ Task: ${step.description}
1215
+ ${step.type === 'agent' ? 'Use this agent to perform the specified task with full context from previous steps.' : ''}
1216
+ ${step.type === 'command' ? 'Execute this command with appropriate parameters based on workflow context.' : ''}
1217
+ ${step.type === 'mcp' ? 'Ensure MCP server is running and utilize its capabilities for the task.' : ''}
1218
+
1219
+ action_template: |
1220
+ echo "🔄 Executing Step ${index + 1}: ${step.name}"
1221
+ echo "📝 Task: ${step.description}"
1222
+ echo "🎯 Using ${step.type}: ${step.path}"
1223
+ # [CLAUDE CODE WILL REPLACE THIS WITH ACTUAL EXECUTION]
1224
+ echo "✅ Step ${index + 1} completed successfully"
1225
+ `).join('\n')}
1226
+
1227
+ #═══════════════════════════════════════════════════════════════════════════════
1228
+ # ⚙️ EXECUTION CONFIGURATION
1229
+ #═══════════════════════════════════════════════════════════════════════════════
1230
+
1231
+ execution:
1232
+ mode: "sequential" # Execute steps one by one, in order
1233
+ on_error: "stop" # Stop workflow if any step fails
1234
+ timeout: 300 # Maximum time per step (5 minutes)
1235
+ continue_on_warning: true # Continue if warnings occur
1236
+ save_outputs: true # Save outputs between steps for context
1237
+
1238
+ #═══════════════════════════════════════════════════════════════════════════════
1239
+ # 📦 INSTALLED COMPONENTS REFERENCE
1240
+ #═══════════════════════════════════════════════════════════════════════════════
1241
+
1242
+ components:
1243
+ agents: [${workflowData.steps.filter(s => s.type === 'agent').map(s => `"${s.path}"`).join(', ')}]
1244
+ commands: [${workflowData.steps.filter(s => s.type === 'command').map(s => `"${s.path}"`).join(', ')}]
1245
+ mcps: [${workflowData.steps.filter(s => s.type === 'mcp').map(s => `"${s.path}"`).join(', ')}]
1246
+
1247
+ #═══════════════════════════════════════════════════════════════════════════════
1248
+ # 🤖 CLAUDE CODE INTEGRATION SETTINGS
1249
+ #═══════════════════════════════════════════════════════════════════════════════
1250
+
1251
+ claudecode:
1252
+ workflow_mode: true # Enable workflow execution mode
1253
+ auto_execute: false # Require user confirmation before starting
1254
+ confirmation_required: true # Ask user before each step
1255
+ show_progress: true # Display progress indicators
1256
+ save_context: true # Maintain context between steps
1257
+
1258
+ # WORKFLOW EXECUTION INSTRUCTIONS FOR CLAUDE:
1259
+ execution_instructions: |
1260
+ When executing this workflow:
1261
+
1262
+ 1. 🎯 PREPARATION PHASE:
1263
+ - Confirm all components are installed in .claude/ directories
1264
+ - Verify user wants to execute this workflow
1265
+ - Explain what will happen in each step
1266
+
1267
+ 2. 🚀 EXECUTION PHASE:
1268
+ - Execute each step sequentially
1269
+ - Use the exact agent/command/mcp specified for each step
1270
+ - Maintain outputs and context between steps
1271
+ - Provide clear progress updates
1272
+
1273
+ 3. ✅ COMPLETION PHASE:
1274
+ - Summarize what was accomplished
1275
+ - Highlight any outputs or files created
1276
+ - Suggest next steps if applicable
1277
+
1278
+ 4. ❌ ERROR HANDLING:
1279
+ - If a step fails, stop execution immediately
1280
+ - Provide clear error message and suggested fixes
1281
+ - Offer to retry the failed step after fixes
1282
+
1283
+ Remember: This workflow was designed to work as a complete automation.
1284
+ Each step builds upon the previous ones. Execute with confidence!
1285
+
1286
+ #═══════════════════════════════════════════════════════════════════════════════
1287
+ # 📋 WORKFLOW SUMMARY
1288
+ #═══════════════════════════════════════════════════════════════════════════════
1289
+ #
1290
+ # This workflow will execute ${workflowData.steps.length} steps in sequence:
1291
+ ${workflowData.steps.map((step, index) => `# ${index + 1}. ${step.description} (${step.type}: ${step.name})`).join('\n')}
1292
+ #
1293
+ # Total estimated time: ${Math.ceil(workflowData.steps.length * 2)} minutes
1294
+ # Components required: ${workflowData.steps.filter(s => s.type === 'agent').length} agents, ${workflowData.steps.filter(s => s.type === 'command').length} commands, ${workflowData.steps.filter(s => s.type === 'mcp').length} MCPs
1295
+ #═══════════════════════════════════════════════════════════════════════════════
1296
+ `;
1297
+
1298
+ return yaml;
1299
+ }
1300
+
1301
+ /**
1302
+ * Handle prompt execution in Claude Code
1303
+ */
1304
+ async function handlePromptExecution(prompt, targetDir) {
1305
+ console.log(chalk.blue('\n🎯 Prompt execution requested...'));
1306
+
1307
+ // Ask user if they want to execute the prompt in Claude Code
1308
+ const { shouldExecute } = await inquirer.prompt([{
1309
+ type: 'confirm',
1310
+ name: 'shouldExecute',
1311
+ message: `Do you want to execute this prompt in Claude Code?\n${chalk.cyan(`"${prompt}"`)}`,
1312
+ default: true
1313
+ }]);
1314
+
1315
+ if (!shouldExecute) {
1316
+ console.log(chalk.yellow('⏹️ Prompt execution skipped by user.'));
1317
+ return;
1318
+ }
1319
+
1320
+ console.log(chalk.blue('🚀 Preparing to launch Claude Code with your prompt...'));
1321
+
1322
+ try {
1323
+ // Check if claude command is available in PATH
1324
+ const { spawn } = require('child_process');
1325
+ const open = require('open');
1326
+
1327
+ // First try to execute claude command directly
1328
+ const claudeProcess = spawn('claude', [prompt], {
1329
+ cwd: targetDir,
1330
+ stdio: ['inherit', 'inherit', 'inherit'],
1331
+ shell: true
1332
+ });
1333
+
1334
+ claudeProcess.on('error', async (error) => {
1335
+ if (error.code === 'ENOENT') {
1336
+ // Claude command not found, try alternative approaches
1337
+ console.log(chalk.yellow('⚠️ Claude Code CLI not found in PATH.'));
1338
+ console.log(chalk.blue('💡 Alternative ways to execute your prompt:'));
1339
+ console.log(chalk.gray(' 1. Install Claude Code CLI: https://claude.ai/code'));
1340
+ console.log(chalk.gray(' 2. Copy and paste this prompt in Claude Code interface:'));
1341
+ console.log(chalk.cyan(`\n "${prompt}"\n`));
1342
+
1343
+ // Ask if user wants to open Claude Code web interface
1344
+ const { openWeb } = await inquirer.prompt([{
1345
+ type: 'confirm',
1346
+ name: 'openWeb',
1347
+ message: 'Would you like to open Claude Code in your browser?',
1348
+ default: true
1349
+ }]);
1350
+
1351
+ if (openWeb) {
1352
+ await open('https://claude.ai/code');
1353
+ console.log(chalk.green('✅ Claude Code opened in your browser!'));
1354
+ console.log(chalk.cyan(`Don't forget to paste your prompt: "${prompt}"`));
1355
+ }
1356
+ } else {
1357
+ throw error;
1358
+ }
1359
+ });
1360
+
1361
+ claudeProcess.on('close', (code) => {
1362
+ if (code === 0) {
1363
+ console.log(chalk.green('✅ Claude Code executed successfully!'));
1364
+ } else if (code !== null) {
1365
+ console.log(chalk.yellow(`⚠️ Claude Code exited with code ${code}`));
1366
+ }
1367
+ });
1368
+
1369
+ } catch (error) {
1370
+ console.log(chalk.red(`❌ Error executing prompt: ${error.message}`));
1371
+ console.log(chalk.blue('💡 You can manually execute this prompt in Claude Code:'));
1372
+ console.log(chalk.cyan(`"${prompt}"`));
1373
+ }
1374
+ }
1375
+
488
1376
  module.exports = { createClaudeConfig, showMainMenu };