claude-code-templates 1.4.3 → 1.5.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.
@@ -0,0 +1,258 @@
1
+ const fs = require('fs-extra');
2
+ const path = require('path');
3
+ const chalk = require('chalk');
4
+ const inquirer = require('inquirer');
5
+ const { spawn } = require('child_process');
6
+
7
+ function estimateTokens(text) {
8
+ if (!text || typeof text !== 'string') return 0;
9
+
10
+ // Clean the text and estimate tokens
11
+ const cleanText = text.replace(/\s+/g, ' ').trim();
12
+ const baseTokens = Math.ceil(cleanText.length / 4);
13
+
14
+ // Add extra tokens for code blocks and complex structures
15
+ const codeBlocks = (text.match(/```[\s\S]*?```/g) || []).length;
16
+ const inlineCode = (text.match(/`[^`]+`/g) || []).length;
17
+ const jsonBlocks = (text.match(/\{[\s\S]*?\}/g) || []).length;
18
+
19
+ const adjustedTokens = baseTokens + (codeBlocks * 5) + (inlineCode * 2) + (jsonBlocks * 3);
20
+ return Math.max(adjustedTokens, 1);
21
+ }
22
+
23
+ async function analyzeHooks(targetDir = process.cwd()) {
24
+ const settingsPath = path.join(targetDir, '.claude', 'settings.json');
25
+
26
+ console.log(chalk.blue('šŸ” Analyzing automation hooks...'));
27
+ console.log(chalk.gray(`Scanning: ${settingsPath}`));
28
+
29
+ if (!await fs.pathExists(settingsPath)) {
30
+ console.log(chalk.yellow('āš ļø No .claude/settings.json file found.'));
31
+ return null;
32
+ }
33
+
34
+ try {
35
+ const settingsContent = await fs.readFile(settingsPath, 'utf8');
36
+ const settings = JSON.parse(settingsContent);
37
+
38
+ if (!settings.hooks || Object.keys(settings.hooks).length === 0) {
39
+ console.log(chalk.yellow('āš ļø No automation hooks found in settings.json.'));
40
+ return null;
41
+ }
42
+
43
+ const hookAnalysis = {
44
+ totalHooks: 0,
45
+ byType: {},
46
+ hooks: []
47
+ };
48
+
49
+ // Analyze each hook type
50
+ for (const [hookType, hooks] of Object.entries(settings.hooks)) {
51
+ if (!Array.isArray(hooks)) continue;
52
+
53
+ hookAnalysis.byType[hookType] = {
54
+ count: hooks.length,
55
+ hooks: []
56
+ };
57
+
58
+ for (const hook of hooks) {
59
+ const hookData = {
60
+ type: hookType,
61
+ name: hook.name || 'Unnamed Hook',
62
+ description: hook.description || '',
63
+ scriptContent: hook.script || hook.command || '',
64
+ enabled: hook.enabled !== false, // Default to true if not specified
65
+ conditions: hook.conditions || [],
66
+ size: JSON.stringify(hook).length,
67
+ lines: (hook.script || hook.command || '').split('\n').length,
68
+ words: (hook.script || hook.command || '').split(/\s+/).filter(word => word.length > 0).length,
69
+ tokens: estimateTokens(JSON.stringify(hook))
70
+ };
71
+
72
+ hookAnalysis.byType[hookType].hooks.push(hookData);
73
+ hookAnalysis.hooks.push(hookData);
74
+ hookAnalysis.totalHooks++;
75
+ }
76
+ }
77
+
78
+ // Get file stats
79
+ const stats = await fs.stat(settingsPath);
80
+ hookAnalysis.fileSize = stats.size;
81
+ hookAnalysis.lastModified = stats.mtime;
82
+
83
+ return hookAnalysis;
84
+
85
+ } catch (error) {
86
+ console.error(chalk.red('āŒ Error reading settings.json:'), error.message);
87
+ return null;
88
+ }
89
+ }
90
+
91
+ function displayHookStats(analysis) {
92
+ if (!analysis || analysis.totalHooks === 0) {
93
+ console.log(chalk.yellow('\nšŸ“Š Hook Analysis Results'));
94
+ console.log(chalk.gray('No automation hooks found to analyze.'));
95
+ return;
96
+ }
97
+
98
+ console.log(chalk.blue('\nšŸ“Š Hook Analysis Results'));
99
+ console.log(chalk.gray(`File: .claude/settings.json (${analysis.fileSize} bytes)`));
100
+ console.log(chalk.gray(`Last Modified: ${analysis.lastModified.toLocaleDateString()}`));
101
+ console.log(chalk.gray(`Total Hooks: ${analysis.totalHooks}`));
102
+
103
+ // Calculate column widths
104
+ const maxNameLength = Math.max(
105
+ ...analysis.hooks.map(hook => hook.name.length),
106
+ 'Hook Name'.length
107
+ );
108
+ const nameWidth = Math.min(maxNameLength, 30);
109
+
110
+ // Header
111
+ const header = chalk.bold.blue(
112
+ 'Hook Name'.padEnd(nameWidth) + ' │ ' +
113
+ 'Type'.padEnd(12) + ' │ ' +
114
+ 'Status'.padEnd(8) + ' │ ' +
115
+ 'Description'
116
+ );
117
+
118
+ const separator = '─'.repeat(nameWidth) + '─┼─' +
119
+ '─'.repeat(12) + '─┼─' +
120
+ '─'.repeat(8) + '─┼─' +
121
+ '─'.repeat(40);
122
+
123
+ console.log('\n' + header);
124
+ console.log(chalk.gray(separator));
125
+
126
+ // Hook rows
127
+ analysis.hooks.forEach(hook => {
128
+ const truncatedName = hook.name.length > nameWidth ?
129
+ hook.name.substring(0, nameWidth - 3) + '...' :
130
+ hook.name;
131
+
132
+ const statusColor = hook.enabled ? chalk.green : chalk.yellow;
133
+ const status = hook.enabled ? 'Enabled' : 'Disabled';
134
+
135
+ const truncatedDesc = hook.description.length > 40 ?
136
+ hook.description.substring(0, 37) + '...' :
137
+ hook.description;
138
+
139
+ const row =
140
+ truncatedName.padEnd(nameWidth) + ' │ ' +
141
+ hook.type.padEnd(12) + ' │ ' +
142
+ statusColor(status.padEnd(8)) + ' │ ' +
143
+ chalk.gray(truncatedDesc);
144
+
145
+ console.log(row);
146
+ });
147
+
148
+ // Summary by type
149
+ console.log(chalk.blue('\nšŸ“ˆ Hook Summary by Type:'));
150
+ for (const [type, data] of Object.entries(analysis.byType)) {
151
+ const enabledCount = data.hooks.filter(h => h.enabled).length;
152
+ const disabledCount = data.hooks.filter(h => !h.enabled).length;
153
+
154
+ console.log(chalk.gray(` ${type}: ${data.count} hooks`) +
155
+ chalk.green(` (${enabledCount} enabled`) +
156
+ (disabledCount > 0 ? chalk.yellow(`, ${disabledCount} disabled)`) : chalk.green(')')));
157
+ }
158
+
159
+ console.log(chalk.blue('\nšŸ”§ Hook Types Found:'));
160
+ Object.keys(analysis.byType).forEach(type => {
161
+ console.log(chalk.gray(` • ${type}`));
162
+ });
163
+ }
164
+
165
+ async function runHookStats(options) {
166
+ const targetDir = options.directory || process.cwd();
167
+
168
+ console.log(chalk.blue('šŸ”§ Claude Code Hook Analysis'));
169
+ console.log(chalk.gray(`Target directory: ${targetDir}`));
170
+
171
+ const analysis = await analyzeHooks(targetDir);
172
+
173
+ if (!analysis) {
174
+ console.log(chalk.yellow('\nšŸ’” No automation hooks found.'));
175
+ console.log(chalk.gray('Would you like to set up Claude Code Templates to add automation hooks?'));
176
+
177
+ const { setupHooks } = await inquirer.prompt([{
178
+ type: 'confirm',
179
+ name: 'setupHooks',
180
+ message: 'Set up automation hooks with Claude Code Templates?',
181
+ default: true
182
+ }]);
183
+
184
+ if (setupHooks) {
185
+ console.log(chalk.blue('\nšŸš€ Starting Claude Code Templates setup...'));
186
+
187
+ // Import and run the main setup
188
+ const createClaudeConfig = require('./index');
189
+ await createClaudeConfig({ ...options, directory: targetDir });
190
+ }
191
+ return;
192
+ }
193
+
194
+ displayHookStats(analysis);
195
+
196
+ // Ask if user wants Claude Code to review and optimize hooks
197
+ console.log(chalk.blue('\nšŸ¤– Optimization Opportunity'));
198
+ console.log(chalk.gray('Claude Code can analyze your automation hooks and suggest optimizations.'));
199
+
200
+ const { optimizeHooks } = await inquirer.prompt([{
201
+ type: 'confirm',
202
+ name: 'optimizeHooks',
203
+ message: 'Would you like Claude Code to review and optimize your automation hooks?',
204
+ default: true
205
+ }]);
206
+
207
+ if (optimizeHooks) {
208
+ console.log(chalk.blue('\nšŸ” Launching Claude Code for hook optimization...'));
209
+
210
+ // Prepare the optimization prompt
211
+ const hookSummary = `I have ${analysis.totalHooks} automation hooks configured in my .claude/settings.json file:
212
+
213
+ ${Object.entries(analysis.byType).map(([type, data]) =>
214
+ `${type}: ${data.count} hooks (${data.hooks.filter(h => h.enabled).length} enabled, ${data.hooks.filter(h => !h.enabled).length} disabled)`
215
+ ).join('\n')}
216
+
217
+ Hook details:
218
+ ${analysis.hooks.map(hook =>
219
+ `- ${hook.name} (${hook.type}): ${hook.enabled ? 'Enabled' : 'Disabled'} - ${hook.tokens} tokens - ${hook.description || 'No description'}`
220
+ ).join('\n')}
221
+
222
+ Please review my automation hook configuration and suggest optimizations for:
223
+ 1. Hook efficiency and performance
224
+ 2. Missing hooks that could improve my workflow
225
+ 3. Hooks that might be redundant or conflicting
226
+ 4. Best practices for hook organization
227
+ 5. Security considerations for the hooks
228
+ 6. Hook conditions and triggers optimization
229
+
230
+ Consider my project structure and suggest hooks that would be most beneficial for my development workflow.`;
231
+
232
+ const claudeCommand = `claude "${hookSummary}"`;
233
+
234
+ try {
235
+ const child = spawn('sh', ['-c', claudeCommand], {
236
+ stdio: 'inherit',
237
+ cwd: targetDir
238
+ });
239
+
240
+ child.on('error', (error) => {
241
+ console.error(chalk.red('āŒ Error launching Claude Code:'), error.message);
242
+ console.log(chalk.yellow('šŸ’” Make sure Claude Code is installed: npm install -g @anthropic-ai/claude-code'));
243
+ });
244
+
245
+ } catch (error) {
246
+ console.error(chalk.red('āŒ Error launching Claude Code:'), error.message);
247
+ console.log(chalk.yellow('šŸ’” Make sure Claude Code is installed and accessible.'));
248
+ }
249
+ } else {
250
+ console.log(chalk.gray('\nāœ… Hook analysis complete. You can run this command again anytime to re-analyze your hooks.'));
251
+ }
252
+ }
253
+
254
+ module.exports = {
255
+ runHookStats,
256
+ analyzeHooks,
257
+ displayHookStats
258
+ };
package/src/index.js CHANGED
@@ -9,16 +9,37 @@ const { createPrompts, interactivePrompts } = require('./prompts');
9
9
  const { copyTemplateFiles, runPostInstallationValidation } = require('./file-operations');
10
10
  const { getHooksForLanguage, getMCPsForLanguage } = require('./hook-scanner');
11
11
  const { runCommandStats } = require('./command-stats');
12
+ const { runHookStats } = require('./hook-stats');
13
+ const { runMCPStats } = require('./mcp-stats');
14
+ const { runAnalytics } = require('./analytics');
12
15
 
13
16
  async function createClaudeConfig(options = {}) {
14
17
  const targetDir = options.directory || process.cwd();
15
18
 
16
- // Handle command stats analysis
17
- if (options.commandStats) {
19
+ // Handle command stats analysis (both singular and plural)
20
+ if (options.commandStats || options.commandsStats) {
18
21
  await runCommandStats(options);
19
22
  return;
20
23
  }
21
24
 
25
+ // Handle hook stats analysis (both singular and plural)
26
+ if (options.hookStats || options.hooksStats) {
27
+ await runHookStats(options);
28
+ return;
29
+ }
30
+
31
+ // Handle MCP stats analysis (both singular and plural)
32
+ if (options.mcpStats || options.mcpsStats) {
33
+ await runMCPStats(options);
34
+ return;
35
+ }
36
+
37
+ // Handle analytics dashboard
38
+ if (options.analytics) {
39
+ await runAnalytics(options);
40
+ return;
41
+ }
42
+
22
43
  console.log(chalk.blue('šŸš€ Setting up Claude Code configuration...'));
23
44
  console.log(chalk.gray(`Target directory: ${targetDir}`));
24
45
 
@@ -0,0 +1,321 @@
1
+ const fs = require('fs-extra');
2
+ const path = require('path');
3
+ const chalk = require('chalk');
4
+ const inquirer = require('inquirer');
5
+ const { spawn } = require('child_process');
6
+
7
+ async function analyzeMCPServers(targetDir = process.cwd()) {
8
+ const mcpConfigPath = path.join(targetDir, '.mcp.json');
9
+
10
+ console.log(chalk.blue('šŸ” Analyzing MCP server configurations...'));
11
+ console.log(chalk.gray(`Scanning: ${mcpConfigPath}`));
12
+
13
+ if (!await fs.pathExists(mcpConfigPath)) {
14
+ console.log(chalk.yellow('āš ļø No .mcp.json file found.'));
15
+ return null;
16
+ }
17
+
18
+ try {
19
+ const mcpContent = await fs.readFile(mcpConfigPath, 'utf8');
20
+ const mcpConfig = JSON.parse(mcpContent);
21
+
22
+ if (!mcpConfig.mcpServers || Object.keys(mcpConfig.mcpServers).length === 0) {
23
+ console.log(chalk.yellow('āš ļø No MCP servers found in .mcp.json.'));
24
+ return null;
25
+ }
26
+
27
+ const mcpAnalysis = {
28
+ totalServers: 0,
29
+ servers: [],
30
+ byCategory: {}
31
+ };
32
+
33
+ // Analyze each MCP server
34
+ for (const [serverKey, serverConfig] of Object.entries(mcpConfig.mcpServers)) {
35
+ const serverData = {
36
+ key: serverKey,
37
+ name: serverConfig.name || serverKey,
38
+ description: serverConfig.description || 'No description provided',
39
+ command: serverConfig.command || 'Unknown',
40
+ args: serverConfig.args || [],
41
+ env: serverConfig.env || {},
42
+ enabled: serverConfig.disabled !== true, // Default to enabled unless explicitly disabled
43
+ category: categorizeServer(serverConfig),
44
+ configSize: JSON.stringify(serverConfig).length,
45
+ complexity: calculateComplexity(serverConfig)
46
+ };
47
+
48
+ mcpAnalysis.servers.push(serverData);
49
+ mcpAnalysis.totalServers++;
50
+
51
+ // Group by category
52
+ if (!mcpAnalysis.byCategory[serverData.category]) {
53
+ mcpAnalysis.byCategory[serverData.category] = [];
54
+ }
55
+ mcpAnalysis.byCategory[serverData.category].push(serverData);
56
+ }
57
+
58
+ // Get file stats
59
+ const stats = await fs.stat(mcpConfigPath);
60
+ mcpAnalysis.fileSize = stats.size;
61
+ mcpAnalysis.lastModified = stats.mtime;
62
+
63
+ return mcpAnalysis;
64
+
65
+ } catch (error) {
66
+ console.error(chalk.red('āŒ Error reading .mcp.json:'), error.message);
67
+ return null;
68
+ }
69
+ }
70
+
71
+ function categorizeServer(serverConfig) {
72
+ const name = (serverConfig.name || '').toLowerCase();
73
+ const command = (serverConfig.command || '').toLowerCase();
74
+ const description = (serverConfig.description || '').toLowerCase();
75
+
76
+ // IDE and Development Tools
77
+ if (name.includes('ide') || name.includes('vscode') || name.includes('jupyter') ||
78
+ command.includes('jupyter') || description.includes('ide')) {
79
+ return 'IDE & Development';
80
+ }
81
+
82
+ // Database Tools
83
+ if (name.includes('postgres') || name.includes('mysql') || name.includes('sqlite') ||
84
+ name.includes('database') || description.includes('database')) {
85
+ return 'Database';
86
+ }
87
+
88
+ // Web and API Tools
89
+ if (name.includes('web') || name.includes('search') || name.includes('api') ||
90
+ name.includes('http') || description.includes('web') || description.includes('search')) {
91
+ return 'Web & API';
92
+ }
93
+
94
+ // File System Tools
95
+ if (name.includes('file') || name.includes('filesystem') ||
96
+ description.includes('file') || description.includes('filesystem')) {
97
+ return 'Filesystem';
98
+ }
99
+
100
+ // Development Tools
101
+ if (name.includes('git') || name.includes('docker') || name.includes('github') ||
102
+ description.includes('git') || description.includes('docker')) {
103
+ return 'DevOps';
104
+ }
105
+
106
+ // AI and ML Tools
107
+ if (name.includes('ai') || name.includes('ml') || name.includes('model') ||
108
+ description.includes('ai') || description.includes('machine learning')) {
109
+ return 'AI & ML';
110
+ }
111
+
112
+ return 'Other';
113
+ }
114
+
115
+ function calculateComplexity(serverConfig) {
116
+ let complexity = 1; // Base complexity
117
+
118
+ // Add complexity for configuration options
119
+ if (serverConfig.args && serverConfig.args.length > 0) complexity += 1;
120
+ if (serverConfig.env && Object.keys(serverConfig.env).length > 0) complexity += 1;
121
+ if (serverConfig.settings && Object.keys(serverConfig.settings).length > 0) complexity += 1;
122
+
123
+ // Add complexity for environment variables
124
+ const envCount = Object.keys(serverConfig.env || {}).length;
125
+ if (envCount > 3) complexity += 1;
126
+ if (envCount > 6) complexity += 1;
127
+
128
+ return Math.min(complexity, 5); // Cap at 5
129
+ }
130
+
131
+ function displayMCPStats(analysis) {
132
+ if (!analysis || analysis.totalServers === 0) {
133
+ console.log(chalk.yellow('\nšŸ“Š MCP Server Analysis Results'));
134
+ console.log(chalk.gray('No MCP servers found to analyze.'));
135
+ return;
136
+ }
137
+
138
+ console.log(chalk.blue('\nšŸ“Š MCP Server Analysis Results'));
139
+ console.log(chalk.gray(`File: .mcp.json (${analysis.fileSize} bytes)`));
140
+ console.log(chalk.gray(`Last Modified: ${analysis.lastModified.toLocaleDateString()}`));
141
+ console.log(chalk.gray(`Total MCP Servers: ${analysis.totalServers}`));
142
+
143
+ // Calculate column widths
144
+ const maxNameLength = Math.max(
145
+ ...analysis.servers.map(server => server.name.length),
146
+ 'Server Name'.length
147
+ );
148
+ const nameWidth = Math.min(maxNameLength, 25);
149
+
150
+ // Header
151
+ const header = chalk.bold.blue(
152
+ 'Server Name'.padEnd(nameWidth) + ' │ ' +
153
+ 'Category'.padEnd(15) + ' │ ' +
154
+ 'Status'.padEnd(8) + ' │ ' +
155
+ 'Command'.padEnd(12) + ' │ ' +
156
+ 'Complexity'.padEnd(10) + ' │ ' +
157
+ 'Description'
158
+ );
159
+
160
+ const separator = '─'.repeat(nameWidth) + '─┼─' +
161
+ '─'.repeat(15) + '─┼─' +
162
+ '─'.repeat(8) + '─┼─' +
163
+ '─'.repeat(12) + '─┼─' +
164
+ '─'.repeat(10) + '─┼─' +
165
+ '─'.repeat(30);
166
+
167
+ console.log('\n' + header);
168
+ console.log(chalk.gray(separator));
169
+
170
+ // Server rows
171
+ analysis.servers.forEach(server => {
172
+ const truncatedName = server.name.length > nameWidth ?
173
+ server.name.substring(0, nameWidth - 3) + '...' :
174
+ server.name;
175
+
176
+ const statusColor = server.enabled ? chalk.green : chalk.yellow;
177
+ const status = server.enabled ? 'Enabled' : 'Disabled';
178
+
179
+ const truncatedCommand = server.command.length > 12 ?
180
+ server.command.substring(0, 9) + '...' :
181
+ server.command;
182
+
183
+ const complexityStars = 'ā˜…'.repeat(server.complexity) + 'ā˜†'.repeat(5 - server.complexity);
184
+
185
+ const truncatedDesc = server.description.length > 30 ?
186
+ server.description.substring(0, 27) + '...' :
187
+ server.description;
188
+
189
+ const row =
190
+ truncatedName.padEnd(nameWidth) + ' │ ' +
191
+ server.category.padEnd(15) + ' │ ' +
192
+ statusColor(status.padEnd(8)) + ' │ ' +
193
+ chalk.cyan(truncatedCommand.padEnd(12)) + ' │ ' +
194
+ chalk.yellow(complexityStars.padEnd(10)) + ' │ ' +
195
+ chalk.gray(truncatedDesc);
196
+
197
+ console.log(row);
198
+ });
199
+
200
+ // Summary by category
201
+ console.log(chalk.blue('\nšŸ“ˆ MCP Server Summary by Category:'));
202
+ for (const [category, servers] of Object.entries(analysis.byCategory)) {
203
+ const enabledCount = servers.filter(s => s.enabled).length;
204
+ const disabledCount = servers.filter(s => !s.enabled).length;
205
+
206
+ console.log(chalk.gray(` ${category}: ${servers.length} servers`) +
207
+ chalk.green(` (${enabledCount} enabled`) +
208
+ (disabledCount > 0 ? chalk.yellow(`, ${disabledCount} disabled)`) : chalk.green(')')));
209
+ }
210
+
211
+ // Complexity analysis
212
+ console.log(chalk.blue('\nšŸ”§ Complexity Distribution:'));
213
+ const complexityCount = {};
214
+ analysis.servers.forEach(server => {
215
+ complexityCount[server.complexity] = (complexityCount[server.complexity] || 0) + 1;
216
+ });
217
+
218
+ for (let i = 1; i <= 5; i++) {
219
+ const count = complexityCount[i] || 0;
220
+ if (count > 0) {
221
+ const stars = 'ā˜…'.repeat(i) + 'ā˜†'.repeat(5 - i);
222
+ console.log(chalk.gray(` ${chalk.yellow(stars)} (${i}/5): ${count} servers`));
223
+ }
224
+ }
225
+ }
226
+
227
+ async function runMCPStats(options) {
228
+ const targetDir = options.directory || process.cwd();
229
+
230
+ console.log(chalk.blue('šŸ”Œ Claude Code MCP Server Analysis'));
231
+ console.log(chalk.gray(`Target directory: ${targetDir}`));
232
+
233
+ const analysis = await analyzeMCPServers(targetDir);
234
+
235
+ if (!analysis) {
236
+ console.log(chalk.yellow('\nšŸ’” No MCP servers found.'));
237
+ console.log(chalk.gray('Would you like to set up Claude Code Templates to add MCP servers?'));
238
+
239
+ const { setupMCP } = await inquirer.prompt([{
240
+ type: 'confirm',
241
+ name: 'setupMCP',
242
+ message: 'Set up MCP servers with Claude Code Templates?',
243
+ default: true
244
+ }]);
245
+
246
+ if (setupMCP) {
247
+ console.log(chalk.blue('\nšŸš€ Starting Claude Code Templates setup...'));
248
+
249
+ // Import and run the main setup
250
+ const createClaudeConfig = require('./index');
251
+ await createClaudeConfig({ ...options, directory: targetDir });
252
+ }
253
+ return;
254
+ }
255
+
256
+ displayMCPStats(analysis);
257
+
258
+ // Ask if user wants Claude Code to review and optimize MCP configuration
259
+ console.log(chalk.blue('\nšŸ¤– Optimization Opportunity'));
260
+ console.log(chalk.gray('Claude Code can analyze your MCP server configuration and suggest optimizations.'));
261
+
262
+ const { optimizeMCP } = await inquirer.prompt([{
263
+ type: 'confirm',
264
+ name: 'optimizeMCP',
265
+ message: 'Would you like Claude Code to review and optimize your MCP server configuration?',
266
+ default: true
267
+ }]);
268
+
269
+ if (optimizeMCP) {
270
+ console.log(chalk.blue('\nšŸ” Launching Claude Code for MCP optimization...'));
271
+
272
+ // Prepare the optimization prompt
273
+ const mcpSummary = `I have ${analysis.totalServers} MCP servers configured in my .mcp.json file:
274
+
275
+ ${Object.entries(analysis.byCategory).map(([category, servers]) =>
276
+ `${category}: ${servers.length} servers (${servers.filter(s => s.enabled).length} enabled, ${servers.filter(s => !s.enabled).length} disabled)`
277
+ ).join('\n')}
278
+
279
+ MCP Server details:
280
+ ${analysis.servers.map(server =>
281
+ `- ${server.name} (${server.category}): ${server.enabled ? 'Enabled' : 'Disabled'} - Command: ${server.command} - Complexity: ${server.complexity}/5 - ${server.description}`
282
+ ).join('\n')}
283
+
284
+ Please review my MCP server configuration and suggest optimizations for:
285
+ 1. Server selection and relevance to my development workflow
286
+ 2. Missing MCP servers that could improve my productivity
287
+ 3. Server configuration optimization (command, args, environment variables)
288
+ 4. Performance considerations and resource usage
289
+ 5. Security best practices for MCP server configurations
290
+ 6. Redundant or conflicting servers
291
+ 7. Integration opportunities between different MCP servers
292
+
293
+ Consider my project structure and development needs to suggest the most beneficial MCP server setup.`;
294
+
295
+ const claudeCommand = `claude "${mcpSummary}"`;
296
+
297
+ try {
298
+ const child = spawn('sh', ['-c', claudeCommand], {
299
+ stdio: 'inherit',
300
+ cwd: targetDir
301
+ });
302
+
303
+ child.on('error', (error) => {
304
+ console.error(chalk.red('āŒ Error launching Claude Code:'), error.message);
305
+ console.log(chalk.yellow('šŸ’” Make sure Claude Code is installed: npm install -g @anthropic-ai/claude-code'));
306
+ });
307
+
308
+ } catch (error) {
309
+ console.error(chalk.red('āŒ Error launching Claude Code:'), error.message);
310
+ console.log(chalk.yellow('šŸ’” Make sure Claude Code is installed and accessible.'));
311
+ }
312
+ } else {
313
+ console.log(chalk.gray('\nāœ… MCP analysis complete. You can run this command again anytime to re-analyze your MCP configuration.'));
314
+ }
315
+ }
316
+
317
+ module.exports = {
318
+ runMCPStats,
319
+ analyzeMCPServers,
320
+ displayMCPStats
321
+ };