fix(config): don't require .claude directory for non-Claude agents#1017
Conversation
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
Deploying with
|
| 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 |
commit: |
ccusage performance comparisonThis compares the PR build against the base branch build on the same CI runner. Committed fixture performanceCommitted small fixtures for stable PR-to-PR feedback and explicit Claude/Codex command coverage. Fixtures: Claude
Large real-world-shaped fixture performanceGenerated 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
Package sizeLower 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

Summary
Fixes #1014.
Running
bunx ccusageon a machine without a Claude data directory crashed with:ccusage now supports
codex,opencode,amp, andpi-agentin addition to Claude Code, so requiring a.claudedirectory just to load config (ccusage.json) is wrong — it blocks every command, includingccusage codex, on systems that never installed Claude Code.The crash originated in
getConfigSearchPaths()(apps/ccusage/src/config-loader-tokens.ts), which called the throwinggetClaudePaths()while building the list of locations to search forccusage.json.Fix
Treat the Claude-derived config dirs as best-effort: if
getClaudePaths()throws, swallow the error viaResult.try+Result.unwrap([])and fall back to the local.ccusagedirectory incwd. All commands (ccusage,ccusage codex,ccusage opencode,ccusage amp,ccusage pi, and the explicitccusage claude …ones) now load config without a Claude directory present. The Claude-specific loaders/debugcommand continue to surface the original error when actually loading Claude data, which is the right behavior.Verification
bun run src/index.tswithCLAUDE_CONFIG_DIR=/tmp/does-not-existnow printsDetected: NoneandNo usage data found.instead of throwing.config-loader-tokens.tsthat pointsCLAUDE_CONFIG_DIRat a directory missingprojects/and assertsloadConfig()returnsundefinedrather than throwing.pnpm typecheck,pnpm run format, andpnpm --filter ccusage test --runall pass (385 tests / 2 skipped).Test plan
pnpm typecheckpnpm run formatpnpm --filter ccusage test --runCLAUDE_CONFIG_DIR=/tmp/does-not-exist bun run src/index.tshttps://claude.ai/code/session_01H93Pfks8XvhJ5PAABFpLqh
Generated by Claude Code
Summary by cubic
Stop requiring a Claude data directory to load config so
ccusage(includingcodex,opencode,amp, andpi-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.getClaudePaths()return possibly empty; addrequireClaudePaths()for Claude-only entry points.requireClaudePaths()in Claude data loaders; config discovery now callsgetClaudePaths()and searches local./.ccusage/ccusage.jsonfirst.loadConfig()returnsundefinedwhenCLAUDE_CONFIG_DIRpoints to a dir withoutprojects/.Written for commit 238798c. Summary will update on new commits. Review in cubic
Summary by CodeRabbit
Bug Fixes
Documentation
Tests