grammata 0.1.0

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/dist/index.js ADDED
@@ -0,0 +1,198 @@
1
+ /**
2
+ * grammata
3
+ *
4
+ * Read and aggregate coding agent usage data from local directories.
5
+ *
6
+ * Supports:
7
+ * - Claude Code (~/.claude/projects/) — JSONL session files
8
+ * - Codex (~/.codex/sessions/) — JSONL rollout files + SQLite metadata
9
+ *
10
+ * Usage:
11
+ * import { readClaude, readCodex, readAll } from 'grammata';
12
+ *
13
+ * const claude = await readClaude();
14
+ * const codex = await readCodex();
15
+ * const all = await readAll();
16
+ */
17
+ export { readClaude } from './claude.js';
18
+ export { readCodex } from './codex.js';
19
+ export { CLAUDE_PRICING, CODEX_PRICING, getClaudePricing, getCodexPricing, } from './pricing.js';
20
+ export { formatTokens, formatCost, formatDuration } from './format.js';
21
+ export async function readAll() {
22
+ const [claude, codex] = await Promise.all([
23
+ (await import('./claude.js')).readClaude(),
24
+ (await import('./codex.js')).readCodex(),
25
+ ]);
26
+ // Claude model breakdown
27
+ const claudeModels = {};
28
+ for (const s of claude.sessions) {
29
+ const entry = claudeModels[s.model] || { sessions: 0, cost: 0 };
30
+ entry.sessions++;
31
+ entry.cost += s.costUsd;
32
+ claudeModels[s.model] = entry;
33
+ }
34
+ // Claude active days
35
+ const claudeDays = new Set(claude.sessions.map((s) => s.firstTimestamp.slice(0, 10)));
36
+ // Claude top tools
37
+ const topTools = Object.entries(claude.toolBreakdown)
38
+ .map(([name, count]) => ({ name, count }))
39
+ .sort((a, b) => b.count - a.count)
40
+ .slice(0, 20);
41
+ // Codex model breakdown
42
+ const codexModels = {};
43
+ for (const s of codex.sessions) {
44
+ const entry = codexModels[s.model] || { sessions: 0, cost: 0 };
45
+ entry.sessions++;
46
+ entry.cost += s.costUsd;
47
+ codexModels[s.model] = entry;
48
+ }
49
+ // Codex active days
50
+ const codexDays = new Set(codex.sessions.map((s) => s.createdAt.slice(0, 10)));
51
+ // Claude projects
52
+ const claudeProjects = new Map();
53
+ for (const s of claude.sessions) {
54
+ const e = claudeProjects.get(s.project) || { sessions: 0, cost: 0 };
55
+ e.sessions++;
56
+ e.cost += s.costUsd;
57
+ claudeProjects.set(s.project, e);
58
+ }
59
+ // Codex projects
60
+ const codexProjects = new Map();
61
+ for (const s of codex.sessions) {
62
+ const e = codexProjects.get(s.project) || { sessions: 0, cost: 0 };
63
+ e.sessions++;
64
+ e.cost += s.costUsd;
65
+ codexProjects.set(s.project, e);
66
+ }
67
+ // Total tool calls
68
+ const totalToolCalls = Object.values(claude.toolBreakdown).reduce((s, c) => s + c, 0);
69
+ // All active days combined (for streak calc)
70
+ const allDays = new Set([...claudeDays, ...codexDays]);
71
+ const totalActiveDays = allDays.size;
72
+ // Longest streak
73
+ const sortedDays = [...allDays].sort();
74
+ let longestStreak = 0;
75
+ let currentStreak = 1;
76
+ for (let i = 1; i < sortedDays.length; i++) {
77
+ const prev = new Date(sortedDays[i - 1]);
78
+ const curr = new Date(sortedDays[i]);
79
+ const diffMs = curr.getTime() - prev.getTime();
80
+ if (diffMs <= 86400000) { // 1 day
81
+ currentStreak++;
82
+ }
83
+ else {
84
+ longestStreak = Math.max(longestStreak, currentStreak);
85
+ currentStreak = 1;
86
+ }
87
+ }
88
+ longestStreak = Math.max(longestStreak, currentStreak);
89
+ if (sortedDays.length === 0)
90
+ longestStreak = 0;
91
+ // Peak hour
92
+ const peakHour = claude.hourDistribution.indexOf(Math.max(...claude.hourDistribution));
93
+ const peakHourLabel = peakHour === 0 ? '12 AM' : peakHour < 12 ? `${peakHour} AM` : peakHour === 12 ? '12 PM' : `${peakHour - 12} PM`;
94
+ // Personality
95
+ let timeType = '';
96
+ if (peakHour >= 22 || peakHour <= 4)
97
+ timeType = 'Night Owl';
98
+ else if (peakHour >= 5 && peakHour <= 8)
99
+ timeType = 'Early Bird';
100
+ else if (peakHour >= 9 && peakHour <= 17)
101
+ timeType = '9-to-5er';
102
+ else
103
+ timeType = 'Evening Coder';
104
+ // Favorite model (by cost across all sources)
105
+ const allModels = { ...claudeModels };
106
+ for (const [m, info] of Object.entries(codexModels)) {
107
+ const e = allModels[m] || { sessions: 0, cost: 0 };
108
+ e.sessions += info.sessions;
109
+ e.cost += info.cost;
110
+ allModels[m] = e;
111
+ }
112
+ const favoriteModel = Object.entries(allModels).sort((a, b) => b[1].cost - a[1].cost)[0]?.[0] || '';
113
+ let archetype = 'Builder';
114
+ if (favoriteModel.includes('opus'))
115
+ archetype = 'Power User';
116
+ else if (favoriteModel.includes('haiku'))
117
+ archetype = 'Speed Runner';
118
+ else if (favoriteModel.includes('sonnet'))
119
+ archetype = 'Balanced Builder';
120
+ else if (favoriteModel.includes('5.3-codex') || favoriteModel.includes('5.4'))
121
+ archetype = 'Codex Pro';
122
+ const personality = `${timeType} / ${archetype}`;
123
+ // Favorite tool
124
+ const favoriteTool = topTools[0]?.name || '';
125
+ // Cache hit rate
126
+ const totalCacheReads = claude.totalCacheReadTokens + codex.totalCachedInputTokens;
127
+ const totalAllInput = claude.totalInputTokens + claude.totalCacheReadTokens + codex.totalInputTokens;
128
+ const cacheHitRate = totalAllInput > 0 ? Math.round((totalCacheReads / totalAllInput) * 100) : 0;
129
+ // Most expensive session
130
+ let mostExpensiveSession = null;
131
+ for (const s of claude.sessions) {
132
+ if (!mostExpensiveSession || s.costUsd > mostExpensiveSession.cost) {
133
+ mostExpensiveSession = { cost: s.costUsd, model: s.model, project: s.project, date: s.firstTimestamp.slice(0, 10) };
134
+ }
135
+ }
136
+ for (const s of codex.sessions) {
137
+ if (!mostExpensiveSession || s.costUsd > mostExpensiveSession.cost) {
138
+ mostExpensiveSession = { cost: s.costUsd, model: s.model, project: s.project, date: s.createdAt.slice(0, 10) };
139
+ }
140
+ }
141
+ const totalSessions = claude.sessions.length + codex.sessions.length;
142
+ const avgCostPerSession = totalSessions > 0 ? (claude.totalCost + codex.totalCost) / totalSessions : 0;
143
+ const avgSessionsPerDay = totalActiveDays > 0 ? totalSessions / totalActiveDays : 0;
144
+ return {
145
+ claude: {
146
+ sessions: claude.sessions.length,
147
+ cost: claude.totalCost,
148
+ inputTokens: claude.totalInputTokens,
149
+ outputTokens: claude.totalOutputTokens,
150
+ cacheReadTokens: claude.totalCacheReadTokens,
151
+ cacheCreateTokens: claude.totalCacheCreateTokens,
152
+ cacheSavingsUsd: claude.cacheSavingsUsd,
153
+ models: claudeModels,
154
+ topTools,
155
+ totalToolCalls,
156
+ hourDistribution: claude.hourDistribution,
157
+ activeDays: claudeDays.size,
158
+ projects: [...claudeProjects.entries()]
159
+ .map(([name, v]) => ({ name, ...v }))
160
+ .sort((a, b) => b.cost - a.cost)
161
+ .slice(0, 20),
162
+ },
163
+ codex: {
164
+ sessions: codex.sessions.length,
165
+ cost: codex.totalCost,
166
+ inputTokens: codex.totalInputTokens,
167
+ cachedInputTokens: codex.totalCachedInputTokens,
168
+ outputTokens: codex.totalOutputTokens,
169
+ models: codexModels,
170
+ activeDays: codexDays.size,
171
+ projects: [...codexProjects.entries()]
172
+ .map(([name, v]) => ({ name, ...v }))
173
+ .sort((a, b) => b.cost - a.cost)
174
+ .slice(0, 20),
175
+ },
176
+ combined: {
177
+ totalCost: claude.totalCost + codex.totalCost,
178
+ totalSessions: totalSessions,
179
+ totalInputTokens: claude.totalInputTokens + codex.totalInputTokens,
180
+ totalOutputTokens: claude.totalOutputTokens + codex.totalOutputTokens,
181
+ totalActiveDays,
182
+ },
183
+ highlights: {
184
+ favoriteModel,
185
+ favoriteTool,
186
+ peakHour,
187
+ peakHourLabel,
188
+ personality,
189
+ totalToolCalls,
190
+ cacheHitRate,
191
+ longestStreak,
192
+ mostExpensiveSession,
193
+ avgCostPerSession,
194
+ avgSessionsPerDay,
195
+ },
196
+ };
197
+ }
198
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Model pricing tables sourced from LiteLLM / official pricing pages.
3
+ * All values are per million tokens.
4
+ */
5
+ export interface ModelPricing {
6
+ input: number;
7
+ output: number;
8
+ cacheRead: number;
9
+ cacheWrite: number;
10
+ }
11
+ export interface CodexModelPricing {
12
+ input: number;
13
+ output: number;
14
+ cachedInput: number;
15
+ }
16
+ export declare const CLAUDE_PRICING: Record<string, ModelPricing>;
17
+ export declare const CODEX_PRICING: Record<string, CodexModelPricing>;
18
+ export declare function getClaudePricing(model: string): ModelPricing;
19
+ export declare function getCodexPricing(model: string): CodexModelPricing;
20
+ //# sourceMappingURL=pricing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pricing.d.ts","sourceRoot":"","sources":["../src/pricing.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;CACrB;AAGD,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAOvD,CAAC;AAGF,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAY3D,CAAC;AAEF,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,YAAY,CAM5D;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,iBAAiB,CAMhE"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Model pricing tables sourced from LiteLLM / official pricing pages.
3
+ * All values are per million tokens.
4
+ */
5
+ // Anthropic / Claude models
6
+ export const CLAUDE_PRICING = {
7
+ 'claude-opus-4-6': { input: 5, output: 25, cacheRead: 0.5, cacheWrite: 6.25 },
8
+ 'claude-opus-4-5-20251101': { input: 5, output: 25, cacheRead: 0.5, cacheWrite: 6.25 },
9
+ 'claude-sonnet-4-6': { input: 3, output: 15, cacheRead: 0.3, cacheWrite: 3.75 },
10
+ 'claude-sonnet-4-20250514': { input: 3, output: 15, cacheRead: 0.3, cacheWrite: 3.75 },
11
+ 'claude-haiku-4-5-20251001': { input: 1, output: 5, cacheRead: 0.1, cacheWrite: 1.25 },
12
+ 'claude-haiku-3-5': { input: 0.8, output: 4, cacheRead: 0.08, cacheWrite: 1 },
13
+ };
14
+ // OpenAI / Codex models
15
+ export const CODEX_PRICING = {
16
+ 'gpt-5.1-codex': { input: 1.25, output: 10, cachedInput: 0.125 },
17
+ 'gpt-5.2-codex': { input: 1.75, output: 14, cachedInput: 0.175 },
18
+ 'gpt-5.3-codex': { input: 1.75, output: 14, cachedInput: 0.175 },
19
+ 'gpt-5.3-codex-spark': { input: 1.75, output: 14, cachedInput: 0.175 },
20
+ 'gpt-5.1-codex-mini': { input: 0.25, output: 2, cachedInput: 0.025 },
21
+ 'gpt-5.4': { input: 2.5, output: 15, cachedInput: 0.25 },
22
+ 'gpt-4o': { input: 2.5, output: 10, cachedInput: 1.25 },
23
+ 'gpt-4o-mini': { input: 0.15, output: 0.6, cachedInput: 0.075 },
24
+ o3: { input: 10, output: 40, cachedInput: 2.5 },
25
+ 'o3-mini': { input: 1.1, output: 4.4, cachedInput: 0.55 },
26
+ 'o4-mini': { input: 1.1, output: 4.4, cachedInput: 0.55 },
27
+ };
28
+ export function getClaudePricing(model) {
29
+ if (CLAUDE_PRICING[model])
30
+ return CLAUDE_PRICING[model];
31
+ for (const [key, pricing] of Object.entries(CLAUDE_PRICING)) {
32
+ if (model.startsWith(key.split('-').slice(0, 3).join('-')))
33
+ return pricing;
34
+ }
35
+ return { input: 3, output: 15, cacheRead: 0.3, cacheWrite: 3.75 };
36
+ }
37
+ export function getCodexPricing(model) {
38
+ if (CODEX_PRICING[model])
39
+ return CODEX_PRICING[model];
40
+ for (const [key, pricing] of Object.entries(CODEX_PRICING)) {
41
+ if (model.includes(key) || key.includes(model))
42
+ return pricing;
43
+ }
44
+ return { input: 1.75, output: 14, cachedInput: 0.175 };
45
+ }
46
+ //# sourceMappingURL=pricing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pricing.js","sourceRoot":"","sources":["../src/pricing.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,52 @@
1
+ {
2
+ "name": "grammata",
3
+ "version": "0.1.0",
4
+ "description": "Read and aggregate coding agent usage data from Claude Code (~/.claude) and Codex (~/.codex)",
5
+ "author": "Pella Labs",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "https://github.com/pella-labs/pharos"
9
+ },
10
+ "homepage": "https://github.com/pella-labs/pharos/tree/main/packages/analytics-engine",
11
+ "engines": {
12
+ "node": ">=18"
13
+ },
14
+ "type": "module",
15
+ "main": "dist/index.js",
16
+ "types": "dist/index.d.ts",
17
+ "exports": {
18
+ ".": {
19
+ "import": "./dist/index.js",
20
+ "types": "./dist/index.d.ts"
21
+ }
22
+ },
23
+ "bin": {
24
+ "grammata": "./dist/cli.js"
25
+ },
26
+ "files": [
27
+ "dist"
28
+ ],
29
+ "scripts": {
30
+ "build": "tsc",
31
+ "dev": "tsc --watch",
32
+ "test": "vitest run",
33
+ "test:watch": "vitest",
34
+ "typecheck": "tsc --noEmit",
35
+ "cli": "tsx src/cli.ts"
36
+ },
37
+ "keywords": [
38
+ "claude-code",
39
+ "codex",
40
+ "analytics",
41
+ "usage",
42
+ "tokens",
43
+ "cost"
44
+ ],
45
+ "license": "MIT",
46
+ "devDependencies": {
47
+ "@types/node": "^25.6.0",
48
+ "tsx": "^4.19.0",
49
+ "typescript": "^5.7.0",
50
+ "vitest": "^4.1.0"
51
+ }
52
+ }