Skip to content

Unified reports ignore source-specific config sections #1957

Closed

Description

@viniciusdsandrade

What happened?

Unified reports (ccusage, ccusage daily, weekly, monthly, session) load every source with the same shared options and never read <source>.defaults, <source>.commands.<report> or commands.<source>:<report>. The config docs say the opposite:

  • docs/guide/config-files.md:290: "Source-specific settings are also applied when running unified reports such as ccusage daily. In that case, each source receives its own merged options before data is loaded."
  • docs/guide/configuration.md:145 says the same.

This is a regression from the TypeScript CLI (up to v19.0.3): apps/ccusage/src/commands/all.ts built one merged option set per agent (mergeAllOptions, merging the config under the name <agent> <kind>) and loaded each agent with it. The native Rust CLI (#977) hands one SharedArgs to every loader.

Where it goes wrong on main (e42e1b4):

  • rust/crates/ccusage-config/src/config.rs:92: option_maps reads <agent>.* only when the detected command has an agent, and ccusage daily has none.
  • rust/crates/ccusage-adapter-all/src/loader.rs:117: load_base_rows builds one loader_shared and hands it to all 18 loaders.
  • rust/crates/ccusage-adapter-all/src/loader.rs:685 and :698 hardcode CodexSpeed::Auto; :219 loads pi with custom_path: None; :246 loads OpenClaw with None. So codex.defaults.speed, pi.defaults.piPath and openclaw.defaults.openClawPath have no effect on unified reports either, even though the same keys drive ccusage codex daily, ccusage pi daily and ccusage openclaw daily.

Steps to reproduce

  1. Keep pi sessions outside the default directory, for example /data/pi/sessions.

  2. Write .ccusage/ccusage.json:

    {
      "pi": { "defaults": { "piPath": "/data/pi/sessions" } },
      "codex": { "defaults": { "speed": "fast", "since": "20260101" } }
    }
  3. Compare ccusage pi daily with ccusage daily: the focused report shows the pi usage, the unified report does not (pi is missing from the Detected: line).

  4. Compare ccusage codex daily with ccusage daily: the unified report prices Codex at the auto-detected tier instead of Fast, and ignores the since bound, so the Codex totals differ between the two reports.

Expected behavior

A unified report loads each source with the options ccusage <source> <report> would use: defaults, then commands.<report>, then <source>.defaults, then <source>.commands.<report>, with command-line flags still on top, as the docs describe.

I would like to implement this. Proposed approach: resolve one option set per source in the binary by parsing the same command line against that source's view of the config (so flags keep their precedence over config), carry those per-source options on AgentCommandArgs, and have the unified loader use them per source, including the Codex speed and the pi and OpenClaw paths.

Version

20.0.42 (main at e42e1b4)

Activity

  1. pullfrog commented on Oct 23, 2026

    @pullfrog
    Contributor
  2. added
    bugSomething isn't working
    priority:mediumA normal bug or meaningful improvement.
    triage:maintainableFits the repository's maintainable scope and needs review.
    on Oct 23, 2026
  3. added
    priority:highHigh user impact or an important regression.
    and removed
    priority:mediumA normal bug or meaningful improvement.
    on Oct 23, 2026
  4. github-actions commented on Oct 23, 2026

    @github-actions
    Contributor

    Pullfrog triage: priority:high
    Kind: bug
    Maintenance fit: maintainable
    Confidence: high

    Unified reports ignore documented per-source config. Docs promise each source gets merged options, TypeScript CLI did this, Rust code uses one shared options object and hardcodes Codex speed and pi and OpenClaw paths. This drops pi usage and misprices Codex costs.

    Decision: kept open; Pullfrog will attempt a focused implementation PR.

  5. viniciusdsandrade commented on Oct 23, 2026

    @viniciusdsandrade
    ContributorAuthor

    The fix is ready on my fork. GitHub rejects pull request creation from my account on this repository (GraphQL CreatePullRequest reports missing permissions, REST returns 404), so I am leaving the branch here:

    What it does: the binary resolves one option set per source the config addresses by parsing the same command line against that source's view of the config (ConfigContext::for_source), so flags keep precedence over the sections, and carries it on AgentCommandArgs.sources. The unified loader then loads each source with its own shared options, uses the configured Codex speed, and reads the pi and OpenClaw paths. Sources the config does not address keep the unified options, so output without source sections is unchanged. Tests cover the config view, the resolution (flags above sections, the bare ccusage, session) and the loader (pi path, per-source date window). I reviewed it by reading and have not run the suite locally, so CI would be the first run.

    If you lgtm me I will open the PR with the full description; otherwise feel free to pull the branch as with #1948.

  6. ryoppippi commented on Nov 10, 2026

    @ryoppippi
    Member

    Note

    🤖 Claude Opus 5.5 responding on behalf of @ryoppippi

    Your fix landed in #1959, which kept your commits and credits you as co-author, and shipped in v20.0.43. Unified reports now apply source-specific config sections. Thanks for preparing the branch.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingpriority:highHigh user impact or an important regression.triage:maintainableFits the repository's maintainable scope and needs review.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions