feat(ccusage): add --prompts flag to claude daily/weekly/monthly reports (rebase of #710 onto v19)#992
feat(ccusage): add --prompts flag to claude daily/weekly/monthly reports (rebase of #710 onto v19)#992akiratee wants to merge 2 commits into
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (2)
📝 WalkthroughWalkthroughThis PR adds a ChangesPrompt Count Feature Implementation
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ESLint
apps/ccusage/src/daily-grouping.ts[baseline-browser-mapping] The data in this module is over two months old. To ensure accurate Baseline data, please update: Oops! Something went wrong! :( ESLint: 9.35.0 Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'eslint-plugin-format' imported from /node_modules/.pnpm/@antfu+eslint-config@4.19.0_@vue+compiler-sfc@3.5.30_eslint@9.35.0_typescript@5.9.2_vit_670a2c5c75d4275eabd7bc195a173ee6/node_modules/@antfu/eslint-config/dist/index.js packages/terminal/src/table.ts[baseline-browser-mapping] The data in this module is over two months old. To ensure accurate Baseline data, please update: Oops! Something went wrong! :( ESLint: 9.35.0 Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'eslint-plugin-format' imported from /node_modules/.pnpm/@antfu+eslint-config@4.19.0_@vue+compiler-sfc@3.5.30_eslint@9.35.0_typescript@5.9.2_vit_670a2c5c75d4275eabd7bc195a173ee6/node_modules/@antfu/eslint-config/dist/index.js 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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (4)
apps/ccusage/src/commands/weekly.ts (2)
56-66:⚠️ Potential issue | 🟠 Major | ⚡ Quick winGate and stabilize
promptCountin weekly JSON output.Line 96/Line 100 always emit
promptCount, but Line 56-66 omits it in empty output. This makes the JSON shape inconsistent and breaks consumers relying on stable fields.💡 Suggested fix
@@ - const weeklyData = await loadWeeklyUsageData(mergedOptions); + const weeklyData = await loadWeeklyUsageData(mergedOptions); + const includePrompts = Boolean(mergedOptions.prompts); @@ - const emptyOutput = { + const emptyOutput = { weekly: [], totals: { inputTokens: 0, outputTokens: 0, cacheCreationTokens: 0, cacheReadTokens: 0, totalTokens: 0, totalCost: 0, + ...(includePrompts && { promptCount: 0 }), }, }; @@ - modelBreakdowns: data.modelBreakdowns, - promptCount: data.promptCount, + modelBreakdowns: data.modelBreakdowns, + ...(includePrompts && { promptCount: data.promptCount }), })), - totals: { - ...createTotalsObject(totals), - promptCount: weeklyData.reduce((sum, data) => sum + (data.promptCount || 0), 0), - }, + totals: { + ...createTotalsObject(totals), + ...(includePrompts && { + promptCount: weeklyData.reduce((sum, data) => sum + (data.promptCount ?? 0), 0), + }), + }, };Also applies to: 86-101
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/ccusage/src/commands/weekly.ts` around lines 56 - 66, The empty JSON shape named emptyOutput is missing the promptCount field which makes the weekly output inconsistent; update the totals object in emptyOutput (and any other default/empty result objects around the same area) to include promptCount: 0 so the weekly output always emits promptCount, ensuring the JSON shape matches the non-empty path that currently sets promptCount.
149-151:⚠️ Potential issue | 🟠 Major | ⚡ Quick winFix breakdown-column shift when
--promptsis enabled.On Line 150,
pushBreakdownRowsstill uses the default pre-metric offset, so with prompts enabled the breakdown metrics render one column too far left.💡 Suggested fix
- if (mergedOptions.breakdown) { - pushBreakdownRows(table, data.modelBreakdowns); - } + if (mergedOptions.breakdown) { + pushBreakdownRows(table, data.modelBreakdowns, includePrompts ? 2 : 1); + }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/ccusage/src/commands/weekly.ts` around lines 149 - 151, The breakdown rows are being rendered with the default pre-metric offset, causing a one-column left shift when prompts are enabled; update the call at the mergedOptions.breakdown branch to pass the current pre-metric offset used for the rest of the table (the same offset variable used when rendering metrics/prompts — e.g., preMetricOffset or columnStart) into pushBreakdownRows, or modify pushBreakdownRows to accept and apply that offset; ensure the function signature for pushBreakdownRows is updated accordingly and all other call sites are adjusted to use the correct offset so breakdown columns align when --prompts is enabled.apps/ccusage/src/commands/daily.ts (1)
109-132:⚠️ Potential issue | 🟠 Major | ⚡ Quick winInclude
promptCountin daily JSON totals when--promptsis enabled.
totalPromptCountis computed, and row-levelpromptCountis conditionally emitted, but JSONtotalsnever includespromptCount.Proposed fix
if (useJson) { + const jsonTotals = { + ...createTotalsObject(totals), + ...(mergedOptions.prompts === true && { promptCount: totalPromptCount }), + }; + // Output JSON format - group by project if instances flag is used const jsonOutput = Boolean(mergedOptions.instances) && dailyData.some((d) => d.project != null) ? { projects: groupByProject(dailyData), - totals: createTotalsObject(totals), + totals: jsonTotals, } : { daily: dailyData.map((data) => ({ date: data.date, @@ ...(mergedOptions.prompts === true && { promptCount: data.promptCount }), ...(data.project != null && { project: data.project }), })), - totals: createTotalsObject(totals), + totals: jsonTotals, };🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/ccusage/src/commands/daily.ts` around lines 109 - 132, The JSON totals object doesn't include promptCount when --prompts is enabled; update the code that builds the JSON output (the branch using createTotalsObject(totals)) to include promptCount conditionally when mergedOptions.prompts === true by pulling the value from the existing totals/totalPromptCount; either modify createTotalsObject to return { ..., promptCount: totals.totalPromptCount } when prompts are enabled or, where createTotalsObject(totals) is used, spread its result and add ...(mergedOptions.prompts === true && { promptCount: totals.totalPromptCount }) so the JSON totals include promptCount.apps/ccusage/src/commands/monthly.ts (1)
47-56:⚠️ Potential issue | 🟠 Major | ⚡ Quick winGate monthly JSON
promptCountbehind--prompts.
promptCountis emitted unconditionally in monthly JSON rows/totals, so--promptscurrently has no effect in JSON mode and changes payload shape even when the flag is off.Proposed fix
const emptyOutput = { monthly: [], totals: { inputTokens: 0, outputTokens: 0, cacheCreationTokens: 0, cacheReadTokens: 0, totalTokens: 0, totalCost: 0, + ...(mergedOptions.prompts === true && { promptCount: 0 }), }, }; @@ monthly: monthlyData.map((data) => ({ month: data.month, inputTokens: data.inputTokens, outputTokens: data.outputTokens, cacheCreationTokens: data.cacheCreationTokens, cacheReadTokens: data.cacheReadTokens, totalTokens: getTotalTokens(data), totalCost: data.totalCost, modelsUsed: data.modelsUsed, modelBreakdowns: data.modelBreakdowns, - promptCount: data.promptCount, + ...(mergedOptions.prompts === true && { promptCount: data.promptCount }), })), totals: { ...createTotalsObject(totals), - promptCount: monthlyData.reduce((sum, data) => sum + (data.promptCount || 0), 0), + ...(mergedOptions.prompts === true && { + promptCount: monthlyData.reduce((sum, data) => sum + (data.promptCount || 0), 0), + }), },Also applies to: 77-92
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/ccusage/src/commands/monthly.ts` around lines 47 - 56, The monthly JSON currently always emits the promptCount field (in the emptyOutput.totals and each monthly row), so the --prompts flag has no effect and changes the payload shape; update the JSON construction logic (references: emptyOutput, monthly array entries, totals, promptCount) to only add the promptCount property when the --prompts flag is true (the same condition used for non-JSON output), and apply the same gating in the other JSON construction site mentioned (the block around lines 77-92) so both per-month rows and the totals object omit promptCount unless the prompts flag is enabled.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@apps/ccusage/README.md`:
- Line 163: The sentence "The prompt count shows exactly how many individual
messages/prompts you sent to Claude each day" overstates semantics; change the
copy to clarify that the metric counts usage-bearing API/chat turns or logged
entries (i.e., prompts that generated usage) rather than literal user-typed
messages. Update the README line containing that exact sentence to something
like: "The prompt count reflects the number of usage-bearing chat turns/entries
recorded per day, not necessarily every individual keystroke or draft message."
Make the same wording change at the other occurrence (the line around the other
referenced sentence) so both descriptions consistently refer to usage-bearing
turns/entries.
- Around line 139-190: The fenced code blocks in README.md lack language
identifiers and trigger markdownlint MD040; update each triple-backtick block
shown (the four sample tables) to include a language tag such as text by
replacing ``` with ```text for those blocks (the Daily, Monthly, Weekly and the
first table) so all code fences include a language identifier.
---
Outside diff comments:
In `@apps/ccusage/src/commands/daily.ts`:
- Around line 109-132: The JSON totals object doesn't include promptCount when
--prompts is enabled; update the code that builds the JSON output (the branch
using createTotalsObject(totals)) to include promptCount conditionally when
mergedOptions.prompts === true by pulling the value from the existing
totals/totalPromptCount; either modify createTotalsObject to return { ...,
promptCount: totals.totalPromptCount } when prompts are enabled or, where
createTotalsObject(totals) is used, spread its result and add
...(mergedOptions.prompts === true && { promptCount: totals.totalPromptCount })
so the JSON totals include promptCount.
In `@apps/ccusage/src/commands/monthly.ts`:
- Around line 47-56: The monthly JSON currently always emits the promptCount
field (in the emptyOutput.totals and each monthly row), so the --prompts flag
has no effect and changes the payload shape; update the JSON construction logic
(references: emptyOutput, monthly array entries, totals, promptCount) to only
add the promptCount property when the --prompts flag is true (the same condition
used for non-JSON output), and apply the same gating in the other JSON
construction site mentioned (the block around lines 77-92) so both per-month
rows and the totals object omit promptCount unless the prompts flag is enabled.
In `@apps/ccusage/src/commands/weekly.ts`:
- Around line 56-66: The empty JSON shape named emptyOutput is missing the
promptCount field which makes the weekly output inconsistent; update the totals
object in emptyOutput (and any other default/empty result objects around the
same area) to include promptCount: 0 so the weekly output always emits
promptCount, ensuring the JSON shape matches the non-empty path that currently
sets promptCount.
- Around line 149-151: The breakdown rows are being rendered with the default
pre-metric offset, causing a one-column left shift when prompts are enabled;
update the call at the mergedOptions.breakdown branch to pass the current
pre-metric offset used for the rest of the table (the same offset variable used
when rendering metrics/prompts — e.g., preMetricOffset or columnStart) into
pushBreakdownRows, or modify pushBreakdownRows to accept and apply that offset;
ensure the function signature for pushBreakdownRows is updated accordingly and
all other call sites are adjusted to use the correct offset so breakdown columns
align when --prompts is enabled.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 187f3d38-9962-4e82-b605-47bcbfc1d5be
📒 Files selected for processing (11)
apps/ccusage/README.mdapps/ccusage/config-schema.jsonapps/ccusage/src/_daily-grouping.tsapps/ccusage/src/_json-output-types.tsapps/ccusage/src/calculate-cost.tsapps/ccusage/src/commands/daily.tsapps/ccusage/src/commands/monthly.tsapps/ccusage/src/commands/session.tsapps/ccusage/src/commands/weekly.tsapps/ccusage/src/data-loader.tspackages/terminal/src/table.ts
- daily.ts: include promptCount in JSON totals when --prompts is set (both flat and --instances project-grouped outputs). - weekly/monthly.ts: gate JSON promptCount behind --prompts so the flag actually has an effect in JSON mode and the payload shape is stable when off. Also gate the emptyOutput totals. - daily/weekly/monthly.ts: pass includePrompts-aware pre-metric offset to pushBreakdownRows so breakdown rows align under the correct columns when --breakdown is combined with --prompts. - README: add language tags to fenced code blocks (markdownlint MD040); clarify that the prompt count reflects usage-bearing entries (one per API request, including tool-call iterations), not literal user-typed messages.
|
Heads up - main moved substantially since I opened this (v19 major cut, the adapter unification in #1004, file-prefix rename in #1007, the all-agent reports in #1000). The rebase isn't mechanical anymore - the data loader now lives in `adapter/claude/data-loader.ts` and command shapes changed enough that I'm going to re-implement on top of v19 rather than force-fit the old diff. Keeping scope the same as #710 - `--prompts` for daily/weekly/monthly on the Claude adapter. Happy to generalize `promptCount` to the shared adapter layer so Codex/Amp/OpenCode/Pi get it for free, but that feels like a separate PR unless you'd prefer it bundled. Let me know. Will push an updated branch shortly. |
Reimplements antonioribeiro's ryoppippi#710 on top of v19's adapter architecture. Adds an optional `--prompts` flag to the Claude-scoped daily, weekly, and monthly reports that displays a Prompts column with the number of usage-bearing entries (one per API request, including each tool-call iteration within a single user message) recorded per bucket. Scope is limited to the Claude adapter to match ryoppippi#710. Generalizing promptCount to the shared adapter layer (so Codex/Amp/OpenCode/Pi inherit the column) is a separate change. Changes: - adapter/claude/data-loader: track `promptCount` on the shared `UsageSummaryAccumulator`, surface it from `finalizeUsageSummary`, and expose it on `DailyUsage`/`WeeklyUsage`/`MonthlyUsage`/`BucketUsage`. Bucket aggregation sums each daily's `promptCount` so weekly/monthly numbers stay consistent with daily. - packages/terminal/table: add `includePrompts` to `UsageReportConfig` and an optional `promptCount` on `UsageData`. When set, `Prompts` slots between Models (or Agent) and Input in both base and compact layouts. `formatUsageDataRow` and `formatTotalsRow` derive whether to render a Prompts cell from `data.promptCount != null`. - commands/daily, commands/weekly, commands/monthly: add `prompts` CLI arg, thread `includePrompts` through table config, row/total formatters, and `pushBreakdownRows` offset (2 instead of 1 when prompts is on) so breakdown rows stay aligned with `--breakdown`. JSON output gates `promptCount` on rows, totals, and `emptyOutput` totals behind `--prompts` so payload shape is stable when the flag is off. - `groupByProject` (daily --instances JSON) takes a new `includePrompts` argument and propagates `promptCount`; `DailyProjectOutput` gained optional `promptCount`. - README: mention the flag in the feature list. - config-schema.json regenerated. Co-Authored-By: Antonio Ribeiro <acr@antoniocarlosribeiro.com>
ab4ff08 to
6f55a7e
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
packages/terminal/src/table.ts (1)
846-855:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winKeep the Prompts column in compact all-agent tables too.
When
includeAgentandincludePromptsare both true, the compact header starts asDate | Agent | Total Tokens | Costand never gets a Prompts column because this logic only inserts beforeInput. On narrow terminals,--promptssilently disappears for that layout.Also applies to: 863-877
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/terminal/src/table.ts` around lines 846 - 855, The compact table configuration omits the Prompts column when both config.includeAgent and config.includePrompts are true; update the logic that builds compactHeaders, compactAligns, and compactMinColumnWidths (the variables compactHeaders, compactAligns, compactMinColumnWidths) so that if config.includePrompts is true you insert a "Prompts" column (with matching alignment 'left' and an appropriate min width) into the compact arrays even in the includeAgent branch; apply the same change to the second compact-building block referenced around the other occurrence (lines constructing those same variables for the alternate case) so compact all-agent tables retain the Prompts column on narrow terminals.
🧹 Nitpick comments (1)
apps/ccusage/src/daily-grouping.ts (1)
63-123: ⚡ Quick winAdd test coverage for the
includePromptsparameter.The tests currently do not verify that
promptCountis conditionally included/excluded based on theincludePromptsflag. Consider adding test cases that assert:
- When
includePromptsisfalse(or omitted), the output records should not containpromptCount.- When
includePromptsistrue, the output records should containpromptCountwith the expected value.✅ Proposed test additions
describe('groupByProject', () => { it('groups daily data by project for JSON output', () => { const mockData = [ { date: createDailyDate('2024-01-01'), project: 'project-a', inputTokens: 1000, outputTokens: 500, cacheCreationTokens: 100, cacheReadTokens: 200, totalCost: 0.01, modelsUsed: [createModelName('claude-sonnet-4-20250514')], modelBreakdowns: [], promptCount: 0, }, { date: createDailyDate('2024-01-01'), project: 'project-b', inputTokens: 2000, outputTokens: 1000, cacheCreationTokens: 200, cacheReadTokens: 300, totalCost: 0.02, modelsUsed: [createModelName('claude-opus-4-20250514')], modelBreakdowns: [], promptCount: 0, }, ]; const result = groupByProject(mockData); expect(Object.keys(result)).toHaveLength(2); expect(result['project-a']).toHaveLength(1); expect(result['project-b']).toHaveLength(1); expect(result['project-a']![0]!.totalTokens).toBe(1800); expect(result['project-b']![0]!.totalTokens).toBe(3500); }); + + it('excludes promptCount when includePrompts is false', () => { + const mockData = [ + { + date: createDailyDate('2024-01-01'), + project: 'project-a', + inputTokens: 1000, + outputTokens: 500, + cacheCreationTokens: 0, + cacheReadTokens: 0, + totalCost: 0.01, + modelsUsed: [createModelName('claude-sonnet-4-20250514')], + modelBreakdowns: [], + promptCount: 5, + }, + ]; + + const result = groupByProject(mockData, false); + + expect(result['project-a']![0]!).not.toHaveProperty('promptCount'); + }); + + it('includes promptCount when includePrompts is true', () => { + const mockData = [ + { + date: createDailyDate('2024-01-01'), + project: 'project-a', + inputTokens: 1000, + outputTokens: 500, + cacheCreationTokens: 0, + cacheReadTokens: 0, + totalCost: 0.01, + modelsUsed: [createModelName('claude-sonnet-4-20250514')], + modelBreakdowns: [], + promptCount: 5, + }, + ]; + + const result = groupByProject(mockData, true); + + expect(result['project-a']![0]!.promptCount).toBe(5); + }); it('handles unknown project names', () => {🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/ccusage/src/daily-grouping.ts` around lines 63 - 123, Add tests for the includePrompts flag in the groupByProject unit suite: create two new cases (or extend existing ones) that call groupByProject(mockData, includePrompts) where includePrompts is omitted/false and where it is true; for the false/omitted case assert that the returned project records do NOT have a promptCount property, and for the true case assert that each record contains promptCount with the expected value (e.g., sum of promptCount from inputs). Reference the groupByProject function and its includePrompts parameter when adding these assertions.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/terminal/src/table.ts`:
- Around line 937-941: The insertion of the Prompts cell should be driven by the
table layout config (e.g., includePrompts) rather than the presence of
data.promptCount: replace the condition that checks data.promptCount with a
check of the layout flag (includePrompts) and always splice a cell at the
computed insertAt index; when promptCount is missing insert an empty string or
placeholder (instead of skipping the splice) so subsequent cells (like Input)
don't shift. Apply the same change for the second occurrence that mirrors lines
979-983, keeping the insert index logic using data.agent and formatting with
formatNumber when promptCount exists.
---
Outside diff comments:
In `@packages/terminal/src/table.ts`:
- Around line 846-855: The compact table configuration omits the Prompts column
when both config.includeAgent and config.includePrompts are true; update the
logic that builds compactHeaders, compactAligns, and compactMinColumnWidths (the
variables compactHeaders, compactAligns, compactMinColumnWidths) so that if
config.includePrompts is true you insert a "Prompts" column (with matching
alignment 'left' and an appropriate min width) into the compact arrays even in
the includeAgent branch; apply the same change to the second compact-building
block referenced around the other occurrence (lines constructing those same
variables for the alternate case) so compact all-agent tables retain the Prompts
column on narrow terminals.
---
Nitpick comments:
In `@apps/ccusage/src/daily-grouping.ts`:
- Around line 63-123: Add tests for the includePrompts flag in the
groupByProject unit suite: create two new cases (or extend existing ones) that
call groupByProject(mockData, includePrompts) where includePrompts is
omitted/false and where it is true; for the false/omitted case assert that the
returned project records do NOT have a promptCount property, and for the true
case assert that each record contains promptCount with the expected value (e.g.,
sum of promptCount from inputs). Reference the groupByProject function and its
includePrompts parameter when adding these assertions.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: f206e3a1-72cc-4baf-847e-41b0f4fbb9fb
📒 Files selected for processing (10)
apps/ccusage/README.mdapps/ccusage/config-schema.jsonapps/ccusage/src/adapter/claude/data-loader.tsapps/ccusage/src/calculate-cost.tsapps/ccusage/src/commands/daily.tsapps/ccusage/src/commands/monthly.tsapps/ccusage/src/commands/weekly.tsapps/ccusage/src/daily-grouping.tsapps/ccusage/src/json-output-types.tspackages/terminal/src/table.ts
✅ Files skipped from review due to trivial changes (2)
- apps/ccusage/README.md
- apps/ccusage/src/calculate-cost.ts
🚧 Files skipped from review as they are similar to previous changes (3)
- apps/ccusage/src/commands/weekly.ts
- apps/ccusage/src/commands/monthly.ts
- apps/ccusage/src/commands/daily.ts
| if (data.promptCount != null) { | ||
| // Prompts column sits just before Input; index = (agent ? 3 : 2) | ||
| const insertAt = data.agent != null ? 3 : 2; | ||
| row.splice(insertAt, 0, formatNumber(data.promptCount)); | ||
| } |
There was a problem hiding this comment.
Drive Prompts-cell insertion from layout config, not from promptCount presence.
If the table is created with includePrompts: true but a row omits promptCount, these helpers emit one fewer cell than the header and shift Input under Prompts. Because UsageData.promptCount is optional, that mismatch is currently reachable from the public API.
Suggested fix
export function formatUsageDataRow(
firstColumnValue: string,
data: UsageData,
+ includePrompts = false,
lastActivity?: string,
): (string | number)[] {
@@
- if (data.promptCount != null) {
- // Prompts column sits just before Input; index = (agent ? 3 : 2)
- const insertAt = data.agent != null ? 3 : 2;
- row.splice(insertAt, 0, formatNumber(data.promptCount));
+ if (includePrompts) {
+ const insertAt = data.agent != null ? 3 : 2;
+ row.splice(insertAt, 0, data.promptCount != null ? formatNumber(data.promptCount) : '');
}
@@
export function formatTotalsRow(
totals: UsageData,
includeLastActivity = false,
includeAgent = false,
+ includePrompts = false,
): (string | number)[] {
@@
- if (totals.promptCount != null) {
- // Prompts column sits just before Input
- const insertAt = includeAgent ? 3 : 2;
- row.splice(insertAt, 0, pc.yellow(formatNumber(totals.promptCount)));
+ if (includePrompts) {
+ const insertAt = includeAgent ? 3 : 2;
+ row.splice(
+ insertAt,
+ 0,
+ totals.promptCount != null ? pc.yellow(formatNumber(totals.promptCount)) : '',
+ );
}Also applies to: 979-983
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/terminal/src/table.ts` around lines 937 - 941, The insertion of the
Prompts cell should be driven by the table layout config (e.g., includePrompts)
rather than the presence of data.promptCount: replace the condition that checks
data.promptCount with a check of the layout flag (includePrompts) and always
splice a cell at the computed insertAt index; when promptCount is missing insert
an empty string or placeholder (instead of skipping the splice) so subsequent
cells (like Input) don't shift. Apply the same change for the second occurrence
that mirrors lines 979-983, keeping the insert index logic using data.agent and
formatting with formatNumber when promptCount exists.
…-review) - terminal/table: when both includeAgent and includePrompts are set, the compact layout has no Input column so the previous insert-before- Input logic silently dropped the Prompts column on narrow terminals. Fall back to inserting before Total Tokens in that case so the Prompts column survives in compact all-agent layouts. Not reachable from any current user path (this PR keeps --prompts on the Claude- only commands which don't set includeAgent) but unblocks the planned all-adapter follow-up. - daily-grouping: add tests covering the includePrompts toggle so the conditional propagation is regression-protected.
Summary
Reimplements @antonioribeiro's #710 (
--promptsflag for daily/weekly/monthly reports) on top of the v19 adapter architecture. The original PR sat against pre-v19 code that has since been substantially reshaped (#1004 adapter unification, #1007 file-prefix rename, #1000 all-agent reports). A literal rebase wasn't viable, so this is a fresh implementation that preserves #710's scope and behavior while fitting the new layout.Scope is intentionally limited to the Claude adapter to match #710. Generalizing
promptCountto the shared adapter layer (so Codex/Amp/OpenCode/Pi inherit the column) is a separate change - happy to do that if you'd prefer it bundled.What's in here
Adapter (
apps/ccusage/src/adapter/claude/data-loader.ts)promptCounton the sharedUsageSummaryAccumulatorand surface it fromfinalizeUsageSummary.promptCount: numbertoDailyUsage,WeeklyUsage,MonthlyUsage, andBucketUsage.promptCountso the numbers stay consistent across reports.Terminal (
packages/terminal/src/table.ts)includePrompts?: booleanonUsageReportConfig.promptCount?: numberonUsageData.Promptscolumn slots between Models (or Agent) and Input in both base and compact layouts.formatUsageDataRowandformatTotalsRowderive whether to render a Prompts cell fromdata.promptCount != null- no signature breakage for existing callers.Commands (
apps/ccusage/src/commands/{daily,weekly,monthly}.ts)promptsboolean CLI arg (defaults tofalse).includePromptsthrough table config, row/total formatters, separator column count, andpushBreakdownRowsoffset (2 instead of 1 when--promptsis on) so--breakdownrows stay aligned.promptCounton rows, totals, andemptyOutputtotals behind--promptsso the payload shape is stable when the flag is off.Project grouping (
apps/ccusage/src/daily-grouping.ts,json-output-types.ts)groupByProjecttakes a newincludePromptsargument and propagatespromptCountintoDailyProjectOutput(which gained an optionalpromptCountfield). Keepsdaily --instances --prompts --jsonconsistent with the flat output.Misc
config-schema.jsonregenerated.Note on semantics
promptCountcounts usage-bearing entries (one per assistant API call). A single user message that triggers N tool iterations counts as N+ entries, not 1. The companion PR #679 (blocks command) filters to user-role messages instead, so the two PRs count different things under the same flag. Worth deciding whether to unify the definition before merging both.Test plan
pnpm test- 498/498 pass (3 pre-existing skipped)pnpm lint- cleanpnpm --filter ccusage typecheck- cleanpnpm --filter ccusage build- cleanccusage claude daily/claude weekly/claude monthlyagainst real Claude Code data: Total-row input-token / cost figures match between flag states (proves no column shift).ccusage claude weekly --breakdown --prompts: breakdown rows have an empty Prompts cell so model token columns stay aligned with the data row above.--jsongating:promptCountabsent on rows and totals without--prompts, present with it.ccusage claude daily --instances --prompts --jsonpropagatespromptCountthroughgroupByProjectand totals.ccusage daily(all-agent unified report) is unaffected.Closes #710. Companion PR #679 is independent.
Summary by CodeRabbit