claude-code-templates 1.4.0 ā 1.4.2
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/package.json +1 -1
- package/src/command-stats.js +101 -19
package/package.json
CHANGED
package/src/command-stats.js
CHANGED
|
@@ -3,6 +3,31 @@ const path = require('path');
|
|
|
3
3
|
const chalk = require('chalk');
|
|
4
4
|
const { spawn } = require('child_process');
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* Estimates token count for text content
|
|
8
|
+
* Based on approximate tokenization rules: ~4 characters per token for English text
|
|
9
|
+
* @param {string} text - Text to analyze
|
|
10
|
+
* @returns {number} Estimated token count
|
|
11
|
+
*/
|
|
12
|
+
function estimateTokens(text) {
|
|
13
|
+
// Remove excessive whitespace and normalize
|
|
14
|
+
const cleanText = text.replace(/\s+/g, ' ').trim();
|
|
15
|
+
|
|
16
|
+
// Basic estimation: ~4 characters per token for English text
|
|
17
|
+
// Adjust for code content which typically has more tokens per character
|
|
18
|
+
const baseTokens = Math.ceil(cleanText.length / 4);
|
|
19
|
+
|
|
20
|
+
// Adjust for markdown and code content
|
|
21
|
+
const codeBlocks = (text.match(/```[\s\S]*?```/g) || []).length;
|
|
22
|
+
const inlineCode = (text.match(/`[^`]*`/g) || []).length;
|
|
23
|
+
const markdownElements = (text.match(/[#*_\[\]()]/g) || []).length;
|
|
24
|
+
|
|
25
|
+
// Add extra tokens for code and markdown formatting
|
|
26
|
+
const adjustedTokens = baseTokens + (codeBlocks * 5) + (inlineCode * 2) + Math.ceil(markdownElements / 2);
|
|
27
|
+
|
|
28
|
+
return adjustedTokens;
|
|
29
|
+
}
|
|
30
|
+
|
|
6
31
|
/**
|
|
7
32
|
* Analyzes existing Claude Code commands in the current project
|
|
8
33
|
* @param {string} targetDir - Directory to analyze (default: current directory)
|
|
@@ -42,6 +67,9 @@ async function analyzeCommands(targetDir = process.cwd()) {
|
|
|
42
67
|
const lines = content.split('\n').filter(line => line.trim());
|
|
43
68
|
const title = lines.find(line => line.startsWith('#')) || file;
|
|
44
69
|
|
|
70
|
+
// Calculate token estimate
|
|
71
|
+
const tokenCount = estimateTokens(content);
|
|
72
|
+
|
|
45
73
|
commands.push({
|
|
46
74
|
name: file.replace('.md', ''),
|
|
47
75
|
filename: file,
|
|
@@ -49,7 +77,8 @@ async function analyzeCommands(targetDir = process.cwd()) {
|
|
|
49
77
|
lastModified: stats.mtime,
|
|
50
78
|
title: title.replace(/^#+\s*/, ''),
|
|
51
79
|
lines: lines.length,
|
|
52
|
-
wordCount: content.split(/\s+/).length
|
|
80
|
+
wordCount: content.split(/\s+/).length,
|
|
81
|
+
tokens: tokenCount
|
|
53
82
|
});
|
|
54
83
|
}
|
|
55
84
|
|
|
@@ -60,7 +89,8 @@ async function analyzeCommands(targetDir = process.cwd()) {
|
|
|
60
89
|
exists: true,
|
|
61
90
|
commands,
|
|
62
91
|
total: commands.length,
|
|
63
|
-
totalSize: commands.reduce((sum, cmd) => sum + cmd.size, 0)
|
|
92
|
+
totalSize: commands.reduce((sum, cmd) => sum + cmd.size, 0),
|
|
93
|
+
totalTokens: commands.reduce((sum, cmd) => sum + cmd.tokens, 0)
|
|
64
94
|
};
|
|
65
95
|
} catch (error) {
|
|
66
96
|
return {
|
|
@@ -76,59 +106,104 @@ async function analyzeCommands(targetDir = process.cwd()) {
|
|
|
76
106
|
*/
|
|
77
107
|
function displayCommandStats(analysis) {
|
|
78
108
|
console.log(chalk.cyan('\nš Claude Code Command Analysis'));
|
|
79
|
-
console.log(chalk.gray('ā'.repeat(
|
|
109
|
+
console.log(chalk.gray('ā'.repeat(97)));
|
|
80
110
|
|
|
81
111
|
if (!analysis.exists) {
|
|
82
112
|
console.log(chalk.yellow('ā ļø ' + analysis.message));
|
|
83
113
|
console.log(chalk.blue('\nš” Run the setup first: npx claude-code-templates'));
|
|
84
|
-
return;
|
|
114
|
+
return false; // Indicate no .claude directory
|
|
85
115
|
}
|
|
86
116
|
|
|
87
117
|
if (analysis.error) {
|
|
88
118
|
console.log(chalk.red('ā ' + analysis.error));
|
|
89
|
-
return;
|
|
119
|
+
return false;
|
|
90
120
|
}
|
|
91
121
|
|
|
92
122
|
if (analysis.commands.length === 0) {
|
|
93
123
|
console.log(chalk.yellow('ā ļø ' + analysis.message));
|
|
94
124
|
console.log(chalk.blue('\nš” No commands found to analyze'));
|
|
95
|
-
return;
|
|
125
|
+
return false; // Indicate no commands found
|
|
96
126
|
}
|
|
97
127
|
|
|
98
128
|
// Summary
|
|
99
129
|
const totalSizeKB = (analysis.totalSize / 1024).toFixed(1);
|
|
100
|
-
|
|
130
|
+
const totalTokens = analysis.totalTokens.toLocaleString();
|
|
131
|
+
console.log(chalk.green(`ā
Found ${analysis.total} command file(s) (${totalSizeKB} KB, ~${totalTokens} tokens total)`));
|
|
101
132
|
console.log('');
|
|
102
133
|
|
|
103
134
|
// Table header
|
|
104
135
|
const header = chalk.bold.blue(
|
|
105
|
-
'Command'.padEnd(
|
|
106
|
-
'Size'.padEnd(
|
|
107
|
-
'Lines'.padEnd(
|
|
108
|
-
'Words'.padEnd(
|
|
136
|
+
'Command'.padEnd(18) +
|
|
137
|
+
'Size'.padEnd(7) +
|
|
138
|
+
'Lines'.padEnd(6) +
|
|
139
|
+
'Words'.padEnd(6) +
|
|
140
|
+
'Tokens (aprox)'.padEnd(14) +
|
|
109
141
|
'Last Modified'
|
|
110
142
|
);
|
|
111
143
|
console.log(header);
|
|
112
|
-
console.log(chalk.gray('ā'.repeat(
|
|
144
|
+
console.log(chalk.gray('ā'.repeat(97)));
|
|
113
145
|
|
|
114
146
|
// Table rows
|
|
115
147
|
analysis.commands.forEach(cmd => {
|
|
116
|
-
const sizeFormatted = `${(cmd.size / 1024).toFixed(1)}KB`.padEnd(
|
|
117
|
-
const linesFormatted = cmd.lines.toString().padEnd(
|
|
118
|
-
const wordsFormatted = cmd.wordCount.toString().padEnd(
|
|
148
|
+
const sizeFormatted = `${(cmd.size / 1024).toFixed(1)}KB`.padEnd(7);
|
|
149
|
+
const linesFormatted = cmd.lines.toString().padEnd(6);
|
|
150
|
+
const wordsFormatted = cmd.wordCount.toString().padEnd(6);
|
|
151
|
+
const tokensFormatted = cmd.tokens.toString().padEnd(14);
|
|
119
152
|
const dateFormatted = cmd.lastModified.toLocaleDateString();
|
|
120
153
|
|
|
121
|
-
const row = chalk.white(cmd.name.padEnd(
|
|
154
|
+
const row = chalk.white(cmd.name.padEnd(18)) +
|
|
122
155
|
chalk.cyan(sizeFormatted) +
|
|
123
156
|
chalk.yellow(linesFormatted) +
|
|
124
157
|
chalk.green(wordsFormatted) +
|
|
158
|
+
chalk.magenta(tokensFormatted) +
|
|
125
159
|
chalk.gray(dateFormatted);
|
|
126
160
|
|
|
127
161
|
console.log(row);
|
|
128
162
|
});
|
|
129
163
|
|
|
130
|
-
console.log(chalk.gray('ā'.repeat(
|
|
131
|
-
console.log(chalk.bold(`Total: ${analysis.total} commands, ${totalSizeKB} KB`));
|
|
164
|
+
console.log(chalk.gray('ā'.repeat(97)));
|
|
165
|
+
console.log(chalk.bold(`Total: ${analysis.total} commands, ${totalSizeKB} KB, ~${totalTokens} tokens`));
|
|
166
|
+
return true; // Indicate commands were found and displayed
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Prompts user to setup Claude Code Templates when no commands are found
|
|
171
|
+
* @param {string} targetDir - Project directory
|
|
172
|
+
*/
|
|
173
|
+
async function promptSetupWhenNoCommands(targetDir) {
|
|
174
|
+
const inquirer = require('inquirer');
|
|
175
|
+
|
|
176
|
+
console.log(chalk.cyan('\nš Claude Code Templates Setup'));
|
|
177
|
+
console.log(chalk.gray('No Claude Code commands found in this project. You can set up Claude Code Templates to get started.'));
|
|
178
|
+
|
|
179
|
+
try {
|
|
180
|
+
const { setupNow } = await inquirer.prompt([{
|
|
181
|
+
type: 'confirm',
|
|
182
|
+
name: 'setupNow',
|
|
183
|
+
message: 'Would you like to start the Claude Code Templates setup now?',
|
|
184
|
+
default: true,
|
|
185
|
+
prefix: chalk.blue('š¤')
|
|
186
|
+
}]);
|
|
187
|
+
|
|
188
|
+
if (!setupNow) {
|
|
189
|
+
console.log(chalk.yellow('āļø Setup skipped. Run "npx claude-code-templates" anytime to set up your project.'));
|
|
190
|
+
return false;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
console.log(chalk.blue('\nš Starting Claude Code Templates setup...'));
|
|
194
|
+
console.log(chalk.gray('This will guide you through language and framework selection.\n'));
|
|
195
|
+
|
|
196
|
+
// Import and run the main setup function
|
|
197
|
+
const createClaudeConfig = require('./index');
|
|
198
|
+
await createClaudeConfig({ directory: targetDir });
|
|
199
|
+
|
|
200
|
+
return true;
|
|
201
|
+
|
|
202
|
+
} catch (error) {
|
|
203
|
+
console.error(chalk.red('Error during setup:'), error.message);
|
|
204
|
+
console.log(chalk.blue('š” You can run setup manually with: npx claude-code-templates'));
|
|
205
|
+
return false;
|
|
206
|
+
}
|
|
132
207
|
}
|
|
133
208
|
|
|
134
209
|
/**
|
|
@@ -235,7 +310,13 @@ async function runCommandStats(options = {}) {
|
|
|
235
310
|
const analysis = await analyzeCommands(targetDir);
|
|
236
311
|
|
|
237
312
|
// Display results
|
|
238
|
-
displayCommandStats(analysis);
|
|
313
|
+
const hasCommands = displayCommandStats(analysis);
|
|
314
|
+
|
|
315
|
+
// If no commands found, offer to start setup
|
|
316
|
+
if (!hasCommands) {
|
|
317
|
+
await promptSetupWhenNoCommands(targetDir);
|
|
318
|
+
return;
|
|
319
|
+
}
|
|
239
320
|
|
|
240
321
|
// Prompt for optimization
|
|
241
322
|
await promptCommandOptimization(analysis, targetDir);
|
|
@@ -245,5 +326,6 @@ module.exports = {
|
|
|
245
326
|
analyzeCommands,
|
|
246
327
|
displayCommandStats,
|
|
247
328
|
promptCommandOptimization,
|
|
329
|
+
promptSetupWhenNoCommands,
|
|
248
330
|
runCommandStats
|
|
249
331
|
};
|