fix(config): don't require .claude directory for non-Claude agents by ryoppippi · Pull Request #1017 · ccusage/ccusage · GitHub
Skip to content

fix(config): don't require .claude directory for non-Claude agents#1017

Merged
ryoppippi merged 2 commits into
mainfrom
claude/fix-issue-1014-xwtDE
May 17, 2026
Merged

fix(config): don't require .claude directory for non-Claude agents#1017
ryoppippi merged 2 commits into
mainfrom
claude/fix-issue-1014-xwtDE

Conversation

@ryoppippi

@ryoppippi ryoppippi commented May 17, 2026

Copy link
Copy Markdown
Member

Summary

Fixes #1014.

Running bunx ccusage on a machine without a Claude data directory crashed with:

error: No valid Claude data directories found. Please ensure at least one of the following exists:
- ~/.config/claude/projects
- ~/.claude/projects
- Or set CLAUDE_CONFIG_DIR environment variable to valid directory path(s) containing a 'projects' subdirectory

ccusage now supports codex, opencode, amp, and pi-agent in addition to Claude Code, so requiring a .claude directory just to load config (ccusage.json) is wrong — it blocks every command, including ccusage codex, on systems that never installed Claude Code.

The crash originated in getConfigSearchPaths() (apps/ccusage/src/config-loader-tokens.ts), which called the throwing getClaudePaths() while building the list of locations to search for ccusage.json.

Fix

Treat the Claude-derived config dirs as best-effort: if getClaudePaths() throws, swallow the error via Result.try + Result.unwrap([]) and fall back to the local .ccusage directory in cwd. All commands (ccusage, ccusage codex, ccusage opencode, ccusage amp, ccusage pi, and the explicit ccusage claude … ones) now load config without a Claude directory present. The Claude-specific loaders/debug command continue to surface the original error when actually loading Claude data, which is the right behavior.

Verification

  • bun run src/index.ts with CLAUDE_CONFIG_DIR=/tmp/does-not-exist now prints Detected: None and No usage data found. instead of throwing.
  • Added a regression test in config-loader-tokens.ts that points CLAUDE_CONFIG_DIR at a directory missing projects/ and asserts loadConfig() returns undefined rather than throwing.
  • pnpm typecheck, pnpm run format, and pnpm --filter ccusage test --run all pass (385 tests / 2 skipped).

Test plan

  • pnpm typecheck
  • pnpm run format
  • pnpm --filter ccusage test --run
  • Manual run with CLAUDE_CONFIG_DIR=/tmp/does-not-exist bun run src/index.ts

https://claude.ai/code/session_01H93Pfks8XvhJ5PAABFpLqh


Generated by Claude Code


Summary by cubic

Stop requiring a Claude data directory to load config so ccusage (including codex, opencode, amp, and pi-agent) runs on machines without .claude. Split Claude path discovery into safe and required variants so Claude-only commands still show a clear setup error; fixes #1014.

  • Bug Fixes
    • Make getClaudePaths() return possibly empty; add requireClaudePaths() for Claude-only entry points.
    • Use requireClaudePaths() in Claude data loaders; config discovery now calls getClaudePaths() and searches local ./.ccusage/ccusage.json first.
    • Add a regression test to ensure loadConfig() returns undefined when CLAUDE_CONFIG_DIR points to a dir without projects/.

Written for commit 238798c. Summary will update on new commits. Review in cubic

Summary by CodeRabbit

  • Bug Fixes

    • Commands that rely on external project data now surface a clear setup error if no valid project directories are found, preventing silent no-op behavior.
  • Documentation

    • Clarified that discovery of external project directories is best-effort; missing or unavailable directories simply contribute no additional search paths.
  • Tests

    • Added test coverage for discovery and loading when project directories are missing or invalid.

Review Change Stack

ccusage now supports codex, opencode, amp, and pi-agent in addition to
Claude Code. Running it on a machine without a Claude data directory
crashed with "No valid Claude data directories found" because
getConfigSearchPaths() called the throwing getClaudePaths() while
discovering ccusage.json locations.

Treat Claude config dirs as best-effort: swallow the error and fall back
to the local .ccusage directory so users of other agents (or no agent
yet) can run ccusage without setting CLAUDE_CONFIG_DIR.

Fixes #1014
@coderabbitai

coderabbitai Bot commented May 17, 2026

Copy link
Copy Markdown

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented May 17, 2026

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
ccusage-guide 238798c Commit Preview URL

Branch Preview URL
May 17 2026, 09:41 AM

@pkg-pr-new

pkg-pr-new Bot commented May 17, 2026

Copy link
Copy Markdown

Open in StackBlitz

npx https://pkg.pr.new/ryoppippi/ccusage@1017

commit: 238798c

@github-actions

github-actions Bot commented May 17, 2026

Copy link
Copy Markdown
Contributor

ccusage performance comparison

This compares the PR build against the base branch build on the same CI runner.

Committed fixture performance

Committed small fixtures for stable PR-to-PR feedback and explicit Claude/Codex command coverage.

Fixtures: Claude apps/ccusage/test/fixtures/claude (0.00 MiB, 2 files), Codex apps/ccusage/test/fixtures/codex (0.00 MiB, 1 files)
Runtime: package ccusage bin from apps/ccusage/package.json through bun -b, --offline --json, measured by hyperfine with 2 warmups and 7 runs.

Command Input Base median PR median PR vs base Base throughput PR throughput
claude daily --offline --json 0.00 MiB 52.5ms 53.0ms 0.99x 0.03 MiB/s 0.03 MiB/s
claude session --offline --json 0.00 MiB 53.1ms 52.6ms 1.01x 0.03 MiB/s 0.03 MiB/s
codex daily --offline --json 0.00 MiB 52.5ms 52.6ms 1.00x 0.02 MiB/s 0.02 MiB/s
codex session --offline --json 0.00 MiB 52.9ms 52.2ms 1.01x 0.02 MiB/s 0.02 MiB/s

Large real-world-shaped fixture performance

Generated fixtures shaped from aggregate local 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 fixtures.

Fixtures: Claude /home/runner/work/_temp/ccusage-large-fixture (1.01 GiB, 2,597 files), Codex /home/runner/work/_temp/ccusage-large-codex-fixture (1.01 GiB, 2,597 files)
Runtime: package ccusage bin from apps/ccusage/package.json through bun -b, --offline --json, measured by hyperfine with 0 warmups and 1 runs.

Command Input Base median PR median PR vs base Base throughput PR throughput
claude --offline --json 1.01 GiB 1.339s 1.334s 1.00x 770.00 MiB/s 772.75 MiB/s
codex --offline --json 1.01 GiB 1.571s 1.557s 1.01x 656.07 MiB/s 662.01 MiB/s

Package size

Package artifact Base PR Delta Ratio
packed ccusage-*.tgz 67.50 KiB 67.53 KiB +0.03 KiB 1.00x

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.

Previously getClaudePaths() threw when no Claude data directory was found,
which forced callers that don't actually need a Claude dir (like config
discovery in getConfigSearchPaths) to wrap the call in try/catch or
Result.try. That asymmetry is what made #1014 easy to hit in the first
place.

Make getClaudePaths() the unsurprising "give me what you find, possibly
nothing" variant, and add requireClaudePaths() for explicit Claude-only
entry points (claude:* command loaders, statusline session lookup) that
want to surface the helpful setup hint when no data exists. debug.ts
already had its own length check so it keeps using getClaudePaths().

The config layer now just calls getClaudePaths() directly — no wrapping
needed — restoring the consistency with the other agents' detect
functions and getClaudeProjectPaths().

No behavior change for users:
- `ccusage` on a machine without .claude still runs and reports "None"
- `ccusage claude daily` without .claude still surfaces the original
  "No valid Claude data directories found" error
@ryoppippi ryoppippi merged commit c6337cf into main May 17, 2026
24 checks passed
@ryoppippi ryoppippi deleted the claude/fix-issue-1014-xwtDE branch May 17, 2026 11:00
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.

ccusage not working without .claude dir

2 participants