claude-code-templates 1.28.3 → 1.28.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/bin/create-claude-config.js +1 -0
- package/package.json +1 -1
- package/src/analytics/core/YearInReview2025.js +928 -0
- package/src/analytics-web/2025.html +2100 -0
- package/src/analytics.js +39 -3
- package/src/index.js +11 -2
- package/src/plugin-dashboard.js +11 -3
- package/src/validation/README.md +1 -1
package/src/analytics.js
CHANGED
|
@@ -14,6 +14,7 @@ const ConversationAnalyzer = require('./analytics/core/ConversationAnalyzer');
|
|
|
14
14
|
const FileWatcher = require('./analytics/core/FileWatcher');
|
|
15
15
|
const SessionAnalyzer = require('./analytics/core/SessionAnalyzer');
|
|
16
16
|
const AgentAnalyzer = require('./analytics/core/AgentAnalyzer');
|
|
17
|
+
const YearInReview2025 = require('./analytics/core/YearInReview2025');
|
|
17
18
|
const DataCache = require('./analytics/data/DataCache');
|
|
18
19
|
const WebSocketServer = require('./analytics/notifications/WebSocketServer');
|
|
19
20
|
const NotificationManager = require('./analytics/notifications/NotificationManager');
|
|
@@ -32,6 +33,7 @@ class ClaudeAnalytics {
|
|
|
32
33
|
this.fileWatcher = new FileWatcher();
|
|
33
34
|
this.sessionAnalyzer = new SessionAnalyzer();
|
|
34
35
|
this.agentAnalyzer = new AgentAnalyzer();
|
|
36
|
+
this.yearInReview2025 = new YearInReview2025();
|
|
35
37
|
this.dataCache = new DataCache();
|
|
36
38
|
this.performanceMonitor = new PerformanceMonitor({
|
|
37
39
|
enabled: true,
|
|
@@ -1244,6 +1246,37 @@ class ClaudeAnalytics {
|
|
|
1244
1246
|
}
|
|
1245
1247
|
});
|
|
1246
1248
|
|
|
1249
|
+
// Year in Review 2025 API endpoint
|
|
1250
|
+
this.app.get('/api/2025', async (req, res) => {
|
|
1251
|
+
try {
|
|
1252
|
+
console.log('📅 Generating 2025 Year in Review...');
|
|
1253
|
+
|
|
1254
|
+
// Load all conversations for analysis
|
|
1255
|
+
const allConversations = await this.conversationAnalyzer.loadConversations(this.stateCalculator);
|
|
1256
|
+
|
|
1257
|
+
// Generate year in review statistics
|
|
1258
|
+
const yearInReview = await this.yearInReview2025.generateYearInReview(allConversations, this.claudeDir);
|
|
1259
|
+
|
|
1260
|
+
console.log(`✅ 2025 Year in Review generated with ${yearInReview.totalConversations} conversations`);
|
|
1261
|
+
|
|
1262
|
+
res.json({
|
|
1263
|
+
...yearInReview,
|
|
1264
|
+
timestamp: new Date().toISOString()
|
|
1265
|
+
});
|
|
1266
|
+
} catch (error) {
|
|
1267
|
+
console.error('Error generating 2025 year in review:', error);
|
|
1268
|
+
res.status(500).json({
|
|
1269
|
+
error: 'Failed to generate year in review',
|
|
1270
|
+
message: error.message
|
|
1271
|
+
});
|
|
1272
|
+
}
|
|
1273
|
+
});
|
|
1274
|
+
|
|
1275
|
+
// Year in Review 2025 page route
|
|
1276
|
+
this.app.get('/2025', (req, res) => {
|
|
1277
|
+
res.sendFile(path.join(__dirname, 'analytics-web', '2025.html'));
|
|
1278
|
+
});
|
|
1279
|
+
|
|
1247
1280
|
// Main dashboard route
|
|
1248
1281
|
this.app.get('/', (req, res) => {
|
|
1249
1282
|
res.sendFile(path.join(__dirname, 'analytics-web', 'index.html'));
|
|
@@ -1268,15 +1301,18 @@ class ClaudeAnalytics {
|
|
|
1268
1301
|
async openBrowser(openTo = null) {
|
|
1269
1302
|
const baseUrl = this.publicUrl || `http://localhost:${this.port}`;
|
|
1270
1303
|
let fullUrl = baseUrl;
|
|
1271
|
-
|
|
1272
|
-
// Add fragment/hash for specific page
|
|
1304
|
+
|
|
1305
|
+
// Add fragment/hash or path for specific page
|
|
1273
1306
|
if (openTo === 'agents') {
|
|
1274
1307
|
fullUrl = `${baseUrl}/#agents`;
|
|
1275
1308
|
console.log(chalk.blue('🌐 Opening browser to Claude Code Chats...'));
|
|
1309
|
+
} else if (openTo === '2025') {
|
|
1310
|
+
fullUrl = `${baseUrl}/2025`;
|
|
1311
|
+
console.log(chalk.blue('🎉 Opening browser to 2025 Year in Review...'));
|
|
1276
1312
|
} else {
|
|
1277
1313
|
console.log(chalk.blue('🌐 Opening browser to Claude Code Analytics...'));
|
|
1278
1314
|
}
|
|
1279
|
-
|
|
1315
|
+
|
|
1280
1316
|
try {
|
|
1281
1317
|
await open(fullUrl);
|
|
1282
1318
|
} catch (error) {
|
package/src/index.js
CHANGED
|
@@ -146,11 +146,12 @@ async function createClaudeConfig(options = {}) {
|
|
|
146
146
|
const targetDir = options.directory || process.cwd();
|
|
147
147
|
|
|
148
148
|
// Validate --tunnel usage
|
|
149
|
-
if (options.tunnel && !options.analytics && !options.chats && !options.agents && !options.chatsMobile) {
|
|
150
|
-
console.log(chalk.red('❌ Error: --tunnel can only be used with --analytics, --chats, or --chats-mobile'));
|
|
149
|
+
if (options.tunnel && !options.analytics && !options.chats && !options.agents && !options.chatsMobile && !options['2025']) {
|
|
150
|
+
console.log(chalk.red('❌ Error: --tunnel can only be used with --analytics, --chats, --2025, or --chats-mobile'));
|
|
151
151
|
console.log(chalk.yellow('💡 Examples:'));
|
|
152
152
|
console.log(chalk.gray(' cct --analytics --tunnel'));
|
|
153
153
|
console.log(chalk.gray(' cct --chats --tunnel'));
|
|
154
|
+
console.log(chalk.gray(' cct --2025 --tunnel'));
|
|
154
155
|
console.log(chalk.gray(' cct --chats-mobile'));
|
|
155
156
|
return;
|
|
156
157
|
}
|
|
@@ -242,6 +243,14 @@ async function createClaudeConfig(options = {}) {
|
|
|
242
243
|
return;
|
|
243
244
|
}
|
|
244
245
|
|
|
246
|
+
// Handle 2025 Year in Review dashboard
|
|
247
|
+
if (options['2025']) {
|
|
248
|
+
trackingService.trackCommandExecution('2025-year-in-review');
|
|
249
|
+
trackingService.trackAnalyticsDashboard({ page: '2025', source: 'command_line' });
|
|
250
|
+
await runAnalytics({ ...options, openTo: '2025' });
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
|
|
245
254
|
// Handle plugin dashboard
|
|
246
255
|
if (options.plugins) {
|
|
247
256
|
trackingService.trackCommandExecution('plugins');
|
package/src/plugin-dashboard.js
CHANGED
|
@@ -151,7 +151,10 @@ class PluginDashboard {
|
|
|
151
151
|
|
|
152
152
|
if (source.source === 'github') return 'GitHub';
|
|
153
153
|
if (source.source === 'git') return 'Git';
|
|
154
|
-
|
|
154
|
+
// Support both 'local' and 'directory' for filesystem-based marketplaces
|
|
155
|
+
// 'directory' is used by Claude Code, 'local' for legacy compatibility
|
|
156
|
+
if (source.source === 'local' || source.source === 'directory') return 'Local';
|
|
157
|
+
if (source.source === 'url') return 'URL';
|
|
155
158
|
return 'Unknown';
|
|
156
159
|
}
|
|
157
160
|
|
|
@@ -249,7 +252,12 @@ class PluginDashboard {
|
|
|
249
252
|
mcps: 0
|
|
250
253
|
};
|
|
251
254
|
|
|
252
|
-
|
|
255
|
+
// Handle both string paths and object-based sources
|
|
256
|
+
// Marketplace aggregators use object format {source: "url", url: "..."} to reference external repos
|
|
257
|
+
// Individual plugins use string paths like "./" or "./plugins/name"
|
|
258
|
+
const pluginSourcePath = typeof pluginDef.source === 'string'
|
|
259
|
+
? path.join(marketplacePath, pluginDef.source)
|
|
260
|
+
: marketplacePath;
|
|
253
261
|
|
|
254
262
|
// Check if plugin has inline component definitions (claude-code-templates style)
|
|
255
263
|
if (pluginDef.agents || pluginDef.commands || pluginDef.mcpServers) {
|
|
@@ -261,7 +269,7 @@ class PluginDashboard {
|
|
|
261
269
|
};
|
|
262
270
|
}
|
|
263
271
|
// Otherwise, try to count from source directory (claude-code-plugins style)
|
|
264
|
-
else if (pluginDef.source) {
|
|
272
|
+
else if (typeof pluginDef.source === 'string') {
|
|
265
273
|
if (await fs.pathExists(pluginSourcePath)) {
|
|
266
274
|
components = await this.countPluginComponents(pluginSourcePath);
|
|
267
275
|
}
|
package/src/validation/README.md
CHANGED
|
@@ -443,7 +443,7 @@ validatorScore = max(0, 100 - (errors * 25) - (warnings * 5))
|
|
|
443
443
|
|
|
444
444
|
## Integration with Component Generation
|
|
445
445
|
|
|
446
|
-
The security validation system integrates with `generate_components_json.py`:
|
|
446
|
+
The security validation system integrates with `scripts/generate_components_json.py`:
|
|
447
447
|
|
|
448
448
|
1. **Automatic Validation** - Runs before generating components.json
|
|
449
449
|
2. **Metadata Inclusion** - Security scores, hashes, validation status
|