claude-code-usage 1.0.0__py3-none-any.whl → 1.0.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {claude_code_usage-1.0.0.dist-info → claude_code_usage-1.0.2.dist-info}/METADATA +23 -26
- claude_code_usage-1.0.2.dist-info/RECORD +15 -0
- claude_code_usage-1.0.2.dist-info/entry_points.txt +2 -0
- src/api.py +5 -4
- src/autostart.py +41 -16
- src/icon_generator.py +22 -2
- claude_code_usage-1.0.0.dist-info/RECORD +0 -15
- claude_code_usage-1.0.0.dist-info/entry_points.txt +0 -5
- {claude_code_usage-1.0.0.dist-info → claude_code_usage-1.0.2.dist-info}/WHEEL +0 -0
- {claude_code_usage-1.0.0.dist-info → claude_code_usage-1.0.2.dist-info}/licenses/LICENSE +0 -0
- {claude_code_usage-1.0.0.dist-info → claude_code_usage-1.0.2.dist-info}/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: claude-code-usage
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.2
|
|
4
4
|
Summary: System tray monitor for Claude Code token usage
|
|
5
5
|
Author: Max
|
|
6
6
|
License: MIT
|
|
@@ -28,6 +28,7 @@ Dynamic: license-file
|
|
|
28
28
|
|
|
29
29
|
A Linux/GNOME system tray application that monitors your Claude Code token usage and alerts you before hitting limits.
|
|
30
30
|
|
|
31
|
+
[](https://pypi.org/project/claude-code-usage/)
|
|
31
32
|

|
|
32
33
|

|
|
33
34
|

|
|
@@ -73,7 +74,20 @@ Install the [AppIndicator Support](https://extensions.gnome.org/extension/615/ap
|
|
|
73
74
|
|
|
74
75
|
## Installation
|
|
75
76
|
|
|
76
|
-
###
|
|
77
|
+
### From PyPI (recommended)
|
|
78
|
+
|
|
79
|
+
1. Install system dependencies (see [System Dependencies](#system-dependencies) above)
|
|
80
|
+
|
|
81
|
+
2. Install with pipx (recommended):
|
|
82
|
+
```bash
|
|
83
|
+
pipx install claude-code-usage --system-site-packages
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
The `--system-site-packages` flag is required to access system GTK libraries.
|
|
87
|
+
|
|
88
|
+
3. Run: `claude-usage`
|
|
89
|
+
|
|
90
|
+
### From Source
|
|
77
91
|
|
|
78
92
|
```bash
|
|
79
93
|
git clone https://github.com/Maex-z9/CC_Usage.git
|
|
@@ -81,32 +95,15 @@ cd CC_Usage
|
|
|
81
95
|
./install.sh
|
|
82
96
|
```
|
|
83
97
|
|
|
84
|
-
This installs system dependencies and the app.
|
|
85
|
-
|
|
86
|
-
### Manual Install
|
|
87
|
-
|
|
88
|
-
1. Install system dependencies:
|
|
89
|
-
```bash
|
|
90
|
-
# Ubuntu/Debian
|
|
91
|
-
sudo apt install python3-gi python3-gi-cairo gir1.2-ayatanaappindicator3-0.1 gir1.2-notify-0.7
|
|
98
|
+
This installs system dependencies and the app automatically.
|
|
92
99
|
|
|
93
|
-
|
|
94
|
-
sudo dnf install python3-gobject python3-cairo libayatana-appindicator-gtk3 libnotify
|
|
100
|
+
### Prerequisites
|
|
95
101
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
```bash
|
|
102
|
-
pip install git+https://github.com/Maex-z9/CC_Usage.git
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
3. Authenticate with Claude Code (if not already done):
|
|
106
|
-
```bash
|
|
107
|
-
claude
|
|
108
|
-
# Follow the authentication flow
|
|
109
|
-
```
|
|
102
|
+
Make sure you have Claude Code CLI installed and authenticated:
|
|
103
|
+
```bash
|
|
104
|
+
claude
|
|
105
|
+
# Follow the authentication flow
|
|
106
|
+
```
|
|
110
107
|
|
|
111
108
|
## Usage
|
|
112
109
|
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
claude_code_usage-1.0.2.dist-info/licenses/LICENSE,sha256=alXcUJ2-k8eqG_Amt8y9Hhlb8fT1nABafZOqWDmdzUw,1060
|
|
2
|
+
src/__init__.py,sha256=rzeXYIMbNbWPF6gpjv7luGXLZA67r_5GU5ZGUNb8pKA,27
|
|
3
|
+
src/api.py,sha256=IymlJFR7_Ou5I_Asij8oyR2b7bx9WurBtREwcysbiJQ,6168
|
|
4
|
+
src/autostart.py,sha256=Xo0JcjUJ8RZ-pervQ6f8mQAxngO73Rf-IDdg0uWzlKw,3369
|
|
5
|
+
src/config.py,sha256=_PIPM7wfbQq1c7tHT26_L39PXbLVQWuzxaB2FMWiavw,5300
|
|
6
|
+
src/icon_generator.py,sha256=h1xJtzjjJp958ulmsla5DOyutOVTR1Q_0T2ymlO1IEk,3537
|
|
7
|
+
src/main.py,sha256=A7Ej5kqbtOYWUGSuZxx6bM-7WNimjjAs--04_kvvta0,506
|
|
8
|
+
src/notifier.py,sha256=3j5ZmhaFMfv5XDLMCFaOgSCCw5jffn4N6dNz2R7gd8I,10267
|
|
9
|
+
src/tray.py,sha256=sCvQLsNdm3uBtdeNGzFmLxzLT1h1w_LH4ZsajZIlg4I,10995
|
|
10
|
+
src/utils.py,sha256=ZqGvw-oyzHompxRMUeYT5FdJFaQ6uvoAthhu-3bPGJk,893
|
|
11
|
+
claude_code_usage-1.0.2.dist-info/METADATA,sha256=LkcegPyA4MNkqfcAmfziXL-MgppRK4TWRG_nfBkbZTM,5568
|
|
12
|
+
claude_code_usage-1.0.2.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
13
|
+
claude_code_usage-1.0.2.dist-info/entry_points.txt,sha256=MY_VQ3t41-QKCQuBjBsd4ug0uOUlCz1Hz-OyK78gfns,47
|
|
14
|
+
claude_code_usage-1.0.2.dist-info/top_level.txt,sha256=74rtVfumQlgAPzR5_2CgYN24MB0XARCg0t-gzk6gTrM,4
|
|
15
|
+
claude_code_usage-1.0.2.dist-info/RECORD,,
|
src/api.py
CHANGED
|
@@ -63,7 +63,9 @@ def fetch_usage(access_token: str) -> UsageData:
|
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
try:
|
|
66
|
-
response = requests.get(
|
|
66
|
+
response = requests.get(
|
|
67
|
+
USAGE_ENDPOINT, headers=headers, timeout=10, verify=True
|
|
68
|
+
)
|
|
67
69
|
except requests.RequestException as e:
|
|
68
70
|
raise APIError(f"Network error: {e}")
|
|
69
71
|
|
|
@@ -113,9 +115,8 @@ def fetch_usage(access_token: str) -> UsageData:
|
|
|
113
115
|
raise APIError(f"Server error: {response.status_code}")
|
|
114
116
|
|
|
115
117
|
else:
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
)
|
|
118
|
+
# Don't expose response body - may contain sensitive server info
|
|
119
|
+
raise APIError(f"Unexpected response: {response.status_code}")
|
|
119
120
|
|
|
120
121
|
|
|
121
122
|
def fetch_with_retry(access_token: str, max_retries: int = 3) -> UsageData:
|
src/autostart.py
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
"""Autostart management for Claude Usage Overlay."""
|
|
2
2
|
|
|
3
3
|
import os
|
|
4
|
+
import shutil
|
|
5
|
+
from configparser import ConfigParser
|
|
4
6
|
from pathlib import Path
|
|
5
7
|
|
|
6
8
|
|
|
@@ -31,6 +33,28 @@ def get_desktop_file_path() -> Path:
|
|
|
31
33
|
return get_autostart_path() / 'claude-usage-overlay.desktop'
|
|
32
34
|
|
|
33
35
|
|
|
36
|
+
def _get_exec_command() -> str:
|
|
37
|
+
"""Determine the best Exec command for the .desktop file.
|
|
38
|
+
|
|
39
|
+
Returns:
|
|
40
|
+
Command string for Exec= line, preferring installed entry point
|
|
41
|
+
"""
|
|
42
|
+
# Prefer the installed 'claude-usage' command if available
|
|
43
|
+
claude_usage_path = shutil.which("claude-usage")
|
|
44
|
+
if claude_usage_path:
|
|
45
|
+
return claude_usage_path
|
|
46
|
+
|
|
47
|
+
# Fallback to running module directly with python
|
|
48
|
+
project_root = Path(__file__).parent.parent.absolute()
|
|
49
|
+
main_py = project_root / "src" / "main.py"
|
|
50
|
+
if main_py.exists():
|
|
51
|
+
# Use sys.executable equivalent for current python
|
|
52
|
+
return f"python3 -m src.main"
|
|
53
|
+
|
|
54
|
+
# Last resort: assume it's installed as module
|
|
55
|
+
return "python3 -m src.main"
|
|
56
|
+
|
|
57
|
+
|
|
34
58
|
def create_autostart_entry(enable: bool = True):
|
|
35
59
|
"""Create or update autostart .desktop file.
|
|
36
60
|
|
|
@@ -39,9 +63,8 @@ def create_autostart_entry(enable: bool = True):
|
|
|
39
63
|
"""
|
|
40
64
|
desktop_file = get_desktop_file_path()
|
|
41
65
|
|
|
42
|
-
# Get
|
|
43
|
-
|
|
44
|
-
exec_path = f"/usr/bin/python3 {project_root}/src/main.py"
|
|
66
|
+
# Get best exec command (prefer installed entry point)
|
|
67
|
+
exec_cmd = _get_exec_command()
|
|
45
68
|
|
|
46
69
|
# Desktop entry content
|
|
47
70
|
hidden_value = "false" if enable else "true"
|
|
@@ -50,7 +73,7 @@ Type=Application
|
|
|
50
73
|
Version=1.0
|
|
51
74
|
Name=Claude Code Usage Monitor
|
|
52
75
|
Comment=System tray monitor for Claude Code token usage
|
|
53
|
-
Exec={
|
|
76
|
+
Exec={exec_cmd}
|
|
54
77
|
Icon=dialog-information
|
|
55
78
|
Terminal=false
|
|
56
79
|
Categories=Utility;Monitor;
|
|
@@ -59,9 +82,10 @@ X-GNOME-Autostart-enabled=true
|
|
|
59
82
|
Hidden={hidden_value}
|
|
60
83
|
"""
|
|
61
84
|
|
|
62
|
-
# Write .desktop file
|
|
85
|
+
# Write .desktop file with secure permissions (rw-r--r--)
|
|
86
|
+
# .desktop files don't need execute bit - they're parsed by desktop environment
|
|
63
87
|
desktop_file.write_text(content)
|
|
64
|
-
desktop_file.chmod(
|
|
88
|
+
desktop_file.chmod(0o644)
|
|
65
89
|
|
|
66
90
|
|
|
67
91
|
def remove_autostart_entry():
|
|
@@ -82,13 +106,14 @@ def is_autostart_enabled() -> bool:
|
|
|
82
106
|
if not desktop_file.exists():
|
|
83
107
|
return False
|
|
84
108
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
109
|
+
# Use configparser for proper INI parsing
|
|
110
|
+
parser = ConfigParser(interpolation=None)
|
|
111
|
+
try:
|
|
112
|
+
parser.read(desktop_file)
|
|
113
|
+
# Desktop files use 'Desktop Entry' section
|
|
114
|
+
# Hidden=true means disabled; absent or false means enabled
|
|
115
|
+
hidden = parser.get('Desktop Entry', 'Hidden', fallback='false')
|
|
116
|
+
return hidden.lower() != 'true'
|
|
117
|
+
except Exception:
|
|
118
|
+
# If parsing fails, assume enabled if file exists
|
|
119
|
+
return True
|
src/icon_generator.py
CHANGED
|
@@ -6,8 +6,27 @@ Generates circular gauge icons using Cairo for system tray display.
|
|
|
6
6
|
import cairo
|
|
7
7
|
import math
|
|
8
8
|
import os
|
|
9
|
+
import tempfile
|
|
10
|
+
from pathlib import Path
|
|
9
11
|
from typing import Tuple
|
|
10
12
|
|
|
13
|
+
# Secure temp directory for icons (created once, reused)
|
|
14
|
+
_icon_temp_dir: str | None = None
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def _get_secure_icon_dir() -> str:
|
|
18
|
+
"""Get or create a secure temporary directory for icon files.
|
|
19
|
+
|
|
20
|
+
Returns:
|
|
21
|
+
Path to secure temp directory with restricted permissions (0o700)
|
|
22
|
+
"""
|
|
23
|
+
global _icon_temp_dir
|
|
24
|
+
if _icon_temp_dir is None or not Path(_icon_temp_dir).exists():
|
|
25
|
+
# Create secure temp directory owned by current user only
|
|
26
|
+
_icon_temp_dir = tempfile.mkdtemp(prefix="claude-usage-icons-")
|
|
27
|
+
os.chmod(_icon_temp_dir, 0o700)
|
|
28
|
+
return _icon_temp_dir
|
|
29
|
+
|
|
11
30
|
|
|
12
31
|
def get_color_for_percentage(percentage: float) -> Tuple[float, float, float]:
|
|
13
32
|
"""
|
|
@@ -85,8 +104,9 @@ def generate_gauge_icon(percentage: float, color_percentage: float, size: int =
|
|
|
85
104
|
ctx.arc(center, center, radius, -math.pi / 2, end_angle)
|
|
86
105
|
ctx.stroke()
|
|
87
106
|
|
|
88
|
-
# Save to
|
|
89
|
-
|
|
107
|
+
# Save to secure temp directory with unique filename (bust GTK icon cache)
|
|
108
|
+
icon_dir = _get_secure_icon_dir()
|
|
109
|
+
icon_path = os.path.join(icon_dir, f"gauge-{int(percentage)}-{color_name}.png")
|
|
90
110
|
surface.write_to_png(icon_path)
|
|
91
111
|
|
|
92
112
|
return os.path.abspath(icon_path)
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
claude_code_usage-1.0.0.dist-info/licenses/LICENSE,sha256=alXcUJ2-k8eqG_Amt8y9Hhlb8fT1nABafZOqWDmdzUw,1060
|
|
2
|
-
src/__init__.py,sha256=rzeXYIMbNbWPF6gpjv7luGXLZA67r_5GU5ZGUNb8pKA,27
|
|
3
|
-
src/api.py,sha256=IChRjcU8vqmiQ64YOQRXiQi8DSNxvknD4Y4mVOwH01g,6100
|
|
4
|
-
src/autostart.py,sha256=2Rnsr1y_yXbwwARnoYJl5_uQfMch8XsD7vgJi2CfTII,2399
|
|
5
|
-
src/config.py,sha256=_PIPM7wfbQq1c7tHT26_L39PXbLVQWuzxaB2FMWiavw,5300
|
|
6
|
-
src/icon_generator.py,sha256=Ljwhrj9ezqJSLspLu2DlmJGbfvcOLJnW50O-4J3gwKE,2861
|
|
7
|
-
src/main.py,sha256=A7Ej5kqbtOYWUGSuZxx6bM-7WNimjjAs--04_kvvta0,506
|
|
8
|
-
src/notifier.py,sha256=3j5ZmhaFMfv5XDLMCFaOgSCCw5jffn4N6dNz2R7gd8I,10267
|
|
9
|
-
src/tray.py,sha256=sCvQLsNdm3uBtdeNGzFmLxzLT1h1w_LH4ZsajZIlg4I,10995
|
|
10
|
-
src/utils.py,sha256=ZqGvw-oyzHompxRMUeYT5FdJFaQ6uvoAthhu-3bPGJk,893
|
|
11
|
-
claude_code_usage-1.0.0.dist-info/METADATA,sha256=tbz_u_pwUI_L31RgUWMCvrIAmkIltnjCKUimCLhyUTA,5613
|
|
12
|
-
claude_code_usage-1.0.0.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
13
|
-
claude_code_usage-1.0.0.dist-info/entry_points.txt,sha256=sRUb89gemjebLTvCQVv6TJWunjYrD-i_it3A3E9bJVc,95
|
|
14
|
-
claude_code_usage-1.0.0.dist-info/top_level.txt,sha256=74rtVfumQlgAPzR5_2CgYN24MB0XARCg0t-gzk6gTrM,4
|
|
15
|
-
claude_code_usage-1.0.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|