fix(ccusage): support agent-scoped config schema#1008
Conversation
Generate the ccusage JSON schema with top-level agent namespaces so configurations can use claude, codex, opencode, amp, and pi sections with defaults and command overrides. Merge those agent-scoped settings at runtime for namespaced ccusage subcommands, while preserving legacy Claude top-level defaults and command overrides. Add CLI coverage for Codex config discovery through the main ccusage command.
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds agent-scoped config (claude, codex, opencode, amp, pi): types and validation, merge logic with provenance and unsafe-key skipping, JSON Schema generator updated for agent namespaces, CLI wiring to load/merge configs for subcommands/all, and tests covering schema and CLI behavior. ChangesAgent-namespaced configuration support
Sequence Diagram(s)sequenceDiagram
participant CLI
participant ConfigLoader
participant Merger
participant Runner
CLI->>ConfigLoader: loadConfig(configPath)
ConfigLoader->>CLI: configJson
CLI->>Merger: mergeConfigWithArgs(ctx.values, configJson)
Merger->>CLI: mergedValues
CLI->>Runner: run command with mergedValues
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
🚥 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 docstrings
🧪 Generate unit tests (beta)
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 |
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
apps/ccusage/scripts/generate-json-schema.ts (1)
54-60: ⚡ Quick winTighten token schema typing instead of
Record<string, any).Line 54, Line 121, and Line 198 rely on
any+ unsafe-member-access suppressions in core schema generation paths. Please introduce a typed arg-token shape and usesatisfiesso malformed token definitions fail at compile time.As per coding guidelines, "Use TypeScript typing with
satisfies,as const satisfies, and safer type suppressions as defined intypescript-styleskill".Also applies to: 121-128, 198-218
🤖 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/scripts/generate-json-schema.ts` around lines 54 - 60, Replace the loose Record<string, any> for the token schema input with a concrete typed shape (e.g., TokenDefinition / TokenEntry) and use TypeScript's satisfies (or as const satisfies) so invalid token entries fail at compile time; update the function signature of tokensSchemaToJsonSchema(schema: Record<string, any>) to tokensSchemaToJsonSchema(schema: Record<string, TokenDefinition> | Record<string, TokenDefinition> satisfies /* your type */) and tighten the same schema parameters used at the other schema-generation sites (the two other functions that currently accept an untyped schema) to the new TokenDefinition type; adjust any internal uses (the arg/argTyped variables and property construction) to rely on the typed fields instead of ts/no-unsafe-assignment suppressions so malformed token definitions are caught by the compiler.apps/ccusage/src/_config-loader-tokens.ts (1)
805-835: ⚡ Quick winCover the
agent:reportpath in tests too.
parseCommandName()has separatecodex dailyandcodex:dailybranches, but this new test only exercises the spaced form. Adding a colon-delimited case would make that parser path much harder to regress.🧪 Minimal test expansion
- it('should merge agent namespace config for namespaced commands', () => { + it.each(['codex daily', 'codex:daily'])( + 'should merge agent namespace config for namespaced commands (%s)', + (name) => { const config = { defaults: { json: false }, codex: { defaults: { speed: 'standard', offline: false, }, commands: { daily: { speed: 'fast', }, }, }, } satisfies ConfigData; const merged = mergeConfigWithArgs( { values: { json: true, speed: 'auto' }, tokens: [{ kind: 'option', name: 'json' }], - name: 'codex daily', + name, }, config, ); expect(merged).toEqual({ json: true, speed: 'fast', offline: false, }); - }); + });🤖 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/_config-loader-tokens.ts` around lines 805 - 835, The test only exercises the space-delimited command name path; add a second assertion that covers the colon-delimited parser branch (e.g., call mergeConfigWithArgs with name: 'codex:daily' or 'agent:report' and the same args/config) so parseCommandName's colon path is exercised; update the test "should merge agent namespace config for namespaced commands" to include this additional case and assert the merged result equals the same expected object (json: true, speed: 'fast', offline: false).
🤖 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/src/_config-loader-tokens.ts`:
- Around line 115-135: The validateAgentConfigJson function currently treats
arrays as objects (since typeof [] === 'object'), letting invalid payloads
through; update validateAgentConfigJson to explicitly reject arrays by using
Array.isArray checks for config.defaults and config.commands (i.e., ensure
config.defaults != null && (typeof config.defaults !== 'object' ||
config.defaults === null || Array.isArray(config.defaults)) returns false) and
similarly for config.commands, and additionally iterate over entries in
config.commands (e.g., for (const key in config.commands)) to ensure each
commands[key] is an object and not an array before returning true so malformed
arrays are rejected before applyOptions runs.
---
Nitpick comments:
In `@apps/ccusage/scripts/generate-json-schema.ts`:
- Around line 54-60: Replace the loose Record<string, any> for the token schema
input with a concrete typed shape (e.g., TokenDefinition / TokenEntry) and use
TypeScript's satisfies (or as const satisfies) so invalid token entries fail at
compile time; update the function signature of tokensSchemaToJsonSchema(schema:
Record<string, any>) to tokensSchemaToJsonSchema(schema: Record<string,
TokenDefinition> | Record<string, TokenDefinition> satisfies /* your type */)
and tighten the same schema parameters used at the other schema-generation sites
(the two other functions that currently accept an untyped schema) to the new
TokenDefinition type; adjust any internal uses (the arg/argTyped variables and
property construction) to rely on the typed fields instead of
ts/no-unsafe-assignment suppressions so malformed token definitions are caught
by the compiler.
In `@apps/ccusage/src/_config-loader-tokens.ts`:
- Around line 805-835: The test only exercises the space-delimited command name
path; add a second assertion that covers the colon-delimited parser branch
(e.g., call mergeConfigWithArgs with name: 'codex:daily' or 'agent:report' and
the same args/config) so parseCommandName's colon path is exercised; update the
test "should merge agent namespace config for namespaced commands" to include
this additional case and assert the merged result equals the same expected
object (json: true, speed: 'fast', offline: false).
🪄 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: ef730d04-6fdc-4a3e-90e2-d2c8775b636a
📒 Files selected for processing (6)
apps/ccusage/config-schema.jsonapps/ccusage/scripts/generate-json-schema.tsapps/ccusage/src/_config-loader-tokens.tsapps/ccusage/src/commands/all.tsapps/ccusage/src/commands/index.tsapps/ccusage/test/cli-output.test.ts
Reject array values in agent namespace config validation before they can be merged as option keys. Tighten schema generator token argument typing and cover both spaced and colon-delimited namespaced command parsing in tests.
Deploying with
|
| Status | Name | Latest Commit | Updated (UTC) |
|---|---|---|---|
| ✅ Deployment successful! View logs |
ccusage-guide | 341d8e8 | May 16 2026, 08:49 PM |
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
@ccusage/amp
ccusage
@ccusage/codex
@ccusage/opencode
@ccusage/pi
commit: |
…gent-namespaces # Conflicts: # apps/ccusage/scripts/generate-json-schema.ts # apps/ccusage/src/commands/all.ts
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
ccusage performance comparisonThis compares the PR build against the base branch build on the same CI runner. Committed fixture performanceCommitted small fixture for stable PR-to-PR feedback and output-shape regressions. Fixture:
Large real-world-shaped fixture performanceGenerated fixture around 1 GiB shaped from aggregate local Claude-log statistics: thousands of JSONL files, many small sessions, and a long tail of larger sessions. No real prompts, paths, or outputs are stored in the fixture. Fixture:
Package size
Lower medians and smaller packed package sizes are better. CI runner noise still applies; use same-run ratios as directional PR feedback, not release guarantees. |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 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/src/config-loader-tokens.ts`:
- Around line 115-142: The top-level validator validateConfigJson currently
allows arrays for defaults/commands (e.g., defaults: [], commands: [], commands:
{ daily: [] }) which later cause incorrect merging; update validateConfigJson to
mirror the array guards used in validateAgentConfigJson: ensure when
config.defaults != null it is an object (not null and not Array.isArray), when
config.commands != null it is an object (not null and not Array.isArray), and
also ensure Object.values(config.commands).every(...) checks that each command
value is an object (not null and not an array); return false on any of these
failures so invalid array shapes are rejected before applyOptions().
- Around line 331-338: The config-loader currently only applies top-level
presets (config.commands?.[parsedCommand.report]) for the 'claude' agent, which
prevents shared command presets from being merged for other namespaced agents;
update the logic around parsedCommand handling so that
applyOptions(config.commands?.[parsedCommand.report], 'command config') is
called for every namespaced agent (i.e., whenever parsedCommand.agent != null &&
parsedCommand.report != null) before or in addition to the agent-specific
applyOptions call, preserving the existing call to
applyOptions(config.commands?.[`${parsedCommand.agent}:${parsedCommand.report}`],
'command config') and keeping the Claude-specific duplicate behavior intact for
backward compatibility.
🪄 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: d1d72d03-c0a2-419a-a646-9f489b307f6d
📒 Files selected for processing (4)
apps/ccusage/scripts/generate-json-schema.tsapps/ccusage/src/commands/all.tsapps/ccusage/src/commands/index.tsapps/ccusage/src/config-loader-tokens.ts
🚧 Files skipped from review as they are similar to previous changes (2)
- apps/ccusage/src/commands/all.ts
- apps/ccusage/src/commands/index.ts
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 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/src/config-loader-tokens.ts`:
- Around line 315-327: The merge routine allows prototype-polluting keys from
JSON to mutate objects; in applyOptions/merged/sources create merged and sources
with null prototypes (use Object.create(null) for merged and for sources) and
guard assignments in applyOptions by skipping dangerous keys (at least
"__proto__", "constructor", "prototype") or by checking
Object.prototype.hasOwnProperty.call(options, key) before assigning; update
references in applyOptions so (merged as Record<string,unknown>)[key] and
sources[key] are only set for safe keys to prevent prototype pollution.
🪄 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: 0fddf46d-5ecd-41ad-b844-89c0bd335345
📒 Files selected for processing (1)
apps/ccusage/src/config-loader-tokens.ts
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
Summary
Testing
Summary by cubic
Adds agent-scoped config to ccusage with per-agent namespaces and applies those settings in all-agent reports and direct agent commands. Preserves legacy Claude keys, hardens config parsing/merging, and documents agent-scoped config and merge order; keeps the schema synced via a pre-commit hook.
New Features
claude,codex,opencode,amp, andpinamespaces withdefaultsandcommands; top-leveldefaults/commandsremain for all-agent reports and legacy Claude.all daily|weekly|monthly|session) merge per-agent settings and pass them to each loader;offlineper agent disables the pricing fetcher. Direct agent commands now load namespaced config and support bothagent:reportandagent report;--configis available on all commands.Bug Fixes
__proto__,constructor,prototype) are ignored and merged into a null-prototype object to prevent prototype pollution.config-schema.jsonon pre-commit to avoid stale schemas; removeprepare-time generation.Written for commit 341d8e8. Summary will update on new commits. Review in cubic
Summary by CodeRabbit
New Features
Bug Fixes
Tests
Chores