-
-
Notifications
You must be signed in to change notification settings - Fork 317
feat!: specify claude dir with CLAUDE_CONFIG_DIR and remove -p/--path option
#70
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat!: specify claude dir with CLAUDE_CONFIG_DIR and remove -p/--path option
#70
Conversation
Co-authored-by: timrogers <[email protected]>
Co-authored-by: timrogers <[email protected]>
|
Warning Rate limit exceeded@ryoppippi has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 7 minutes and 40 seconds before requesting another review. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. 📒 Files selected for processing (2)
WalkthroughThe changes introduce support for the Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant CLI
participant DataLoader
User->>CLI: Run ccusage (without --path)
CLI->>DataLoader: getDefaultClaudePath()
DataLoader->>process.env: Check CLAUDE_CONFIG_DIR
alt CLAUDE_CONFIG_DIR is set and non-empty
DataLoader-->>CLI: Return trimmed CLAUDE_CONFIG_DIR path if valid directory
else
DataLoader-->>CLI: Return default ~/.claude path if valid directory
end
CLI-->>User: Use resolved config directory for operations
Poem
✨ Finishing Touches
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Summary of Changes
Hello @timrogers, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!
This pull request enhances the flexibility of specifying the Claude data directory by adding support for the CLAUDE_CONFIG_DIR environment variable. This provides an alternative to the existing --path command-line option and addresses issue #66. The implementation ensures that the command-line option takes precedence over the environment variable.
Highlights
- Environment Variable Support: Introduced support for the
CLAUDE_CONFIG_DIRenvironment variable to specify the custom path to the Claude data directory. - Configuration Precedence: Implemented logic to prioritize the existing
--pathcommand-line option over the newCLAUDE_CONFIG_DIRenvironment variable, ensuring backward compatibility. - Documentation Updates: Updated the
README.mdto include examples of using theCLAUDE_CONFIG_DIRenvironment variable and clarify the precedence rules between the environment variable and the--pathoption. - Unit Tests: Added unit tests for the
getDefaultClaudePathfunction to verify its behavior when theCLAUDE_CONFIG_DIRenvironment variable is set, not set, or set to an empty/whitespace value.
Using Gemini Code Assist
The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.
Invoking Gemini
You can request assistance from Gemini at any point in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands.
| Feature | Command | Description |
|---|---|---|
| Code Review | /gemini review |
Performs a code review for the current pull request in its current state. |
| Pull Request Summary | /gemini summary |
Provides a summary of the current pull request in its current state. |
| Comment | @gemini-code-assist | Responds in comments when explicitly tagged, both in issue comments and review comments. |
| Help | /gemini help |
Displays a list of available commands. |
Customization
To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.
Limitations & Feedback
Gemini Code Assist is currently in preview and may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments to provide feedback.
You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.
Footnotes
-
Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configureGemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution. ↩
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code Review
This pull request successfully implements the feature to allow specifying the Claude config directory using the $CLAUDE_CONFIG_DIR environment variable, addressing issue #66. The changes are well-contained within the data-loader.ts file and include comprehensive unit tests in data-loader.test.ts to cover the new logic, including edge cases like empty or whitespace environment variables. The README.md has been updated clearly to document this new functionality, explaining its usage and precedence relative to the --path command-line option. The implementation is clean and follows good practices for handling environment variables and testing. Overall, this is a solid and well-executed feature addition.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (3)
src/data-loader.ts (1)
16-19: Consider normalising or resolving the user-supplied path
getDefaultClaudePathreturns the raw value ofCLAUDE_CONFIG_DIR.
If the variable is set to a relative path ("./.claude"), contains~, or mixes slashes, callers will receive it unchanged, which can later surface as subtle “file not found” errors when code that expects an absolute, normalised path tries tojoin/resolveagain.A minimal improvement is to run the env value through
path.resolve(or at leastpath.normalize) before returning:- return (envPath != null && envPath.trim() !== '') ? envPath : path.join(homedir(), '.claude'); + if (envPath != null && envPath.trim() !== '') { + return path.resolve(envPath.trim()); + } + return path.join(homedir(), '.claude');Keeps backward compatibility while guarding against surprising relative inputs.
🧰 Tools
🪛 ESLint
[error] 17-17: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 17-17: Unsafe member access .env on an
errortyped value.(ts/no-unsafe-member-access)
[error] 18-18: Unsafe return of a value of type error.
(ts/no-unsafe-return)
[error] 18-18: Unsafe call of a(n)
errortype typed value.(ts/no-unsafe-call)
[error] 18-18: Unsafe member access .trim on an
errortyped value.(ts/no-unsafe-member-access)
[error] 18-18: Unsafe call of a(n)
errortype typed value.(ts/no-unsafe-call)
[error] 18-18: Unsafe member access .join on an
errortyped value.(ts/no-unsafe-member-access)
[error] 18-18: Unsafe call of a(n)
errortype typed value.(ts/no-unsafe-call)
src/data-loader.test.ts (1)
33-93: PreferbeforeEach/afterEachto manageprocess.envand avoiddeleteAll three tests temporarily mutate
process.env.CLAUDE_CONFIG_DIRand then usedeleteto restore state. Besides the Biome warning about thedeleteoperator, repeating the try/finally pattern clutters the spec.You can DRY this up and avoid
deleteby snapshotting all env vars once per test:-describe('getDefaultClaudePath', () => { - test('returns CLAUDE_CONFIG_DIR when environment variable is set', () => { - const originalEnv = process.env.CLAUDE_CONFIG_DIR; - ... - }); - ... -}); +describe('getDefaultClaudePath', () => { + let originalEnv: NodeJS.ProcessEnv; + + beforeEach(() => { + originalEnv = { ...process.env }; + }); + + afterEach(() => { + process.env = originalEnv; // single assignment, no delete needed + }); + + test('returns CLAUDE_CONFIG_DIR when environment variable is set', () => { + process.env.CLAUDE_CONFIG_DIR = '/custom/claude/path'; + expect(getDefaultClaudePath()).toBe('/custom/claude/path'); + }); + + test('returns default path when CLAUDE_CONFIG_DIR is not set', () => { + delete process.env.CLAUDE_CONFIG_DIR; + const result = getDefaultClaudePath(); + expect(result).toContain('.claude'); + expect(result).not.toBe('.claude'); + }); + + test('returns default path when CLAUDE_CONFIG_DIR is empty or whitespace', () => { + process.env.CLAUDE_CONFIG_DIR = ' '; + expect(getDefaultClaudePath()).toContain('.claude'); + }); +});Cleaner, avoids repeating restoration code, and removes the performance-related lint warning.
🧰 Tools
🪛 Biome (1.9.4)
[error] 48-48: Avoid the delete operator which can impact performance.
Unsafe fix: Use an undefined assignment instead.
(lint/performance/noDelete)
[error] 57-57: Avoid the delete operator which can impact performance.
Unsafe fix: Use an undefined assignment instead.
(lint/performance/noDelete)
[error] 90-90: Avoid the delete operator which can impact performance.
Unsafe fix: Use an undefined assignment instead.
(lint/performance/noDelete)
🪛 ESLint
[error] 33-33: Unsafe call of a(n)
errortype typed value.(ts/no-unsafe-call)
[error] 34-34: Unsafe call of a(n)
errortype typed value.(ts/no-unsafe-call)
[error] 35-35: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 35-35: Unsafe member access .env on an
errortyped value.(ts/no-unsafe-member-access)
[error] 39-39: Unsafe member access .env on an
errortyped value.(ts/no-unsafe-member-access)
[error] 40-40: Unsafe call of a(n)
errortype typed value.(ts/no-unsafe-call)
[error] 40-40: Unsafe call of a(n)
errortype typed value.(ts/no-unsafe-call)
[error] 40-40: Unsafe member access .toBe on an
errortyped value.(ts/no-unsafe-member-access)
[error] 45-45: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 45-45: Unsafe member access .env on an
errortyped value.(ts/no-unsafe-member-access)
[error] 48-48: Unsafe member access .env on an
errortyped value.(ts/no-unsafe-member-access)
[error] 53-53: Unsafe call of a(n)
errortype typed value.(ts/no-unsafe-call)
[error] 54-54: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 54-54: Unsafe member access .env on an
errortyped value.(ts/no-unsafe-member-access)
[error] 57-57: Unsafe member access .env on an
errortyped value.(ts/no-unsafe-member-access)
[error] 59-59: Unsafe call of a(n)
errortype typed value.(ts/no-unsafe-call)
[error] 59-59: Unsafe call of a(n)
errortype typed value.(ts/no-unsafe-call)
[error] 59-59: Unsafe member access .toContain on an
errortyped value.(ts/no-unsafe-member-access)
[error] 60-60: Unsafe call of a(n)
errortype typed value.(ts/no-unsafe-call)
[error] 60-60: Unsafe call of a(n)
errortype typed value.(ts/no-unsafe-call)
[error] 60-60: Unsafe member access .not on an
errortyped value.(ts/no-unsafe-member-access)
[error] 65-65: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 65-65: Unsafe member access .env on an
errortyped value.(ts/no-unsafe-member-access)
[error] 70-70: Unsafe call of a(n)
errortype typed value.(ts/no-unsafe-call)
[error] 71-71: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 71-71: Unsafe member access .env on an
errortyped value.(ts/no-unsafe-member-access)
[error] 75-75: Unsafe member access .env on an
errortyped value.(ts/no-unsafe-member-access)
[error] 77-77: Unsafe call of a(n)
errortype typed value.(ts/no-unsafe-call)
[error] 77-77: Unsafe call of a(n)
errortype typed value.(ts/no-unsafe-call)
[error] 77-77: Unsafe member access .toContain on an
errortyped value.(ts/no-unsafe-member-access)
[error] 80-80: Unsafe member access .env on an
errortyped value.(ts/no-unsafe-member-access)
[error] 82-82: Unsafe call of a(n)
errortype typed value.(ts/no-unsafe-call)
[error] 82-82: Unsafe call of a(n)
errortype typed value.(ts/no-unsafe-call)
[error] 82-82: Unsafe member access .toContain on an
errortyped value.(ts/no-unsafe-member-access)
[error] 87-87: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 87-87: Unsafe member access .env on an
errortyped value.(ts/no-unsafe-member-access)
[error] 90-90: Unsafe member access .env on an
errortyped value.(ts/no-unsafe-member-access)
README.md (1)
247-260: Minor wording tweak for clarityThe paragraph is missing the definite article “the” before “environment variable”.
-When both the environment variable and `--path` option are provided, the `--path` option takes precedence, ensuring backward compatibility. +When both the environment variable and the `--path` option are provided, the `--path` option takes precedence, ensuring backward compatibility.Pure documentation nit; feel free to ignore if house style differs.
🧰 Tools
🪛 LanguageTool
[uncategorized] ~260-~260: You might be missing the article “the” here.
Context: ... When both the environment variable and--pathoption are provided, the `--path...(AI_EN_LECTOR_MISSING_DETERMINER_THE)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
README.md(5 hunks)src/data-loader.test.ts(2 hunks)src/data-loader.ts(2 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
src/data-loader.test.ts (1)
src/data-loader.ts (1)
getDefaultClaudePath(16-19)
🪛 ESLint
src/data-loader.ts
[error] 17-17: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 17-17: Unsafe member access .env on an error typed value.
(ts/no-unsafe-member-access)
[error] 18-18: Unsafe return of a value of type error.
(ts/no-unsafe-return)
[error] 18-18: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 18-18: Unsafe member access .trim on an error typed value.
(ts/no-unsafe-member-access)
[error] 18-18: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 18-18: Unsafe member access .join on an error typed value.
(ts/no-unsafe-member-access)
[error] 18-18: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
src/data-loader.test.ts
[error] 33-33: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 34-34: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 35-35: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 35-35: Unsafe member access .env on an error typed value.
(ts/no-unsafe-member-access)
[error] 39-39: Unsafe member access .env on an error typed value.
(ts/no-unsafe-member-access)
[error] 40-40: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 40-40: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 40-40: Unsafe member access .toBe on an error typed value.
(ts/no-unsafe-member-access)
[error] 45-45: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 45-45: Unsafe member access .env on an error typed value.
(ts/no-unsafe-member-access)
[error] 48-48: Unsafe member access .env on an error typed value.
(ts/no-unsafe-member-access)
[error] 53-53: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 54-54: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 54-54: Unsafe member access .env on an error typed value.
(ts/no-unsafe-member-access)
[error] 57-57: Unsafe member access .env on an error typed value.
(ts/no-unsafe-member-access)
[error] 59-59: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 59-59: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 59-59: Unsafe member access .toContain on an error typed value.
(ts/no-unsafe-member-access)
[error] 60-60: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 60-60: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 60-60: Unsafe member access .not on an error typed value.
(ts/no-unsafe-member-access)
[error] 65-65: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 65-65: Unsafe member access .env on an error typed value.
(ts/no-unsafe-member-access)
[error] 70-70: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 71-71: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 71-71: Unsafe member access .env on an error typed value.
(ts/no-unsafe-member-access)
[error] 75-75: Unsafe member access .env on an error typed value.
(ts/no-unsafe-member-access)
[error] 77-77: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 77-77: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 77-77: Unsafe member access .toContain on an error typed value.
(ts/no-unsafe-member-access)
[error] 80-80: Unsafe member access .env on an error typed value.
(ts/no-unsafe-member-access)
[error] 82-82: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 82-82: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 82-82: Unsafe member access .toContain on an error typed value.
(ts/no-unsafe-member-access)
[error] 87-87: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 87-87: Unsafe member access .env on an error typed value.
(ts/no-unsafe-member-access)
[error] 90-90: Unsafe member access .env on an error typed value.
(ts/no-unsafe-member-access)
🪛 LanguageTool
README.md
[uncategorized] ~260-~260: You might be missing the article “the” here.
Context: ... When both the environment variable and --path option are provided, the `--path...
(AI_EN_LECTOR_MISSING_DETERMINER_THE)
🪛 Biome (1.9.4)
src/data-loader.test.ts
[error] 48-48: Avoid the delete operator which can impact performance.
Unsafe fix: Use an undefined assignment instead.
(lint/performance/noDelete)
[error] 57-57: Avoid the delete operator which can impact performance.
Unsafe fix: Use an undefined assignment instead.
(lint/performance/noDelete)
[error] 90-90: Avoid the delete operator which can impact performance.
Unsafe fix: Use an undefined assignment instead.
(lint/performance/noDelete)
|
Thank you!
|
README.md
Outdated
| - `-s, --since <date>`: Filter from date (YYYYMMDD format) | ||
| - `-u, --until <date>`: Filter until date (YYYYMMDD format) | ||
| - `-p, --path <path>`: Custom path to Claude data directory (default: `~/.claude`) | ||
| - `-p, --path <path>`: Custom path to Claude data directory (default: `$CLAUDE_CONFIG_DIR` or `~/.claude`) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you can remove -p option
src/data-loader.test.ts
Outdated
| const testPath = '/custom/claude/path'; | ||
|
|
||
| try { | ||
| process.env.CLAUDE_CONFIG_DIR = testPath; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
because bun test is not isolated each other you need to mock process.env in each test case
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also if you can mock claude project path using fs-fixture that'd be brilliant
src/data-loader.ts
Outdated
| const envPath = process.env.CLAUDE_CONFIG_DIR; | ||
| return (envPath != null && envPath.trim() !== '') ? envPath : path.join(homedir(), '.claude'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| const envPath = process.env.CLAUDE_CONFIG_DIR; | |
| return (envPath != null && envPath.trim() !== '') ? envPath : path.join(homedir(), '.claude'); | |
| const defaultClaudeCodePath = path.join(homedir(), '.claude'); | |
| const envClaudeCodePath = process.env.CLAUDE_CONFIG_DIR?.trim(); | |
| if(existsSync(envClaudeCodePath)){ | |
| return envClaudeCodePath | |
| } | |
| return defaultClaudeCodePath; |
I think this is more readable! (you need to import fs.existsSync tho), and format it.
or, you may use isDirectorySync from https://github.com/sindresorhus/path-type to check if the path is directory (I prefer this approach in this case over fs.existsSync)
|
@timrogers if you don't have time i'll do that |
|
@ryoppippi Go ahead! Feel free to take over as I won't have time for a few days. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR introduces support for specifying the Claude configuration directory via the CLAUDE_CONFIG_DIR environment variable, updating both the implementation and documentation, and adding tests to validate the behavior.
- Introduces a new import and logic in getDefaultClaudePath() in src/data-loader.ts
- Adds comprehensive tests in src/data-loader.test.ts to verify behavior with and without the environment variable
- Updates README.md to include instructions for using the CLAUDE_CONFIG_DIR environment variable
Reviewed Changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| src/data-loader.ts | Implements environment variable check for CLAUDE_CONFIG_DIR in getDefaultClaudePath() |
| src/data-loader.test.ts | Adds tests covering various cases of the CLAUDE_CONFIG_DIR environment variable |
| README.md | Updates documentation to explain the use and precedence of the CLAUDE_CONFIG_DIR setting |
$CLAUDE_CONFIG_DIRCLAUDE_CONFIG_DIR and remove -p option
… isDirectorySync to determine default path
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (3)
src/data-loader.ts (3)
5-5:processimport is redundant in ESM Node – consider removing
processis exposed as a global in Node. Importing it adds no functional value and slightly increases cognitive load. Unless you have ESLint/tsconfig rules that forbid usage of globals, dropping the import is the leaner choice.-import process from 'node:process';
8-8: New dependencypath-type– double-check footprint & licence
path-typeis lightweight but still adds a transitive dependency tree (≈2 KB JS +type-fest). Verify:
- It is already used elsewhere; otherwise importing only
fs.statSyncwould suffice.- Its licence is compatible with your project’s licence.
If the single sync call is the only usage, a small helper is arguably cheaper than an extra package.
17-18: Constant name mismatch with commentConstant is
DEFAULT_CLAUDE_CODE_PATHbut comment refers to “path for Claude data directory”.
DEFAULT_CLAUDE_CONFIG_DIRwould mirror the env-var name and reduce mental mapping.Nit-level, but improves consistency.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
bun.lockis excluded by!**/*.lock
📒 Files selected for processing (2)
package.json(1 hunks)src/data-loader.ts(2 hunks)
✅ Files skipped from review due to trivial changes (1)
- package.json
🧰 Additional context used
🪛 ESLint
src/data-loader.ts
[error] 17-17: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 17-17: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 17-17: Unsafe member access .join on an error typed value.
(ts/no-unsafe-member-access)
[error] 17-17: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 24-24: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 24-24: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 24-24: Unsafe member access .env on an error typed value.
(ts/no-unsafe-member-access)
[error] 25-25: Unexpected any value in conditional. An explicit comparison or type conversion is required.
(ts/strict-boolean-expressions)
[error] 25-25: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 26-26: Unsafe return of a value of type error.
(ts/no-unsafe-return)
[error] 28-28: Unsafe return of a value of type error.
(ts/no-unsafe-return)
Refactor and expand tests for getDefaultClaudePath to cover additional edge cases, including handling of whitespace, non-existent directories, and invalid paths. Use beforeEach and afterEach hooks for environment cleanup and restoration. This ensures more robust and reliable behavior
The -p short option is no longer needed since the path can now be configured via the CLAUDE_CONFIG_DIR environment variable. Users can still use --path for the full option name when needed. This simplifies the CLI interface by reducing the number of short options and encouraging use of the environment variable for persistent configuration.
Update the README documentation to reflect the removal of the -p short option. The --path long option remains available for users who need to override the default Claude data directory location.
CLAUDE_CONFIG_DIR and remove -p optionCLAUDE_CONFIG_DIR and remove -p/--path option
…able Remove the --path CLI option completely since the Claude data directory can now be configured via the CLAUDE_CONFIG_DIR environment variable. Changes: - Remove path argument from shared-args.internal.ts - Update all commands (daily, monthly, session, mcp) to use getDefaultClaudePath() - Remove unused import from shared-args.internal.ts - Fix import order in mcp.ts command This simplifies the CLI interface and encourages users to set the CLAUDE_CONFIG_DIR environment variable for persistent configuration instead of passing the path on every command invocation.
The --path option has been completely removed from the CLI. Users should now use the CLAUDE_CONFIG_DIR environment variable to configure custom Claude data directory locations.
Update all example commands to remove --path option usage. The tool now exclusively uses the CLAUDE_CONFIG_DIR environment variable for custom data directory configuration. Updated sections: - Daily report examples - Session report examples - Environment variable documentation
Remove import of getDefaultClaudePath since the path option has been removed entirely from the shared arguments.
commit: |
Update test to properly handle both local and CI environments: - In local dev: ~/.claude might exist, test passes - In CI: ~/.claude does not exist, test expects error This makes the test work correctly in both environments while maintaining proper validation behavior.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 5
🧹 Nitpick comments (3)
src/commands/daily.ts (1)
28-28: Surface a friendlier error when the path is invalid
getDefaultClaudePath()throws synchronously.
If the directory is missing, the whole command exits with an uncaught exception and an unformatted stack-trace. Consider wrapping the call in atry { } catch (err)block and logging a concise message (e.g. “Claude data directory not found – set CLAUDE_CONFIG_DIR or create ~/.claude”) before exiting with a non-zero code.src/data-loader.test.ts (2)
39-44: Prefer assigningundefinedoverdeletewhen clearing env vars in testsBiome warns that
deleteon object properties has a perf hit; here the cost is negligible, but swapping to anundefinedassignment silences the linter and keeps intent clear.- delete process.env.CLAUDE_CONFIG_DIR; + process.env.CLAUDE_CONFIG_DIR = undefined as unknown as string;(Apply similarly in
afterEach. No functional change, just lint-clean.)Also applies to: 44-52
36-52:originalEnvcapture can be stale if tests mutate it
originalEnvis captured once before all tests, so if the suite itself runs after a previous suite that already mutatedprocess.env.CLAUDE_CONFIG_DIR, we propagate that value. Capture insidebeforeEachto guarantee per-test isolation:- const originalEnv = process.env.CLAUDE_CONFIG_DIR; - -beforeEach(() => { - // Clean up env var before each test - delete process.env.CLAUDE_CONFIG_DIR; + let originalEnv: string | undefined; + + beforeEach(() => { + originalEnv = process.env.CLAUDE_CONFIG_DIR; + process.env.CLAUDE_CONFIG_DIR = undefined as unknown as string; });
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
bun.lockis excluded by!**/*.lock
📒 Files selected for processing (9)
README.md(4 hunks)package.json(1 hunks)src/commands/daily.ts(3 hunks)src/commands/mcp.ts(2 hunks)src/commands/monthly.ts(3 hunks)src/commands/session.ts(3 hunks)src/data-loader.test.ts(2 hunks)src/data-loader.ts(1 hunks)src/shared-args.internal.ts(0 hunks)
💤 Files with no reviewable changes (1)
- src/shared-args.internal.ts
🚧 Files skipped from review as they are similar to previous changes (2)
- package.json
- README.md
🧰 Additional context used
🧬 Code Graph Analysis (3)
src/commands/monthly.ts (2)
src/data-loader.ts (1)
getDefaultClaudePath(23-33)src/debug.ts (1)
detectMismatches(53-182)
src/commands/session.ts (2)
src/data-loader.ts (1)
getDefaultClaudePath(23-33)src/debug.ts (1)
detectMismatches(53-182)
src/data-loader.test.ts (1)
src/data-loader.ts (1)
getDefaultClaudePath(23-33)
🪛 ESLint
src/commands/mcp.ts
[error] 26-26: Unsafe assignment of an any value.
(ts/no-unsafe-assignment)
[error] 26-26: Unsafe member access .values on an any value.
(ts/no-unsafe-member-access)
[error] 29-29: Unsafe member access .level on an error typed value.
(ts/no-unsafe-member-access)
src/data-loader.test.ts
[error] 36-36: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 37-37: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 37-37: Unsafe member access .env on an error typed value.
(ts/no-unsafe-member-access)
[error] 39-39: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 41-41: Unsafe member access .env on an error typed value.
(ts/no-unsafe-member-access)
[error] 44-44: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 47-47: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 47-47: Unsafe member access .env on an error typed value.
(ts/no-unsafe-member-access)
[error] 50-50: Unsafe member access .env on an error typed value.
(ts/no-unsafe-member-access)
[error] 54-54: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 55-57: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 55-55: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 58-58: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 58-58: Unsafe member access .env on an error typed value.
(ts/no-unsafe-member-access)
[error] 58-58: Unsafe member access .path on an error typed value.
(ts/no-unsafe-member-access)
[error] 60-60: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 60-60: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 60-60: Unsafe member access .toBe on an error typed value.
(ts/no-unsafe-member-access)
[error] 60-60: Unsafe member access .path on an error typed value.
(ts/no-unsafe-member-access)
[error] 63-63: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 65-65: Unsafe member access .env on an error typed value.
(ts/no-unsafe-member-access)
[error] 69-69: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 69-69: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 69-69: Unsafe member access .toMatch on an error typed value.
(ts/no-unsafe-member-access)
[error] 70-70: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 70-70: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 70-70: Unsafe member access .toContain on an error typed value.
(ts/no-unsafe-member-access)
[error] 70-70: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 73-73: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 74-76: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 74-74: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 78-78: Unsafe member access .env on an error typed value.
(ts/no-unsafe-member-access)
[error] 78-78: Unsafe member access .path on an error typed value.
(ts/no-unsafe-member-access)
[error] 80-80: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 80-80: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 80-80: Unsafe member access .toBe on an error typed value.
(ts/no-unsafe-member-access)
[error] 80-80: Unsafe member access .path on an error typed value.
(ts/no-unsafe-member-access)
[error] 83-83: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 84-84: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 84-84: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 85-85: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 85-85: Unsafe member access .env on an error typed value.
(ts/no-unsafe-member-access)
[error] 85-85: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 85-85: Unsafe member access .path on an error typed value.
(ts/no-unsafe-member-access)
[error] 87-87: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 87-87: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 87-87: Unsafe member access .toThrow on an error typed value.
(ts/no-unsafe-member-access)
[error] 90-90: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 91-91: Unsafe member access .env on an error typed value.
(ts/no-unsafe-member-access)
[error] 93-93: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 93-93: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 93-93: Unsafe member access .toThrow on an error typed value.
(ts/no-unsafe-member-access)
[error] 96-96: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 98-98: Unsafe member access .env on an error typed value.
(ts/no-unsafe-member-access)
[error] 100-100: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 100-100: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 100-100: Unsafe member access .toThrow on an error typed value.
(ts/no-unsafe-member-access)
src/data-loader.ts
[error] 17-17: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 17-17: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 17-17: Unsafe member access .join on an error typed value.
(ts/no-unsafe-member-access)
[error] 17-17: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 24-24: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 24-24: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 24-24: Unsafe member access .env on an error typed value.
(ts/no-unsafe-member-access)
[error] 25-25: Unexpected any value in conditional. An explicit comparison or type conversion is required.
(ts/strict-boolean-expressions)
[error] 25-25: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 32-32: Unsafe return of a value of type error.
(ts/no-unsafe-return)
🪛 Biome (1.9.4)
src/data-loader.test.ts
[error] 41-41: Avoid the delete operator which can impact performance.
Unsafe fix: Use an undefined assignment instead.
(lint/performance/noDelete)
[error] 50-50: Avoid the delete operator which can impact performance.
Unsafe fix: Use an undefined assignment instead.
(lint/performance/noDelete)
[error] 65-65: Avoid the delete operator which can impact performance.
Unsafe fix: Use an undefined assignment instead.
(lint/performance/noDelete)
🪛 GitHub Check: ci
src/data-loader.ts
[failure] 26-26: error: Claude data directory does not exist: /home/runner/.claude.
Please set CLAUDE_CONFIG_DIR to a valid path, or ensure /home/runner/.claude exists.
at getDefaultClaudePath (/home/runner/work/ccusage/ccusage/src/data-loader.ts:26:9)
at (/home/runner/work/ccusage/ccusage/src/data-loader.test.ts:68:22)
at (/home/runner/work/ccusage/ccusage/src/data-loader.test.ts:63:65)
| const dailyData = await loadDailyUsageData({ | ||
| since: ctx.values.since, | ||
| until: ctx.values.until, | ||
| claudePath: ctx.values.path, | ||
| claudePath: getDefaultClaudePath(), | ||
| mode: ctx.values.mode, | ||
| order: ctx.values.order, | ||
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Cache the resolved Claude path once instead of invoking getDefaultClaudePath() twice
getDefaultClaudePath() performs I/O + validation on every call.
Resolve it once, reuse it for both loadDailyUsageData and detectMismatches, and avoid the (minor) overhead while guaranteeing both calls operate on the identical directory.
- const dailyData = await loadDailyUsageData({
+ const claudePath = getDefaultClaudePath();
+
+ const dailyData = await loadDailyUsageData({
since: ctx.values.since,
until: ctx.values.until,
- claudePath: getDefaultClaudePath(),
+ claudePath,
mode: ctx.values.mode,
order: ctx.values.order,
});
…
- const mismatchStats = await detectMismatches(getDefaultClaudePath());
+ const mismatchStats = await detectMismatches(claudePath);
printMismatchReport(mismatchStats, ctx.values.debugSamples);Also applies to: 46-49
🧰 Tools
🪛 ESLint
[error] 26-26: Unsafe assignment of an any value.
(ts/no-unsafe-assignment)
[error] 26-26: Unsafe member access .values on an any value.
(ts/no-unsafe-member-access)
[error] 27-27: Unsafe assignment of an any value.
(ts/no-unsafe-assignment)
[error] 27-27: Unsafe member access .values on an any value.
(ts/no-unsafe-member-access)
[error] 29-29: Unsafe member access .values on an any value.
(ts/no-unsafe-member-access)
[error] 30-30: Unsafe member access .values on an any value.
(ts/no-unsafe-member-access)
🤖 Prompt for AI Agents
In src/commands/daily.ts around lines 25 to 31 and 46 to 49, the function
getDefaultClaudePath() is called twice, causing redundant I/O and validation.
Fix this by calling getDefaultClaudePath() once, storing its result in a
variable, and then passing that variable to both loadDailyUsageData and
detectMismatches to ensure consistent usage and reduce overhead.
| const monthlyData = await loadMonthlyUsageData({ | ||
| since: ctx.values.since, | ||
| until: ctx.values.until, | ||
| claudePath: ctx.values.path, | ||
| claudePath: getDefaultClaudePath(), | ||
| mode: ctx.values.mode, | ||
| order: ctx.values.order, | ||
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Reuse a single claudePath variable
Same duplication pattern as in daily – resolve once, pass to both loadMonthlyUsageData and detectMismatches.
- const monthlyData = await loadMonthlyUsageData({
+ const claudePath = getDefaultClaudePath();
+ const monthlyData = await loadMonthlyUsageData({
since: ctx.values.since,
until: ctx.values.until,
- claudePath: getDefaultClaudePath(),
+ claudePath,
mode: ctx.values.mode,
order: ctx.values.order,
});
…
- const mismatchStats = await detectMismatches(getDefaultClaudePath());
+ const mismatchStats = await detectMismatches(claudePath);Also applies to: 57-60
🧰 Tools
🪛 ESLint
[error] 26-26: Unsafe assignment of an any value.
(ts/no-unsafe-assignment)
[error] 26-26: Unsafe member access .values on an any value.
(ts/no-unsafe-member-access)
[error] 27-27: Unsafe assignment of an any value.
(ts/no-unsafe-assignment)
[error] 27-27: Unsafe member access .values on an any value.
(ts/no-unsafe-member-access)
[error] 29-29: Unsafe member access .values on an any value.
(ts/no-unsafe-member-access)
[error] 30-30: Unsafe member access .values on an any value.
(ts/no-unsafe-member-access)
🤖 Prompt for AI Agents
In src/commands/monthly.ts around lines 25 to 31 and also lines 57 to 60, the
code calls getDefaultClaudePath() multiple times causing duplication. Fix this
by declaring a single variable claudePath before these calls, assign it the
result of getDefaultClaudePath(), and then pass this variable to both
loadMonthlyUsageData and detectMismatches functions to reuse the value.
| const sessionData = await loadSessionData({ | ||
| since: ctx.values.since, | ||
| until: ctx.values.until, | ||
| claudePath: ctx.values.path, | ||
| claudePath: getDefaultClaudePath(), | ||
| mode: ctx.values.mode, | ||
| order: ctx.values.order, | ||
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Deduplicate getDefaultClaudePath() invocations
Mirror the optimisation applied to the other commands.
- const sessionData = await loadSessionData({
+ const claudePath = getDefaultClaudePath();
+ const sessionData = await loadSessionData({
since: ctx.values.since,
until: ctx.values.until,
- claudePath: getDefaultClaudePath(),
+ claudePath,
mode: ctx.values.mode,
order: ctx.values.order,
});
…
- const mismatchStats = await detectMismatches(getDefaultClaudePath());
+ const mismatchStats = await detectMismatches(claudePath);Also applies to: 46-49
🧰 Tools
🪛 ESLint
[error] 26-26: Unsafe assignment of an any value.
(ts/no-unsafe-assignment)
[error] 26-26: Unsafe member access .values on an any value.
(ts/no-unsafe-member-access)
[error] 27-27: Unsafe assignment of an any value.
(ts/no-unsafe-assignment)
[error] 27-27: Unsafe member access .values on an any value.
(ts/no-unsafe-member-access)
[error] 29-29: Unsafe member access .values on an any value.
(ts/no-unsafe-member-access)
[error] 30-30: Unsafe member access .values on an any value.
(ts/no-unsafe-member-access)
🤖 Prompt for AI Agents
In src/commands/session.ts around lines 25 to 31 and also lines 46 to 49, the
function getDefaultClaudePath() is called multiple times unnecessarily. To
optimize, call getDefaultClaudePath() once, store its result in a variable, and
reuse that variable in the loadSessionData calls instead of invoking the
function repeatedly.
| const { type, mode, port } = ctx.values; | ||
| // disable info logging | ||
| if (type === 'stdio') { | ||
| logger.level = 0; | ||
| } | ||
|
|
||
| const server = createMcpServer({ | ||
| claudePath: path, | ||
| claudePath: getDefaultClaudePath(), | ||
| mode, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Inline duplication & potential exception propagation
- Resolve the path once and reuse.
- As with the other commands, wrap the resolution in
try/catchto avoid raw stack traces on invalid paths.
- const { type, mode, port } = ctx.values;
+ const { type, mode, port } = ctx.values;
+
+ const claudePath = getDefaultClaudePath();
…
- const server = createMcpServer({
- claudePath: getDefaultClaudePath(),
+ const server = createMcpServer({
+ claudePath,
mode,
});📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const { type, mode, port } = ctx.values; | |
| // disable info logging | |
| if (type === 'stdio') { | |
| logger.level = 0; | |
| } | |
| const server = createMcpServer({ | |
| claudePath: path, | |
| claudePath: getDefaultClaudePath(), | |
| mode, | |
| const { type, mode, port } = ctx.values; | |
| const claudePath = getDefaultClaudePath(); | |
| // disable info logging | |
| if (type === 'stdio') { | |
| logger.level = 0; | |
| } | |
| const server = createMcpServer({ | |
| claudePath, | |
| mode, | |
| }); |
🧰 Tools
🪛 ESLint
[error] 26-26: Unsafe assignment of an any value.
(ts/no-unsafe-assignment)
[error] 26-26: Unsafe member access .values on an any value.
(ts/no-unsafe-member-access)
[error] 29-29: Unsafe member access .level on an error typed value.
(ts/no-unsafe-member-access)
🤖 Prompt for AI Agents
In src/commands/mcp.ts around lines 26 to 34, the code calls
getDefaultClaudePath() directly inside createMcpServer, causing duplicate path
resolution and risking unhandled exceptions. Fix this by resolving the Claude
path once before the server creation, wrapping the resolution in a try/catch
block to handle invalid paths gracefully and prevent raw stack traces, then pass
the resolved path variable to createMcpServer.
| const envClaudeCodePath = process.env.CLAUDE_CONFIG_DIR?.trim() ?? DEFAULT_CLAUDE_CODE_PATH; | ||
| if (!isDirectorySync(envClaudeCodePath)) { | ||
| throw new Error( | ||
| ` Claude data directory does not exist: ${envClaudeCodePath}. | ||
| Please set CLAUDE_CONFIG_DIR to a valid path, or ensure ${DEFAULT_CLAUDE_CODE_PATH} exists. | ||
| `.trim(), | ||
| ); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Guard against empty/undefined CLAUDE_CONFIG_DIR and avoid hard-fail on missing default dir
isDirectorySync(envClaudeCodePath) is invoked even when
a) CLAUDE_CONFIG_DIR is an empty string after .trim() or
b) the env var is unset (falls back to DEFAULT_CLAUDE_CODE_PATH, which may not exist in CI / first-run environments).
This currently crashes the whole process (see CI failure).
A safer approach:
- Validate the env var only if it is present and non-empty.
- Re-use previous behaviour for the default path – just return it without enforcing existence (let callers decide).
export function getDefaultClaudePath(): string {
- const envClaudeCodePath = process.env.CLAUDE_CONFIG_DIR?.trim() ?? DEFAULT_CLAUDE_CODE_PATH;
- if (!isDirectorySync(envClaudeCodePath)) {
- throw new Error(
- ` Claude data directory does not exist: ${envClaudeCodePath}.
-Please set CLAUDE_CONFIG_DIR to a valid path, or ensure ${DEFAULT_CLAUDE_CODE_PATH} exists.
- `.trim(),
- );
- }
- return envClaudeCodePath;
+ const raw = process.env.CLAUDE_CONFIG_DIR;
+ const envPath = raw?.trim();
+
+ // If the user explicitly provided a path, validate it
+ if (envPath && envPath.length > 0) {
+ if (!isDirectorySync(envPath)) {
+ throw new Error(`CLAUDE_CONFIG_DIR points to a non-existent directory: ${envPath}`);
+ }
+ return envPath;
+ }
+
+ // Fallback to default path (preserves previous non-blocking behaviour)
+ return DEFAULT_CLAUDE_CODE_PATH;
}This prevents the empty-string crash, keeps the strict check for explicit custom paths, and lets CI/tests run without needing to create ~/.claude.
🧰 Tools
🪛 ESLint
[error] 24-24: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 24-24: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 24-24: Unsafe member access .env on an error typed value.
(ts/no-unsafe-member-access)
[error] 25-25: Unexpected any value in conditional. An explicit comparison or type conversion is required.
(ts/strict-boolean-expressions)
[error] 25-25: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
🪛 GitHub Check: ci
[failure] 26-26: error: Claude data directory does not exist: /home/runner/.claude.
Please set CLAUDE_CONFIG_DIR to a valid path, or ensure /home/runner/.claude exists.
at getDefaultClaudePath (/home/runner/work/ccusage/ccusage/src/data-loader.ts:26:9)
at (/home/runner/work/ccusage/ccusage/src/data-loader.test.ts:68:22)
at (/home/runner/work/ccusage/ccusage/src/data-loader.test.ts:63:65)
🤖 Prompt for AI Agents
In src/data-loader.ts around lines 24 to 31, modify the code to only check if
the directory exists when the CLAUDE_CONFIG_DIR environment variable is set and
non-empty after trimming. If CLAUDE_CONFIG_DIR is empty or undefined, do not
perform the directory existence check and simply return the default path without
throwing an error. This avoids crashing the process on missing default
directories while maintaining strict validation for explicitly set custom paths.
- Add step to create default Claude directory in CI environment - Remove try-catch block from test, making it clean and simple - Test now works consistently in both local and CI environments
…be0f-269b8b06a70d feat!: specify claude dir with `CLAUDE_CONFIG_DIR` and remove `-p`/`--path` option
|
fixes: #66 |
…be0f-269b8b06a70d feat!: specify claude dir with `CLAUDE_CONFIG_DIR` and remove `-p`/`--path` option
Summary
Changes Made
CLI Interface Changes
Documentation Updates
Test Coverage
Breaking Change Notice
```bash
Before (no longer works):
ccusage daily --path /custom/path
After:
export CLAUDE_CONFIG_DIR="/custom/path"
ccusage daily
```
Test Plan
Summary by CodeRabbit