Skip to content

feat(codex): add weekly usage report command#904

Open
Cheese-Yu wants to merge 1 commit intoryoppippi:mainfrom
Cheese-Yu:codex/create-branch-for-feature-support
Open

feat(codex): add weekly usage report command#904
Cheese-Yu wants to merge 1 commit intoryoppippi:mainfrom
Cheese-Yu:codex/create-branch-for-feature-support

Conversation

@Cheese-Yu
Copy link
Copy Markdown

@Cheese-Yu Cheese-Yu commented Mar 25, 2026

Motivation

  • Add a weekly aggregation/reporting command to the Codex CLI so users can view token usage grouped by week, matching the existing daily/monthly/session reports and addressing issue support weekly in @ccusage/codex@latest #780.
  • Keep Codex parity with other ccusage apps by reusing the same pricing and presentation patterns (pricing fetch, JSON/table output, timezone/locale handling).

Description

  • Add a new weekly subcommand implemented in apps/codex/src/commands/weekly.ts and register it in the CLI router in apps/codex/src/run.ts.
  • Implement weekly aggregation and cost calculation in apps/codex/src/weekly-report.ts, using PricingSource for per-model pricing and producing per-model breakdowns.
  • Extend utilities and types: add toWeekKey() to apps/codex/src/date-utils.ts and add WeeklyUsageSummary / WeeklyReportRow in apps/codex/src/_types.ts.
  • Add in-source vitest tests for weekly aggregation and update apps/codex/README.md to document the new weekly command and feature list.

Testing

  • Ran pnpm --filter @ccusage/codex format, pnpm --filter @ccusage/codex typecheck, and pnpm --filter @ccusage/codex test, and the Codex package formatting, typecheck and tests passed (Codex tests: all reported test files passed).
  • Ran workspace-level pnpm run typecheck and pnpm run test; these produced failures unrelated to this change (other packages had network/config dependent failures and test failures in apps/ccusage), so workspace-wide CI may need environment/pricing fetch fixes to fully green.
  • The PR message includes an issue reference so it can be linked/closed: closes support weekly in @ccusage/codex@latest #780.

Summary by CodeRabbit

  • New Features
    • Introduced weekly usage rollup capability to display token consumption grouped by calendar week.
    • Weekly reports include per-week token breakdowns, cost analysis by model, and aggregate totals.
    • Supports timezone-aware grouping, locale formatting, and date range filtering with existing command options.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 25, 2026

📝 Walkthrough

Walkthrough

This PR introduces a new weekly reporting feature to the Codex CLI. It adds type definitions for weekly summaries, implements a date utility for week-key derivation, creates a report builder that aggregates token usage and costs by week with pricing calculations, registers a new weekly CLI command, and updates documentation to reflect weekly rollup support.

Changes

Cohort / File(s) Summary
Type Definitions
apps/codex/src/_types.ts
Added WeeklyUsageSummary and WeeklyReportRow types to support weekly aggregation with token breakdowns (inputTokens, cachedInputTokens, outputTokens, reasoningOutputTokens, totalTokens), cost tracking, and per-model usage records.
Date Utilities
apps/codex/src/date-utils.ts
Added toWeekKey(timestamp, timezone?) function that computes week-start dates (Sunday) in ISO YYYY-MM-DD format, respecting timezone adjustments.
Report Building
apps/codex/src/weekly-report.ts
New async buildWeeklyReport() function that filters token usage events by date range, groups by week, aggregates totals and per-model usage, fetches pricing for each model, calculates weekly costs, and returns sorted array of WeeklyReportRow objects with embedded Vitest test block.
CLI Command & Registration
apps/codex/src/commands/weekly.ts, apps/codex/src/run.ts
New weeklyCommand CLI command that loads events, validates date filters, calls buildWeeklyReport, and outputs results as JSON or formatted terminal table with per-week breakdowns and totals; command registered in run.ts subcommands map.
Documentation
apps/codex/README.md
Added weekly command to "Common Commands" section and updated "Features" list to reflect support for daily, weekly, and monthly rollups.

Sequence Diagram

sequenceDiagram
    participant CLI as Weekly CLI Command
    participant EventLoader as Event Loader
    participant ReportBuilder as Report Builder
    participant PricingSource as Pricing Source
    participant Output as Output Formatter

    CLI->>EventLoader: Load token usage events
    EventLoader-->>CLI: Return TokenUsageEvent[]
    CLI->>ReportBuilder: buildWeeklyReport(events, filters, timezone)
    ReportBuilder->>ReportBuilder: Filter events by since/until
    ReportBuilder->>ReportBuilder: Group events by weekKey
    ReportBuilder->>ReportBuilder: Aggregate per-week & per-model usage
    ReportBuilder->>PricingSource: Fetch pricing for each model
    PricingSource-->>ReportBuilder: Model pricing data
    ReportBuilder->>ReportBuilder: Calculate weekly costUSD
    ReportBuilder-->>CLI: WeeklyReportRow[]
    CLI->>Output: Format rows as JSON or table
    Output-->>CLI: Formatted result
    CLI-->>User: Display weekly report with totals
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • ryoppippi

Poem

🐰 A new week arrives, bundled with care,
Tokens grouped up, costs laid bare,
From Sunday to Sunday, the usage flows,
Per-model and totaled—behold what it shows! 🌟

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat(codex): add weekly usage report command' directly and accurately summarizes the main change in the pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
apps/codex/src/weekly-report.ts (1)

83-86: Consider parallelizing pricing lookups for better performance.

The sequential await in the loop fetches pricing one model at a time. For reports with many unique models, this could be slow. Using Promise.all would parallelize the requests.

♻️ Suggested parallel fetch
 const modelPricing = new Map<string, Awaited<ReturnType<PricingSource['getPricing']>>>();
-for (const modelName of uniqueModels) {
-	modelPricing.set(modelName, await pricingSource.getPricing(modelName));
-}
+const pricingEntries = await Promise.all(
+	Array.from(uniqueModels).map(async (modelName) => {
+		const pricing = await pricingSource.getPricing(modelName);
+		return [modelName, pricing] as const;
+	}),
+);
+for (const [modelName, pricing] of pricingEntries) {
+	modelPricing.set(modelName, pricing);
+}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/codex/src/weekly-report.ts` around lines 83 - 86, The loop that fills
modelPricing does sequential awaits (for const modelName of uniqueModels) which
is slow; instead map uniqueModels to an array of promises using
pricingSource.getPricing(modelName), run them in parallel with Promise.all, then
populate the modelPricing Map with the resolved results; update the code that
currently references modelPricing, uniqueModels, and pricingSource.getPricing to
use the Promise.all pattern and preserve the same Map entries (key = modelName,
value = resolved pricing).
apps/codex/src/commands/weekly.ts (1)

77-95: Consider reusing the totalsForDisplay accumulation logic.

The totals are computed twice: once in lines 77-95 for JSON output and again in lines 135-151 for display. While the structures differ slightly (reasoningOutputTokens vs reasoningTokens), consider extracting a single accumulation pass or reusing the first result to avoid redundant iteration over rows.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/codex/src/commands/weekly.ts` around lines 77 - 95, The code iterates
rows twice to compute totals (first into totals via rows.reduce and again into
totalsForDisplay), which is redundant; modify the logic to compute a single
accumulator from rows (reuse the existing rows.reduce that produces totals) and
then derive totalsForDisplay from that result (map totals.reasoningOutputTokens
to reasoningTokens and compute any display-specific fields) or replace the
second reduce with a conversion function that transforms totals into the display
shape; update references to use the single computed totals to avoid the
duplicate pass.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@apps/codex/src/commands/weekly.ts`:
- Around line 77-95: The code iterates rows twice to compute totals (first into
totals via rows.reduce and again into totalsForDisplay), which is redundant;
modify the logic to compute a single accumulator from rows (reuse the existing
rows.reduce that produces totals) and then derive totalsForDisplay from that
result (map totals.reasoningOutputTokens to reasoningTokens and compute any
display-specific fields) or replace the second reduce with a conversion function
that transforms totals into the display shape; update references to use the
single computed totals to avoid the duplicate pass.

In `@apps/codex/src/weekly-report.ts`:
- Around line 83-86: The loop that fills modelPricing does sequential awaits
(for const modelName of uniqueModels) which is slow; instead map uniqueModels to
an array of promises using pricingSource.getPricing(modelName), run them in
parallel with Promise.all, then populate the modelPricing Map with the resolved
results; update the code that currently references modelPricing, uniqueModels,
and pricingSource.getPricing to use the Promise.all pattern and preserve the
same Map entries (key = modelName, value = resolved pricing).

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a96db863-d886-492b-8323-2bcc6416993c

📥 Commits

Reviewing files that changed from the base of the PR and between d3cb6df and a8f546e.

📒 Files selected for processing (6)
  • apps/codex/README.md
  • apps/codex/src/_types.ts
  • apps/codex/src/commands/weekly.ts
  • apps/codex/src/date-utils.ts
  • apps/codex/src/run.ts
  • apps/codex/src/weekly-report.ts

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

support weekly in @ccusage/codex@latest

1 participant