claude-code-templates 1.26.2 → 1.26.4
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/chats-mobile.js +41 -12
- package/src/index.js +18 -5
- package/src/tracking-service.js +72 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-code-templates",
|
|
3
|
-
"version": "1.26.
|
|
3
|
+
"version": "1.26.4",
|
|
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": {
|
package/src/chats-mobile.js
CHANGED
|
@@ -1187,6 +1187,12 @@ class ChatsMobile {
|
|
|
1187
1187
|
* Stop the server
|
|
1188
1188
|
*/
|
|
1189
1189
|
async stop() {
|
|
1190
|
+
// Prevent multiple stop calls
|
|
1191
|
+
if (this.isStopped) {
|
|
1192
|
+
return;
|
|
1193
|
+
}
|
|
1194
|
+
this.isStopped = true;
|
|
1195
|
+
|
|
1190
1196
|
if (this.cloudflaredProcess) {
|
|
1191
1197
|
try {
|
|
1192
1198
|
this.cloudflaredProcess.kill('SIGTERM');
|
|
@@ -1195,26 +1201,28 @@ class ChatsMobile {
|
|
|
1195
1201
|
this.log('warn', chalk.yellow('⚠️ Error stopping Cloudflare Tunnel:', error.message));
|
|
1196
1202
|
}
|
|
1197
1203
|
}
|
|
1198
|
-
|
|
1204
|
+
|
|
1199
1205
|
if (this.webSocketServer) {
|
|
1200
1206
|
try {
|
|
1207
|
+
console.log(chalk.gray('🔌 Closing WebSocket server...'));
|
|
1201
1208
|
await this.webSocketServer.close();
|
|
1202
|
-
|
|
1209
|
+
console.log(chalk.green('✅ WebSocket server closed'));
|
|
1203
1210
|
} catch (error) {
|
|
1204
1211
|
this.log('warn', chalk.yellow('⚠️ Error stopping WebSocket server:', error.message));
|
|
1205
1212
|
}
|
|
1206
1213
|
}
|
|
1207
|
-
|
|
1214
|
+
|
|
1208
1215
|
if (this.httpServer) {
|
|
1209
1216
|
await new Promise((resolve) => {
|
|
1210
1217
|
this.httpServer.close(resolve);
|
|
1211
1218
|
});
|
|
1212
1219
|
}
|
|
1213
|
-
|
|
1220
|
+
|
|
1214
1221
|
if (this.fileWatcher) {
|
|
1222
|
+
console.log(chalk.gray('🛑 Stopping file watchers...'));
|
|
1215
1223
|
await this.fileWatcher.stop();
|
|
1216
1224
|
}
|
|
1217
|
-
|
|
1225
|
+
|
|
1218
1226
|
console.log(chalk.gray('🛑 Chats Mobile server stopped'));
|
|
1219
1227
|
}
|
|
1220
1228
|
}
|
|
@@ -1245,14 +1253,35 @@ async function startChatsMobile(options = {}) {
|
|
|
1245
1253
|
}
|
|
1246
1254
|
|
|
1247
1255
|
console.log(chalk.gray('Press Ctrl+C to stop'));
|
|
1248
|
-
|
|
1249
|
-
// Handle graceful shutdown
|
|
1250
|
-
|
|
1256
|
+
|
|
1257
|
+
// Handle graceful shutdown - remove existing listeners first to prevent duplicates
|
|
1258
|
+
const shutdownHandler = async () => {
|
|
1259
|
+
if (chatsMobile.isShuttingDown) return; // Prevent multiple shutdown attempts
|
|
1260
|
+
chatsMobile.isShuttingDown = true;
|
|
1261
|
+
|
|
1251
1262
|
console.log(chalk.yellow('\n🛑 Shutting down...'));
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1263
|
+
|
|
1264
|
+
// Remove this specific handler to prevent it from being called again
|
|
1265
|
+
process.removeListener('SIGINT', shutdownHandler);
|
|
1266
|
+
process.removeListener('SIGTERM', shutdownHandler);
|
|
1267
|
+
|
|
1268
|
+
try {
|
|
1269
|
+
await chatsMobile.stop();
|
|
1270
|
+
process.exit(0);
|
|
1271
|
+
} catch (error) {
|
|
1272
|
+
console.error(chalk.red('❌ Error during shutdown:'), error);
|
|
1273
|
+
process.exit(1);
|
|
1274
|
+
}
|
|
1275
|
+
};
|
|
1276
|
+
|
|
1277
|
+
// Remove any existing SIGINT/SIGTERM listeners to prevent duplicates
|
|
1278
|
+
process.removeAllListeners('SIGINT');
|
|
1279
|
+
process.removeAllListeners('SIGTERM');
|
|
1280
|
+
|
|
1281
|
+
// Add the new handler
|
|
1282
|
+
process.on('SIGINT', shutdownHandler);
|
|
1283
|
+
process.on('SIGTERM', shutdownHandler);
|
|
1284
|
+
|
|
1256
1285
|
} catch (error) {
|
|
1257
1286
|
console.error(chalk.red('❌ Failed to start Chats Mobile:'), error);
|
|
1258
1287
|
process.exit(1);
|
package/src/index.js
CHANGED
|
@@ -126,6 +126,10 @@ async function createClaudeConfig(options = {}) {
|
|
|
126
126
|
|
|
127
127
|
// Handle sandbox execution FIRST (before individual components)
|
|
128
128
|
if (options.sandbox) {
|
|
129
|
+
trackingService.trackCommandExecution('sandbox', {
|
|
130
|
+
provider: options.sandbox,
|
|
131
|
+
hasPrompt: !!options.prompt
|
|
132
|
+
});
|
|
129
133
|
await executeSandbox(options, targetDir);
|
|
130
134
|
return;
|
|
131
135
|
}
|
|
@@ -174,24 +178,28 @@ async function createClaudeConfig(options = {}) {
|
|
|
174
178
|
|
|
175
179
|
// Handle command stats analysis (both singular and plural)
|
|
176
180
|
if (options.commandStats || options.commandsStats) {
|
|
181
|
+
trackingService.trackCommandExecution('command-stats');
|
|
177
182
|
await runCommandStats(options);
|
|
178
183
|
return;
|
|
179
184
|
}
|
|
180
|
-
|
|
185
|
+
|
|
181
186
|
// Handle hook stats analysis (both singular and plural)
|
|
182
187
|
if (options.hookStats || options.hooksStats) {
|
|
188
|
+
trackingService.trackCommandExecution('hook-stats');
|
|
183
189
|
await runHookStats(options);
|
|
184
190
|
return;
|
|
185
191
|
}
|
|
186
|
-
|
|
192
|
+
|
|
187
193
|
// Handle MCP stats analysis (both singular and plural)
|
|
188
194
|
if (options.mcpStats || options.mcpsStats) {
|
|
195
|
+
trackingService.trackCommandExecution('mcp-stats');
|
|
189
196
|
await runMCPStats(options);
|
|
190
197
|
return;
|
|
191
198
|
}
|
|
192
199
|
|
|
193
200
|
// Handle analytics dashboard
|
|
194
201
|
if (options.analytics) {
|
|
202
|
+
trackingService.trackCommandExecution('analytics', { tunnel: options.tunnel || false });
|
|
195
203
|
trackingService.trackAnalyticsDashboard({ page: 'dashboard', source: 'command_line' });
|
|
196
204
|
await runAnalytics(options);
|
|
197
205
|
return;
|
|
@@ -199,6 +207,7 @@ async function createClaudeConfig(options = {}) {
|
|
|
199
207
|
|
|
200
208
|
// Handle plugin dashboard
|
|
201
209
|
if (options.plugins) {
|
|
210
|
+
trackingService.trackCommandExecution('plugins');
|
|
202
211
|
trackingService.trackAnalyticsDashboard({ page: 'plugins', source: 'command_line' });
|
|
203
212
|
await runPluginDashboard(options);
|
|
204
213
|
return;
|
|
@@ -206,20 +215,23 @@ async function createClaudeConfig(options = {}) {
|
|
|
206
215
|
|
|
207
216
|
// Handle chats dashboard (now points to mobile chats interface)
|
|
208
217
|
if (options.chats) {
|
|
218
|
+
trackingService.trackCommandExecution('chats', { tunnel: options.tunnel || false });
|
|
209
219
|
trackingService.trackAnalyticsDashboard({ page: 'chats-mobile', source: 'command_line' });
|
|
210
220
|
await startChatsMobile(options);
|
|
211
221
|
return;
|
|
212
222
|
}
|
|
213
|
-
|
|
223
|
+
|
|
214
224
|
// Handle agents dashboard (separate from chats)
|
|
215
225
|
if (options.agents) {
|
|
226
|
+
trackingService.trackCommandExecution('agents', { tunnel: options.tunnel || false });
|
|
216
227
|
trackingService.trackAnalyticsDashboard({ page: 'agents', source: 'command_line' });
|
|
217
228
|
await runAnalytics({ ...options, openTo: 'agents' });
|
|
218
229
|
return;
|
|
219
230
|
}
|
|
220
|
-
|
|
231
|
+
|
|
221
232
|
// Handle mobile chats interface
|
|
222
233
|
if (options.chatsMobile) {
|
|
234
|
+
trackingService.trackCommandExecution('chats-mobile', { tunnel: options.tunnel || false });
|
|
223
235
|
trackingService.trackAnalyticsDashboard({ page: 'chats-mobile', source: 'command_line' });
|
|
224
236
|
await startChatsMobile(options);
|
|
225
237
|
return;
|
|
@@ -269,8 +281,9 @@ async function createClaudeConfig(options = {}) {
|
|
|
269
281
|
// Handle health check
|
|
270
282
|
let shouldRunSetup = false;
|
|
271
283
|
if (options.healthCheck || options.health || options.check || options.verify) {
|
|
284
|
+
trackingService.trackCommandExecution('health-check');
|
|
272
285
|
const healthResult = await runHealthCheck();
|
|
273
|
-
|
|
286
|
+
|
|
274
287
|
// Track health check usage
|
|
275
288
|
trackingService.trackHealthCheck({
|
|
276
289
|
setup_recommended: healthResult.runSetup,
|
package/src/tracking-service.js
CHANGED
|
@@ -214,6 +214,78 @@ class TrackingService {
|
|
|
214
214
|
...metadata
|
|
215
215
|
});
|
|
216
216
|
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Track CLI command execution
|
|
220
|
+
* @param {string} commandName - Command name (chats, analytics, health-check, plugins, sandbox, etc.)
|
|
221
|
+
* @param {object} metadata - Additional context (optional)
|
|
222
|
+
*/
|
|
223
|
+
async trackCommandExecution(commandName, metadata = {}) {
|
|
224
|
+
if (!this.trackingEnabled) {
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
try {
|
|
229
|
+
const payload = {
|
|
230
|
+
command: commandName,
|
|
231
|
+
cliVersion: this.getCliVersion(),
|
|
232
|
+
nodeVersion: process.version,
|
|
233
|
+
platform: process.platform,
|
|
234
|
+
arch: process.arch,
|
|
235
|
+
sessionId: this.generateSessionId(),
|
|
236
|
+
metadata: metadata
|
|
237
|
+
};
|
|
238
|
+
|
|
239
|
+
// Fire-and-forget to Neon Database
|
|
240
|
+
this.sendCommandTracking(payload)
|
|
241
|
+
.catch(error => {
|
|
242
|
+
if (process.env.CCT_DEBUG === 'true') {
|
|
243
|
+
console.debug('📊 Command tracking info (non-critical):', error.message);
|
|
244
|
+
}
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
} catch (error) {
|
|
248
|
+
if (process.env.CCT_DEBUG === 'true') {
|
|
249
|
+
console.debug('📊 Command tracking error (non-critical):', error.message);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* Send command tracking to Neon Database
|
|
256
|
+
*/
|
|
257
|
+
async sendCommandTracking(payload) {
|
|
258
|
+
const controller = new AbortController();
|
|
259
|
+
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
260
|
+
|
|
261
|
+
try {
|
|
262
|
+
const response = await fetch('https://www.aitmpl.com/api/track-command-usage', {
|
|
263
|
+
method: 'POST',
|
|
264
|
+
headers: {
|
|
265
|
+
'Content-Type': 'application/json',
|
|
266
|
+
'User-Agent': `claude-code-templates/${payload.cliVersion}`
|
|
267
|
+
},
|
|
268
|
+
body: JSON.stringify(payload),
|
|
269
|
+
signal: controller.signal
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
clearTimeout(timeoutId);
|
|
273
|
+
|
|
274
|
+
if (process.env.CCT_DEBUG === 'true') {
|
|
275
|
+
if (response.ok) {
|
|
276
|
+
console.debug('📊 Command execution tracked successfully');
|
|
277
|
+
} else {
|
|
278
|
+
console.debug(`📊 Command tracking failed with status: ${response.status}`);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
} catch (error) {
|
|
283
|
+
clearTimeout(timeoutId);
|
|
284
|
+
if (process.env.CCT_DEBUG === 'true') {
|
|
285
|
+
console.debug('📊 Command tracking failed (non-critical):', error.message);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
}
|
|
217
289
|
}
|
|
218
290
|
|
|
219
291
|
// Export singleton instance
|