ccusage 17.1.7 → 17.2.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/README.md CHANGED
@@ -148,6 +148,26 @@ npx ccusage monthly --compact # Compact monthly report
148
148
 
149
149
  Full documentation is available at **[ccusage.com](https://ccusage.com/)**
150
150
 
151
+ ## Development Setup
152
+
153
+ ### Using Nix (Recommended for Contributors)
154
+
155
+ For contributors and developers working on ccusage, we provide a Nix flake-based development environment:
156
+
157
+ ```bash
158
+ # Clone the repository
159
+ git clone https://github.com/ryoppippi/ccusage.git
160
+ cd ccusage
161
+
162
+ # Allow direnv (automatically loads Nix environment)
163
+ direnv allow
164
+
165
+ # Or manually enter the development shell
166
+ nix develop
167
+ ```
168
+
169
+ This ensures consistent tooling versions across all contributors and CI systems. The development environment is defined in `flake.nix` and automatically activated via direnv when entering the project directory.
170
+
151
171
  ## Sponsors
152
172
 
153
173
  ### Featured Sponsor
@@ -578,6 +578,11 @@ const statuslineHookJsonSchema = /* @__PURE__ */ object({
578
578
  total_api_duration_ms: /* @__PURE__ */ optional(/* @__PURE__ */ number()),
579
579
  total_lines_added: /* @__PURE__ */ optional(/* @__PURE__ */ number()),
580
580
  total_lines_removed: /* @__PURE__ */ optional(/* @__PURE__ */ number())
581
+ })),
582
+ context_window: /* @__PURE__ */ optional(/* @__PURE__ */ object({
583
+ total_input_tokens: /* @__PURE__ */ number(),
584
+ total_output_tokens: /* @__PURE__ */ optional(/* @__PURE__ */ number()),
585
+ context_window_size: /* @__PURE__ */ number()
581
586
  }))
582
587
  });
583
588
  export { object as A, boolean as C, maxValue as D, integer as E, string as F, transform as I, trim as L, parse as M, pipe as N, minValue as O, safeParse as P, union as R, array as S, flatten as T, requestIdSchema as _, createDailyDate as a, versionSchema as b, createSessionId as c, filterDateSchema as d, isoTimestampSchema as f, projectPathSchema as g, monthlyDateSchema as h, createBucket as i, optional as j, number as k, createWeeklyDate as l, modelNameSchema as m, SortOrders as n, createMonthlyDate as o, messageIdSchema as p, activityDateSchema as r, createProjectPath as s, CostModes as t, dailyDateSchema as u, sessionIdSchema as v, check as w, weeklyDateSchema as x, statuslineHookJsonSchema as y, getTotalTokens as z };
@@ -1,4 +1,4 @@
1
- import { z as getTotalTokens } from "./_types-pJw1UnFi.js";
1
+ import { z as getTotalTokens } from "./_types-BFL_bTNX.js";
2
2
  function calculateTotals(data) {
3
3
  return data.reduce((acc, item) => ({
4
4
  inputTokens: acc.inputTokens + item.inputTokens,
@@ -1,3 +1,3 @@
1
- import { z as getTotalTokens } from "./_types-pJw1UnFi.js";
2
- import { n as createTotalsObject, t as calculateTotals } from "./calculate-cost-rv80nQ-a.js";
1
+ import { z as getTotalTokens } from "./_types-BFL_bTNX.js";
2
+ import { n as createTotalsObject, t as calculateTotals } from "./calculate-cost-CKH-OC_c.js";
3
3
  export { calculateTotals, createTotalsObject, getTotalTokens };
@@ -1,5 +1,5 @@
1
- import { A as object, C as boolean, F as string, M as parse$2, P as safeParse, R as union, S as array, _ as requestIdSchema, a as createDailyDate, b as versionSchema, c as createSessionId, f as isoTimestampSchema, g as projectPathSchema, h as monthlyDateSchema, i as createBucket, j as optional, k as number, l as createWeeklyDate, m as modelNameSchema, o as createMonthlyDate, p as messageIdSchema, r as activityDateSchema, s as createProjectPath, u as dailyDateSchema, v as sessionIdSchema, x as weeklyDateSchema, z as getTotalTokens } from "./_types-pJw1UnFi.js";
2
- import { n as logger } from "./logger-C7kqABy7.js";
1
+ import { A as object, C as boolean, F as string, M as parse$2, P as safeParse, R as union, S as array, _ as requestIdSchema, a as createDailyDate, b as versionSchema, c as createSessionId, f as isoTimestampSchema, g as projectPathSchema, h as monthlyDateSchema, i as createBucket, j as optional, k as number, l as createWeeklyDate, m as modelNameSchema, o as createMonthlyDate, p as messageIdSchema, r as activityDateSchema, s as createProjectPath, u as dailyDateSchema, v as sessionIdSchema, x as weeklyDateSchema, z as getTotalTokens } from "./_types-BFL_bTNX.js";
2
+ import { n as logger } from "./logger-CxSjxkLv.js";
3
3
  import { createRequire } from "node:module";
4
4
  import * as nativeFs from "node:fs";
5
5
  import b, { createReadStream } from "node:fs";
@@ -1,4 +1,4 @@
1
- import { C as transcriptUsageSchema, S as transcriptMessageSchema, T as weeklyUsageSchema, _ as loadWeeklyUsageData, a as dailyUsageSchema, b as sessionUsageSchema, c as getEarliestTimestamp, d as loadBucketUsageData, f as loadDailyUsageData, g as loadSessionUsageById, h as loadSessionData, i as createUniqueHash, l as getUsageLimitResetTime, m as loadSessionBlockData, n as calculateContextTokens, o as extractProjectFromPath, p as loadMonthlyUsageData, r as calculateCostForEntry, s as getClaudePaths, t as bucketUsageSchema, u as globUsageFiles, v as modelBreakdownSchema, w as usageDataSchema, x as sortFilesByTimestamp, y as monthlyUsageSchema } from "./data-loader-DbW9eql2.js";
2
- import "./_types-pJw1UnFi.js";
3
- import "./logger-C7kqABy7.js";
1
+ import { C as transcriptUsageSchema, S as transcriptMessageSchema, T as weeklyUsageSchema, _ as loadWeeklyUsageData, a as dailyUsageSchema, b as sessionUsageSchema, c as getEarliestTimestamp, d as loadBucketUsageData, f as loadDailyUsageData, g as loadSessionUsageById, h as loadSessionData, i as createUniqueHash, l as getUsageLimitResetTime, m as loadSessionBlockData, n as calculateContextTokens, o as extractProjectFromPath, p as loadMonthlyUsageData, r as calculateCostForEntry, s as getClaudePaths, t as bucketUsageSchema, u as globUsageFiles, v as modelBreakdownSchema, w as usageDataSchema, x as sortFilesByTimestamp, y as monthlyUsageSchema } from "./data-loader-Cwm3YlHL.js";
2
+ import "./_types-BFL_bTNX.js";
3
+ import "./logger-CxSjxkLv.js";
4
4
  export { bucketUsageSchema, calculateContextTokens, calculateCostForEntry, createUniqueHash, dailyUsageSchema, extractProjectFromPath, getClaudePaths, getEarliestTimestamp, getUsageLimitResetTime, globUsageFiles, loadBucketUsageData, loadDailyUsageData, loadMonthlyUsageData, loadSessionBlockData, loadSessionData, loadSessionUsageById, loadWeeklyUsageData, modelBreakdownSchema, monthlyUsageSchema, sessionUsageSchema, sortFilesByTimestamp, transcriptMessageSchema, transcriptUsageSchema, usageDataSchema, weeklyUsageSchema };
@@ -1,6 +1,6 @@
1
- import { B as CLAUDE_PROJECTS_DIR_NAME, F as _usingCtx, H as DEBUG_MATCH_THRESHOLD_PERCENT, Q as glob, X as USAGE_DATA_GLOB_PATTERN, et as unwrap, j as PricingFetcher, s as getClaudePaths, tt as try_, ut as isFailure, w as usageDataSchema } from "./data-loader-DbW9eql2.js";
2
- import { P as safeParse } from "./_types-pJw1UnFi.js";
3
- import { n as logger } from "./logger-C7kqABy7.js";
1
+ import { B as CLAUDE_PROJECTS_DIR_NAME, F as _usingCtx, H as DEBUG_MATCH_THRESHOLD_PERCENT, Q as glob, X as USAGE_DATA_GLOB_PATTERN, et as unwrap, j as PricingFetcher, s as getClaudePaths, tt as try_, ut as isFailure, w as usageDataSchema } from "./data-loader-Cwm3YlHL.js";
2
+ import { P as safeParse } from "./_types-BFL_bTNX.js";
3
+ import { n as logger } from "./logger-CxSjxkLv.js";
4
4
  import { readFile } from "node:fs/promises";
5
5
  import path from "node:path";
6
6
  async function detectMismatches(claudePath) {
package/dist/debug.js CHANGED
@@ -1,5 +1,5 @@
1
- import "./data-loader-DbW9eql2.js";
2
- import "./_types-pJw1UnFi.js";
3
- import "./logger-C7kqABy7.js";
4
- import { n as printMismatchReport, t as detectMismatches } from "./debug-BZyKxY0R.js";
1
+ import "./data-loader-Cwm3YlHL.js";
2
+ import "./_types-BFL_bTNX.js";
3
+ import "./logger-CxSjxkLv.js";
4
+ import { n as printMismatchReport, t as detectMismatches } from "./debug-BjAuokNY.js";
5
5
  export { detectMismatches, printMismatchReport };
package/dist/index.js CHANGED
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env node
2
- import { $ as uniq, A as projectBlockUsage, D as calculateBurnRate, E as DEFAULT_SESSION_DURATION_HOURS, F as _usingCtx, G as DEFAULT_RECENT_DAYS, I as BLOCKS_COMPACT_WIDTH_THRESHOLD, J as MIN_REFRESH_INTERVAL_SECONDS, K as DEFAULT_REFRESH_INTERVAL_SECONDS, L as BLOCKS_DEFAULT_TERMINAL_WIDTH, M as formatDateCompact, N as getFileModifiedTime, O as filterRecentBlocks, P as unreachable, R as BLOCKS_WARNING_THRESHOLD, U as DEFAULT_CONTEXT_USAGE_THRESHOLDS, V as CONFIG_FILE_NAME, W as DEFAULT_LOCALE, Y as MIN_RENDER_INTERVAL_MS, Z as WEEK_DAYS, _ as loadWeeklyUsageData, at as inspect, c as getEarliestTimestamp, ct as isSuccess, dt as toArray, et as unwrap, f as loadDailyUsageData, ft as __commonJSMin, g as loadSessionUsageById, h as loadSessionData, i as createUniqueHash, it as inspectError, j as PricingFetcher, k as identifySessionBlocks, l as getUsageLimitResetTime, lt as andThen, m as loadSessionBlockData, mt as __toESM, n as calculateContextTokens, nt as pipe, ot as fail, p as loadMonthlyUsageData, pt as __require, q as MAX_REFRESH_INTERVAL_SECONDS, r as calculateCostForEntry, rt as map$2, s as getClaudePaths, st as succeed, tt as try_, u as globUsageFiles, ut as isFailure, w as usageDataSchema, x as sortFilesByTimestamp, z as BURN_RATE_THRESHOLDS } from "./data-loader-DbW9eql2.js";
3
- import { D as maxValue, E as integer$1, F as string, I as transform, L as trim, M as parse$1, N as pipe$1, O as minValue, P as safeParse, R as union, T as flatten, d as filterDateSchema, k as number, n as SortOrders, t as CostModes, w as check, y as statuslineHookJsonSchema, z as getTotalTokens } from "./_types-pJw1UnFi.js";
4
- import { n as createTotalsObject, t as calculateTotals } from "./calculate-cost-rv80nQ-a.js";
5
- import { a as version, i as name, n as logger, r as description, t as log } from "./logger-C7kqABy7.js";
6
- import { n as printMismatchReport, t as detectMismatches } from "./debug-BZyKxY0R.js";
2
+ import { $ as uniq, A as projectBlockUsage, D as calculateBurnRate, E as DEFAULT_SESSION_DURATION_HOURS, F as _usingCtx, G as DEFAULT_RECENT_DAYS, I as BLOCKS_COMPACT_WIDTH_THRESHOLD, J as MIN_REFRESH_INTERVAL_SECONDS, K as DEFAULT_REFRESH_INTERVAL_SECONDS, L as BLOCKS_DEFAULT_TERMINAL_WIDTH, M as formatDateCompact, N as getFileModifiedTime, O as filterRecentBlocks, P as unreachable, R as BLOCKS_WARNING_THRESHOLD, U as DEFAULT_CONTEXT_USAGE_THRESHOLDS, V as CONFIG_FILE_NAME, W as DEFAULT_LOCALE, Y as MIN_RENDER_INTERVAL_MS, Z as WEEK_DAYS, _ as loadWeeklyUsageData, at as inspect, c as getEarliestTimestamp, ct as isSuccess, dt as toArray, et as unwrap, f as loadDailyUsageData, ft as __commonJSMin, g as loadSessionUsageById, h as loadSessionData, i as createUniqueHash, it as inspectError, j as PricingFetcher, k as identifySessionBlocks, l as getUsageLimitResetTime, lt as andThen, m as loadSessionBlockData, mt as __toESM, n as calculateContextTokens, nt as pipe, ot as fail, p as loadMonthlyUsageData, pt as __require, q as MAX_REFRESH_INTERVAL_SECONDS, r as calculateCostForEntry, rt as map$2, s as getClaudePaths, st as succeed, tt as try_, u as globUsageFiles, ut as isFailure, w as usageDataSchema, x as sortFilesByTimestamp, z as BURN_RATE_THRESHOLDS } from "./data-loader-Cwm3YlHL.js";
3
+ import { D as maxValue, E as integer$1, F as string, I as transform, L as trim, M as parse$1, N as pipe$1, O as minValue, P as safeParse, R as union, T as flatten, d as filterDateSchema, k as number, n as SortOrders, t as CostModes, w as check, y as statuslineHookJsonSchema, z as getTotalTokens } from "./_types-BFL_bTNX.js";
4
+ import { n as createTotalsObject, t as calculateTotals } from "./calculate-cost-CKH-OC_c.js";
5
+ import { a as version, i as name, n as logger, r as description, t as log } from "./logger-CxSjxkLv.js";
6
+ import { n as printMismatchReport, t as detectMismatches } from "./debug-BjAuokNY.js";
7
7
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
8
8
  import a, { readFile, stat } from "node:fs/promises";
9
9
  import path, { join } from "node:path";
@@ -6181,13 +6181,20 @@ const statuslineCommand = define({
6181
6181
  blockInfo: "No active block",
6182
6182
  burnRateInfo: ""
6183
6183
  }));
6184
- const contextInfo = await pipe(try_({
6185
- try: calculateContextTokens(hookData.transcript_path, hookData.model.id, mergedOptions.offline),
6184
+ const formatContextInfo = (inputTokens, contextLimit) => {
6185
+ const percentage = Math.round(inputTokens / contextLimit * 100);
6186
+ const coloredPercentage = (percentage < ctx.values.contextLowThreshold ? import_picocolors.default.green : percentage < ctx.values.contextMediumThreshold ? import_picocolors.default.yellow : import_picocolors.default.red)(`${percentage}%`);
6187
+ return `${inputTokens.toLocaleString()} (${coloredPercentage})`;
6188
+ };
6189
+ const contextInfo = pipe(hookData.context_window != null ? succeed({
6190
+ inputTokens: hookData.context_window.total_input_tokens,
6191
+ contextLimit: hookData.context_window.context_window_size
6192
+ }) : await try_({
6193
+ try: async () => calculateContextTokens(hookData.transcript_path, hookData.model.id, mergedOptions.offline),
6186
6194
  catch: (error) => error
6187
- }), inspectError((error) => logger.debug(`Failed to calculate context tokens: ${error instanceof Error ? error.message : String(error)}`)), map$2((contextResult) => {
6195
+ })(), inspectError((error) => logger.debug(`Failed to calculate context tokens: ${error instanceof Error ? error.message : String(error)}`)), map$2((contextResult) => {
6188
6196
  if (contextResult == null) return;
6189
- const coloredPercentage = (contextResult.percentage < ctx.values.contextLowThreshold ? import_picocolors.default.green : contextResult.percentage < ctx.values.contextMediumThreshold ? import_picocolors.default.yellow : import_picocolors.default.red)(`${contextResult.percentage}%`);
6190
- return `${contextResult.inputTokens.toLocaleString()} (${coloredPercentage})`;
6197
+ return formatContextInfo(contextResult.inputTokens, contextResult.contextLimit);
6191
6198
  }), unwrap(void 0));
6192
6199
  return `🤖 ${hookData.model.display_name} | 💰 ${(() => {
6193
6200
  if (ccCost != null || ccusageCost != null) return `(${ccCost != null ? formatCurrency(ccCost) : "N/A"} cc / ${ccusageCost != null ? formatCurrency(ccusageCost) : "N/A"} ccusage)`;
@@ -866,7 +866,7 @@ function createLogger(name$1) {
866
866
  }
867
867
  const log = console.log;
868
868
  var name = "ccusage";
869
- var version = "17.1.7";
869
+ var version = "17.2.0";
870
870
  var description = "Usage analysis tool for Claude Code";
871
871
  const logger = createLogger(name);
872
872
  const log$1 = log;
package/dist/logger.d.ts CHANGED
@@ -17,6 +17,9 @@ declare const logger: consola0.ConsolaInstance;
17
17
  /**
18
18
  * Direct console.log function for cases where logger formatting is not desired
19
19
  */
20
- declare const log: (message?: any, ...optionalParams: any[]) => void;
20
+ declare const log: {
21
+ (...data: any[]): void;
22
+ (message?: any, ...optionalParams: any[]): void;
23
+ };
21
24
  //#endregion
22
25
  export { log, logger };
package/dist/logger.js CHANGED
@@ -1,2 +1,2 @@
1
- import { n as logger, t as log } from "./logger-C7kqABy7.js";
1
+ import { n as logger, t as log } from "./logger-CxSjxkLv.js";
2
2
  export { log, logger };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ccusage",
3
- "version": "17.1.7",
3
+ "version": "17.2.0",
4
4
  "description": "Usage analysis tool for Claude Code",
5
5
  "homepage": "https://github.com/ryoppippi/ccusage#readme",
6
6
  "bugs": {