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.
- package/bin/create-claude-config.js +1 -0
- package/package.json +1 -1
- package/src/command-stats.js +249 -0
- package/src/index.js +7 -0
|
@@ -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
|
@@ -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
|
|