claude-code-templates 1.3.9 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -41,6 +41,7 @@ program
41
41
  .option('-d, --directory <directory>', 'target directory (default: current directory)')
42
42
  .option('-y, --yes', 'skip prompts and use defaults')
43
43
  .option('--dry-run', 'show what would be copied without actually copying')
44
+ .option('--command-stats', 'analyze existing Claude Code commands and offer optimization')
44
45
  .action(async (options) => {
45
46
  try {
46
47
  await createClaudeConfig(options);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-code-templates",
3
- "version": "1.3.9",
3
+ "version": "1.4.0",
4
4
  "description": "CLI tool to setup Claude Code configurations with framework-specific commands, automation hooks and MCP Servers for your projects",
5
5
  "main": "src/index.js",
6
6
  "bin": {
@@ -0,0 +1,249 @@
1
+ const fs = require('fs-extra');
2
+ const path = require('path');
3
+ const chalk = require('chalk');
4
+ const { spawn } = require('child_process');
5
+
6
+ /**
7
+ * Analyzes existing Claude Code commands in the current project
8
+ * @param {string} targetDir - Directory to analyze (default: current directory)
9
+ * @returns {Array} Array of command analysis results
10
+ */
11
+ async function analyzeCommands(targetDir = process.cwd()) {
12
+ const commandsDir = path.join(targetDir, '.claude', 'commands');
13
+
14
+ // Check if .claude/commands directory exists
15
+ if (!fs.existsSync(commandsDir)) {
16
+ return {
17
+ exists: false,
18
+ message: 'No .claude/commands directory found in current project'
19
+ };
20
+ }
21
+
22
+ try {
23
+ const commandFiles = await fs.readdir(commandsDir);
24
+ const markdownFiles = commandFiles.filter(file => file.endsWith('.md'));
25
+
26
+ if (markdownFiles.length === 0) {
27
+ return {
28
+ exists: true,
29
+ commands: [],
30
+ message: 'No command files (.md) found in .claude/commands directory'
31
+ };
32
+ }
33
+
34
+ const commands = [];
35
+
36
+ for (const file of markdownFiles) {
37
+ const filePath = path.join(commandsDir, file);
38
+ const stats = await fs.stat(filePath);
39
+ const content = await fs.readFile(filePath, 'utf8');
40
+
41
+ // Extract first line as title/description
42
+ const lines = content.split('\n').filter(line => line.trim());
43
+ const title = lines.find(line => line.startsWith('#')) || file;
44
+
45
+ commands.push({
46
+ name: file.replace('.md', ''),
47
+ filename: file,
48
+ size: stats.size,
49
+ lastModified: stats.mtime,
50
+ title: title.replace(/^#+\s*/, ''),
51
+ lines: lines.length,
52
+ wordCount: content.split(/\s+/).length
53
+ });
54
+ }
55
+
56
+ // Sort by last modified (newest first)
57
+ commands.sort((a, b) => b.lastModified - a.lastModified);
58
+
59
+ return {
60
+ exists: true,
61
+ commands,
62
+ total: commands.length,
63
+ totalSize: commands.reduce((sum, cmd) => sum + cmd.size, 0)
64
+ };
65
+ } catch (error) {
66
+ return {
67
+ exists: true,
68
+ error: `Error analyzing commands: ${error.message}`
69
+ };
70
+ }
71
+ }
72
+
73
+ /**
74
+ * Displays command statistics in a formatted table
75
+ * @param {Object} analysis - Result from analyzeCommands()
76
+ */
77
+ function displayCommandStats(analysis) {
78
+ console.log(chalk.cyan('\nšŸ“Š Claude Code Command Analysis'));
79
+ console.log(chalk.gray('═'.repeat(80)));
80
+
81
+ if (!analysis.exists) {
82
+ console.log(chalk.yellow('āš ļø ' + analysis.message));
83
+ console.log(chalk.blue('\nšŸ’” Run the setup first: npx claude-code-templates'));
84
+ return;
85
+ }
86
+
87
+ if (analysis.error) {
88
+ console.log(chalk.red('āŒ ' + analysis.error));
89
+ return;
90
+ }
91
+
92
+ if (analysis.commands.length === 0) {
93
+ console.log(chalk.yellow('āš ļø ' + analysis.message));
94
+ console.log(chalk.blue('\nšŸ’” No commands found to analyze'));
95
+ return;
96
+ }
97
+
98
+ // Summary
99
+ const totalSizeKB = (analysis.totalSize / 1024).toFixed(1);
100
+ console.log(chalk.green(`āœ… Found ${analysis.total} command file(s) (${totalSizeKB} KB total)`));
101
+ console.log('');
102
+
103
+ // Table header
104
+ const header = chalk.bold.blue(
105
+ 'Command'.padEnd(20) +
106
+ 'Size'.padEnd(8) +
107
+ 'Lines'.padEnd(8) +
108
+ 'Words'.padEnd(8) +
109
+ 'Last Modified'
110
+ );
111
+ console.log(header);
112
+ console.log(chalk.gray('─'.repeat(80)));
113
+
114
+ // Table rows
115
+ analysis.commands.forEach(cmd => {
116
+ const sizeFormatted = `${(cmd.size / 1024).toFixed(1)}KB`.padEnd(8);
117
+ const linesFormatted = cmd.lines.toString().padEnd(8);
118
+ const wordsFormatted = cmd.wordCount.toString().padEnd(8);
119
+ const dateFormatted = cmd.lastModified.toLocaleDateString();
120
+
121
+ const row = chalk.white(cmd.name.padEnd(20)) +
122
+ chalk.cyan(sizeFormatted) +
123
+ chalk.yellow(linesFormatted) +
124
+ chalk.green(wordsFormatted) +
125
+ chalk.gray(dateFormatted);
126
+
127
+ console.log(row);
128
+ });
129
+
130
+ console.log(chalk.gray('─'.repeat(80)));
131
+ console.log(chalk.bold(`Total: ${analysis.total} commands, ${totalSizeKB} KB`));
132
+ }
133
+
134
+ /**
135
+ * Prompts user for command optimization and executes Claude Code if approved
136
+ * @param {Object} analysis - Result from analyzeCommands()
137
+ * @param {string} targetDir - Project directory
138
+ */
139
+ async function promptCommandOptimization(analysis, targetDir) {
140
+ if (!analysis.exists || analysis.commands.length === 0) {
141
+ return;
142
+ }
143
+
144
+ const inquirer = require('inquirer');
145
+
146
+ console.log(chalk.cyan('\nšŸ”§ Command Optimization'));
147
+ console.log(chalk.gray('Claude Code can analyze your commands and suggest improvements based on your project structure.'));
148
+
149
+ try {
150
+ const { optimize } = await inquirer.prompt([{
151
+ type: 'confirm',
152
+ name: 'optimize',
153
+ message: 'Would you like Claude Code to review and optimize your commands?',
154
+ default: true,
155
+ prefix: chalk.blue('šŸ¤–')
156
+ }]);
157
+
158
+ if (!optimize) {
159
+ console.log(chalk.yellow('ā­ļø Skipping optimization. You can run this anytime with --command-stats'));
160
+ return;
161
+ }
162
+
163
+ console.log(chalk.blue('\nšŸš€ Starting Claude Code command optimization...'));
164
+ console.log(chalk.gray('This will analyze your project structure and suggest command improvements.\n'));
165
+
166
+ // Create optimization prompt for Claude
167
+ const optimizationPrompt = createOptimizationPrompt(analysis, targetDir);
168
+
169
+ // Execute Claude Code with optimization prompt
170
+ const claudeCommand = `claude "${optimizationPrompt.replace(/"/g, '\\"')}"`;
171
+
172
+ const claudeProcess = spawn('sh', ['-c', claudeCommand], {
173
+ cwd: targetDir,
174
+ stdio: 'inherit'
175
+ });
176
+
177
+ claudeProcess.on('error', (error) => {
178
+ if (error.code === 'ENOENT') {
179
+ console.log(chalk.yellow('\nāš ļø Claude Code CLI not found in PATH.'));
180
+ console.log(chalk.blue('šŸ’” To run optimization manually later, use: claude "Analyze and optimize .claude/commands/ based on project structure"'));
181
+ } else {
182
+ console.error(chalk.red('Error running Claude Code optimization:'), error.message);
183
+ }
184
+ });
185
+
186
+ claudeProcess.on('close', (code) => {
187
+ if (code === 0) {
188
+ console.log(chalk.green('\nāœ… Claude Code optimization completed successfully!'));
189
+ } else if (code !== null) {
190
+ console.log(chalk.yellow(`\nāš ļø Claude Code optimization exited with code ${code}`));
191
+ }
192
+ });
193
+
194
+ } catch (error) {
195
+ console.error(chalk.red('Error during optimization setup:'), error.message);
196
+ console.log(chalk.blue('šŸ’” You can run optimization manually with: claude "Analyze .claude/commands/ directory"'));
197
+ }
198
+ }
199
+
200
+ /**
201
+ * Creates detailed optimization prompt for Claude Code
202
+ * @param {Object} analysis - Command analysis results
203
+ * @param {string} targetDir - Project directory
204
+ * @returns {string} Formatted prompt for Claude
205
+ */
206
+ function createOptimizationPrompt(analysis, targetDir) {
207
+ const commandList = analysis.commands.map(cmd => `- ${cmd.name}.md (${cmd.lines} lines)`).join('\n');
208
+
209
+ return `Analyze and optimize the Claude Code commands in this project:
210
+
211
+ 1. **Review project structure**: Use LS to examine the current project (package.json, src/, etc.) and identify technologies/frameworks used
212
+
213
+ 2. **Analyze existing commands**: Review all files in .claude/commands/ directory:
214
+ ${commandList}
215
+
216
+ 3. **Command optimization**:
217
+ - Check if commands are relevant for this project's tech stack
218
+ - Suggest improvements to existing commands based on project structure
219
+ - Recommend missing commands that would be useful for this project
220
+ - Update command content to match project's specific setup and dependencies
221
+
222
+ 4. **Make improvements**: If you find commands that need updates or see missing useful commands, implement the changes directly to the .claude/commands/ files
223
+
224
+ Focus on making the commands as useful and specific as possible for this project's actual setup and development workflow.`;
225
+ }
226
+
227
+ /**
228
+ * Main function to run command stats analysis
229
+ * @param {Object} options - CLI options
230
+ */
231
+ async function runCommandStats(options = {}) {
232
+ const targetDir = options.directory || process.cwd();
233
+
234
+ // Analyze existing commands
235
+ const analysis = await analyzeCommands(targetDir);
236
+
237
+ // Display results
238
+ displayCommandStats(analysis);
239
+
240
+ // Prompt for optimization
241
+ await promptCommandOptimization(analysis, targetDir);
242
+ }
243
+
244
+ module.exports = {
245
+ analyzeCommands,
246
+ displayCommandStats,
247
+ promptCommandOptimization,
248
+ runCommandStats
249
+ };
package/src/index.js CHANGED
@@ -8,10 +8,17 @@ const { getTemplateConfig, TEMPLATES_CONFIG } = require('./templates');
8
8
  const { createPrompts, interactivePrompts } = require('./prompts');
9
9
  const { copyTemplateFiles, runPostInstallationValidation } = require('./file-operations');
10
10
  const { getHooksForLanguage, getMCPsForLanguage } = require('./hook-scanner');
11
+ const { runCommandStats } = require('./command-stats');
11
12
 
12
13
  async function createClaudeConfig(options = {}) {
13
14
  const targetDir = options.directory || process.cwd();
14
15
 
16
+ // Handle command stats analysis
17
+ if (options.commandStats) {
18
+ await runCommandStats(options);
19
+ return;
20
+ }
21
+
15
22
  console.log(chalk.blue('šŸš€ Setting up Claude Code configuration...'));
16
23
  console.log(chalk.gray(`Target directory: ${targetDir}`));
17
24