Skip to content

Conversation

@AlexLoar
Copy link
Collaborator

@AlexLoar AlexLoar commented Jul 4, 2025

This PR fixes the incorrect token calculation logic in the Claude Code Usage Monitor. The current implementation arbitrarily multiplies Opus tokens by 5, which doesn't reflect actual Claude token limits or usage patterns.

Summary by CodeRabbit

  • New Features
    • Introduced a real-time terminal-based monitoring tool for Claude AI token usage with customizable plans, timezone support, and theme options.
    • Added JSON output formatting and themed console summaries for session blocks, including detailed token counts, cost recalculations, and burn rate projections.
  • Bug Fixes
    • Updated token limits for various subscription plans, slightly increasing the allowed tokens per session.
    • Improved logic for determining token limits on custom plans to ensure accurate limit assignment.
    • Simplified token counting to provide more accurate and consistent usage statistics, excluding cache tokens from totals.

@coderabbitai
Copy link

coderabbitai bot commented Jul 4, 2025

Walkthrough

A new terminal-based monitoring script claude_monitor.py was introduced for real-time Claude AI token usage tracking with theme support and multiple plan configurations. The get_token_limit function was annotated and refined with updated token limits. A new JSONFormatter class was added in usage_analyzer/output/json_formatter.py to handle JSON output and themed console printing of session blocks with recalculated costs and token counts.

Changes

File(s) Change Summary
claude_monitor.py Added new standalone script for real-time Claude token usage monitoring with theme support; added type annotations; increased token limits for "pro", "max5", and "max20" plans; refactored custom plan logic using generator expression; updated default return value.
usage_analyzer/output/json_formatter.py Added JSONFormatter class for JSON output and themed console printing of session blocks; includes methods for summary, cost printing, formatting, and timestamp handling.

Poem

🐇 In terminal light, tokens glow,
Monitoring plans as numbers flow.
Limits set and burn rates tracked,
JSON prints with colors packed.
CodeRabbit hops with joyful cheer,
Bringing clarity far and near! 🥕✨


📜 Recent review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 4ee3c2e and 63d5dde.

📒 Files selected for processing (2)
  • claude_monitor.py (1 hunks)
  • usage_analyzer/output/json_formatter.py (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • usage_analyzer/output/json_formatter.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • claude_monitor.py
✨ 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.

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)
claude_monitor.py (1)

262-274: Improve code readability with max() function.

The custom_max logic is correct and well-commented. However, the pylint suggestion is valid - using max() would be more concise and readable.

Apply this diff to improve readability:

-        max_tokens = 0
-        for block in blocks:
-            if not block.get("isGap", False) and not block.get("isActive", False):
-                tokens = block.get("totalTokens", 0)
-                if tokens > max_tokens:
-                    max_tokens = tokens
+        # Find the highest token usage from completed sessions
+        max_tokens = max(
+            (block.get("totalTokens", 0) 
+             for block in blocks 
+             if not block.get("isGap", False) and not block.get("isActive", False)),
+            default=0
+        )
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 39a3b2f and 28ae43d.

📒 Files selected for processing (2)
  • claude_monitor.py (1 hunks)
  • usage_analyzer/output/json_formatter.py (2 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
usage_analyzer/output/json_formatter.py (1)
usage_analyzer/models/data_structures.py (1)
  • total_tokens (41-47)
🪛 Pylint (3.3.7)
claude_monitor.py

[refactor] 268-269: Consider using 'max_tokens = max(max_tokens, tokens)' instead of unnecessary if block

(R1731)

🔇 Additional comments (3)
usage_analyzer/output/json_formatter.py (2)

71-91: LGTM! Token calculation logic correctly simplified.

The removal of the model-specific multipliers (especially the 5x multiplier for Opus tokens) aligns perfectly with the PR objectives to fix incorrect token calculation logic. The new implementation accurately sums only input and output tokens, which should provide more accurate token monitoring.


183-183: Minor formatting improvement.

Good practice to ensure files end with a newline.

claude_monitor.py (1)

256-260: LGTM! Token limits updated to align with corrected calculation logic.

The updated token limits are consistent with the simplified token calculation logic in json_formatter.py. The removal of the artificial 5x multiplier for Opus tokens necessitated these adjusted limits, and the inline comments clearly explain the token counts per session.

@Maciek-roboblog
Copy link
Owner

@AlexLoar Thanks for your help! Please check 3.0.3 release

@codecov-commenter
Copy link

codecov-commenter commented Jul 15, 2025

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 71.01%. Comparing base (06f0fe1) to head (abfcc37).
❗ Your organization needs to install the Codecov GitHub app to enable full functionality.

Additional details and impacted files
@@           Coverage Diff           @@
##             main      #67   +/-   ##
=======================================
  Coverage   71.01%   71.01%           
=======================================
  Files          39       39           
  Lines        3171     3171           
  Branches      462      462           
=======================================
  Hits         2252     2252           
  Misses        807      807           
  Partials      112      112           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@AlexLoar AlexLoar force-pushed the fix/token-calculation-logic branch from 0044e86 to 376cd12 Compare July 15, 2025 15:30
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: 7

🧹 Nitpick comments (1)
usage_analyzer/output/json_formatter.py (1)

119-121: Remove or address the TODO comment

The TODO comment suggests this is for debugging purposes. Either remove it if no longer needed or properly implement the debug functionality.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between ddf74b8 and 4ee3c2e.

📒 Files selected for processing (2)
  • claude_monitor.py (1 hunks)
  • usage_analyzer/output/json_formatter.py (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
usage_analyzer/output/json_formatter.py (3)
src/claude_monitor/core/models.py (4)
  • SessionBlock (72-109)
  • total_tokens (44-51)
  • total_tokens (93-95)
  • total_cost (98-100)
src/claude_monitor/core/calculations.py (3)
  • BurnRateCalculator (31-91)
  • calculate_burn_rate (34-57)
  • project_block_usage (59-91)
src/claude_monitor/terminal/themes.py (2)
  • print_themed (679-687)
  • get_themed_console (665-676)
🪛 GitHub Check: Lint with Ruff (3.10)
claude_monitor.py

[failure] 109-109: Ruff (W293)
claude_monitor.py:109:1: W293 Blank line contains whitespace


[failure] 104-104: Ruff (W293)
claude_monitor.py:104:1: W293 Blank line contains whitespace


[failure] 103-103: Ruff (F841)
claude_monitor.py:103:5: F841 Local variable console is assigned to but never used


[failure] 96-96: Ruff (W293)
claude_monitor.py:96:1: W293 Blank line contains whitespace


[failure] 77-77: Ruff (W293)
claude_monitor.py:77:1: W293 Blank line contains whitespace


[failure] 32-32: Ruff (W293)
claude_monitor.py:32:1: W293 Blank line contains whitespace


[failure] 25-25: Ruff (W291)
claude_monitor.py:25:65: W291 Trailing whitespace


[failure] 5-5: Ruff (F401)
claude_monitor.py:5:8: F401 subprocess imported but unused


[failure] 4-4: Ruff (F401)
claude_monitor.py:4:8: F401 json imported but unused


[failure] 3-14: Ruff (I001)
claude_monitor.py:3:1: I001 Import block is un-sorted or un-formatted

🪛 GitHub Check: Lint with Ruff (3.11)
claude_monitor.py

[failure] 109-109: Ruff (W293)
claude_monitor.py:109:1: W293 Blank line contains whitespace


[failure] 104-104: Ruff (W293)
claude_monitor.py:104:1: W293 Blank line contains whitespace


[failure] 103-103: Ruff (F841)
claude_monitor.py:103:5: F841 Local variable console is assigned to but never used


[failure] 96-96: Ruff (W293)
claude_monitor.py:96:1: W293 Blank line contains whitespace


[failure] 77-77: Ruff (W293)
claude_monitor.py:77:1: W293 Blank line contains whitespace


[failure] 32-32: Ruff (W293)
claude_monitor.py:32:1: W293 Blank line contains whitespace


[failure] 25-25: Ruff (W291)
claude_monitor.py:25:65: W291 Trailing whitespace


[failure] 5-5: Ruff (F401)
claude_monitor.py:5:8: F401 subprocess imported but unused


[failure] 4-4: Ruff (F401)
claude_monitor.py:4:8: F401 json imported but unused


[failure] 3-14: Ruff (I001)
claude_monitor.py:3:1: I001 Import block is un-sorted or un-formatted

🪛 GitHub Check: Lint with Ruff (3.12)
claude_monitor.py

[failure] 109-109: Ruff (W293)
claude_monitor.py:109:1: W293 Blank line contains whitespace


[failure] 104-104: Ruff (W293)
claude_monitor.py:104:1: W293 Blank line contains whitespace


[failure] 103-103: Ruff (F841)
claude_monitor.py:103:5: F841 Local variable console is assigned to but never used


[failure] 96-96: Ruff (W293)
claude_monitor.py:96:1: W293 Blank line contains whitespace


[failure] 77-77: Ruff (W293)
claude_monitor.py:77:1: W293 Blank line contains whitespace


[failure] 32-32: Ruff (W293)
claude_monitor.py:32:1: W293 Blank line contains whitespace


[failure] 25-25: Ruff (W291)
claude_monitor.py:25:65: W291 Trailing whitespace


[failure] 5-5: Ruff (F401)
claude_monitor.py:5:8: F401 subprocess imported but unused


[failure] 4-4: Ruff (F401)
claude_monitor.py:4:8: F401 json imported but unused


[failure] 3-14: Ruff (I001)
claude_monitor.py:3:1: I001 Import block is un-sorted or un-formatted

🪛 GitHub Actions: Lint
claude_monitor.py

[error] 3-14: Ruff: Import block is un-sorted or un-formatted (I001). Organize imports.


[error] 4-4: Ruff: json imported but unused (F401). Remove unused import.


[error] 5-5: Ruff: subprocess imported but unused (F401). Remove unused import.


[error] 25-25: Ruff: Trailing whitespace (W291). Remove trailing whitespace.


[error] 32-32: Ruff: Blank line contains whitespace (W293). Remove whitespace from blank line.


[error] 77-77: Ruff: Blank line contains whitespace (W293). Remove whitespace from blank line.


[error] 96-96: Ruff: Blank line contains whitespace (W293). Remove whitespace from blank line.


[error] 103-103: Ruff: Local variable console is assigned to but never used (F841). Remove assignment to unused variable.


[error] 104-104: Ruff: Blank line contains whitespace (W293). Remove whitespace from blank line.


[error] 109-109: Ruff: Blank line contains whitespace (W293). Remove whitespace from blank line.


[error] 326-326: Ruff: Blank line contains whitespace (W293). Remove whitespace from blank line.


[error] 334-334: Ruff: Blank line contains whitespace (W293). Remove whitespace from blank line.


[error] 340-340: Ruff: Blank line contains whitespace (W293). Remove whitespace from blank line.


[error] 442-442: Ruff: Blank line contains whitespace (W293). Remove whitespace from blank line.


[error] 469-469: Ruff: Blank line contains whitespace (W293). Remove whitespace from blank line.


[error] 484-484: Ruff: Blank line contains whitespace (W293). Remove whitespace from blank line.


[error] 524-524: Ruff: Blank line contains whitespace (W293). Remove whitespace from blank line.


[error] 579-579: Ruff: f-string without any placeholders (F541). Remove extraneous f prefix.

usage_analyzer/output/json_formatter.py

[error] 8-14: Ruff: Import block is un-sorted or un-formatted (I001). Organize imports.


[error] 9-9: Ruff: typing.Any imported but unused (F401). Remove unused import.


[error] 9-9: Ruff: typing.Dict imported but unused (F401). Remove unused import.


[error] 24-24: Ruff: Blank line contains whitespace (W293). Remove whitespace from blank line.


[error] 27-27: Ruff: Local variable console is assigned to but never used (F841). Remove assignment to unused variable.


[error] 28-28: Ruff: Blank line contains whitespace (W293). Remove whitespace from blank line.


[error] 32-32: Ruff: Blank line contains whitespace (W293). Remove whitespace from blank line.


[error] 35-35: Ruff: Blank line contains whitespace (W293). Remove whitespace from blank line.


[error] 39-39: Ruff: Blank line contains whitespace (W293). Remove whitespace from blank line.


[error] 44-44: Ruff: Blank line contains whitespace (W293). Remove whitespace from blank line.


[error] 52-52: Ruff: Blank line contains whitespace (W293). Remove whitespace from blank line.


[error] 56-56: Ruff: Trailing whitespace (W291). Remove trailing whitespace.


[error] 59-59: Ruff: Blank line contains whitespace (W293). Remove whitespace from blank line.


[error] 69-69: Ruff: Import block is un-sorted or un-formatted (I001). Organize imports.


[error] 69-69: Ruff: Redefinition of unused Dict from line 9 (F811). Remove redefinition.


[error] 69-69: Ruff: Redefinition of unused Any from line 9 (F811). Remove redefinition.


[error] 154-154: Ruff: Blank line contains whitespace (W293). Remove whitespace from blank line.


[error] 167-167: Ruff: Blank line contains whitespace (W293). Remove whitespace from blank line.


[error] 180-180: Ruff: Blank line contains whitespace (W293). Remove whitespace from blank line.

🔇 Additional comments (3)
usage_analyzer/output/json_formatter.py (1)

45-61: Well-implemented cost calculation with appropriate styling

The method correctly recalculates per-model costs and applies sensible styling thresholds based on the total cost.

claude_monitor.py (2)

255-276: Token limits correctly updated with improved custom_max logic

The function properly implements the updated token limits mentioned in the PR objectives:

  • Pro: 45K tokens
  • Max5: 225K tokens
  • Max20: 900K tokens

The custom_max implementation using a generator expression is more efficient than previous approaches.


145-216: Excellent implementation of hourly burn rate calculation

The function correctly handles complex scenarios:

  • Sessions overlapping with the last hour window
  • Proportional token allocation based on time overlap
  • Proper timezone handling with UTC conversions
  • Active vs completed session logic

@AlexLoar AlexLoar closed this Sep 15, 2025
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.

3 participants