claude-monitor
Version:
Real-time terminal monitoring tool for Claude AI token usage
92 lines • 4.52 kB
JavaScript
import { UsageDataReader } from './data/reader.js';
import { SessionAnalyzer } from './data/analyzer.js';
import { CostMode } from './types/index.js';
import { getTotalTokens } from './types/index.js';
import { readdir } from 'fs/promises';
import path from 'path';
async function debugTokens() {
const reader = new UsageDataReader();
const analyzer = new SessionAnalyzer();
const dataPath = path.join(process.env.HOME || '', '.claude/projects');
console.log('Checking data path:', dataPath);
try {
const files = await readdir(dataPath);
const jsonlFiles = files.filter(f => f.endsWith('.jsonl'));
console.log(`Found ${jsonlFiles.length} JSONL files`);
const projects = new Set();
for (const file of jsonlFiles) {
const parts = file.split('/');
if (parts.length > 0) {
const projectPath = parts[0];
projects.add(projectPath);
}
}
console.log('\nProjects found:');
projects.forEach(p => console.log(` - ${p}`));
}
catch (err) {
console.error('Error reading directory:', err);
}
console.log('\n--- Loading Usage Entries ---');
const result = await reader.loadUsageEntries({
hoursBack: 5,
costMode: CostMode.AUTO,
});
console.log(`Total entries loaded: ${result.entries.length}`);
const entriesByProject = new Map();
for (const entry of result.entries) {
const projectKey = entry.requestId?.split('/')[0] || 'unknown';
if (!entriesByProject.has(projectKey)) {
entriesByProject.set(projectKey, []);
}
entriesByProject.get(projectKey).push(entry);
}
console.log('\n--- Token Usage by Project ---');
let grandTotal = 0;
entriesByProject.forEach((entries, project) => {
const totalTokens = entries.reduce((sum, e) => sum + e.inputTokens + e.outputTokens + e.cacheCreationTokens + e.cacheReadTokens, 0);
grandTotal += totalTokens;
console.log(` ${project}: ${totalTokens.toLocaleString()} tokens (${entries.length} entries)`);
});
console.log(` GRAND TOTAL: ${grandTotal.toLocaleString()} tokens`);
console.log('\n--- Session Blocks ---');
const blocks = analyzer.transformToBlocks(result.entries);
for (const block of blocks) {
if (!block.isGap) {
const totalTokens = getTotalTokens(block.tokenCounts);
console.log(`\nSession ${block.id}:`);
console.log(` Start: ${block.startTime.toLocaleString()}`);
console.log(` End: ${block.endTime.toLocaleString()}`);
console.log(` Active: ${block.isActive}`);
console.log(` Entries: ${block.entries.length}`);
console.log(` Total tokens: ${totalTokens.toLocaleString()}`);
console.log(` Token breakdown:`);
console.log(` - Input: ${block.tokenCounts.inputTokens.toLocaleString()}`);
console.log(` - Output: ${block.tokenCounts.outputTokens.toLocaleString()}`);
console.log(` - Cache Create: ${block.tokenCounts.cacheCreationTokens.toLocaleString()}`);
console.log(` - Cache Read: ${block.tokenCounts.cacheReadTokens.toLocaleString()}`);
if (totalTokens > 1_000_000) {
console.log(` ⚠️ WARNING: Session has over 1M tokens!`);
console.log(` Sample entries:`);
const samples = block.entries.slice(0, 3);
samples.forEach((entry, i) => {
console.log(` Entry ${i + 1}:`);
console.log(` Model: ${entry.model}`);
console.log(` Input: ${entry.inputTokens}`);
console.log(` Output: ${entry.outputTokens}`);
console.log(` Cache: ${entry.cacheCreationTokens + entry.cacheReadTokens}`);
console.log(` Time: ${entry.timestamp.toLocaleString()}`);
});
}
}
}
console.log('\n--- Analysis ---');
console.log('The high token count could be due to:');
console.log('1. Loading data from multiple Claude projects/workspaces');
console.log('2. Cache tokens being counted (which can be very large)');
console.log('3. Multiple Claude instances running in parallel');
console.log('4. Actual heavy usage in the current session');
}
debugTokens().catch(console.error);
//# sourceMappingURL=debug-tokens.js.map