claude-code-templates 1.5.1 → 1.5.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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/analytics.js +59 -11
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-code-templates",
3
- "version": "1.5.1",
3
+ "version": "1.5.2",
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/analytics.js CHANGED
@@ -70,12 +70,33 @@ class ClaudeAnalytics {
70
70
  const conversations = [];
71
71
 
72
72
  try {
73
- const files = await fs.readdir(this.claudeDir);
74
- const jsonlFiles = files.filter(file => file.endsWith('.jsonl'));
73
+ // Search for .jsonl files recursively in all subdirectories
74
+ const findJsonlFiles = async (dir) => {
75
+ const files = [];
76
+ const items = await fs.readdir(dir);
77
+
78
+ for (const item of items) {
79
+ const itemPath = path.join(dir, item);
80
+ const stats = await fs.stat(itemPath);
81
+
82
+ if (stats.isDirectory()) {
83
+ // Recursively search subdirectories
84
+ const subFiles = await findJsonlFiles(itemPath);
85
+ files.push(...subFiles);
86
+ } else if (item.endsWith('.jsonl')) {
87
+ files.push(itemPath);
88
+ }
89
+ }
90
+
91
+ return files;
92
+ };
75
93
 
76
- for (const file of jsonlFiles) {
77
- const filePath = path.join(this.claudeDir, file);
94
+ const jsonlFiles = await findJsonlFiles(this.claudeDir);
95
+ console.log(chalk.blue(`Found ${jsonlFiles.length} conversation files`));
96
+
97
+ for (const filePath of jsonlFiles) {
78
98
  const stats = await fs.stat(filePath);
99
+ const filename = path.basename(filePath);
79
100
 
80
101
  try {
81
102
  const content = await fs.readFile(filePath, 'utf8');
@@ -88,21 +109,25 @@ class ClaudeAnalytics {
88
109
  }
89
110
  }).filter(Boolean);
90
111
 
112
+ // Extract project name from path
113
+ const projectFromPath = this.extractProjectFromPath(filePath);
114
+
91
115
  const conversation = {
92
- id: file.replace('.jsonl', ''),
93
- filename: file,
116
+ id: filename.replace('.jsonl', ''),
117
+ filename: filename,
118
+ filePath: filePath,
94
119
  messageCount: messages.length,
95
120
  fileSize: stats.size,
96
121
  lastModified: stats.mtime,
97
122
  created: stats.birthtime,
98
123
  tokens: this.estimateTokens(content),
99
- project: this.extractProjectFromConversation(messages),
124
+ project: projectFromPath || this.extractProjectFromConversation(messages),
100
125
  status: this.determineConversationStatus(messages, stats.mtime)
101
126
  };
102
127
 
103
128
  conversations.push(conversation);
104
129
  } catch (error) {
105
- console.warn(chalk.yellow(`Warning: Could not parse ${file}:`, error.message));
130
+ console.warn(chalk.yellow(`Warning: Could not parse ${filename}:`, error.message));
106
131
  }
107
132
  }
108
133
 
@@ -160,6 +185,27 @@ class ClaudeAnalytics {
160
185
  return Math.ceil(text.length / 4);
161
186
  }
162
187
 
188
+ extractProjectFromPath(filePath) {
189
+ // Extract project name from file path like:
190
+ // /Users/user/.claude/projects/-Users-user-Projects-MyProject/conversation.jsonl
191
+ const pathParts = filePath.split('/');
192
+ const projectIndex = pathParts.findIndex(part => part === 'projects');
193
+
194
+ if (projectIndex !== -1 && projectIndex + 1 < pathParts.length) {
195
+ const projectDir = pathParts[projectIndex + 1];
196
+ // Clean up the project directory name
197
+ const cleanName = projectDir
198
+ .replace(/^-/, '')
199
+ .replace(/-/g, '/')
200
+ .split('/')
201
+ .pop() || 'Unknown';
202
+
203
+ return cleanName;
204
+ }
205
+
206
+ return null;
207
+ }
208
+
163
209
  extractProjectFromConversation(messages) {
164
210
  // Try to extract project information from conversation
165
211
  for (const message of messages.slice(0, 5)) {
@@ -233,8 +279,10 @@ class ClaudeAnalytics {
233
279
  setupFileWatchers() {
234
280
  console.log(chalk.blue('👀 Setting up file watchers for real-time updates...'));
235
281
 
236
- // Watch conversation files
237
- const conversationWatcher = chokidar.watch(path.join(this.claudeDir, '*.jsonl'), {
282
+ // Watch conversation files recursively in all subdirectories
283
+ const conversationWatcher = chokidar.watch([
284
+ path.join(this.claudeDir, '**/*.jsonl')
285
+ ], {
238
286
  persistent: true,
239
287
  ignoreInitial: true
240
288
  });
@@ -257,7 +305,7 @@ class ClaudeAnalytics {
257
305
  const projectWatcher = chokidar.watch(this.claudeDir, {
258
306
  persistent: true,
259
307
  ignoreInitial: true,
260
- depth: 1
308
+ depth: 2 // Increased depth to catch subdirectories
261
309
  });
262
310
 
263
311
  projectWatcher.on('addDir', async () => {