Skip to content

Conversation

@ryoppippi
Copy link
Owner

@ryoppippi ryoppippi commented Jun 19, 2025

Summary

fixes: #121

This PR adds support for multiple Claude data directories to handle different Claude Code installations and the breaking change where logs moved from ~/.claude to ~/.config/claude.

Key Features

Multiple Path Support: Automatically searches both ~/.config/claude/projects/ (new default) and ~/.claude/projects/ (old default)
Environment Variable: Set CLAUDE_CONFIG_DIR to specify custom path(s) - supports comma-separated multiple paths
Data Aggregation: Usage data from all valid directories is automatically combined
Backward Compatibility: Existing configurations continue to work without changes

Implementation Highlights

Core Functionality: New getClaudePaths() function with path normalization and duplicate removal
Environment Support: CLAUDE_CONFIG_DIR accepts single or comma-separated multiple paths
Robust Testing: Comprehensive test coverage with CI improvements for multiple path scenarios
Code Quality: Refactored imports to use .ts extensions, replaced custom utilities with @antfu/utils

Commit Organization

Each commit represents a logical grouping:

  1. Constants: Core constants for multiple path support
  2. Core Implementation: getClaudePaths function and data loading updates
  3. Code Quality: Dependency updates and import standardization
  4. Testing Infrastructure: CI improvements for multiple path testing
  5. Documentation: Updated README and CLAUDE.md with usage examples

Breaking Changes

None - this is fully backward compatible. Existing users will see no changes in behavior.

Migration Path

No Action Required: Existing ~/.claude installations continue working
Optional: Set CLAUDE_CONFIG_DIR environment variable for custom paths
Future-Proof: New ~/.config/claude installations are automatically detected

Test Plan

  • Existing functionality works unchanged
  • Multiple paths are correctly detected and combined
  • Environment variable support works for single and multiple paths
  • Path normalization prevents duplicates
  • CI tests pass with both directory structures
  • Backward compatibility maintained for deprecated functions

Summary by CodeRabbit

  • New Features

    • Added support for detecting and aggregating Claude Code usage data from multiple directories, including both new and legacy default locations.
    • Users can now specify custom data directories using the CLAUDE_CONFIG_DIR environment variable, supporting multiple comma-separated paths.
  • Documentation

    • Updated documentation and README to explain multi-directory support and new configuration options.
  • Chores

    • Enhanced CI workflow to create both legacy and new default data directories for testing.
    • Added a new development dependency for utilities.

@coderabbitai
Copy link

coderabbitai bot commented Jun 19, 2025

Warning

Rate limit exceeded

@ryoppippi has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 18 minutes and 21 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

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.

📥 Commits

Reviewing files that changed from the base of the PR and between 1e62e473455a17408fa31027f47d5ea57c01a4b6 and b58b655.

⛔ Files ignored due to path filters (1)
  • bun.lock is excluded by !**/*.lock
📒 Files selected for processing (10)
  • .github/workflows/ci.yaml (1 hunks)
  • CLAUDE.md (2 hunks)
  • README.md (1 hunks)
  • package.json (1 hunks)
  • src/_consts.ts (1 hunks)
  • src/_session-blocks.ts (1 hunks)
  • src/commands/blocks.ts (1 hunks)
  • src/commands/mcp.ts (1 hunks)
  • src/data-loader.ts (8 hunks)
  • src/debug.ts (1 hunks)

Walkthrough

This update introduces support for multiple Claude Code data directories by adding logic to aggregate usage data from both the old and new default paths, as well as custom directories specified via the CLAUDE_CONFIG_DIR environment variable. Documentation, constants, data loading functions, import statements, and tests are updated accordingly.

Changes

File(s) Change Summary
CLAUDE.md, README.md Extended documentation to describe multi-directory support and configuration via CLAUDE_CONFIG_DIR environment variable.
src/consts.internal.ts Added constants for new default Claude config path and environment variable name for custom directories.
src/data-loader.ts Added multi-path support with getClaudePaths(), updated data loading functions to aggregate usage from multiple directories, deprecated getDefaultClaudePath(), and added tests.
.github/workflows/ci.yaml Updated CI workflow to create both old and new default Claude project directories for testing.
package.json Added "@antfu/utils" as a new development dependency.
src/commands/blocks.ts, src/commands/mcp.ts, src/debug.ts, src/session-blocks.internal.ts Changed import statements to use .ts extensions for local files instead of .js.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant CLI Tool
    participant DataLoader
    participant FileSystem

    User->>CLI Tool: Run usage command
    CLI Tool->>DataLoader: Request usage data
    DataLoader->>FileSystem: Read CLAUDE_CONFIG_DIR env var
    alt CLAUDE_CONFIG_DIR set
        DataLoader->>FileSystem: Parse comma-separated paths
    else
        DataLoader->>FileSystem: Use default paths (~/.config/claude, ~/.claude)
    end
    DataLoader->>FileSystem: Validate and aggregate project directories
    DataLoader->>FileSystem: Load and merge usage data from all valid directories
    DataLoader-->>CLI Tool: Return aggregated usage data
    CLI Tool-->>User: Display results
Loading

Assessment against linked issues

Objective Addressed Explanation
Support both old (~/.claude) and new (~/.config/claude) Claude data directories for v1.0.30+ ( #121 )
Allow custom Claude data directories via CLAUDE_CONFIG_DIR env var ( #121 )
Aggregate usage data from all valid directories for backward compatibility ( #121 )

Assessment against linked issues: Out-of-scope changes

Code Change Explanation
Addition of "@antfu/utils" dev dependency (package.json) No objectives mention adding or requiring this dependency; its necessity is unclear.

Possibly related PRs

Poem

In burrows deep where Claude logs sleep,
Now rabbits hop to more than one heap.
Old paths and new, we gather the clues,
With env vars too, we never lose!
Data multiplies, the code complies—
A patch well-earned, with carrots in our eyes! 🥕

✨ Finishing Touches
  • 📝 Generate Docstrings

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.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need 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)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@ryoppippi ryoppippi requested a review from Copilot June 19, 2025 21:33
@pkg-pr-new
Copy link

pkg-pr-new bot commented Jun 19, 2025

Open in StackBlitz

npm i https://pkg.pr.new/ryoppippi/ccusage@122

commit: b58b655

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a 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 @ryoppippi, 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 significantly enhances the flexibility and robustness of ccusage by enabling it to seamlessly handle usage data spread across multiple Claude Code installation directories. This change ensures backward compatibility and future-proofs the tool against potential changes in Claude Code's data storage locations, providing a more reliable experience for users with varying Claude Code versions or custom setups.

Highlights

  • Multi-Directory Support: Implemented support for ccusage to automatically detect and aggregate usage data from multiple Claude Code data directories, specifically addressing the path change from ~/.claude/projects/ to ~/.config/claude/projects/ in Claude Code v1.0.30+.
  • Environment Variable Configuration: Introduced support for the CLAUDE_CONFIG_DIR environment variable, allowing users to specify one or more custom, comma-separated Claude data directory paths, which take precedence over default locations.
  • Enhanced Data Loading: Modified core data loading functions (loadDailyUsageData, loadSessionData, loadSessionBlockData) to collect and process usage data from all identified Claude data directories, ensuring comprehensive reporting regardless of where the data resides.
  • New Path Resolution Logic: Added a new getClaudePaths() function to resolve all valid Claude data directories based on environment variables, the new default path (~/.config/claude), and the legacy default path (~/.claude), while deprecating the old getDefaultClaudePath().
  • Utility Function & Tests: Included a new ensureArray() utility function for cleaner array handling and added comprehensive unit and integration tests to validate the multi-path functionality, environment variable parsing, and data aggregation.
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

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a 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 enhances ccusage by adding support for multiple Claude data directories. The changes include a new getClaudePaths function for path discovery and updates to data loading functions to aggregate data from multiple sources. The PR is well-structured and the code is clear. I suggest optimizing a potentially O(N^2) operation in loadSessionData and improving the determinism of a unit test for getClaudePaths.

Comment on lines 799 to 802
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The current method of re-associating baseDir with sorted file paths uses filesWithBase.find() inside a map() call, which can lead to O(N^2) time complexity. Consider using a Map to store baseDir associated with each file path before sorting for O(1) lookups during re-association, making it O(N).

Additionally, item?.baseDir ?? '' will result in an empty baseDir if item is unexpectedly undefined, potentially leading to incorrect session and project path extraction. A more robust approach would be to throw an error if item is not found, or ensure baseDir is never an empty string if a valid path is expected.

sortedFiles.map((file) => {
			const item = filesWithBase.find(f => f.file === file);
			return { file, baseDir: item?.baseDir ?? '' }; 
		}),

Comment on lines 3674 to 3726
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The test case for getClaudePaths() when the environment variable is not set relies on the test environment's file system, which can make the test non-deterministic. Consider mocking isDirectorySync to control its return value for specific paths and verify getClaudePaths() behavior under controlled conditions (e.g., no default paths found, only old default path found, etc.). This ensures the test verifies the logic independently of the environment's file system state.

This comment was marked as outdated.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
CLAUDE.md (1)

49-60: Good documentation update with minor punctuation suggestion.

The multi-directory support documentation is clear and helpful for developers. Consider adding a comma for better readability on line 60.

-This addresses the breaking change in Claude Code where logs moved from `~/.claude` to `~/.config/claude`.
+This addresses the breaking change in Claude Code, where logs moved from `~/.claude` to `~/.config/claude`.
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e2f4b7b and e1d4058d3c8384796d026e83fbd54b5c95df2e95.

📒 Files selected for processing (5)
  • CLAUDE.md (1 hunks)
  • README.md (1 hunks)
  • src/consts.internal.ts (1 hunks)
  • src/data-loader.ts (7 hunks)
  • src/utils.internal.ts (2 hunks)
🧰 Additional context used
🪛 ESLint
src/utils.internal.ts

[error] 379-379: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 380-380: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 381-381: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 381-381: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 381-381: Unsafe member access .toEqual on an error typed value.

(ts/no-unsafe-member-access)


[error] 382-382: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 382-382: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 382-382: Unsafe member access .toEqual on an error typed value.

(ts/no-unsafe-member-access)


[error] 383-383: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 383-383: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 383-383: Unsafe member access .toEqual on an error typed value.

(ts/no-unsafe-member-access)


[error] 386-386: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 387-387: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 387-387: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 387-387: Unsafe member access .toEqual on an error typed value.

(ts/no-unsafe-member-access)


[error] 388-388: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 388-388: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 388-388: Unsafe member access .toEqual on an error typed value.

(ts/no-unsafe-member-access)


[error] 389-389: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 389-389: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 389-389: Unsafe member access .toEqual on an error typed value.

(ts/no-unsafe-member-access)


[error] 390-390: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 390-390: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 390-390: Unsafe member access .toEqual on an error typed value.

(ts/no-unsafe-member-access)


[error] 393-393: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 395-395: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 395-395: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 395-395: Unsafe member access .toEqual on an error typed value.

(ts/no-unsafe-member-access)


[error] 396-396: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 396-396: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 396-396: Unsafe member access .toBe on an error typed value.

(ts/no-unsafe-member-access)

src/data-loader.ts

[error] 61-61: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 61-61: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 61-61: Unsafe member access .env on an error typed value.

(ts/no-unsafe-member-access)


[error] 61-61: Unsafe member access .trim on an error typed value.

(ts/no-unsafe-member-access)


[error] 63-63: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 63-63: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 63-63: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 63-63: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 63-63: Unsafe member access .split on an error typed value.

(ts/no-unsafe-member-access)


[error] 63-63: Unsafe member access .map on an error typed value.

(ts/no-unsafe-member-access)


[error] 63-63: Unsafe return of a value of type any.

(ts/no-unsafe-return)


[error] 63-63: Unsafe call of a(n) any typed value.

(ts/no-unsafe-call)


[error] 63-63: Unsafe member access .trim on an any value.

(ts/no-unsafe-member-access)


[error] 63-63: Unsafe member access .filter on an error typed value.

(ts/no-unsafe-member-access)


[error] 65-65: Unexpected any value in conditional. An explicit comparison or type conversion is required.

(ts/strict-boolean-expressions)


[error] 65-65: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 66-66: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 66-66: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 66-66: Unsafe member access .join on an error typed value.

(ts/no-unsafe-member-access)


[error] 67-67: Unexpected any value in conditional. An explicit comparison or type conversion is required.

(ts/strict-boolean-expressions)


[error] 67-67: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 69-69: Unsafe argument of type error typed assigned to a parameter of type string.

(ts/no-unsafe-argument)


[error] 70-70: Unsafe argument of type error typed assigned to a parameter of type string.

(ts/no-unsafe-argument)


[error] 79-79: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 79-79: Unsafe member access .join 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 member access .join on an error typed value.

(ts/no-unsafe-member-access)


[error] 84-84: Unexpected any value in conditional. An explicit comparison or type conversion is required.

(ts/strict-boolean-expressions)


[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 call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 85-85: Unsafe member access .join on an error typed value.

(ts/no-unsafe-member-access)


[error] 86-86: Unexpected any value in conditional. An explicit comparison or type conversion is required.

(ts/strict-boolean-expressions)


[error] 86-86: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 88-88: Unsafe argument of type error typed assigned to a parameter of type string.

(ts/no-unsafe-argument)


[error] 89-89: Unsafe argument of type error typed assigned to a parameter of type string.

(ts/no-unsafe-argument)


[error] 98-98: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 98-98: Unsafe member access .join on an error typed value.

(ts/no-unsafe-member-access)


[error] 99-99: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 99-99: Unsafe member access .join on an error typed value.

(ts/no-unsafe-member-access)


[error] 114-114: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 114-114: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 114-114: Unsafe member access .env on an error typed value.

(ts/no-unsafe-member-access)


[error] 114-114: Unsafe member access .trim on an error typed value.

(ts/no-unsafe-member-access)


[error] 117-117: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 117-117: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 117-117: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 117-117: Unsafe member access .split on an error typed value.

(ts/no-unsafe-member-access)


[error] 117-117: Unsafe member access [0] on an error typed value.

(ts/no-unsafe-member-access)


[error] 119-119: Unexpected any value in conditional. An explicit comparison or type conversion is required.

(ts/strict-boolean-expressions)


[error] 119-119: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 122-122: Unsafe return of a value of type error.

(ts/no-unsafe-return)


[error] 127-127: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 127-127: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 127-127: Unsafe member access .join on an error typed value.

(ts/no-unsafe-member-access)


[error] 128-128: Unexpected any value in conditional. An explicit comparison or type conversion is required.

(ts/strict-boolean-expressions)


[error] 128-128: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 129-129: Unsafe return of a value of type error.

(ts/no-unsafe-return)


[error] 133-133: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 133-133: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 133-133: Unsafe member access .join on an error typed value.

(ts/no-unsafe-member-access)


[error] 134-134: Unexpected any value in conditional. An explicit comparison or type conversion is required.

(ts/strict-boolean-expressions)


[error] 134-134: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 135-135: Unsafe return of a value of type error.

(ts/no-unsafe-return)


[error] 139-139: Unsafe return of a value of type error.

(ts/no-unsafe-return)


[error] 651-651: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 651-651: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 651-651: Unsafe member access .join on an error typed value.

(ts/no-unsafe-member-access)


[error] 652-655: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 652-652: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 653-653: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 656-656: Unsafe spread of an error typed type.

(ts/no-unsafe-argument)


[error] 780-780: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 780-780: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 780-780: Unsafe member access .join on an error typed value.

(ts/no-unsafe-member-access)


[error] 781-784: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 781-781: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 782-782: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 787-787: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 787-787: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 827-827: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 827-827: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 827-827: Unsafe member access .relative on an error typed value.

(ts/no-unsafe-member-access)


[error] 1033-1033: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 1033-1033: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 1033-1033: Unsafe member access .join on an error typed value.

(ts/no-unsafe-member-access)


[error] 1034-1037: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 1034-1034: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 1035-1035: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 1038-1038: Unsafe spread of an error typed type.

(ts/no-unsafe-argument)


[error] 3652-3652: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3653-3653: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3654-3654: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3654-3654: Unsafe member access .unstubAllEnvs on an error typed value.

(ts/no-unsafe-member-access)


[error] 3657-3657: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3658-3660: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 3658-3658: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3661-3663: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 3661-3661: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3665-3665: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3665-3665: Unsafe member access .stubEnv on an error typed value.

(ts/no-unsafe-member-access)


[error] 3665-3665: Unsafe member access .path on an error typed value.

(ts/no-unsafe-member-access)


[error] 3665-3665: Unsafe member access .path on an error typed value.

(ts/no-unsafe-member-access)


[error] 3668-3668: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3668-3668: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3668-3668: Unsafe member access .toEqual on an error typed value.

(ts/no-unsafe-member-access)


[error] 3668-3668: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3668-3668: Unsafe member access .arrayContaining on an error typed value.

(ts/no-unsafe-member-access)


[error] 3668-3668: Unsafe member access .path on an error typed value.

(ts/no-unsafe-member-access)


[error] 3668-3668: Unsafe member access .path on an error typed value.

(ts/no-unsafe-member-access)


[error] 3670-3670: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3670-3670: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3670-3670: Unsafe member access .toBe on an error typed value.

(ts/no-unsafe-member-access)


[error] 3670-3670: Unsafe member access .path on an error typed value.

(ts/no-unsafe-member-access)


[error] 3671-3671: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3671-3671: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3671-3671: Unsafe member access .toBe on an error typed value.

(ts/no-unsafe-member-access)


[error] 3671-3671: Unsafe member access .path on an error typed value.

(ts/no-unsafe-member-access)


[error] 3674-3674: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3675-3675: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3675-3675: Unsafe member access .stubEnv on an error typed value.

(ts/no-unsafe-member-access)


[error] 3680-3680: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3680-3680: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3680-3680: Unsafe member access .toBe on an error typed value.

(ts/no-unsafe-member-access)


[error] 3681-3681: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3681-3681: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3681-3681: Unsafe member access .toBeGreaterThan on an error typed value.

(ts/no-unsafe-member-access)


[error] 3684-3684: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3684-3684: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3684-3684: Unsafe member access .toMatch on an error typed value.

(ts/no-unsafe-member-access)


[error] 3688-3688: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3689-3691: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 3689-3689: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3693-3693: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3693-3693: Unsafe member access .stubEnv on an error typed value.

(ts/no-unsafe-member-access)


[error] 3693-3693: Unsafe member access .path on an error typed value.

(ts/no-unsafe-member-access)


[error] 3696-3696: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3696-3696: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3696-3696: Unsafe member access .toEqual on an error typed value.

(ts/no-unsafe-member-access)


[error] 3696-3696: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3696-3696: Unsafe member access .arrayContaining on an error typed value.

(ts/no-unsafe-member-access)


[error] 3696-3696: Unsafe member access .path on an error typed value.

(ts/no-unsafe-member-access)


[error] 3697-3697: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3697-3697: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3697-3697: Unsafe member access .toBe on an error typed value.

(ts/no-unsafe-member-access)


[error] 3697-3697: Unsafe member access .path on an error typed value.

(ts/no-unsafe-member-access)


[error] 3700-3700: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3701-3703: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 3701-3701: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3705-3705: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3705-3705: Unsafe member access .stubEnv on an error typed value.

(ts/no-unsafe-member-access)


[error] 3705-3705: Unsafe member access .path on an error typed value.

(ts/no-unsafe-member-access)


[error] 3705-3705: Unsafe member access .path on an error typed value.

(ts/no-unsafe-member-access)


[error] 3709-3709: Unsafe member access .path on an error typed value.

(ts/no-unsafe-member-access)


[error] 3710-3710: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3710-3710: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3710-3710: Unsafe member access .toBe on an error typed value.

(ts/no-unsafe-member-access)


[error] 3714-3714: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3715-3715: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3716-3728: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 3716-3716: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3730-3742: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 3730-3730: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3744-3744: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3744-3744: Unsafe member access .stubEnv on an error typed value.

(ts/no-unsafe-member-access)


[error] 3744-3744: Unsafe member access .path on an error typed value.

(ts/no-unsafe-member-access)


[error] 3744-3744: Unsafe member access .path on an error typed value.

(ts/no-unsafe-member-access)


[error] 3748-3748: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 3748-3748: Unsafe member access .date on an error typed value.

(ts/no-unsafe-member-access)


[error] 3749-3749: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3749-3749: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3749-3749: Unsafe member access .toBeDefined on an error typed value.

(ts/no-unsafe-member-access)


[error] 3750-3750: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3750-3750: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3750-3750: Unsafe member access .inputTokens on an error typed value.

(ts/no-unsafe-member-access)


[error] 3750-3750: Unsafe member access .toBe on an error typed value.

(ts/no-unsafe-member-access)


[error] 3751-3751: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3751-3751: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3751-3751: Unsafe member access .outputTokens on an error typed value.

(ts/no-unsafe-member-access)


[error] 3751-3751: Unsafe member access .toBe on an error typed value.

(ts/no-unsafe-member-access)


[error] 3752-3752: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3752-3752: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3752-3752: Unsafe member access .totalCost on an error typed value.

(ts/no-unsafe-member-access)


[error] 3752-3752: Unsafe member access .toBe on an error typed value.

(ts/no-unsafe-member-access)

🪛 LanguageTool
CLAUDE.md

[uncategorized] ~60-60: Possible missing comma found.
Context: ...addresses the breaking change in Claude Code where logs moved from ~/.claude to `
...

(AI_HYDRA_LEO_MISSING_COMMA)

🔇 Additional comments (11)
src/utils.internal.ts (2)

251-260: LGTM! Clean utility function with good type safety.

The ensureArray function is well-implemented with proper generic typing and clear logic. The JSDoc documentation is comprehensive and the function serves its purpose perfectly for the multi-directory support feature.


379-398: Comprehensive test coverage looks good.

The tests cover all the important scenarios including arrays, primitives, null/undefined values, and object reference preservation. The static analysis errors about "unsafe calls" are false positives related to the vitest testing setup and can be safely ignored.

src/consts.internal.ts (2)

45-49: LGTM! New constant properly supports v1.0.30+ Claude path.

The DEFAULT_CLAUDE_CONFIG_PATH constant correctly defines the new default Claude data directory path, complementing the existing legacy path constant.


51-55: LGTM! Environment variable constant is well-defined.

The CLAUDE_CONFIG_DIR_ENV constant provides a clean way to reference the environment variable name and supports the comma-separated paths feature as described in the PR objectives.

README.md (1)

126-149: Excellent documentation for the multi-directory feature.

The new Configuration section clearly explains how ccusage handles multiple Claude data directories, provides helpful context about the v1.0.30 breaking change, and shows practical examples of environment variable usage. This will be very helpful for users managing multiple Claude Code installations.

CLAUDE.md (1)

64-68: LGTM! Architecture documentation properly updated.

The updates to the architecture overview correctly reflect the multi-directory support feature and maintain consistency with the implementation changes.

src/data-loader.ts (5)

107-140: Well-implemented backward compatibility

The deprecated function maintains backward compatibility effectively by:

  • Only using the first path when multiple are provided
  • Preferring the old default path if it exists
  • Clear deprecation notice pointing to the new function

645-657: Correct implementation of multi-path support

The changes properly handle both single paths and arrays of paths using ensureArray, and correctly aggregate files from all valid directories.


778-803: Excellent handling of multiple base directories

The implementation correctly tracks the base directory for each file, which is essential for proper session and project path extraction. The approach of storing { file, baseDir } pairs ensures accurate relative path computation.


1027-1039: Consistent multi-path implementation

The changes follow the same pattern as the other load functions, ensuring consistency across the codebase.


61-61: Fix TypeScript type safety for environment variable access

The static analysis indicates type safety issues with process.env access. Consider adding proper type annotations or using optional chaining more defensively.

-	const envPaths = (process.env[CLAUDE_CONFIG_DIR_ENV] ?? '').trim();
+	const envPaths = (process.env[CLAUDE_CONFIG_DIR_ENV] || '').trim();

Likely an incorrect or invalid review comment.

@socket-security
Copy link

socket-security bot commented Jun 20, 2025

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Added@​antfu/​utils@​9.2.01001007681100

View full report

Copy link

@coderabbitai coderabbitai bot left a 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 (1)
src/data-loader.ts (1)

115-145: Good backward compatibility implementation with minor documentation suggestion.

The deprecated function maintains backward compatibility well. Consider enhancing the deprecation notice:

/**
 * Default path for Claude data directory
 * Uses environment variable CLAUDE_CONFIG_DIR if set, otherwise defaults to ~/.claude
- * @deprecated Use getClaudePaths() instead for multiple path support
+ * @deprecated Use getClaudePaths() instead for multiple path support. This function only returns the first path when multiple are configured.
 */
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2feda46a1b3c6005e7b74623af1a39faba5904e7 and aec9f94cd8d5574fa9289fe796fea9f5cb4d6fd8.

⛔ Files ignored due to path filters (1)
  • bun.lock is excluded by !**/*.lock
📒 Files selected for processing (2)
  • package.json (1 hunks)
  • src/data-loader.ts (8 hunks)
✅ Files skipped from review due to trivial changes (1)
  • package.json
🧰 Additional context used
🪛 ESLint
src/data-loader.ts

[error] 62-62: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 62-62: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 62-62: Unsafe member access .env on an error typed value.

(ts/no-unsafe-member-access)


[error] 62-62: Unsafe member access .trim on an error typed value.

(ts/no-unsafe-member-access)


[error] 64-64: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 64-64: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 64-64: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 64-64: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 64-64: Unsafe member access .split on an error typed value.

(ts/no-unsafe-member-access)


[error] 64-64: Unsafe member access .map on an error typed value.

(ts/no-unsafe-member-access)


[error] 64-64: Unsafe return of a value of type any.

(ts/no-unsafe-return)


[error] 64-64: Unsafe call of a(n) any typed value.

(ts/no-unsafe-call)


[error] 64-64: Unsafe member access .trim on an any value.

(ts/no-unsafe-member-access)


[error] 64-64: Unsafe member access .filter on an error typed value.

(ts/no-unsafe-member-access)


[error] 66-66: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 66-66: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 66-66: Unsafe member access .resolve on an error typed value.

(ts/no-unsafe-member-access)


[error] 67-67: Unexpected any value in conditional. An explicit comparison or type conversion is required.

(ts/strict-boolean-expressions)


[error] 67-67: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 68-68: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 68-68: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 68-68: Unsafe member access .join on an error typed value.

(ts/no-unsafe-member-access)


[error] 69-69: Unexpected any value in conditional. An explicit comparison or type conversion is required.

(ts/strict-boolean-expressions)


[error] 69-69: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 71-71: Unsafe argument of type error typed assigned to a parameter of type string.

(ts/no-unsafe-argument)


[error] 72-72: Unsafe argument of type error typed assigned to a parameter of type string.

(ts/no-unsafe-argument)


[error] 73-73: Unsafe argument of type error typed assigned to a parameter of type string.

(ts/no-unsafe-argument)


[error] 82-82: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 82-82: Unsafe member access .join 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] 83-83: Unsafe member access .join 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 call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 87-87: Unsafe member access .resolve on an error typed value.

(ts/no-unsafe-member-access)


[error] 88-88: Unexpected any value in conditional. An explicit comparison or type conversion is required.

(ts/strict-boolean-expressions)


[error] 88-88: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 89-89: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 89-89: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 89-89: Unsafe member access .join on an error typed value.

(ts/no-unsafe-member-access)


[error] 90-90: Unexpected any value in conditional. An explicit comparison or type conversion is required.

(ts/strict-boolean-expressions)


[error] 90-90: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 92-92: Unsafe argument of type error typed assigned to a parameter of type string.

(ts/no-unsafe-argument)


[error] 93-93: Unsafe argument of type error typed assigned to a parameter of type string.

(ts/no-unsafe-argument)


[error] 94-94: Unsafe argument of type error typed assigned to a parameter of type string.

(ts/no-unsafe-argument)


[error] 103-103: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 103-103: Unsafe member access .join on an error typed value.

(ts/no-unsafe-member-access)


[error] 104-104: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 104-104: Unsafe member access .join on an error typed value.

(ts/no-unsafe-member-access)


[error] 119-119: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 119-119: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 119-119: Unsafe member access .env on an error typed value.

(ts/no-unsafe-member-access)


[error] 119-119: Unsafe member access .trim on an error typed value.

(ts/no-unsafe-member-access)


[error] 122-122: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 122-122: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 122-122: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 122-122: Unsafe member access .split on an error typed value.

(ts/no-unsafe-member-access)


[error] 122-122: Unsafe member access [0] on an error typed value.

(ts/no-unsafe-member-access)


[error] 124-124: Unexpected any value in conditional. An explicit comparison or type conversion is required.

(ts/strict-boolean-expressions)


[error] 124-124: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 127-127: Unsafe return of a value of type error.

(ts/no-unsafe-return)


[error] 132-132: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 132-132: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 132-132: Unsafe member access .join on an error typed value.

(ts/no-unsafe-member-access)


[error] 133-133: Unexpected any value in conditional. An explicit comparison or type conversion is required.

(ts/strict-boolean-expressions)


[error] 133-133: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 134-134: Unsafe return of a value of type error.

(ts/no-unsafe-return)


[error] 138-138: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 138-138: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 138-138: Unsafe member access .join on an error typed value.

(ts/no-unsafe-member-access)


[error] 139-139: Unexpected any value in conditional. An explicit comparison or type conversion is required.

(ts/strict-boolean-expressions)


[error] 139-139: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 140-140: Unsafe return of a value of type error.

(ts/no-unsafe-return)


[error] 144-144: Unsafe return of a value of type error.

(ts/no-unsafe-return)


[error] 651-651: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 651-651: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 656-656: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 656-656: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 656-656: Unsafe member access .join on an error typed value.

(ts/no-unsafe-member-access)


[error] 657-660: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 657-657: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 658-658: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 661-661: Unsafe spread of an error typed type.

(ts/no-unsafe-argument)


[error] 780-780: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 780-780: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 785-785: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 785-785: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 785-785: Unsafe member access .join on an error typed value.

(ts/no-unsafe-member-access)


[error] 786-789: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 786-786: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 787-787: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 792-792: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 792-792: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 834-834: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 834-834: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 834-834: Unsafe member access .relative on an error typed value.

(ts/no-unsafe-member-access)


[error] 1035-1035: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 1035-1035: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 1040-1040: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 1040-1040: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 1040-1040: Unsafe member access .join on an error typed value.

(ts/no-unsafe-member-access)


[error] 1041-1044: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 1041-1041: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 1042-1042: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 1045-1045: Unsafe spread of an error typed type.

(ts/no-unsafe-argument)


[error] 1200-1200: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 1200-1200: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 1200-1200: Unsafe member access .toMatch on an error typed value.

(ts/no-unsafe-member-access)


[error] 3659-3659: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3660-3660: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3661-3661: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3661-3661: Unsafe member access .unstubAllEnvs on an error typed value.

(ts/no-unsafe-member-access)


[error] 3664-3664: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3665-3667: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 3665-3665: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3669-3669: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3669-3669: Unsafe member access .stubEnv on an error typed value.

(ts/no-unsafe-member-access)


[error] 3669-3669: Unsafe member access .path on an error typed value.

(ts/no-unsafe-member-access)


[error] 3671-3671: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3671-3671: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3671-3671: Unsafe member access .toBe on an error typed value.

(ts/no-unsafe-member-access)


[error] 3671-3671: Unsafe member access .path on an error typed value.

(ts/no-unsafe-member-access)


[error] 3674-3674: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3675-3675: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3675-3675: Unsafe member access .stubEnv on an error typed value.

(ts/no-unsafe-member-access)


[error] 3680-3680: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3680-3680: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3680-3680: Unsafe member access .toBe on an error typed value.

(ts/no-unsafe-member-access)


[error] 3681-3681: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3681-3681: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3681-3681: Unsafe member access .toBeGreaterThan on an error typed value.

(ts/no-unsafe-member-access)


[error] 3684-3684: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3685-3687: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 3685-3685: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3688-3690: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 3688-3688: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3692-3692: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3692-3692: Unsafe member access .stubEnv on an error typed value.

(ts/no-unsafe-member-access)


[error] 3692-3692: Unsafe member access .path on an error typed value.

(ts/no-unsafe-member-access)


[error] 3692-3692: Unsafe member access .path on an error typed value.

(ts/no-unsafe-member-access)


[error] 3694-3694: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3694-3694: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3694-3694: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3694-3694: Unsafe member access .resolve on an error typed value.

(ts/no-unsafe-member-access)


[error] 3694-3694: Unsafe member access .toBe on an error typed value.

(ts/no-unsafe-member-access)


[error] 3694-3694: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3694-3694: Unsafe member access .resolve on an error typed value.

(ts/no-unsafe-member-access)


[error] 3694-3694: Unsafe member access .path on an error typed value.

(ts/no-unsafe-member-access)


[error] 3698-3698: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3699-3699: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3700-3700: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3700-3700: Unsafe member access .unstubAllEnvs on an error typed value.

(ts/no-unsafe-member-access)


[error] 3703-3703: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3704-3706: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 3704-3704: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3707-3709: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 3707-3707: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3711-3711: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3711-3711: Unsafe member access .stubEnv on an error typed value.

(ts/no-unsafe-member-access)


[error] 3711-3711: Unsafe member access .path on an error typed value.

(ts/no-unsafe-member-access)


[error] 3711-3711: Unsafe member access .path on an error typed value.

(ts/no-unsafe-member-access)


[error] 3714-3714: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 3714-3714: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3714-3714: Unsafe member access .resolve on an error typed value.

(ts/no-unsafe-member-access)


[error] 3714-3714: Unsafe member access .path on an error typed value.

(ts/no-unsafe-member-access)


[error] 3715-3715: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 3715-3715: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3715-3715: Unsafe member access .resolve on an error typed value.

(ts/no-unsafe-member-access)


[error] 3715-3715: Unsafe member access .path on an error typed value.

(ts/no-unsafe-member-access)


[error] 3717-3717: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3717-3717: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3717-3717: Unsafe member access .toEqual on an error typed value.

(ts/no-unsafe-member-access)


[error] 3717-3717: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3717-3717: Unsafe member access .arrayContaining on an error typed value.

(ts/no-unsafe-member-access)


[error] 3719-3719: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3719-3719: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3719-3719: Unsafe member access .toBe on an error typed value.

(ts/no-unsafe-member-access)


[error] 3720-3720: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3720-3720: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3720-3720: Unsafe member access .toBe on an error typed value.

(ts/no-unsafe-member-access)


[error] 3723-3723: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3724-3726: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 3724-3724: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3728-3728: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3728-3728: Unsafe member access .stubEnv on an error typed value.

(ts/no-unsafe-member-access)


[error] 3728-3728: Unsafe member access .path on an error typed value.

(ts/no-unsafe-member-access)


[error] 3731-3731: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 3731-3731: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3731-3731: Unsafe member access .resolve on an error typed value.

(ts/no-unsafe-member-access)


[error] 3731-3731: Unsafe member access .path on an error typed value.

(ts/no-unsafe-member-access)


[error] 3732-3732: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3732-3732: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3732-3732: Unsafe member access .toEqual on an error typed value.

(ts/no-unsafe-member-access)


[error] 3732-3732: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3732-3732: Unsafe member access .arrayContaining on an error typed value.

(ts/no-unsafe-member-access)


[error] 3733-3733: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3733-3733: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3733-3733: Unsafe member access .toBe on an error typed value.

(ts/no-unsafe-member-access)


[error] 3736-3736: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3737-3739: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 3737-3737: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3741-3741: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3741-3741: Unsafe member access .stubEnv on an error typed value.

(ts/no-unsafe-member-access)


[error] 3741-3741: Unsafe member access .path on an error typed value.

(ts/no-unsafe-member-access)


[error] 3741-3741: Unsafe member access .path on an error typed value.

(ts/no-unsafe-member-access)


[error] 3744-3744: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 3744-3744: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3744-3744: Unsafe member access .resolve on an error typed value.

(ts/no-unsafe-member-access)


[error] 3744-3744: Unsafe member access .path on an error typed value.

(ts/no-unsafe-member-access)


[error] 3747-3747: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3747-3747: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3747-3747: Unsafe member access .toBe on an error typed value.

(ts/no-unsafe-member-access)


[error] 3751-3751: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3752-3752: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3753-3765: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 3753-3753: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3767-3779: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 3767-3767: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3781-3781: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3781-3781: Unsafe member access .stubEnv on an error typed value.

(ts/no-unsafe-member-access)


[error] 3781-3781: Unsafe member access .path on an error typed value.

(ts/no-unsafe-member-access)


[error] 3781-3781: Unsafe member access .path on an error typed value.

(ts/no-unsafe-member-access)


[error] 3785-3785: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 3785-3785: Unsafe member access .date on an error typed value.

(ts/no-unsafe-member-access)


[error] 3786-3786: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3786-3786: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3786-3786: Unsafe member access .toBeDefined on an error typed value.

(ts/no-unsafe-member-access)


[error] 3787-3787: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3787-3787: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3787-3787: Unsafe member access .inputTokens on an error typed value.

(ts/no-unsafe-member-access)


[error] 3787-3787: Unsafe member access .toBe on an error typed value.

(ts/no-unsafe-member-access)


[error] 3788-3788: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3788-3788: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3788-3788: Unsafe member access .outputTokens on an error typed value.

(ts/no-unsafe-member-access)


[error] 3788-3788: Unsafe member access .toBe on an error typed value.

(ts/no-unsafe-member-access)


[error] 3789-3789: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3789-3789: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3789-3789: Unsafe member access .totalCost on an error typed value.

(ts/no-unsafe-member-access)


[error] 3789-3789: Unsafe member access .toBe on an error typed value.

(ts/no-unsafe-member-access)

🔇 Additional comments (5)
src/data-loader.ts (5)

12-12: LGTM! Good imports for the new functionality.

The toArray utility and updated constants properly support the multi-path functionality.

Also applies to: 20-20


57-110: Excellent implementation of multi-path support.

The getClaudePaths() function is well-designed with proper:

  • Environment variable parsing with comma-separated support
  • Path normalization and validation
  • Set-based deduplication to avoid duplicates
  • Error handling when no valid paths are found
  • Prioritization of environment paths over defaults

This effectively addresses the Claude Code v1.0.30+ breaking change while maintaining flexibility.


650-662: Well-implemented multi-path data aggregation.

The data loading functions correctly:

  • Use toArray to handle both single paths and arrays
  • Collect files from all configured Claude directories
  • Maintain existing deduplication and sorting logic
  • Properly track base directories for session path extraction (lines 801-810)

The Map-based approach for file-to-baseDir lookup addresses previous O(N²) performance concerns.

Also applies to: 779-810, 1034-1046


3658-3791: Comprehensive test coverage for multi-path functionality.

The tests effectively cover:

  • Environment variable parsing with single and multiple paths
  • Path validation and filtering
  • Data aggregation across multiple directories
  • Deduplication logic
  • Backward compatibility scenarios

This provides confidence in the robustness of the implementation.


62-110: Address ESLint false positives for standard Node.js operations.

The ESLint errors about "unsafe" operations on process.env and path module usage are false positives. These are standard, type-safe Node.js operations. Consider updating your ESLint configuration to properly handle these patterns or add specific type annotations if needed.

The actual implementation is correct and safe.

Could you run the following to verify these are false positives:

#!/bin/bash
# Check if these are standard Node.js patterns that should be safe
echo "Checking process.env usage patterns..."
rg "process\.env\[" --type ts -A 2 -B 2

echo "Checking path module usage..."
rg "path\.(join|resolve|relative)" --type ts -A 1 -B 1

Also applies to: 119-145

@ryoppippi ryoppippi force-pushed the feature/multiple-claude-paths branch from aec9f94 to 1e62e47 Compare June 20, 2025 10:19
@ryoppippi ryoppippi requested a review from Copilot June 20, 2025 10:23
Copy link
Contributor

Copilot AI left a 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 multiple Claude data directories to handle the new installation paths and maintain backward compatibility via a new environment variable.

  • Updated import paths to use TypeScript (.ts) extensions.
  • Added a new getClaudePaths() function and refactored data loading to aggregate JSONL usage files from multiple directories.
  • Enhanced CI and documentation to reflect changes in configuration and default directory locations.

Reviewed Changes

Copilot reviewed 10 out of 11 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
src/session-blocks.internal.ts Updated import extension from .js to .ts for consistency.
src/debug.ts Updated import paths to .ts and removed deprecated constants.
src/data-loader.ts Added getClaudePaths() function and refactored default path logic for multi-directory support.
src/consts.internal.ts Introduced new constants for the new default path and CLAUDE_CONFIG_DIR environment variable.
src/commands/mcp.ts & src/commands/blocks.ts Updated import paths to .ts.
package.json Added dependency @antfu/utils for utility functions.
README.md & CLAUDE.md Updated documentation to include new configuration options and path support.
.github/workflows/ci.yaml Modified CI to create both legacy and new default directories for tests.

Comment on lines +143 to +148
Copy link

Copilot AI Jun 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fallback logic in getDefaultClaudePath returns the old default path even if it isn't a valid directory, which may lead to unexpected behavior. Consider clarifying the fallback behavior by either throwing an error or explicitly documenting that returning a non-existent path is intentional.

Suggested change
// If neither exists, return the old default for backward compatibility
return oldDefaultPath;
// If neither exists, throw an error to avoid returning a non-existent path
throw new Error(`Neither the new default path (${newDefaultPath}) nor the old default path (${oldDefaultPath}) exists. Please ensure a valid Claude data directory is available.`);

Copilot uses AI. Check for mistakes.
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (2)
src/data-loader.ts (2)

801-810: Optimize file-to-base mapping performance

The current implementation creates a Map for O(1) lookups, which is good, but there's still a potential issue with the fallback to empty string.

The performance optimization using Map is well-implemented, but as noted in past reviews, returning an empty baseDir when item is undefined could lead to incorrect session/project path extraction. Consider throwing an error instead:

	const sortedFilesWithBase = await sortFilesByTimestamp(
		filesWithBase.map(f => f.file),
	).then(sortedFiles =>
		sortedFiles.map(file => ({
			file,
-			baseDir: fileToBaseMap.get(file) ?? '',
+			baseDir: fileToBaseMap.get(file) ?? (() => { throw new Error(`Base directory not found for file: ${file}`); })(),
		})),
	);

653-662: Extract shared file collection logic to reduce duplication

The logic for collecting files across multiple paths is repeated in three loader functions. This creates maintenance overhead and potential inconsistencies.

As suggested in past reviews, consider extracting this into a shared helper function:

async function collectFilesFromPaths(
	claudePaths: string[],
	projectsDirName: string,
	globPattern: string
): Promise<string[]> {
	const allFiles: string[] = [];
	for (const claudePath of claudePaths) {
		const claudeDir = path.join(claudePath, projectsDirName);
		const files = await glob([globPattern], {
			cwd: claudeDir,
			absolute: true,
		});
		allFiles.push(...files);
	}
	return allFiles;
}

Then update the loader functions:

-	// Collect files from all paths
-	const allFiles: string[] = [];
-	for (const claudePath of claudePaths) {
-		const claudeDir = path.join(claudePath, CLAUDE_PROJECTS_DIR_NAME);
-		const files = await glob([USAGE_DATA_GLOB_PATTERN], {
-			cwd: claudeDir,
-			absolute: true,
-		});
-		allFiles.push(...files);
-	}
+	const allFiles = await collectFilesFromPaths(claudePaths, CLAUDE_PROJECTS_DIR_NAME, USAGE_DATA_GLOB_PATTERN);

Also applies to: 782-794, 1037-1046

🧹 Nitpick comments (3)
CLAUDE.md (2)

60-60: Add missing comma for clarity

Insert a comma after "Claude Code" to improve readability:

- This addresses the breaking change in Claude Code where logs moved...
+ This addresses the breaking change in Claude Code, where logs moved...

64-69: Document getClaudePaths() and resolution priority

Enhance the architecture overview to mention the new getClaudePaths() utility and clarify the path resolution order:

  1. Paths from CLAUDE_CONFIG_DIR
  2. New default (~/.config/claude/projects/)
  3. Legacy (~/.claude/projects/)

This will help maintainers understand how multi‐path support is orchestrated.

src/data-loader.ts (1)

100-107: Improve error message clarity and usefulness

The error message could be more helpful by providing specific guidance and checking actual directory states.

	if (paths.length === 0) {
		throw new Error(
-			`No valid Claude data directories found. Please ensure at least one of the following exists:
-- ${path.join(USER_HOME_DIR, DEFAULT_CLAUDE_CONFIG_PATH, CLAUDE_PROJECTS_DIR_NAME)}
-- ${path.join(USER_HOME_DIR, DEFAULT_CLAUDE_CODE_PATH, CLAUDE_PROJECTS_DIR_NAME)}
-- Or set ${CLAUDE_CONFIG_DIR_ENV} environment variable to valid directory path(s) containing a '${CLAUDE_PROJECTS_DIR_NAME}' subdirectory`.trim(),
+			`No valid Claude data directories found. 
+
+Searched locations:
+- ${path.join(USER_HOME_DIR, DEFAULT_CLAUDE_CONFIG_PATH, CLAUDE_PROJECTS_DIR_NAME)} ${isDirectorySync(path.join(USER_HOME_DIR, DEFAULT_CLAUDE_CONFIG_PATH)) ? '(directory exists, but no projects subdirectory)' : '(directory not found)'}
+- ${path.join(USER_HOME_DIR, DEFAULT_CLAUDE_CODE_PATH, CLAUDE_PROJECTS_DIR_NAME)} ${isDirectorySync(path.join(USER_HOME_DIR, DEFAULT_CLAUDE_CODE_PATH)) ? '(directory exists, but no projects subdirectory)' : '(directory not found)'}
+
+To fix this:
+1. Install Claude Code application, or
+2. Set ${CLAUDE_CONFIG_DIR_ENV} environment variable to a directory containing a '${CLAUDE_PROJECTS_DIR_NAME}' subdirectory`.trim(),
		);
	}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between aec9f94cd8d5574fa9289fe796fea9f5cb4d6fd8 and 1e62e473455a17408fa31027f47d5ea57c01a4b6.

⛔ Files ignored due to path filters (1)
  • bun.lock is excluded by !**/*.lock
📒 Files selected for processing (10)
  • .github/workflows/ci.yaml (1 hunks)
  • CLAUDE.md (2 hunks)
  • README.md (1 hunks)
  • package.json (1 hunks)
  • src/commands/blocks.ts (1 hunks)
  • src/commands/mcp.ts (1 hunks)
  • src/consts.internal.ts (1 hunks)
  • src/data-loader.ts (8 hunks)
  • src/debug.ts (1 hunks)
  • src/session-blocks.internal.ts (1 hunks)
✅ Files skipped from review due to trivial changes (4)
  • src/commands/mcp.ts
  • src/debug.ts
  • src/session-blocks.internal.ts
  • src/commands/blocks.ts
🚧 Files skipped from review as they are similar to previous changes (4)
  • .github/workflows/ci.yaml
  • package.json
  • src/consts.internal.ts
  • README.md
🧰 Additional context used
🪛 ESLint
src/data-loader.ts

[error] 62-62: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 62-62: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 62-62: Unsafe member access .env on an error typed value.

(ts/no-unsafe-member-access)


[error] 62-62: Unsafe member access .trim on an error typed value.

(ts/no-unsafe-member-access)


[error] 64-64: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 64-64: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 64-64: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 64-64: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 64-64: Unsafe member access .split on an error typed value.

(ts/no-unsafe-member-access)


[error] 64-64: Unsafe member access .map on an error typed value.

(ts/no-unsafe-member-access)


[error] 64-64: Unsafe return of a value of type any.

(ts/no-unsafe-return)


[error] 64-64: Unsafe call of a(n) any typed value.

(ts/no-unsafe-call)


[error] 64-64: Unsafe member access .trim on an any value.

(ts/no-unsafe-member-access)


[error] 64-64: Unsafe member access .filter on an error typed value.

(ts/no-unsafe-member-access)


[error] 66-66: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 66-66: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 66-66: Unsafe member access .resolve on an error typed value.

(ts/no-unsafe-member-access)


[error] 67-67: Unexpected any value in conditional. An explicit comparison or type conversion is required.

(ts/strict-boolean-expressions)


[error] 67-67: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 68-68: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 68-68: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 68-68: Unsafe member access .join on an error typed value.

(ts/no-unsafe-member-access)


[error] 69-69: Unexpected any value in conditional. An explicit comparison or type conversion is required.

(ts/strict-boolean-expressions)


[error] 69-69: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 71-71: Unsafe argument of type error typed assigned to a parameter of type string.

(ts/no-unsafe-argument)


[error] 72-72: Unsafe argument of type error typed assigned to a parameter of type string.

(ts/no-unsafe-argument)


[error] 73-73: Unsafe argument of type error typed assigned to a parameter of type string.

(ts/no-unsafe-argument)


[error] 82-82: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 82-82: Unsafe member access .join 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] 83-83: Unsafe member access .join 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 call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 87-87: Unsafe member access .resolve on an error typed value.

(ts/no-unsafe-member-access)


[error] 88-88: Unexpected any value in conditional. An explicit comparison or type conversion is required.

(ts/strict-boolean-expressions)


[error] 88-88: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 89-89: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 89-89: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 89-89: Unsafe member access .join on an error typed value.

(ts/no-unsafe-member-access)


[error] 90-90: Unexpected any value in conditional. An explicit comparison or type conversion is required.

(ts/strict-boolean-expressions)


[error] 90-90: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 92-92: Unsafe argument of type error typed assigned to a parameter of type string.

(ts/no-unsafe-argument)


[error] 93-93: Unsafe argument of type error typed assigned to a parameter of type string.

(ts/no-unsafe-argument)


[error] 94-94: Unsafe argument of type error typed assigned to a parameter of type string.

(ts/no-unsafe-argument)


[error] 103-103: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 103-103: Unsafe member access .join on an error typed value.

(ts/no-unsafe-member-access)


[error] 104-104: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 104-104: Unsafe member access .join on an error typed value.

(ts/no-unsafe-member-access)


[error] 119-119: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 119-119: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 119-119: Unsafe member access .env on an error typed value.

(ts/no-unsafe-member-access)


[error] 119-119: Unsafe member access .trim on an error typed value.

(ts/no-unsafe-member-access)


[error] 122-122: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 122-122: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 122-122: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 122-122: Unsafe member access .split on an error typed value.

(ts/no-unsafe-member-access)


[error] 122-122: Unsafe member access [0] on an error typed value.

(ts/no-unsafe-member-access)


[error] 124-124: Unexpected any value in conditional. An explicit comparison or type conversion is required.

(ts/strict-boolean-expressions)


[error] 124-124: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 127-127: Unsafe return of a value of type error.

(ts/no-unsafe-return)


[error] 132-132: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 132-132: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 132-132: Unsafe member access .join on an error typed value.

(ts/no-unsafe-member-access)


[error] 133-133: Unexpected any value in conditional. An explicit comparison or type conversion is required.

(ts/strict-boolean-expressions)


[error] 133-133: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 134-134: Unsafe return of a value of type error.

(ts/no-unsafe-return)


[error] 138-138: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 138-138: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 138-138: Unsafe member access .join on an error typed value.

(ts/no-unsafe-member-access)


[error] 139-139: Unexpected any value in conditional. An explicit comparison or type conversion is required.

(ts/strict-boolean-expressions)


[error] 139-139: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 140-140: Unsafe return of a value of type error.

(ts/no-unsafe-return)


[error] 144-144: Unsafe return of a value of type error.

(ts/no-unsafe-return)


[error] 651-651: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 651-651: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 656-656: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 656-656: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 656-656: Unsafe member access .join on an error typed value.

(ts/no-unsafe-member-access)


[error] 657-660: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 657-657: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 658-658: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 661-661: Unsafe spread of an error typed type.

(ts/no-unsafe-argument)


[error] 780-780: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 780-780: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 785-785: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 785-785: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 785-785: Unsafe member access .join on an error typed value.

(ts/no-unsafe-member-access)


[error] 786-789: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 786-786: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 787-787: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 792-792: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 792-792: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 834-834: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 834-834: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 834-834: Unsafe member access .relative on an error typed value.

(ts/no-unsafe-member-access)


[error] 1035-1035: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 1035-1035: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 1040-1040: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 1040-1040: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 1040-1040: Unsafe member access .join on an error typed value.

(ts/no-unsafe-member-access)


[error] 1041-1044: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 1041-1041: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 1042-1042: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 1045-1045: Unsafe spread of an error typed type.

(ts/no-unsafe-argument)


[error] 1200-1200: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 1200-1200: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 1200-1200: Unsafe member access .toMatch on an error typed value.

(ts/no-unsafe-member-access)


[error] 3659-3659: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3660-3660: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3661-3661: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3661-3661: Unsafe member access .unstubAllEnvs on an error typed value.

(ts/no-unsafe-member-access)


[error] 3664-3664: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3665-3667: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 3665-3665: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3669-3669: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3669-3669: Unsafe member access .stubEnv on an error typed value.

(ts/no-unsafe-member-access)


[error] 3669-3669: Unsafe member access .path on an error typed value.

(ts/no-unsafe-member-access)


[error] 3671-3671: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3671-3671: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3671-3671: Unsafe member access .toBe on an error typed value.

(ts/no-unsafe-member-access)


[error] 3671-3671: Unsafe member access .path on an error typed value.

(ts/no-unsafe-member-access)


[error] 3674-3674: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3675-3675: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3675-3675: Unsafe member access .stubEnv on an error typed value.

(ts/no-unsafe-member-access)


[error] 3680-3680: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3680-3680: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3680-3680: Unsafe member access .toBe on an error typed value.

(ts/no-unsafe-member-access)


[error] 3681-3681: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3681-3681: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3681-3681: Unsafe member access .toBeGreaterThan on an error typed value.

(ts/no-unsafe-member-access)


[error] 3684-3684: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3685-3687: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 3685-3685: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3688-3690: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 3688-3688: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3692-3692: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3692-3692: Unsafe member access .stubEnv on an error typed value.

(ts/no-unsafe-member-access)


[error] 3692-3692: Unsafe member access .path on an error typed value.

(ts/no-unsafe-member-access)


[error] 3692-3692: Unsafe member access .path on an error typed value.

(ts/no-unsafe-member-access)


[error] 3694-3694: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3694-3694: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3694-3694: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3694-3694: Unsafe member access .resolve on an error typed value.

(ts/no-unsafe-member-access)


[error] 3694-3694: Unsafe member access .toBe on an error typed value.

(ts/no-unsafe-member-access)


[error] 3694-3694: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3694-3694: Unsafe member access .resolve on an error typed value.

(ts/no-unsafe-member-access)


[error] 3694-3694: Unsafe member access .path on an error typed value.

(ts/no-unsafe-member-access)


[error] 3698-3698: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3699-3699: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3700-3700: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3700-3700: Unsafe member access .unstubAllEnvs on an error typed value.

(ts/no-unsafe-member-access)


[error] 3701-3701: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3701-3701: Unsafe member access .unstubAllGlobals on an error typed value.

(ts/no-unsafe-member-access)


[error] 3704-3704: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3705-3707: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 3705-3705: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3708-3710: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 3708-3708: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3712-3712: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3712-3712: Unsafe member access .stubEnv on an error typed value.

(ts/no-unsafe-member-access)


[error] 3712-3712: Unsafe member access .path on an error typed value.

(ts/no-unsafe-member-access)


[error] 3712-3712: Unsafe member access .path on an error typed value.

(ts/no-unsafe-member-access)


[error] 3715-3715: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 3715-3715: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3715-3715: Unsafe member access .resolve on an error typed value.

(ts/no-unsafe-member-access)


[error] 3715-3715: Unsafe member access .path on an error typed value.

(ts/no-unsafe-member-access)


[error] 3716-3716: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 3716-3716: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3716-3716: Unsafe member access .resolve on an error typed value.

(ts/no-unsafe-member-access)


[error] 3716-3716: Unsafe member access .path on an error typed value.

(ts/no-unsafe-member-access)


[error] 3718-3718: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3718-3718: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3718-3718: Unsafe member access .toEqual on an error typed value.

(ts/no-unsafe-member-access)


[error] 3718-3718: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3718-3718: Unsafe member access .arrayContaining on an error typed value.

(ts/no-unsafe-member-access)


[error] 3720-3720: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3720-3720: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3720-3720: Unsafe member access .toBe on an error typed value.

(ts/no-unsafe-member-access)


[error] 3721-3721: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3721-3721: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3721-3721: Unsafe member access .toBe on an error typed value.

(ts/no-unsafe-member-access)


[error] 3724-3724: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3725-3727: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 3725-3725: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3729-3729: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3729-3729: Unsafe member access .stubEnv on an error typed value.

(ts/no-unsafe-member-access)


[error] 3729-3729: Unsafe member access .path on an error typed value.

(ts/no-unsafe-member-access)


[error] 3732-3732: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 3732-3732: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3732-3732: Unsafe member access .resolve on an error typed value.

(ts/no-unsafe-member-access)


[error] 3732-3732: Unsafe member access .path on an error typed value.

(ts/no-unsafe-member-access)


[error] 3733-3733: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3733-3733: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3733-3733: Unsafe member access .toEqual on an error typed value.

(ts/no-unsafe-member-access)


[error] 3733-3733: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3733-3733: Unsafe member access .arrayContaining on an error typed value.

(ts/no-unsafe-member-access)


[error] 3734-3734: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3734-3734: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3734-3734: Unsafe member access .toBe on an error typed value.

(ts/no-unsafe-member-access)


[error] 3737-3737: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3738-3740: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 3738-3738: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3742-3742: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3742-3742: Unsafe member access .stubEnv on an error typed value.

(ts/no-unsafe-member-access)


[error] 3742-3742: Unsafe member access .path on an error typed value.

(ts/no-unsafe-member-access)


[error] 3742-3742: Unsafe member access .path on an error typed value.

(ts/no-unsafe-member-access)


[error] 3745-3745: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 3745-3745: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3745-3745: Unsafe member access .resolve on an error typed value.

(ts/no-unsafe-member-access)


[error] 3745-3745: Unsafe member access .path on an error typed value.

(ts/no-unsafe-member-access)


[error] 3748-3748: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3748-3748: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3748-3748: Unsafe member access .toBe on an error typed value.

(ts/no-unsafe-member-access)


[error] 3751-3751: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3752-3752: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 3752-3752: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3752-3752: Unsafe member access .fn on an error typed value.

(ts/no-unsafe-member-access)


[error] 3755-3755: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3755-3755: Unsafe member access .importActual on an error typed value.

(ts/no-unsafe-member-access)


[error] 3756-3756: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3756-3756: Unsafe member access .doMock on an error typed value.

(ts/no-unsafe-member-access)


[error] 3757-3757: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 3765-3765: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3765-3765: Unsafe member access .mockImplementation on an error typed value.

(ts/no-unsafe-member-access)


[error] 3785-3785: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3785-3785: Unsafe member access .stubEnv on an error typed value.

(ts/no-unsafe-member-access)


[error] 3793-3793: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3793-3793: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3793-3793: Unsafe member access .toContain on an error typed value.

(ts/no-unsafe-member-access)


[error] 3793-3793: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3793-3793: Unsafe member access .resolve on an error typed value.

(ts/no-unsafe-member-access)


[error] 3794-3794: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3794-3794: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3794-3794: Unsafe member access .toContain on an error typed value.

(ts/no-unsafe-member-access)


[error] 3794-3794: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3794-3794: Unsafe member access .resolve on an error typed value.

(ts/no-unsafe-member-access)


[error] 3795-3795: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3795-3795: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3795-3795: Unsafe member access .not on an error typed value.

(ts/no-unsafe-member-access)


[error] 3795-3795: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3795-3795: Unsafe member access .resolve on an error typed value.

(ts/no-unsafe-member-access)


[error] 3798-3798: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3798-3798: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3798-3798: Unsafe member access .toHaveBeenCalledWith on an error typed value.

(ts/no-unsafe-member-access)


[error] 3798-3798: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3798-3798: Unsafe member access .resolve on an error typed value.

(ts/no-unsafe-member-access)


[error] 3799-3799: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3799-3799: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3799-3799: Unsafe member access .toHaveBeenCalledWith on an error typed value.

(ts/no-unsafe-member-access)


[error] 3799-3799: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3799-3799: Unsafe member access .resolve on an error typed value.

(ts/no-unsafe-member-access)


[error] 3800-3800: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3800-3800: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3800-3800: Unsafe member access .toHaveBeenCalledWith on an error typed value.

(ts/no-unsafe-member-access)


[error] 3800-3800: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3800-3800: Unsafe member access .resolve on an error typed value.

(ts/no-unsafe-member-access)


[error] 3803-3803: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3803-3803: Unsafe member access .doUnmock on an error typed value.

(ts/no-unsafe-member-access)


[error] 3807-3807: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3808-3808: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3809-3821: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 3809-3809: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3823-3835: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 3823-3823: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3837-3837: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3837-3837: Unsafe member access .stubEnv on an error typed value.

(ts/no-unsafe-member-access)


[error] 3837-3837: Unsafe member access .path on an error typed value.

(ts/no-unsafe-member-access)


[error] 3837-3837: Unsafe member access .path on an error typed value.

(ts/no-unsafe-member-access)


[error] 3841-3841: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 3841-3841: Unsafe member access .date on an error typed value.

(ts/no-unsafe-member-access)


[error] 3842-3842: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3842-3842: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3842-3842: Unsafe member access .toBeDefined on an error typed value.

(ts/no-unsafe-member-access)


[error] 3843-3843: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3843-3843: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3843-3843: Unsafe member access .inputTokens on an error typed value.

(ts/no-unsafe-member-access)


[error] 3843-3843: Unsafe member access .toBe on an error typed value.

(ts/no-unsafe-member-access)


[error] 3844-3844: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3844-3844: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3844-3844: Unsafe member access .outputTokens on an error typed value.

(ts/no-unsafe-member-access)


[error] 3844-3844: Unsafe member access .toBe on an error typed value.

(ts/no-unsafe-member-access)


[error] 3845-3845: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3845-3845: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3845-3845: Unsafe member access .totalCost on an error typed value.

(ts/no-unsafe-member-access)


[error] 3845-3845: Unsafe member access .toBe on an error typed value.

(ts/no-unsafe-member-access)

🪛 GitHub Check: ci
src/data-loader.ts

[failure] 3793-3793: src/data-loader.ts > getClaudePaths > handles directory existence checks deterministically with mocked isDirectorySync
AssertionError: expected [ '/home/runner/.config/claude', …(1) ] to include '/mock/path1'
❯ src/data-loader.ts:3793:18

🪛 GitHub Actions: CI
src/data-loader.ts

[error] 3793-3793: Test failure in 'getClaudePaths' - handles directory existence checks deterministically with mocked isDirectorySync: AssertionError: expected [ '/home/runner/.config/claude', …(1) ] to include '/mock/path1'

🪛 LanguageTool
CLAUDE.md

[uncategorized] ~60-60: Possible missing comma found.
Context: ...addresses the breaking change in Claude Code where logs moved from ~/.claude to `
...

(AI_HYDRA_LEO_MISSING_COMMA)

🔇 Additional comments (3)
src/data-loader.ts (3)

12-12: Verify import consistency

The import of toArray from @antfu/utils is appropriate for normalizing the claudePath parameter to always be an array. This is a clean solution for handling both single path and multi-path scenarios.

Also applies to: 20-20


115-116: Deprecation notice is well-documented

The deprecation notice clearly indicates the preferred alternative function and maintains backward compatibility while guiding users toward the new multi-path approach.


62-64: Fix TypeScript safety issues with environment variable access

The code has multiple unsafe operations when accessing process.env. Environment variables can be undefined, but the code treats them as strings.

-	const envPaths = (process.env[CLAUDE_CONFIG_DIR_ENV] ?? '').trim();
+	const envPaths = (process.env[CLAUDE_CONFIG_DIR_ENV] ?? '').trim();
	if (envPaths !== '') {
-		const envPathList = envPaths.split(',').map(p => p.trim()).filter(p => p !== '');
+		const envPathList = envPaths.split(',').map((p: string) => p.trim()).filter((p: string) => p !== '');

However, the real issue is the TypeScript configuration is too strict. Consider using proper type assertions:

-	const envPaths = (process.env[CLAUDE_CONFIG_DIR_ENV] ?? '').trim();
+	const envVar = process.env[CLAUDE_CONFIG_DIR_ENV];
+	const envPaths = (envVar ?? '').trim();

Likely an incorrect or invalid review comment.

CLAUDE.md Outdated
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Use proper markdown heading for the new section

The new "Multiple Claude Data Directories" section should follow the file’s established heading conventions (e.g., ## Multiple Claude Data Directories) instead of using bold text.

🤖 Prompt for AI Agents
In CLAUDE.md at line 49, replace the bold text "**Multiple Claude Data
Directories:**" with a proper markdown heading using the established convention,
such as "## Multiple Claude Data Directories". This change will ensure
consistency with the rest of the file's section headings.

Comment on lines 3751 to 3763
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix the failing test by properly mocking the module

The test is failing because the mocking approach isn't working correctly in the test environment. The issue is that vi.doMock doesn't affect already imported modules.

-		it('handles directory existence checks deterministically with mocked isDirectorySync', async () => {
-			const mockIsDirectorySync = vi.fn();
-
-			// Mock the path-type module
-			await vi.importActual('path-type');
-			vi.doMock('path-type', () => ({
-				isDirectorySync: mockIsDirectorySync,
-			}));
+		it('handles directory existence checks deterministically with mocked isDirectorySync', async () => {
+			const { isDirectorySync } = await import('path-type');
+			const mockIsDirectorySync = vi.fn().mockImplementation((path: string) => {
+				if (path === '/mock/path1' || path === '/mock/path1/projects') return true;
+				if (path === '/mock/path2' || path === '/mock/path2/projects') return true;
+				if (path.includes('/mock/nonexistent')) return false;
+				return false;
+			});
+			
+			vi.mocked(isDirectorySync).mockImplementation(mockIsDirectorySync);

Alternatively, consider using a simpler approach by mocking at the function level rather than the entire module.

Committable suggestion skipped: line range outside the PR's diff.

🧰 Tools
🪛 GitHub Check: ci

[failure] 3793-3793: src/data-loader.ts > getClaudePaths > handles directory existence checks deterministically with mocked isDirectorySync
AssertionError: expected [ '/home/runner/.config/claude', …(1) ] to include '/mock/path1'
❯ src/data-loader.ts:3793:18

🪛 ESLint

[error] 3751-3751: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3752-3752: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 3752-3752: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3752-3752: Unsafe member access .fn on an error typed value.

(ts/no-unsafe-member-access)


[error] 3755-3755: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3755-3755: Unsafe member access .importActual on an error typed value.

(ts/no-unsafe-member-access)


[error] 3756-3756: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3756-3756: Unsafe member access .doMock on an error typed value.

(ts/no-unsafe-member-access)


[error] 3757-3757: Unsafe assignment of an error typed value.

(ts/no-unsafe-assignment)


[error] 3765-3765: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3765-3765: Unsafe member access .mockImplementation on an error typed value.

(ts/no-unsafe-member-access)


[error] 3785-3785: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3785-3785: Unsafe member access .stubEnv on an error typed value.

(ts/no-unsafe-member-access)


[error] 3793-3793: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3793-3793: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3793-3793: Unsafe member access .toContain on an error typed value.

(ts/no-unsafe-member-access)


[error] 3793-3793: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3793-3793: Unsafe member access .resolve on an error typed value.

(ts/no-unsafe-member-access)


[error] 3794-3794: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3794-3794: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3794-3794: Unsafe member access .toContain on an error typed value.

(ts/no-unsafe-member-access)


[error] 3794-3794: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3794-3794: Unsafe member access .resolve on an error typed value.

(ts/no-unsafe-member-access)


[error] 3795-3795: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3795-3795: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3795-3795: Unsafe member access .not on an error typed value.

(ts/no-unsafe-member-access)


[error] 3795-3795: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3795-3795: Unsafe member access .resolve on an error typed value.

(ts/no-unsafe-member-access)


[error] 3798-3798: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3798-3798: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3798-3798: Unsafe member access .toHaveBeenCalledWith on an error typed value.

(ts/no-unsafe-member-access)


[error] 3798-3798: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3798-3798: Unsafe member access .resolve on an error typed value.

(ts/no-unsafe-member-access)


[error] 3799-3799: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3799-3799: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3799-3799: Unsafe member access .toHaveBeenCalledWith on an error typed value.

(ts/no-unsafe-member-access)


[error] 3799-3799: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3799-3799: Unsafe member access .resolve on an error typed value.

(ts/no-unsafe-member-access)


[error] 3800-3800: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3800-3800: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3800-3800: Unsafe member access .toHaveBeenCalledWith on an error typed value.

(ts/no-unsafe-member-access)


[error] 3800-3800: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3800-3800: Unsafe member access .resolve on an error typed value.

(ts/no-unsafe-member-access)


[error] 3803-3803: Unsafe call of a(n) error type typed value.

(ts/no-unsafe-call)


[error] 3803-3803: Unsafe member access .doUnmock on an error typed value.

(ts/no-unsafe-member-access)

🪛 GitHub Actions: CI

[error] 3793-3793: Test failure in 'getClaudePaths' - handles directory existence checks deterministically with mocked isDirectorySync: AssertionError: expected [ '/home/runner/.config/claude', …(1) ] to include '/mock/path1'

🤖 Prompt for AI Agents
In src/data-loader.ts around lines 3751 to 3804, the test fails because
vi.doMock does not override already imported modules. To fix this, avoid using
vi.doMock for the entire module; instead, mock only the isDirectorySync function
directly using vi.spyOn or vi.fn before importing the module. This ensures the
mock is applied correctly and the test behaves deterministically. Also, ensure
to reset or restore mocks after the test to avoid side effects.

Add CLAUDE_CONFIG_DIRECTORIES and related constants to support multiple Claude data directories.
- Add getClaudePaths() function to support multiple Claude data directories

- Support environment variable (comma-separated paths)

- Support both new default (~/.config/claude) and old default (~/.claude)

- Implement path normalization and duplicate removal

- Update data loading functions to use multiple paths

- Maintain backward compatibility with getDefaultClaudePath()
- Replace custom ensureArray implementation with @antfu/utils toArray

- Update import paths to use .ts extensions for local modules

- Remove obsolete utils.internal.ts file

- Improve code maintainability and consistency
- Create both ~/.claude/projects and ~/.config/claude/projects in CI

- Ensure tests run correctly with multiple Claude paths in CI environment

- Support testing both legacy and new default Claude directories
- Document multiple Claude data directories support in README

- Update CLAUDE.md with import convention (.ts extensions)

- Explain environment variable and path priority

- Add backward compatibility information

- Update examples and usage instructions
Replace complex mocked test with simpler filesystem-based test

Removes problematic vi.doMock that was causing test failures

Uses real directory checks which are more reliable in CI environment
@ryoppippi ryoppippi force-pushed the feature/multiple-claude-paths branch from ad8b5fc to b3acdf7 Compare June 20, 2025 10:41
@ryoppippi ryoppippi force-pushed the feature/multiple-claude-paths branch from 6f5a129 to b58b655 Compare June 20, 2025 10:43
@ryoppippi ryoppippi merged commit 1b8a8e2 into main Jun 20, 2025
9 checks passed
@ryoppippi ryoppippi deleted the feature/multiple-claude-paths branch June 20, 2025 10:44
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @ryoppippi!
I noticed ClaudeCode_Dashboard was removed from Related Projects in this commit.
Was there any issue with it?
Please let me know if I need to fix anything.
Thank you!

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OMG I failed to create a correct merge commit. I'm sorry
Could you send a PR again?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No problem! I'll send a new PR shortly 😊

ryoppippi added a commit that referenced this pull request Jun 22, 2025
feat: Support multiple Claude data directories to handle v1.0.30+ path change
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.

claude code v1.0.30 changed the path from ~/.claude -> ~/.config/.claude

3 participants