costhawk 1.5.6 → 1.5.8

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.
@@ -1,2 +1,2 @@
1
- export declare const BUILD_COMMIT_SHA = "4d821f2";
1
+ export declare const BUILD_COMMIT_SHA = "0e74f66";
2
2
  //# sourceMappingURL=build-info.d.ts.map
@@ -1,3 +1,3 @@
1
1
  // Auto-generated during release builds. Values may be empty in dev.
2
- export const BUILD_COMMIT_SHA = "4d821f2";
2
+ export const BUILD_COMMIT_SHA = "0e74f66";
3
3
  //# sourceMappingURL=build-info.js.map
@@ -22,11 +22,13 @@ export interface CodexSessionUsage {
22
22
  messageCount: number;
23
23
  startTime: string;
24
24
  endTime: string;
25
+ activeMinutesEstimate: number;
25
26
  filePath: string;
26
27
  }
27
28
  export interface CodexSessionUsageDetailed extends CodexSessionUsage {
28
29
  dailyUsage: Record<string, TokenUsage>;
29
30
  rangeUsage?: TokenUsage;
31
+ rangeActiveMinutesEstimate?: number;
30
32
  }
31
33
  export interface CodexSessionFile {
32
34
  path: string;
@@ -1 +1 @@
1
- {"version":3,"file":"codex-parser.d.ts","sourceRoot":"","sources":["../src/codex-parser.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAOH,MAAM,WAAW,UAAU;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,UAAU,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,yBAA0B,SAAQ,iBAAiB;IAClE,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IACvC,UAAU,CAAC,EAAE,UAAU,CAAC;CACzB;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,IAAI,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;CACd;AA2OD,wBAAgB,mBAAmB,IAAI,MAAM,CAI5C;AAED,wBAAgB,oBAAoB,IAAI,OAAO,CAE9C;AAED,wBAAgB,qBAAqB,CAAC,WAAW,GAAE,MAAW,GAAG,gBAAgB,EAAE,CA+BlF;AAED,wBAAgB,yBAAyB,CACvC,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE;IAAE,UAAU,CAAC,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,EAAE,IAAI,CAAA;CAAE,GAC/C,yBAAyB,GAAG,IAAI,CA+IlC;AAED,wBAAgB,6BAA6B,CAC3C,WAAW,GAAE,MAAW,EACxB,OAAO,CAAC,EAAE;IAAE,UAAU,CAAC,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,EAAE,IAAI,CAAA;CAAE,GAC/C,yBAAyB,EAAE,CAY7B"}
1
+ {"version":3,"file":"codex-parser.d.ts","sourceRoot":"","sources":["../src/codex-parser.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAOH,MAAM,WAAW,UAAU;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,UAAU,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,qBAAqB,EAAE,MAAM,CAAC;IAC9B,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,yBAA0B,SAAQ,iBAAiB;IAClE,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IACvC,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,0BAA0B,CAAC,EAAE,MAAM,CAAC;CACrC;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,IAAI,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;CACd;AAqPD,wBAAgB,mBAAmB,IAAI,MAAM,CAI5C;AAED,wBAAgB,oBAAoB,IAAI,OAAO,CAE9C;AAED,wBAAgB,qBAAqB,CAAC,WAAW,GAAE,MAAW,GAAG,gBAAgB,EAAE,CA+BlF;AAED,wBAAgB,yBAAyB,CACvC,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE;IAAE,UAAU,CAAC,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,EAAE,IAAI,CAAA;CAAE,GAC/C,yBAAyB,GAAG,IAAI,CA+KlC;AAED,wBAAgB,6BAA6B,CAC3C,WAAW,GAAE,MAAW,EACxB,OAAO,CAAC,EAAE;IAAE,UAAU,CAAC,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,EAAE,IAAI,CAAA;CAAE,GAC/C,yBAAyB,EAAE,CAY7B"}
@@ -59,6 +59,16 @@ function getDateKey(timestamp) {
59
59
  return null;
60
60
  return date.toISOString().split("T")[0];
61
61
  }
62
+ const ACTIVE_GAP_CAP_MS = 20 * 60 * 1000;
63
+ const ACTIVE_TERMINAL_BUFFER_MS = 5 * 60 * 1000;
64
+ function addActiveGap(previous, current) {
65
+ if (!previous)
66
+ return 0;
67
+ const gap = current.getTime() - previous.getTime();
68
+ if (!Number.isFinite(gap) || gap <= 0)
69
+ return 0;
70
+ return Math.min(gap, ACTIVE_GAP_CAP_MS);
71
+ }
62
72
  function normalizeTotals(totals) {
63
73
  const input = totals?.input_tokens ??
64
74
  totals?.inputTokens ??
@@ -216,6 +226,10 @@ export function parseCodexSessionDetailed(filePath, options) {
216
226
  let endTime = null;
217
227
  let lastTimestamp = null;
218
228
  let lastTotals = null;
229
+ let activeMs = 0;
230
+ let rangeActiveMs = 0;
231
+ let lastActiveTimestamp = null;
232
+ let lastRangeActiveTimestamp = null;
219
233
  let sessionId = extractSessionIdFromFilename(basename(filePath));
220
234
  let projectHash = "unknown";
221
235
  let modelProvider = null;
@@ -224,6 +238,18 @@ export function parseCodexSessionDetailed(filePath, options) {
224
238
  try {
225
239
  const entry = JSON.parse(line);
226
240
  if (entry.timestamp) {
241
+ const timestampDate = new Date(entry.timestamp);
242
+ if (!Number.isNaN(timestampDate.getTime())) {
243
+ activeMs += addActiveGap(lastActiveTimestamp, timestampDate);
244
+ lastActiveTimestamp = timestampDate;
245
+ if (options?.rangeStart &&
246
+ options?.rangeEnd &&
247
+ timestampDate >= options.rangeStart &&
248
+ timestampDate <= options.rangeEnd) {
249
+ rangeActiveMs += addActiveGap(lastRangeActiveTimestamp, timestampDate);
250
+ lastRangeActiveTimestamp = timestampDate;
251
+ }
252
+ }
227
253
  if (!startTime) {
228
254
  startTime = entry.timestamp;
229
255
  }
@@ -299,6 +325,12 @@ export function parseCodexSessionDetailed(filePath, options) {
299
325
  if (messageCount === 0) {
300
326
  return null;
301
327
  }
328
+ if (lastActiveTimestamp) {
329
+ activeMs += ACTIVE_TERMINAL_BUFFER_MS;
330
+ }
331
+ if (lastRangeActiveTimestamp) {
332
+ rangeActiveMs += ACTIVE_TERMINAL_BUFFER_MS;
333
+ }
302
334
  projectHash = hashProject(cwd);
303
335
  const modelFromConfig = getCodexModel();
304
336
  const model = modelFromConfig
@@ -316,9 +348,13 @@ export function parseCodexSessionDetailed(filePath, options) {
316
348
  messageCount,
317
349
  startTime: startTime || new Date().toISOString(),
318
350
  endTime: endTime || new Date().toISOString(),
351
+ activeMinutesEstimate: Math.max(1, Math.round(activeMs / 60000)),
319
352
  filePath,
320
353
  dailyUsage,
321
354
  rangeUsage,
355
+ rangeActiveMinutesEstimate: options?.rangeStart && options?.rangeEnd && lastRangeActiveTimestamp
356
+ ? Math.max(1, Math.round(rangeActiveMs / 60000))
357
+ : undefined,
322
358
  };
323
359
  }
324
360
  catch {
@@ -1 +1 @@
1
- {"version":3,"file":"codex-parser.js","sourceRoot":"","sources":["../src/codex-parser.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"codex-parser.js","sourceRoot":"","sources":["../src/codex-parser.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -18,7 +18,7 @@ const REQUEST_TIMEOUT_MS = 30000; // 30 seconds
18
18
  const API_BASE_URL = process.env.COSTHAWK_API_URL || "https://costhawk.ai";
19
19
  const DEFAULT_BROWSER_LOGIN_HOSTS = ["costhawk.ai", "www.costhawk.ai"];
20
20
  const DEFAULT_API_KEY = process.env.COSTHAWK_API_KEY;
21
- const CLIENT_VERSION = "1.5.4";
21
+ const CLIENT_VERSION = "1.5.8";
22
22
  const DEBUG_ENABLED = process.env.COSTHAWK_DEBUG === "true";
23
23
  const DEFAULT_LOGIN_SCOPES = ["mcp:read", "mcp:write", "otel:ingest"];
24
24
  const CODEX_DIR_NOT_FOUND_MESSAGE = "Error: Codex sessions directory not found. Checked standard locations (~/.codex/sessions, ~/.config/codex/sessions, ~/.local/share/codex/sessions). You can override with COSTHAWK_CODEX_SESSIONS_DIR.";
@@ -1192,6 +1192,173 @@ function formatSavingsBreakdownMarkdown(data) {
1192
1192
  }
1193
1193
  return truncateResponse(output);
1194
1194
  }
1195
+ function formatExecutiveCurrency(value) {
1196
+ return new Intl.NumberFormat("en-US", {
1197
+ style: "currency",
1198
+ currency: "USD",
1199
+ maximumFractionDigits: value >= 1000 ? 0 : 2,
1200
+ }).format(value);
1201
+ }
1202
+ function formatHours(value) {
1203
+ return `${value.toFixed(value >= 10 ? 1 : 2)} hrs`;
1204
+ }
1205
+ function formatDateLabel(value) {
1206
+ const date = new Date(value);
1207
+ if (Number.isNaN(date.getTime()))
1208
+ return value;
1209
+ return date.toLocaleDateString("en-US", {
1210
+ month: "short",
1211
+ day: "numeric",
1212
+ year: "numeric",
1213
+ });
1214
+ }
1215
+ function formatMultiple(value) {
1216
+ if (value === null || !Number.isFinite(value))
1217
+ return "N/A";
1218
+ return `${value.toFixed(value >= 100 ? 0 : value >= 10 ? 1 : 2)}x`;
1219
+ }
1220
+ function wrapText(value, width) {
1221
+ const words = value.split(/\s+/).filter(Boolean);
1222
+ const lines = [];
1223
+ let current = "";
1224
+ for (const word of words) {
1225
+ const next = current ? `${current} ${word}` : word;
1226
+ if (next.length <= width) {
1227
+ current = next;
1228
+ continue;
1229
+ }
1230
+ if (current) {
1231
+ lines.push(current);
1232
+ }
1233
+ if (word.length <= width) {
1234
+ current = word;
1235
+ continue;
1236
+ }
1237
+ let remaining = word;
1238
+ while (remaining.length > width) {
1239
+ lines.push(remaining.slice(0, width - 1) + "-");
1240
+ remaining = remaining.slice(width - 1);
1241
+ }
1242
+ current = remaining;
1243
+ }
1244
+ if (current) {
1245
+ lines.push(current);
1246
+ }
1247
+ return lines.length > 0 ? lines : [value];
1248
+ }
1249
+ function clipCell(value, width) {
1250
+ if (value.length <= width)
1251
+ return value;
1252
+ if (width <= 3)
1253
+ return value.slice(0, width);
1254
+ return `${value.slice(0, width - 3)}...`;
1255
+ }
1256
+ function renderAsciiTable(headers, rows) {
1257
+ const widths = headers.map((header, columnIndex) => {
1258
+ const rowWidth = Math.max(0, ...rows.map((row) => (row[columnIndex] ? row[columnIndex].length : 0)));
1259
+ return Math.min(Math.max(header.length, rowWidth), 28);
1260
+ });
1261
+ const divider = `+${widths.map((width) => "-".repeat(width + 2)).join("+")}+`;
1262
+ const renderRow = (cells) => `| ${cells
1263
+ .map((cell, index) => clipCell(cell, widths[index]).padEnd(widths[index], " "))
1264
+ .join(" | ")} |`;
1265
+ return [divider, renderRow(headers), divider, ...rows.map(renderRow), divider].join("\n");
1266
+ }
1267
+ function formatLocalRoiMarkdown(data) {
1268
+ const sourceLabel = data.tracked.source === "combined"
1269
+ ? "Claude Code + Codex"
1270
+ : data.tracked.source === "claude_code"
1271
+ ? "Claude Code"
1272
+ : "Codex";
1273
+ const hourLabel = data.tracked.source === "claude_code"
1274
+ ? "Claude Hour"
1275
+ : data.tracked.source === "codex"
1276
+ ? "Codex Hour"
1277
+ : "AI Hour";
1278
+ const sectionDivider = "=".repeat(78);
1279
+ const subDivider = "-".repeat(78);
1280
+ const trackedPeriodLabel = `${formatDateLabel(data.period.start)} -> ${formatDateLabel(data.period.end)}`;
1281
+ const assumptions = [
1282
+ `Engineering rate: ${formatExecutiveCurrency(data.assumptions.engineerHourlyRateUsd)} per hour`,
1283
+ `Broader value multiplier: ${data.assumptions.broaderValueMultiplier.toFixed(2)}x (${data.assumptions.broaderScenarioLabel})`,
1284
+ `Active time method: ${data.assumptions.activeTimeMethod}`,
1285
+ ];
1286
+ if (data.assumptions.claudeSubscriptionPlan) {
1287
+ assumptions.push(`Claude subscription basis: ${data.assumptions.claudeSubscriptionPlan}`);
1288
+ }
1289
+ if (data.assumptions.additionalToolCostUsd > 0) {
1290
+ assumptions.push(`Additional tool cost included: ${formatExecutiveCurrency(data.assumptions.additionalToolCostUsd)}`);
1291
+ }
1292
+ assumptions.push("ROI is directional and depends on your human-equivalent effort estimate.");
1293
+ const overviewTable = renderAsciiTable(["Metric", "Value"], [
1294
+ ["Tracked source", sourceLabel],
1295
+ ["Period", trackedPeriodLabel],
1296
+ ["Active time", formatHours(data.tracked.activeHours)],
1297
+ ["Active days", String(data.period.activeDays)],
1298
+ ["Sessions", formatNumber(data.tracked.sessions)],
1299
+ ["Tracked tokens", formatNumber(data.tracked.totalTokens)],
1300
+ ["Retail equivalent", formatExecutiveCurrency(data.tracked.retailCost)],
1301
+ ["Estimated tool cost", formatExecutiveCurrency(data.tracked.actualCost)],
1302
+ ]);
1303
+ const valueTable = renderAsciiTable(["Value Basis", "Total Value", "Tracked Hours", `$ / ${hourLabel}`], [
1304
+ [
1305
+ "Engineering only",
1306
+ formatExecutiveCurrency(data.outcomes.engineeringValueUsd),
1307
+ formatHours(data.tracked.activeHours),
1308
+ formatExecutiveCurrency(data.outcomes.engineeringValuePerAiHourUsd),
1309
+ ],
1310
+ [
1311
+ data.assumptions.broaderScenarioLabel,
1312
+ formatExecutiveCurrency(data.outcomes.broaderValueUsd),
1313
+ formatHours(data.tracked.activeHours),
1314
+ formatExecutiveCurrency(data.outcomes.broaderValuePerAiHourUsd),
1315
+ ],
1316
+ ]);
1317
+ const sourceTable = renderAsciiTable(["Source", "Sessions", "Tokens", "AI Hours", "Cost Basis", "Actual Cost"], data.tracked.sources.map((source) => [
1318
+ source.source === "claude_code" ? "Claude Code" : "Codex",
1319
+ String(source.sessions),
1320
+ formatNumber(source.totalTokens),
1321
+ formatHours(source.activeHours),
1322
+ source.costBasis,
1323
+ formatExecutiveCurrency(source.actualCost),
1324
+ ]));
1325
+ let output = `${sectionDivider}\n`;
1326
+ output += `EXECUTIVE ROI REPORT\n`;
1327
+ output += `${sectionDivider}\n`;
1328
+ output += `Source: ${sourceLabel}\n`;
1329
+ output += `Period: ${trackedPeriodLabel}\n`;
1330
+ output += `Tracked activity: ${formatHours(data.tracked.activeHours)} across ${data.period.activeDays} active day${data.period.activeDays === 1 ? "" : "s"} and ${data.tracked.sessions} session${data.tracked.sessions === 1 ? "" : "s"}\n`;
1331
+ output += `${subDivider}\n`;
1332
+ output += `Snapshot:\n${overviewTable}\n`;
1333
+ output += `${subDivider}\n`;
1334
+ output += `Value per ${hourLabel}:\n${valueTable}\n`;
1335
+ output += `${subDivider}\n`;
1336
+ output += `Speed vs. Human Team:\n`;
1337
+ output += `- Equivalent human hours for same work: ${formatNumber(Math.round(data.assumptions.equivalentHumanHours))} hours\n`;
1338
+ output += `- Tracked ${hourLabel.toLowerCase()}s: ${formatHours(data.tracked.activeHours)}\n`;
1339
+ output += `- Speed multiplier: ${formatMultiple(data.outcomes.speedMultiplier)}\n`;
1340
+ output += `${subDivider}\n`;
1341
+ output += `Cost Comparison:\n`;
1342
+ output += `- Estimated tool cost: ${formatExecutiveCurrency(data.tracked.actualCost)}\n`;
1343
+ output += `- Net engineering value: ${formatExecutiveCurrency(data.outcomes.netEngineeringValueUsd)}\n`;
1344
+ output += `- Net ${data.assumptions.broaderScenarioLabel}: ${formatExecutiveCurrency(data.outcomes.netBroaderValueUsd)}\n`;
1345
+ output += `- Engineering value multiple: ${formatMultiple(data.outcomes.engineeringGrossMultiple)}\n`;
1346
+ output += `- ${data.assumptions.broaderScenarioLabel} value multiple: ${formatMultiple(data.outcomes.broaderGrossMultiple)}\n`;
1347
+ output += `${subDivider}\n`;
1348
+ output += `Source Breakdown:\n${sourceTable}\n`;
1349
+ output += `${subDivider}\n`;
1350
+ output += `Executive Headline:\n`;
1351
+ for (const line of wrapText(data.headline, 76)) {
1352
+ output += `${line}\n`;
1353
+ }
1354
+ output += `${subDivider}\n`;
1355
+ output += `Assumptions:\n`;
1356
+ for (const [index, item] of assumptions.entries()) {
1357
+ output += `${index + 1}. ${item}\n`;
1358
+ }
1359
+ output += `${sectionDivider}\n`;
1360
+ return truncateResponse(output);
1361
+ }
1195
1362
  // Claude Code local usage formatters
1196
1363
  function formatClaudeCodeLocalUsageMarkdown(data) {
1197
1364
  let output = `# Claude Code Local Usage\n\n`;
@@ -1797,6 +1964,52 @@ const GetSavingsBreakdownSchema = {
1797
1964
  orgId: z.string().optional().describe("Optional organization ID to scope the breakdown"),
1798
1965
  format: z.enum(["markdown", "json"]).optional().default("markdown").describe("Response format"),
1799
1966
  };
1967
+ const GetLocalRoiReportSchema = {
1968
+ source: z
1969
+ .enum(["claude_code", "codex", "combined"])
1970
+ .optional()
1971
+ .default("combined")
1972
+ .describe("Which local activity to analyze: Claude Code, Codex, or both combined"),
1973
+ maxAgeHours: z
1974
+ .number()
1975
+ .min(1)
1976
+ .max(720)
1977
+ .optional()
1978
+ .default(168)
1979
+ .describe("Only include local sessions modified within this many hours (default 168 = 7 days)"),
1980
+ equivalentHumanHours: z
1981
+ .number()
1982
+ .positive()
1983
+ .describe("Estimated human hours it would have taken to do the same work without AI"),
1984
+ engineerHourlyRateUsd: z
1985
+ .number()
1986
+ .positive()
1987
+ .optional()
1988
+ .default(125)
1989
+ .describe("Hourly rate used for engineering value (default $125/hr)"),
1990
+ broaderValueMultiplier: z
1991
+ .number()
1992
+ .positive()
1993
+ .optional()
1994
+ .default(1)
1995
+ .describe("Multiplier to represent broader organizational value beyond direct engineering labor"),
1996
+ broaderScenarioLabel: z
1997
+ .string()
1998
+ .optional()
1999
+ .default("Broader team value")
2000
+ .describe("Label for the broader value scenario, e.g. Growth Co or Full team value"),
2001
+ claudeSubscriptionPlan: z
2002
+ .enum(["pro", "max_5x", "max_20x"])
2003
+ .optional()
2004
+ .describe("Optional Claude subscription plan to use instead of retail cost for Claude Code work"),
2005
+ additionalToolCostUsd: z
2006
+ .number()
2007
+ .min(0)
2008
+ .optional()
2009
+ .default(0)
2010
+ .describe("Additional non-Claude tool cost to include in the ROI calculation"),
2011
+ format: z.enum(["markdown", "json"]).optional().default("markdown").describe("Response format"),
2012
+ };
1800
2013
  // Claude Code local transcript schemas
1801
2014
  const SyncClaudeCodeUsageSchema = {
1802
2015
  apiKey: z
@@ -2264,6 +2477,241 @@ server.registerTool("costhawk_get_savings_breakdown", {
2264
2477
  };
2265
2478
  }
2266
2479
  });
2480
+ server.registerTool("costhawk_get_local_roi_report", {
2481
+ description: `Turn local Claude Code and Codex activity into an executive ROI report. Uses tracked AI work plus your human-effort assumptions to estimate value created, speed multiplier, and cost justification for skeptical stakeholders.`,
2482
+ inputSchema: GetLocalRoiReportSchema,
2483
+ annotations: READ_ONLY_ANNOTATIONS,
2484
+ }, async (args, _extra) => {
2485
+ try {
2486
+ const source = args.source ?? "combined";
2487
+ const maxAgeHours = args.maxAgeHours ?? 168;
2488
+ const equivalentHumanHours = args.equivalentHumanHours;
2489
+ const engineerHourlyRateUsd = args.engineerHourlyRateUsd ?? 125;
2490
+ const broaderValueMultiplier = args.broaderValueMultiplier ?? 1;
2491
+ const broaderScenarioLabel = args.broaderScenarioLabel ?? "Broader team value";
2492
+ const additionalToolCostUsd = args.additionalToolCostUsd ?? 0;
2493
+ const rangeEnd = new Date();
2494
+ const rangeStart = new Date(rangeEnd.getTime() - maxAgeHours * 60 * 60 * 1000);
2495
+ const sourceSummaries = [];
2496
+ const activeDaySet = new Set();
2497
+ let periodStart = rangeEnd.toISOString();
2498
+ let periodEnd = rangeStart.toISOString();
2499
+ const updatePeriod = (startTime, endTime) => {
2500
+ const start = new Date(startTime);
2501
+ const end = new Date(endTime);
2502
+ if (!Number.isNaN(start.getTime()) && start.toISOString() < periodStart) {
2503
+ periodStart = start.toISOString();
2504
+ }
2505
+ if (!Number.isNaN(end.getTime()) && end.toISOString() > periodEnd) {
2506
+ periodEnd = end.toISOString();
2507
+ }
2508
+ };
2509
+ if (source === "claude_code" || source === "combined") {
2510
+ if (claudeCodeDirectoryExists()) {
2511
+ const sessions = parseAllTranscriptsDetailed(maxAgeHours, { rangeStart, rangeEnd });
2512
+ const sessionsInRange = sessions
2513
+ .map((session) => {
2514
+ const rangeTokens = session.rangeUsage || {
2515
+ inputTokens: 0,
2516
+ outputTokens: 0,
2517
+ cacheCreationTokens: 0,
2518
+ cacheReadTokens: 0,
2519
+ };
2520
+ const totalTokens = rangeTokens.inputTokens +
2521
+ rangeTokens.outputTokens +
2522
+ rangeTokens.cacheCreationTokens +
2523
+ rangeTokens.cacheReadTokens;
2524
+ return { session, rangeTokens, totalTokens };
2525
+ })
2526
+ .filter((entry) => entry.totalTokens > 0);
2527
+ if (sessionsInRange.length > 0) {
2528
+ const activeMinutes = sessionsInRange.reduce((sum, entry) => sum + (entry.session.rangeActiveMinutesEstimate ?? entry.session.activeMinutesEstimate), 0);
2529
+ const retailCost = sessionsInRange.reduce((sum, entry) => sum + calculateCost(entry.rangeTokens, entry.session.model).totalCost, 0);
2530
+ for (const { session } of sessionsInRange) {
2531
+ updatePeriod(session.startTime, session.endTime);
2532
+ for (const dayKey of Object.keys(session.dailyUsage)) {
2533
+ const dayDate = new Date(`${dayKey}T00:00:00.000Z`);
2534
+ if (dayDate >= rangeStart && dayDate <= rangeEnd) {
2535
+ activeDaySet.add(dayKey);
2536
+ }
2537
+ }
2538
+ }
2539
+ const claudeDays = Math.max(1, new Set(sessionsInRange.flatMap(({ session }) => Object.keys(session.dailyUsage).filter((dayKey) => {
2540
+ const dayDate = new Date(`${dayKey}T00:00:00.000Z`);
2541
+ return dayDate >= rangeStart && dayDate <= rangeEnd;
2542
+ }))).size);
2543
+ let actualCost = retailCost;
2544
+ let costBasis = "Retail estimate from tracked Claude tokens";
2545
+ if (args.claudeSubscriptionPlan) {
2546
+ const subscription = CLAUDE_SUBSCRIPTIONS[args.claudeSubscriptionPlan];
2547
+ actualCost = subscription.monthlyFee * (claudeDays / 30);
2548
+ costBasis = `${subscription.name} prorated for ${claudeDays} day${claudeDays === 1 ? "" : "s"}`;
2549
+ }
2550
+ sourceSummaries.push({
2551
+ source: "claude_code",
2552
+ sessions: sessionsInRange.length,
2553
+ activeHours: Math.round((activeMinutes / 60) * 10) / 10,
2554
+ activeDays: claudeDays,
2555
+ totalTokens: sessionsInRange.reduce((sum, entry) => sum + entry.totalTokens, 0),
2556
+ retailCost,
2557
+ actualCost,
2558
+ costBasis,
2559
+ });
2560
+ }
2561
+ }
2562
+ else if (source === "claude_code") {
2563
+ return {
2564
+ content: [
2565
+ {
2566
+ type: "text",
2567
+ text: "Error: Claude Code directory not found at ~/.claude/projects/. Make sure you have used Claude Code at least once.",
2568
+ },
2569
+ ],
2570
+ isError: true,
2571
+ };
2572
+ }
2573
+ }
2574
+ if (source === "codex" || source === "combined") {
2575
+ if (codexDirectoryExists()) {
2576
+ const sessions = parseAllCodexSessionsDetailed(maxAgeHours, { rangeStart, rangeEnd });
2577
+ const sessionsInRange = sessions
2578
+ .map((session) => {
2579
+ const rangeTokens = session.rangeUsage || {
2580
+ inputTokens: 0,
2581
+ outputTokens: 0,
2582
+ cacheCreationTokens: 0,
2583
+ cacheReadTokens: 0,
2584
+ };
2585
+ const totalTokens = rangeTokens.inputTokens +
2586
+ rangeTokens.outputTokens +
2587
+ rangeTokens.cacheCreationTokens +
2588
+ rangeTokens.cacheReadTokens;
2589
+ return { session, rangeTokens, totalTokens };
2590
+ })
2591
+ .filter((entry) => entry.totalTokens > 0);
2592
+ if (sessionsInRange.length > 0) {
2593
+ const activeMinutes = sessionsInRange.reduce((sum, entry) => sum + (entry.session.rangeActiveMinutesEstimate ?? entry.session.activeMinutesEstimate), 0);
2594
+ const retailCost = sessionsInRange.reduce((sum, entry) => sum + calculateCost(entry.rangeTokens, entry.session.model).totalCost, 0);
2595
+ for (const { session } of sessionsInRange) {
2596
+ updatePeriod(session.startTime, session.endTime);
2597
+ for (const dayKey of Object.keys(session.dailyUsage)) {
2598
+ const dayDate = new Date(`${dayKey}T00:00:00.000Z`);
2599
+ if (dayDate >= rangeStart && dayDate <= rangeEnd) {
2600
+ activeDaySet.add(dayKey);
2601
+ }
2602
+ }
2603
+ }
2604
+ const codexDays = Math.max(1, new Set(sessionsInRange.flatMap(({ session }) => Object.keys(session.dailyUsage).filter((dayKey) => {
2605
+ const dayDate = new Date(`${dayKey}T00:00:00.000Z`);
2606
+ return dayDate >= rangeStart && dayDate <= rangeEnd;
2607
+ }))).size);
2608
+ sourceSummaries.push({
2609
+ source: "codex",
2610
+ sessions: sessionsInRange.length,
2611
+ activeHours: Math.round((activeMinutes / 60) * 10) / 10,
2612
+ activeDays: codexDays,
2613
+ totalTokens: sessionsInRange.reduce((sum, entry) => sum + entry.totalTokens, 0),
2614
+ retailCost,
2615
+ actualCost: retailCost,
2616
+ costBasis: "Retail estimate from tracked Codex tokens",
2617
+ });
2618
+ }
2619
+ }
2620
+ else if (source === "codex") {
2621
+ return {
2622
+ content: [{ type: "text", text: CODEX_DIR_NOT_FOUND_MESSAGE }],
2623
+ isError: true,
2624
+ };
2625
+ }
2626
+ }
2627
+ if (sourceSummaries.length === 0) {
2628
+ return {
2629
+ content: [
2630
+ {
2631
+ type: "text",
2632
+ text: `No local ${source === "combined" ? "Claude Code or Codex" : source.replace("_", " ")} sessions found within the last ${maxAgeHours} hours.`,
2633
+ },
2634
+ ],
2635
+ };
2636
+ }
2637
+ const totalActiveHours = sourceSummaries.reduce((sum, item) => sum + item.activeHours, 0);
2638
+ const totalRetailCost = sourceSummaries.reduce((sum, item) => sum + item.retailCost, 0);
2639
+ const totalActualCost = sourceSummaries.reduce((sum, item) => sum + item.actualCost, 0) + additionalToolCostUsd;
2640
+ const totalSessions = sourceSummaries.reduce((sum, item) => sum + item.sessions, 0);
2641
+ const totalTokens = sourceSummaries.reduce((sum, item) => sum + item.totalTokens, 0);
2642
+ const activeDays = Math.max(activeDaySet.size, 1);
2643
+ if (totalActiveHours <= 0) {
2644
+ return {
2645
+ content: [
2646
+ {
2647
+ type: "text",
2648
+ text: "Error: Unable to estimate active AI hours from local session activity.",
2649
+ },
2650
+ ],
2651
+ isError: true,
2652
+ };
2653
+ }
2654
+ const engineeringValueUsd = equivalentHumanHours * engineerHourlyRateUsd;
2655
+ const broaderValueUsd = engineeringValueUsd * broaderValueMultiplier;
2656
+ const engineeringValuePerAiHourUsd = engineeringValueUsd / totalActiveHours;
2657
+ const broaderValuePerAiHourUsd = broaderValueUsd / totalActiveHours;
2658
+ const speedMultiplier = equivalentHumanHours / totalActiveHours;
2659
+ const netEngineeringValueUsd = engineeringValueUsd - totalActualCost;
2660
+ const netBroaderValueUsd = broaderValueUsd - totalActualCost;
2661
+ const engineeringGrossMultiple = totalActualCost > 0 ? engineeringValueUsd / totalActualCost : null;
2662
+ const broaderGrossMultiple = totalActualCost > 0 ? broaderValueUsd / totalActualCost : null;
2663
+ const report = {
2664
+ period: {
2665
+ start: periodStart,
2666
+ end: periodEnd,
2667
+ maxAgeHours,
2668
+ activeDays,
2669
+ },
2670
+ tracked: {
2671
+ source,
2672
+ sessions: totalSessions,
2673
+ totalTokens,
2674
+ activeHours: Math.round(totalActiveHours * 10) / 10,
2675
+ retailCost: totalRetailCost,
2676
+ actualCost: totalActualCost,
2677
+ sources: sourceSummaries,
2678
+ },
2679
+ assumptions: {
2680
+ equivalentHumanHours,
2681
+ engineerHourlyRateUsd,
2682
+ broaderValueMultiplier,
2683
+ broaderScenarioLabel,
2684
+ claudeSubscriptionPlan: args.claudeSubscriptionPlan
2685
+ ? CLAUDE_SUBSCRIPTIONS[args.claudeSubscriptionPlan].name
2686
+ : undefined,
2687
+ additionalToolCostUsd,
2688
+ activeTimeMethod: "Estimated from local event timestamps using a 20-minute idle cap plus a 5-minute terminal buffer per session.",
2689
+ },
2690
+ outcomes: {
2691
+ engineeringValueUsd,
2692
+ broaderValueUsd,
2693
+ engineeringValuePerAiHourUsd,
2694
+ broaderValuePerAiHourUsd,
2695
+ speedMultiplier,
2696
+ netEngineeringValueUsd,
2697
+ netBroaderValueUsd,
2698
+ engineeringGrossMultiple,
2699
+ broaderGrossMultiple,
2700
+ },
2701
+ headline: `CostHawk tracked approximately ${formatHours(Math.round(totalActiveHours * 10) / 10)} of AI work across ${activeDays} active day${activeDays === 1 ? "" : "s"} and estimates ${formatExecutiveCurrency(broaderValueUsd)} of ${broaderScenarioLabel.toLowerCase()} from work that would have taken about ${formatNumber(Math.round(equivalentHumanHours))} human hours.`,
2702
+ };
2703
+ const text = args.format === "json" ? JSON.stringify(report, null, 2) : formatLocalRoiMarkdown(report);
2704
+ return {
2705
+ content: [{ type: "text", text }],
2706
+ };
2707
+ }
2708
+ catch (error) {
2709
+ return {
2710
+ content: [{ type: "text", text: `Error: ${error instanceof Error ? error.message : "Unknown error"}` }],
2711
+ isError: true,
2712
+ };
2713
+ }
2714
+ });
2267
2715
  server.registerTool("costhawk_list_alerts", {
2268
2716
  description: `List recent alerts including budget warnings, cost spikes, and anomaly notifications.`,
2269
2717
  inputSchema: ListAlertsSchema,