claude-code-templates 1.15.0 → 1.15.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.
Files changed (101) hide show
  1. package/README.md +7 -7
  2. package/bin/create-claude-config.js +15 -8
  3. package/package.json +2 -3
  4. package/src/analytics/core/AgentAnalyzer.js +17 -3
  5. package/src/analytics/core/ProcessDetector.js +23 -7
  6. package/src/analytics/core/StateCalculator.js +102 -33
  7. package/src/analytics/data/DataCache.js +7 -7
  8. package/src/analytics-web/chats_mobile.html +2590 -0
  9. package/src/analytics-web/components/App.js +10 -10
  10. package/src/analytics-web/components/SessionTimer.js +1 -1
  11. package/src/analytics-web/components/Sidebar.js +5 -14
  12. package/src/analytics-web/index.html +932 -78
  13. package/src/analytics.js +263 -5
  14. package/src/chats-mobile.js +682 -0
  15. package/src/claude-api-proxy.js +460 -0
  16. package/src/file-operations.js +422 -83
  17. package/src/health-check.js +310 -0
  18. package/src/index.js +944 -56
  19. package/src/tracking-service.js +31 -34
  20. package/components/agents/api-security-audit.md +0 -92
  21. package/components/agents/database-optimization.md +0 -94
  22. package/components/agents/react-performance-optimization.md +0 -64
  23. package/components/commands/check-file.md +0 -53
  24. package/components/commands/generate-tests.md +0 -68
  25. package/components/mcps/deepgraph-nextjs.json +0 -12
  26. package/components/mcps/deepgraph-react.json +0 -12
  27. package/components/mcps/deepgraph-typescript.json +0 -12
  28. package/components/mcps/deepgraph-vue.json +0 -12
  29. package/components/mcps/filesystem-access.json +0 -12
  30. package/components/mcps/github-integration.json +0 -11
  31. package/components/mcps/memory-integration.json +0 -8
  32. package/components/mcps/mysql-integration.json +0 -11
  33. package/components/mcps/postgresql-integration.json +0 -11
  34. package/components/mcps/web-fetch.json +0 -8
  35. package/src/analytics-web/components/AgentsPage.js +0 -4761
  36. package/templates/common/.claude/commands/git-workflow.md +0 -239
  37. package/templates/common/.claude/commands/project-setup.md +0 -316
  38. package/templates/common/.mcp.json +0 -41
  39. package/templates/common/CLAUDE.md +0 -109
  40. package/templates/common/README.md +0 -96
  41. package/templates/go/.mcp.json +0 -78
  42. package/templates/go/README.md +0 -25
  43. package/templates/javascript-typescript/.claude/commands/api-endpoint.md +0 -51
  44. package/templates/javascript-typescript/.claude/commands/debug.md +0 -52
  45. package/templates/javascript-typescript/.claude/commands/lint.md +0 -48
  46. package/templates/javascript-typescript/.claude/commands/npm-scripts.md +0 -48
  47. package/templates/javascript-typescript/.claude/commands/refactor.md +0 -55
  48. package/templates/javascript-typescript/.claude/commands/test.md +0 -61
  49. package/templates/javascript-typescript/.claude/commands/typescript-migrate.md +0 -51
  50. package/templates/javascript-typescript/.claude/settings.json +0 -142
  51. package/templates/javascript-typescript/.mcp.json +0 -80
  52. package/templates/javascript-typescript/CLAUDE.md +0 -185
  53. package/templates/javascript-typescript/README.md +0 -259
  54. package/templates/javascript-typescript/examples/angular-app/.claude/commands/components.md +0 -63
  55. package/templates/javascript-typescript/examples/angular-app/.claude/commands/services.md +0 -62
  56. package/templates/javascript-typescript/examples/node-api/.claude/commands/api-endpoint.md +0 -46
  57. package/templates/javascript-typescript/examples/node-api/.claude/commands/database.md +0 -56
  58. package/templates/javascript-typescript/examples/node-api/.claude/commands/middleware.md +0 -61
  59. package/templates/javascript-typescript/examples/node-api/.claude/commands/route.md +0 -57
  60. package/templates/javascript-typescript/examples/node-api/CLAUDE.md +0 -102
  61. package/templates/javascript-typescript/examples/react-app/.claude/commands/component.md +0 -29
  62. package/templates/javascript-typescript/examples/react-app/.claude/commands/hooks.md +0 -44
  63. package/templates/javascript-typescript/examples/react-app/.claude/commands/state-management.md +0 -45
  64. package/templates/javascript-typescript/examples/react-app/CLAUDE.md +0 -81
  65. package/templates/javascript-typescript/examples/react-app/agents/react-performance-optimization.md +0 -530
  66. package/templates/javascript-typescript/examples/react-app/agents/react-state-management.md +0 -295
  67. package/templates/javascript-typescript/examples/vue-app/.claude/commands/components.md +0 -46
  68. package/templates/javascript-typescript/examples/vue-app/.claude/commands/composables.md +0 -51
  69. package/templates/python/.claude/commands/lint.md +0 -111
  70. package/templates/python/.claude/commands/test.md +0 -73
  71. package/templates/python/.claude/settings.json +0 -153
  72. package/templates/python/.mcp.json +0 -78
  73. package/templates/python/CLAUDE.md +0 -276
  74. package/templates/python/examples/django-app/.claude/commands/admin.md +0 -264
  75. package/templates/python/examples/django-app/.claude/commands/django-model.md +0 -124
  76. package/templates/python/examples/django-app/.claude/commands/views.md +0 -222
  77. package/templates/python/examples/django-app/CLAUDE.md +0 -313
  78. package/templates/python/examples/django-app/agents/django-api-security.md +0 -642
  79. package/templates/python/examples/django-app/agents/django-database-optimization.md +0 -752
  80. package/templates/python/examples/fastapi-app/.claude/commands/api-endpoints.md +0 -513
  81. package/templates/python/examples/fastapi-app/.claude/commands/auth.md +0 -775
  82. package/templates/python/examples/fastapi-app/.claude/commands/database.md +0 -657
  83. package/templates/python/examples/fastapi-app/.claude/commands/deployment.md +0 -160
  84. package/templates/python/examples/fastapi-app/.claude/commands/testing.md +0 -927
  85. package/templates/python/examples/fastapi-app/CLAUDE.md +0 -229
  86. package/templates/python/examples/flask-app/.claude/commands/app-factory.md +0 -384
  87. package/templates/python/examples/flask-app/.claude/commands/blueprint.md +0 -243
  88. package/templates/python/examples/flask-app/.claude/commands/database.md +0 -410
  89. package/templates/python/examples/flask-app/.claude/commands/deployment.md +0 -620
  90. package/templates/python/examples/flask-app/.claude/commands/flask-route.md +0 -217
  91. package/templates/python/examples/flask-app/.claude/commands/testing.md +0 -559
  92. package/templates/python/examples/flask-app/CLAUDE.md +0 -391
  93. package/templates/ruby/.claude/commands/model.md +0 -360
  94. package/templates/ruby/.claude/commands/test.md +0 -480
  95. package/templates/ruby/.claude/settings.json +0 -146
  96. package/templates/ruby/.mcp.json +0 -83
  97. package/templates/ruby/CLAUDE.md +0 -284
  98. package/templates/ruby/examples/rails-app/.claude/commands/authentication.md +0 -490
  99. package/templates/ruby/examples/rails-app/CLAUDE.md +0 -376
  100. package/templates/rust/.mcp.json +0 -78
  101. package/templates/rust/README.md +0 -26
package/src/analytics.js CHANGED
@@ -4,6 +4,9 @@ const path = require('path');
4
4
  const express = require('express');
5
5
  const open = require('open');
6
6
  const os = require('os');
7
+ const inquirer = require('inquirer');
8
+ const boxen = require('boxen');
9
+ const { spawn } = require('child_process');
7
10
  const packageJson = require('../package.json');
8
11
  const StateCalculator = require('./analytics/core/StateCalculator');
9
12
  const ProcessDetector = require('./analytics/core/ProcessDetector');
@@ -16,9 +19,12 @@ const WebSocketServer = require('./analytics/notifications/WebSocketServer');
16
19
  const NotificationManager = require('./analytics/notifications/NotificationManager');
17
20
  const PerformanceMonitor = require('./analytics/utils/PerformanceMonitor');
18
21
  const ConsoleBridge = require('./console-bridge');
22
+ const ClaudeAPIProxy = require('./claude-api-proxy');
19
23
 
20
24
  class ClaudeAnalytics {
21
- constructor() {
25
+ constructor(options = {}) {
26
+ this.options = options;
27
+ this.verbose = options.verbose || false;
22
28
  this.app = express();
23
29
  this.port = 3333;
24
30
  this.stateCalculator = new StateCalculator();
@@ -36,6 +42,9 @@ class ClaudeAnalytics {
36
42
  this.notificationManager = null;
37
43
  this.httpServer = null;
38
44
  this.consoleBridge = null;
45
+ this.cloudflareProcess = null;
46
+ this.publicUrl = null;
47
+ this.claudeApiProxy = null;
39
48
  this.data = {
40
49
  conversations: [],
41
50
  summary: {},
@@ -49,6 +58,29 @@ class ClaudeAnalytics {
49
58
  };
50
59
  }
51
60
 
61
+ /**
62
+ * Log messages only if verbose mode is enabled
63
+ * @param {string} level - Log level ('info', 'warn', 'error')
64
+ * @param {string} message - Message to log
65
+ * @param {...any} args - Additional arguments
66
+ */
67
+ log(level, message, ...args) {
68
+ if (!this.verbose) return;
69
+
70
+ switch (level) {
71
+ case 'error':
72
+ console.error(message, ...args);
73
+ break;
74
+ case 'warn':
75
+ console.warn(message, ...args);
76
+ break;
77
+ case 'info':
78
+ default:
79
+ console.log(message, ...args);
80
+ break;
81
+ }
82
+ }
83
+
52
84
  async initialize() {
53
85
  const homeDir = os.homedir();
54
86
  this.claudeDir = path.join(homeDir, '.claude');
@@ -1181,7 +1213,7 @@ class ClaudeAnalytics {
1181
1213
  }
1182
1214
 
1183
1215
  async openBrowser(openTo = null) {
1184
- const baseUrl = `http://localhost:${this.port}`;
1216
+ const baseUrl = this.publicUrl || `http://localhost:${this.port}`;
1185
1217
  let fullUrl = baseUrl;
1186
1218
 
1187
1219
  // Add fragment/hash for specific page
@@ -1200,6 +1232,191 @@ class ClaudeAnalytics {
1200
1232
  }
1201
1233
  }
1202
1234
 
1235
+ /**
1236
+ * Prompt user if they want to use Cloudflare Tunnel
1237
+ */
1238
+ async promptCloudflareSetup() {
1239
+ console.log('');
1240
+ console.log(chalk.yellow('🌐 Analytics Dashboard Access Options'));
1241
+ console.log('');
1242
+ console.log(chalk.cyan('🔒 About Cloudflare Tunnel:'));
1243
+ console.log(chalk.gray('• Creates a secure connection between your localhost and the web'));
1244
+ console.log(chalk.gray('• Only you will have access to the generated URL (not public)'));
1245
+ console.log(chalk.gray('• The connection is end-to-end encrypted'));
1246
+ console.log(chalk.gray('• Automatically closes when you end the session'));
1247
+ console.log(chalk.gray('• No firewall or port configuration required'));
1248
+ console.log('');
1249
+ console.log(chalk.green('✅ It is completely secure - only you can access the dashboard'));
1250
+ console.log('');
1251
+
1252
+ const { useCloudflare } = await inquirer.prompt([{
1253
+ type: 'confirm',
1254
+ name: 'useCloudflare',
1255
+ message: 'Enable Cloudflare Tunnel for secure remote access?',
1256
+ default: true
1257
+ }]);
1258
+
1259
+ return useCloudflare;
1260
+ }
1261
+
1262
+ /**
1263
+ * Start Cloudflare Tunnel
1264
+ */
1265
+ async startCloudflareTunnel() {
1266
+ try {
1267
+ console.log(chalk.blue('🔧 Starting Cloudflare Tunnel...'));
1268
+
1269
+ // Check if cloudflared is installed
1270
+ const checkProcess = spawn('cloudflared', ['version'], { stdio: 'pipe' });
1271
+
1272
+ return new Promise((resolve, reject) => {
1273
+ checkProcess.on('error', (error) => {
1274
+ console.log(chalk.red('❌ Cloudflared is not installed.'));
1275
+ console.log('');
1276
+ console.log(chalk.yellow('📥 To install Cloudflare Tunnel:'));
1277
+ console.log(chalk.gray('• macOS: brew install cloudflared'));
1278
+ console.log(chalk.gray('• Windows: winget install --id Cloudflare.cloudflared'));
1279
+ console.log(chalk.gray('• Linux: apt-get install cloudflared'));
1280
+ console.log('');
1281
+ console.log(chalk.blue('💡 More info: https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/downloads/'));
1282
+ resolve(false);
1283
+ });
1284
+
1285
+ checkProcess.on('close', (code) => {
1286
+ if (code === 0) {
1287
+ this.createCloudflareTunnel();
1288
+ resolve(true);
1289
+ } else {
1290
+ resolve(false);
1291
+ }
1292
+ });
1293
+ });
1294
+ } catch (error) {
1295
+ console.log(chalk.red(`❌ Error checking Cloudflare Tunnel: ${error.message}`));
1296
+ return false;
1297
+ }
1298
+ }
1299
+
1300
+ /**
1301
+ * Create the actual Cloudflare Tunnel
1302
+ */
1303
+ async createCloudflareTunnel() {
1304
+ try {
1305
+ console.log(chalk.blue('🚀 Creating secure tunnel...'));
1306
+
1307
+ // Start cloudflared tunnel normally, but filter the output to capture URL
1308
+ this.cloudflareProcess = spawn('cloudflared', [
1309
+ 'tunnel',
1310
+ '--url', `http://localhost:${this.port}`
1311
+ ], {
1312
+ stdio: ['pipe', 'pipe', 'pipe']
1313
+ });
1314
+
1315
+ let tunnelEstablished = false;
1316
+
1317
+ return new Promise((resolve) => {
1318
+ // Monitor stderr for the tunnel URL (cloudflared outputs most info to stderr)
1319
+ this.cloudflareProcess.stderr.on('data', (data) => {
1320
+ const output = data.toString();
1321
+
1322
+ // Use the cleaner regex to extract URL from the logs
1323
+ const urlMatch = output.match(/https:\/\/[a-zA-Z0-9.-]+\.trycloudflare\.com/);
1324
+
1325
+ if (urlMatch && !tunnelEstablished) {
1326
+ tunnelEstablished = true;
1327
+ this.publicUrl = urlMatch[0];
1328
+
1329
+ // Create a prominent, boxed display for the tunnel URL
1330
+ const tunnelMessage = chalk.green.bold('🌍 CLOUDFLARE TUNNEL ACTIVE') + '\n\n' +
1331
+ chalk.cyan.bold('Public URL: ') + chalk.white.underline(this.publicUrl) + '\n\n' +
1332
+ chalk.yellow('🔗 Share this URL to access your dashboard remotely') + '\n' +
1333
+ chalk.gray('🔒 This tunnel is private and secure - only accessible by you');
1334
+
1335
+ console.log('\n');
1336
+ console.log(boxen(tunnelMessage, {
1337
+ padding: 1,
1338
+ margin: 1,
1339
+ borderStyle: 'double',
1340
+ borderColor: 'cyan',
1341
+ backgroundColor: '#1a1a1a'
1342
+ }));
1343
+ console.log('\n');
1344
+ resolve(true);
1345
+ }
1346
+ });
1347
+
1348
+ // Also check stdout just in case
1349
+ this.cloudflareProcess.stdout.on('data', (data) => {
1350
+ const output = data.toString();
1351
+ const urlMatch = output.match(/https:\/\/[a-zA-Z0-9.-]+\.trycloudflare\.com/);
1352
+
1353
+ if (urlMatch && !tunnelEstablished) {
1354
+ tunnelEstablished = true;
1355
+ this.publicUrl = urlMatch[0];
1356
+
1357
+ // Create a prominent, boxed display for the tunnel URL
1358
+ const tunnelMessage = chalk.green.bold('🌍 CLOUDFLARE TUNNEL ACTIVE') + '\n\n' +
1359
+ chalk.cyan.bold('Public URL: ') + chalk.white.underline(this.publicUrl) + '\n\n' +
1360
+ chalk.yellow('🔗 Share this URL to access your dashboard remotely') + '\n' +
1361
+ chalk.gray('🔒 This tunnel is private and secure - only accessible by you');
1362
+
1363
+ console.log('\n');
1364
+ console.log(boxen(tunnelMessage, {
1365
+ padding: 1,
1366
+ margin: 1,
1367
+ borderStyle: 'double',
1368
+ borderColor: 'cyan',
1369
+ backgroundColor: '#1a1a1a'
1370
+ }));
1371
+ console.log('\n');
1372
+ resolve(true);
1373
+ }
1374
+ });
1375
+
1376
+ this.cloudflareProcess.on('close', (code) => {
1377
+ if (code !== 0) {
1378
+ console.log(chalk.red(`❌ Cloudflare Tunnel terminated with code: ${code}`));
1379
+ }
1380
+ this.publicUrl = null;
1381
+ this.cloudflareProcess = null;
1382
+ if (!tunnelEstablished) {
1383
+ resolve(false);
1384
+ }
1385
+ });
1386
+
1387
+ this.cloudflareProcess.on('error', (error) => {
1388
+ console.log(chalk.red(`❌ Error with Cloudflare Tunnel: ${error.message}`));
1389
+ this.publicUrl = null;
1390
+ this.cloudflareProcess = null;
1391
+ resolve(false);
1392
+ });
1393
+
1394
+ // Timeout after 15 seconds if tunnel doesn't establish
1395
+ setTimeout(() => {
1396
+ if (!tunnelEstablished) {
1397
+ console.log(chalk.red('❌ Timeout waiting for Cloudflare Tunnel to establish'));
1398
+ resolve(false);
1399
+ }
1400
+ }, 15000);
1401
+ });
1402
+ } catch (error) {
1403
+ console.log(chalk.red(`❌ Error creating Cloudflare Tunnel: ${error.message}`));
1404
+ return false;
1405
+ }
1406
+ }
1407
+
1408
+ /**
1409
+ * Stop Cloudflare Tunnel
1410
+ */
1411
+ stopCloudflareTunnel() {
1412
+ if (this.cloudflareProcess) {
1413
+ console.log(chalk.yellow('🛑 Closing Cloudflare Tunnel...'));
1414
+ this.cloudflareProcess.kill('SIGTERM');
1415
+ this.cloudflareProcess = null;
1416
+ this.publicUrl = null;
1417
+ }
1418
+ }
1419
+
1203
1420
  /**
1204
1421
  * Initialize WebSocket server and notification manager
1205
1422
  */
@@ -1219,6 +1436,12 @@ class ClaudeAnalytics {
1219
1436
  // Connect notification manager to file watcher for typing detection
1220
1437
  this.fileWatcher.setNotificationManager(this.notificationManager);
1221
1438
 
1439
+ // Initialize Claude API Proxy for bidirectional communication
1440
+ console.log(chalk.blue('🌉 Initializing Claude API Proxy...'));
1441
+ this.claudeApiProxy = new ClaudeAPIProxy();
1442
+ await this.claudeApiProxy.start();
1443
+ console.log(chalk.green('✅ Claude API Proxy initialized on port 3335'));
1444
+
1222
1445
  // Setup notification subscriptions
1223
1446
  this.setupNotificationSubscriptions();
1224
1447
 
@@ -1815,6 +2038,9 @@ class ClaudeAnalytics {
1815
2038
  // Stop file watchers
1816
2039
  this.fileWatcher.stop();
1817
2040
 
2041
+ // Stop Cloudflare Tunnel
2042
+ this.stopCloudflareTunnel();
2043
+
1818
2044
  // Stop server
1819
2045
  // Close WebSocket server
1820
2046
  if (this.webSocketServer) {
@@ -1831,6 +2057,11 @@ class ClaudeAnalytics {
1831
2057
  this.consoleBridge.shutdown();
1832
2058
  }
1833
2059
 
2060
+ // Stop Claude API Proxy
2061
+ if (this.claudeApiProxy) {
2062
+ this.claudeApiProxy.stop();
2063
+ }
2064
+
1834
2065
  if (this.httpServer) {
1835
2066
  this.httpServer.close();
1836
2067
  }
@@ -1857,24 +2088,51 @@ async function runAnalytics(options = {}) {
1857
2088
  console.log(chalk.blue('📊 Starting Claude Code Analytics Dashboard...'));
1858
2089
  }
1859
2090
 
1860
- const analytics = new ClaudeAnalytics();
2091
+ const analytics = new ClaudeAnalytics(options);
1861
2092
 
1862
2093
  try {
2094
+ // Handle Cloudflare Tunnel prompt BEFORE initializing anything
2095
+ let useCloudflare = false;
2096
+
2097
+ if (options.tunnel) {
2098
+ useCloudflare = await analytics.promptCloudflareSetup();
2099
+ }
2100
+
1863
2101
  await analytics.initialize();
1864
2102
 
1865
2103
  // Create web dashboard files
1866
2104
  // Web dashboard files are now static in analytics-web directory
1867
2105
 
1868
2106
  await analytics.startServer();
2107
+
2108
+ // Start Cloudflare Tunnel BEFORE other services if requested and confirmed
2109
+ if (useCloudflare) {
2110
+ const cloudflareStarted = await analytics.startCloudflareTunnel();
2111
+ if (!cloudflareStarted) {
2112
+ console.log(chalk.yellow('⚠️ Continuing with localhost only...'));
2113
+ }
2114
+ // Wait a bit longer for tunnel to stabilize
2115
+ await new Promise(resolve => setTimeout(resolve, 2000));
2116
+ }
2117
+
1869
2118
  await analytics.openBrowser(openTo);
1870
2119
 
2120
+ const accessUrl = analytics.publicUrl || `http://localhost:${analytics.port}`;
2121
+
1871
2122
  if (openTo === 'agents') {
1872
2123
  console.log(chalk.green('✅ Claude Code Chats dashboard is running!'));
1873
- console.log(chalk.cyan(`📱 Access at: http://localhost:${analytics.port}/#agents`));
2124
+ console.log(chalk.cyan(`📱 Access at: ${accessUrl}/#agents`));
1874
2125
  } else {
1875
2126
  console.log(chalk.green('✅ Analytics dashboard is running!'));
1876
- console.log(chalk.cyan(`📱 Access at: http://localhost:${analytics.port}`));
2127
+ console.log(chalk.cyan(`📱 Access at: ${accessUrl}`));
1877
2128
  }
2129
+
2130
+ if (analytics.publicUrl) {
2131
+ console.log(chalk.gray('🔒 Secure access via Cloudflare Tunnel'));
2132
+ } else {
2133
+ console.log(chalk.gray('🏠 Local access only'));
2134
+ }
2135
+
1878
2136
  console.log(chalk.gray('Press Ctrl+C to stop the server'));
1879
2137
 
1880
2138
  // Handle graceful shutdown