Skip to content

Commit b16cc74

Browse files
authored
Merge pull request #513 from rajbos/claude
Claude Code support
2 parents 68ff5cf + 69cdfe3 commit b16cc74

File tree

14 files changed

+1610
-15
lines changed

14 files changed

+1610
-15
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ Track your GitHub Copilot token usage and AI Fluency across VS Code, Visual Stud
1111
- GitHub Copilot CLI
1212
- OpenCode + GitHub Copilot
1313
- Crush + GitHub Copilot
14+
- Claude Code (Anthropic)
1415
- Visual Studio + GitHub Copilot
1516

1617
---

cli/src/commands/stats.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ function getEditorDisplayName(source: string): string {
137137
'cursor': 'Cursor',
138138
'copilot-cli': 'Copilot CLI',
139139
'opencode': 'OpenCode',
140+
'claude-code': 'Claude Code',
140141
};
141142
return names[source] || source;
142143
}

cli/src/helpers.ts

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { OpenCodeDataAccess } from '../../vscode-extension/src/opencode';
1111
import { CrushDataAccess } from '../../vscode-extension/src/crush';
1212
import { ContinueDataAccess } from '../../vscode-extension/src/continue';
1313
import { VisualStudioDataAccess } from '../../vscode-extension/src/visualstudio';
14+
import { ClaudeCodeDataAccess } from '../../vscode-extension/src/claudecode';
1415
import { parseSessionFileContent } from '../../vscode-extension/src/sessionParser';
1516
import { estimateTokensFromText, getModelFromRequest, isJsonlContent, estimateTokensFromJsonlSession, calculateEstimatedCost, getModelTier } from '../../vscode-extension/src/tokenEstimation';
1617
import type { DetailedStats, PeriodStats, ModelUsage, EditorUsage, SessionFileCache, UsageAnalysisStats, UsageAnalysisPeriod } from '../../vscode-extension/src/types';
@@ -60,15 +61,21 @@ function createVisualStudio(): VisualStudioDataAccess {
6061
return new VisualStudioDataAccess();
6162
}
6263

64+
/** Create Claude Code data access instance for CLI */
65+
function createClaudeCode(): ClaudeCodeDataAccess {
66+
return new ClaudeCodeDataAccess();
67+
}
68+
6369
// Module-level singletons so sql.js WASM is only initialised once across all session files
6470
const _openCodeInstance = createOpenCode();
6571
const _crushInstance = createCrush();
6672
const _continueInstance = createContinue();
6773
const _visualStudioInstance = createVisualStudio();
74+
const _claudeCodeInstance = createClaudeCode();
6875

6976
/** Create session discovery instance for CLI */
7077
function createSessionDiscovery(): SessionDiscovery {
71-
return new SessionDiscovery({ log, warn, error, openCode: _openCodeInstance, crush: _crushInstance, continue_: _continueInstance, visualStudio: _visualStudioInstance });
78+
return new SessionDiscovery({ log, warn, error, openCode: _openCodeInstance, crush: _crushInstance, continue_: _continueInstance, visualStudio: _visualStudioInstance, claudeCode: _claudeCodeInstance });
7279
}
7380

7481
/** Discover all session files on this machine */
@@ -136,6 +143,7 @@ function getEditorSourceFromPath(filePath: string): string {
136143
if (normalized.includes('/.copilot/')) { return 'copilot-cli'; }
137144
if (normalized.includes('/.crush/crush.db#')) { return 'crush'; }
138145
if (normalized.includes('/opencode/')) { return 'opencode'; }
146+
if (normalized.includes('/.claude/projects/')) { return 'claude-code'; }
139147
if (normalized.includes('.vscode-server')) { return 'vscode-remote'; }
140148
if (normalized.includes('/.vs/') && normalized.includes('/copilot-chat/')) { return 'Visual Studio'; }
141149
return 'vscode';
@@ -219,6 +227,24 @@ const crushResult: SessionData = {
219227
return vsResult;
220228
}
221229

230+
// Handle Claude Code sessions (JSONL with actual Anthropic API token counts)
231+
if (_claudeCodeInstance.isClaudeCodeSessionFile(filePath)) {
232+
const result = _claudeCodeInstance.getTokensFromClaudeCodeSession(filePath);
233+
const interactions = _claudeCodeInstance.countClaudeCodeInteractions(filePath);
234+
const modelUsage = _claudeCodeInstance.getClaudeCodeModelUsage(filePath);
235+
const claudeResult: SessionData = {
236+
file: filePath,
237+
tokens: result.tokens,
238+
thinkingTokens: result.thinkingTokens,
239+
interactions,
240+
modelUsage,
241+
lastModified: stats.mtime,
242+
editorSource: getEditorSourceFromPath(filePath),
243+
};
244+
setCached(filePath, stats.mtimeMs, stats.size, claudeResult);
245+
return claudeResult;
246+
}
247+
222248
const content = await fs.promises.readFile(filePath, 'utf-8');
223249

224250
if (!content.trim()) {
@@ -411,6 +437,7 @@ export async function calculateUsageAnalysisStats(sessionFiles: string[]): Promi
411437
crush: _crushInstance,
412438
continue_: _continueInstance,
413439
visualStudio: _visualStudioInstance,
440+
claudeCode: _claudeCodeInstance,
414441
tokenEstimators,
415442
modelPricing,
416443
toolNameMap,

docs/cli/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,7 @@ The CLI scans the same session files as the [VS Code extension](../vscode-extens
157157
- **VS Code Remote** / Codespaces sessions
158158
- **Copilot CLI** agent mode sessions
159159
- **OpenCode** sessions (JSON and SQLite)
160+
- **Claude Code** sessions (Anthropic CLI/IDE extension, actual API token counts)
160161

161162
---
162163

docs/logFilesSchema/README.md

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,29 @@
11
# Session File Schema Documentation
22

3-
This directory contains documentation and analysis of GitHub Copilot session file schemas.
3+
This directory contains documentation and analysis of AI tool session file schemas.
44

55
## Files
66

77
### session-file-schema.json
8-
**Manually curated documentation** of the Copilot session file structure. This file describes:
8+
**Manually curated documentation** of the GitHub Copilot session file structure. This file describes:
99
- File locations and formats (.json and .jsonl)
1010
- Complete schema for JSON session files
1111
- Complete schema for JSONL session files (both Copilot CLI and VS Code Incremental formats)
1212
- Links to official vscode-copilot-chat repository source code
1313
- Which fields the extension actually uses
1414
- Detailed descriptions and examples
1515

16-
This is the **primary reference** for understanding session file structure.
16+
This is the **primary reference** for understanding Copilot session file structure.
17+
18+
### claude-code-session-schema.json
19+
**Manually curated documentation** of the Claude Code (Anthropic CLI/IDE extension) session file structure. This file describes:
20+
- File locations: `~/.claude/projects/{project-hash}/{session-uuid}.jsonl` and subagent files
21+
- All event types: `user`, `assistant`, `queue-operation`, `file-history-snapshot`, `ai-title`
22+
- The `assistant.message.usage` object containing **actual Anthropic API token counts** (no estimation needed)
23+
- Prompt cache token fields: `cache_creation_input_tokens`, `cache_read_input_tokens`
24+
- Sub-agent session structure and how it differs from the main session
25+
- The `~/.claude/stats-cache.json` pre-aggregated stats format
26+
- Integration guidance for extending the token tracker to support Claude Code
1727

1828
### session-file-schema-analysis.json
1929
**Auto-generated analysis** from actual session files on disk. Generated by running:
@@ -28,13 +38,14 @@ Contains:
2838

2939
## Session File Formats
3040

31-
The extension supports three distinct session file formats:
41+
The extension supports the following session file formats:
3242

33-
| Format | Extension | Location | Discriminator |
34-
|--------|-----------|----------|---------------|
35-
| **JSON** | `.json` | workspaceStorage, globalStorage | N/A (standard JSON) |
36-
| **JSONL CLI** | `.jsonl` | `~/.copilot/session-state/` | `type` field (string) |
37-
| **JSONL Incremental** | `.jsonl` | workspaceStorage (VS Code Insiders) | `kind` field (number) |
43+
| Format | Tool | Extension | Location | Discriminator |
44+
|--------|------|-----------|----------|---------------|
45+
| **JSON** | GitHub Copilot | `.json` | workspaceStorage, globalStorage | N/A (standard JSON) |
46+
| **JSONL CLI** | GitHub Copilot | `.jsonl` | `~/.copilot/session-state/` | `type` field (string) |
47+
| **JSONL Incremental** | GitHub Copilot | `.jsonl` | workspaceStorage (VS Code Insiders) | `kind` field (number) |
48+
| **JSONL Claude Code** | Claude Code (Anthropic) | `.jsonl` | `~/.claude/projects/{hash}/` | Path-based: `~/.claude/` prefix |
3849

3950
### JSONL Format Detection
4051

@@ -51,8 +62,17 @@ VS Code Insiders introduced a new incremental JSONL format that stores session d
5162

5263
See `session-file-schema.json``jsonlIncrementalSchema` for full details.
5364

54-
## Official Source References
65+
### Claude Code Format (New)
66+
67+
Claude Code (Anthropic's CLI/IDE extension) writes sessions to `~/.claude/projects/{project-hash}/{session-uuid}.jsonl`:
68+
- Each line is a `user`, `assistant`, `queue-operation`, `file-history-snapshot`, or `ai-title` event
69+
- **Key advantage**: Assistant events contain actual Anthropic API token counts in `message.usage` — no estimation needed
70+
- Includes prompt cache fields: `cache_creation_input_tokens`, `cache_read_input_tokens`
71+
- Sub-agents are stored in `{session-uuid}/subagents/{agent-id}.jsonl`
5572

73+
See `claude-code-session-schema.json` for full details.
74+
75+
## Official Source References
5676

5777
The session file schemas are defined in the following repositories:
5878

0 commit comments

Comments
 (0)