claude-code-usage 1.0.2__py3-none-any.whl → 2.0.0__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.2.dist-info → claude_code_usage-2.0.0.dist-info}/METADATA +18 -8
- claude_code_usage-2.0.0.dist-info/RECORD +15 -0
- {claude_code_usage-1.0.2.dist-info → claude_code_usage-2.0.0.dist-info}/WHEEL +1 -1
- claude_code_usage-2.0.0.dist-info/entry_points.txt +5 -0
- src/autostart.py +268 -34
- src/config.py +35 -14
- src/icon_generator.py +66 -58
- src/notifier.py +95 -82
- src/tray.py +127 -198
- claude_code_usage-1.0.2.dist-info/RECORD +0 -15
- claude_code_usage-1.0.2.dist-info/entry_points.txt +0 -2
- {claude_code_usage-1.0.2.dist-info/licenses → claude_code_usage-2.0.0.dist-info}/LICENSE +0 -0
- {claude_code_usage-1.0.2.dist-info → claude_code_usage-2.0.0.dist-info}/top_level.txt +0 -0
src/tray.py
CHANGED
|
@@ -1,25 +1,26 @@
|
|
|
1
1
|
"""
|
|
2
2
|
System tray indicator for Claude Code usage overlay.
|
|
3
3
|
|
|
4
|
+
Cross-platform: uses pystray for Windows, macOS, and Linux.
|
|
5
|
+
|
|
4
6
|
Displays usage data via:
|
|
5
|
-
- System tray icon with color-coded gauge (green/yellow/
|
|
6
|
-
-
|
|
7
|
+
- System tray icon with color-coded gauge (green/yellow/red)
|
|
8
|
+
- Tooltip showing compact status (e.g., "Session: 45% | Weekly: 67%")
|
|
7
9
|
- Dropdown menu with detailed usage info and reset times
|
|
8
10
|
|
|
9
|
-
Note:
|
|
10
|
-
|
|
11
|
+
Note: Panel labels (text next to icon) are not supported by pystray.
|
|
12
|
+
Tooltip is used instead for quick status display.
|
|
11
13
|
"""
|
|
12
|
-
import gi
|
|
13
|
-
|
|
14
|
-
gi.require_version('AyatanaAppIndicator3', '0.1')
|
|
15
|
-
gi.require_version('Gtk', '3.0')
|
|
16
|
-
from gi.repository import AyatanaAppIndicator3 as AppIndicator3, Gtk, GLib
|
|
17
14
|
import sys
|
|
15
|
+
import threading
|
|
16
|
+
from typing import Optional
|
|
17
|
+
|
|
18
|
+
import pystray
|
|
18
19
|
|
|
19
20
|
from src.icon_generator import generate_gauge_icon
|
|
20
21
|
from src.utils import format_time_until
|
|
21
22
|
from src.config import get_access_token, UserConfig, get_config_path
|
|
22
|
-
from src.api import fetch_with_retry, APIError, AuthenticationError
|
|
23
|
+
from src.api import fetch_with_retry, APIError, AuthenticationError, UsageData
|
|
23
24
|
from src.notifier import UsageNotifier
|
|
24
25
|
from src.autostart import create_autostart_entry, is_autostart_enabled, remove_autostart_entry
|
|
25
26
|
|
|
@@ -27,14 +28,12 @@ from src.autostart import create_autostart_entry, is_autostart_enabled, remove_a
|
|
|
27
28
|
class TrayIndicator:
|
|
28
29
|
"""System tray indicator for Claude Code usage."""
|
|
29
30
|
|
|
30
|
-
APPINDICATOR_ID = 'claude-usage-overlay'
|
|
31
|
-
|
|
32
31
|
def __init__(self):
|
|
33
32
|
"""Initialize the tray indicator."""
|
|
34
|
-
self.usage_data = None
|
|
35
|
-
self.
|
|
36
|
-
self.
|
|
37
|
-
self.
|
|
33
|
+
self.usage_data: Optional[UsageData] = None
|
|
34
|
+
self.icon: Optional[pystray.Icon] = None
|
|
35
|
+
self._stop_event = threading.Event()
|
|
36
|
+
self._update_thread: Optional[threading.Thread] = None
|
|
38
37
|
|
|
39
38
|
# Load configuration
|
|
40
39
|
self.config = UserConfig.load()
|
|
@@ -47,42 +46,71 @@ class TrayIndicator:
|
|
|
47
46
|
|
|
48
47
|
self._setup_indicator()
|
|
49
48
|
|
|
50
|
-
# Defer initial update and timer start until GTK main loop is running
|
|
51
|
-
# This ensures the UI is fully initialized before we update it
|
|
52
|
-
GLib.idle_add(self._initial_update)
|
|
53
|
-
|
|
54
49
|
def _setup_indicator(self):
|
|
55
|
-
"""Set up the
|
|
56
|
-
# Create initial icon at 0% fill with green color
|
|
50
|
+
"""Set up the pystray icon with initial state."""
|
|
51
|
+
# Create initial icon at 0% fill with green color
|
|
57
52
|
initial_icon = generate_gauge_icon(0, 0)
|
|
58
53
|
|
|
59
|
-
# Create
|
|
60
|
-
self.
|
|
61
|
-
|
|
62
|
-
initial_icon,
|
|
63
|
-
|
|
54
|
+
# Create pystray Icon
|
|
55
|
+
self.icon = pystray.Icon(
|
|
56
|
+
name="claude-usage-overlay",
|
|
57
|
+
icon=initial_icon,
|
|
58
|
+
title="Claude Usage: Loading...",
|
|
59
|
+
menu=self._build_menu()
|
|
64
60
|
)
|
|
65
|
-
self.indicator.set_status(AppIndicator3.IndicatorStatus.ACTIVE)
|
|
66
|
-
|
|
67
|
-
# Set initial label while loading
|
|
68
|
-
self.indicator.set_label("...", "100%|100%")
|
|
69
61
|
|
|
70
|
-
|
|
71
|
-
menu
|
|
72
|
-
loading_item = Gtk.MenuItem(label="Loading...")
|
|
73
|
-
loading_item.set_sensitive(False)
|
|
74
|
-
menu.append(loading_item)
|
|
75
|
-
menu.show_all()
|
|
76
|
-
|
|
77
|
-
self.menu = menu
|
|
78
|
-
self.indicator.set_menu(menu)
|
|
79
|
-
|
|
80
|
-
def _update_usage(self) -> bool:
|
|
81
|
-
"""Fetch usage data and refresh display.
|
|
62
|
+
def _build_menu(self) -> pystray.Menu:
|
|
63
|
+
"""Build the dropdown menu with usage info and actions.
|
|
82
64
|
|
|
83
65
|
Returns:
|
|
84
|
-
|
|
66
|
+
pystray.Menu: The constructed menu
|
|
85
67
|
"""
|
|
68
|
+
# Usage line (shows current percentages or loading state)
|
|
69
|
+
if self.usage_data is not None:
|
|
70
|
+
session_percent = self.usage_data.session_percent
|
|
71
|
+
weekly_percent = self.usage_data.weekly_percent
|
|
72
|
+
usage_text = f"Session: {session_percent:.0f}% | Weekly: {weekly_percent:.0f}%"
|
|
73
|
+
reset_time_str = format_time_until(self.usage_data.session_resets_at)
|
|
74
|
+
reset_text = f"Resets in {reset_time_str}"
|
|
75
|
+
else:
|
|
76
|
+
usage_text = "Loading..."
|
|
77
|
+
reset_text = ""
|
|
78
|
+
|
|
79
|
+
menu_items = [
|
|
80
|
+
pystray.MenuItem(usage_text, None, enabled=False),
|
|
81
|
+
]
|
|
82
|
+
|
|
83
|
+
if reset_text:
|
|
84
|
+
menu_items.append(pystray.MenuItem(reset_text, None, enabled=False))
|
|
85
|
+
|
|
86
|
+
menu_items.extend([
|
|
87
|
+
pystray.Menu.SEPARATOR,
|
|
88
|
+
pystray.MenuItem("Refresh", self._on_refresh_clicked),
|
|
89
|
+
pystray.MenuItem(
|
|
90
|
+
"Settings",
|
|
91
|
+
pystray.Menu(
|
|
92
|
+
pystray.MenuItem(
|
|
93
|
+
"Pause Notifications",
|
|
94
|
+
self._on_pause_toggled,
|
|
95
|
+
checked=lambda item: self.config.pause_notifications
|
|
96
|
+
),
|
|
97
|
+
pystray.MenuItem(
|
|
98
|
+
"Autostart on Login",
|
|
99
|
+
self._on_autostart_toggled,
|
|
100
|
+
checked=lambda item: is_autostart_enabled()
|
|
101
|
+
),
|
|
102
|
+
pystray.Menu.SEPARATOR,
|
|
103
|
+
pystray.MenuItem("Edit Config File...", self._on_edit_config_clicked),
|
|
104
|
+
)
|
|
105
|
+
),
|
|
106
|
+
pystray.Menu.SEPARATOR,
|
|
107
|
+
pystray.MenuItem("Quit", self._on_quit_clicked),
|
|
108
|
+
])
|
|
109
|
+
|
|
110
|
+
return pystray.Menu(*menu_items)
|
|
111
|
+
|
|
112
|
+
def _update_usage(self):
|
|
113
|
+
"""Fetch usage data and refresh display."""
|
|
86
114
|
try:
|
|
87
115
|
token = get_access_token()
|
|
88
116
|
self.usage_data = fetch_with_retry(token)
|
|
@@ -91,53 +119,18 @@ class TrayIndicator:
|
|
|
91
119
|
except AuthenticationError as e:
|
|
92
120
|
error_msg = f"Authentication failed: {e}"
|
|
93
121
|
print(error_msg, file=sys.stderr)
|
|
94
|
-
self.
|
|
122
|
+
if self.icon:
|
|
123
|
+
self.icon.title = error_msg
|
|
95
124
|
|
|
96
125
|
except (APIError, ValueError, FileNotFoundError) as e:
|
|
97
126
|
error_msg = f"Error: {e}"
|
|
98
127
|
print(error_msg, file=sys.stderr)
|
|
99
|
-
self.
|
|
100
|
-
|
|
101
|
-
# Return GLib.SOURCE_CONTINUE to keep timer running
|
|
102
|
-
return GLib.SOURCE_CONTINUE
|
|
103
|
-
|
|
104
|
-
def _initial_update(self):
|
|
105
|
-
"""Perform initial update after GTK main loop starts.
|
|
106
|
-
|
|
107
|
-
Sets loading label, then defers the API call to give GTK time to render.
|
|
108
|
-
|
|
109
|
-
Returns:
|
|
110
|
-
GLib.SOURCE_REMOVE to run only once
|
|
111
|
-
"""
|
|
112
|
-
# Set loading label now that main loop is running
|
|
113
|
-
self.indicator.set_label("...", "100%|100%")
|
|
114
|
-
|
|
115
|
-
# Defer API call with small timeout so GTK can render the loading label
|
|
116
|
-
GLib.timeout_add(50, self._do_initial_fetch) # 50ms delay
|
|
117
|
-
return GLib.SOURCE_REMOVE
|
|
118
|
-
|
|
119
|
-
def _do_initial_fetch(self):
|
|
120
|
-
"""Fetch initial data and start update timer.
|
|
121
|
-
|
|
122
|
-
Returns:
|
|
123
|
-
GLib.SOURCE_REMOVE to run only once
|
|
124
|
-
"""
|
|
125
|
-
self._update_usage()
|
|
126
|
-
self._start_update_timer()
|
|
127
|
-
return GLib.SOURCE_REMOVE
|
|
128
|
-
|
|
129
|
-
def _start_update_timer(self):
|
|
130
|
-
"""Start or restart periodic update timer with config interval."""
|
|
131
|
-
if self.timer_id is not None:
|
|
132
|
-
GLib.source_remove(self.timer_id)
|
|
133
|
-
self.timer_id = GLib.timeout_add_seconds(
|
|
134
|
-
self.config.polling_interval,
|
|
135
|
-
self._update_usage
|
|
136
|
-
)
|
|
128
|
+
if self.icon:
|
|
129
|
+
self.icon.title = error_msg
|
|
137
130
|
|
|
138
131
|
def _refresh_display(self):
|
|
139
132
|
"""Update icon, tooltip, and menu based on current usage data."""
|
|
140
|
-
if self.usage_data is None:
|
|
133
|
+
if self.usage_data is None or self.icon is None:
|
|
141
134
|
return
|
|
142
135
|
|
|
143
136
|
session_percent = self.usage_data.session_percent
|
|
@@ -147,32 +140,25 @@ class TrayIndicator:
|
|
|
147
140
|
# Color shows worst-case urgency (max of session and weekly)
|
|
148
141
|
worst_case_percent = max(session_percent, weekly_percent)
|
|
149
142
|
|
|
150
|
-
# Generate icon
|
|
151
|
-
|
|
152
|
-
self.
|
|
143
|
+
# Generate new icon image
|
|
144
|
+
new_icon = generate_gauge_icon(session_percent, worst_case_percent)
|
|
145
|
+
self.icon.icon = new_icon
|
|
153
146
|
|
|
154
|
-
# Update
|
|
147
|
+
# Update tooltip (shown on hover)
|
|
155
148
|
tooltip = f"Session: {session_percent:.0f}% | Weekly: {weekly_percent:.0f}%"
|
|
156
|
-
self.
|
|
157
|
-
|
|
158
|
-
# Display compact status in panel (next to icon)
|
|
159
|
-
# Note: AppIndicator on GNOME Shell doesn't show hover tooltips (known limitation).
|
|
160
|
-
# This label appears as text in the panel for quick visual reference.
|
|
161
|
-
compact_label = f"{session_percent:.0f}%|{weekly_percent:.0f}%"
|
|
162
|
-
self.indicator.set_label(compact_label, "100%|100%") # guide string for sizing
|
|
149
|
+
self.icon.title = tooltip
|
|
163
150
|
|
|
164
151
|
# Rebuild menu with current data
|
|
165
|
-
self._build_menu()
|
|
152
|
+
self.icon.menu = self._build_menu()
|
|
166
153
|
|
|
167
154
|
# Pass pause flag to notifier before check_and_notify
|
|
168
155
|
self.notifier.pause_notifications = self.config.pause_notifications
|
|
169
156
|
|
|
170
157
|
# Check thresholds and show notifications if needed
|
|
171
|
-
# Convert datetime to timestamp for notifier
|
|
172
158
|
session_reset_ts = (self.usage_data.session_resets_at.timestamp()
|
|
173
|
-
|
|
159
|
+
if self.usage_data.session_resets_at else 0)
|
|
174
160
|
weekly_reset_ts = (self.usage_data.weekly_resets_at.timestamp()
|
|
175
|
-
|
|
161
|
+
if self.usage_data.weekly_resets_at else 0)
|
|
176
162
|
|
|
177
163
|
self.notifier.check_and_notify(
|
|
178
164
|
session_percent,
|
|
@@ -181,122 +167,65 @@ class TrayIndicator:
|
|
|
181
167
|
weekly_reset_ts
|
|
182
168
|
)
|
|
183
169
|
|
|
184
|
-
def
|
|
185
|
-
"""
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
Gtk.Menu: The constructed menu
|
|
189
|
-
"""
|
|
190
|
-
menu = Gtk.Menu()
|
|
170
|
+
def _update_loop(self):
|
|
171
|
+
"""Background thread that periodically updates usage data."""
|
|
172
|
+
# Initial update
|
|
173
|
+
self._update_usage()
|
|
191
174
|
|
|
192
|
-
#
|
|
193
|
-
|
|
194
|
-
weekly_percent = self.usage_data.weekly_percent
|
|
195
|
-
usage_text = f"Session: {session_percent:.0f}% | Weekly: {weekly_percent:.0f}%"
|
|
196
|
-
usage_item = Gtk.MenuItem(label=usage_text)
|
|
197
|
-
usage_item.set_sensitive(False)
|
|
198
|
-
menu.append(usage_item)
|
|
199
|
-
|
|
200
|
-
# Add reset time line (non-clickable)
|
|
201
|
-
# Use session_resets_at (5-hour is more relevant for active users)
|
|
202
|
-
reset_time_str = format_time_until(self.usage_data.session_resets_at)
|
|
203
|
-
reset_item = Gtk.MenuItem(label=f"Resets in {reset_time_str}")
|
|
204
|
-
reset_item.set_sensitive(False)
|
|
205
|
-
menu.append(reset_item)
|
|
206
|
-
|
|
207
|
-
# Add separator
|
|
208
|
-
menu.append(Gtk.SeparatorMenuItem())
|
|
209
|
-
|
|
210
|
-
# Add Refresh item
|
|
211
|
-
# Note: AppIndicator menus don't support GTK accelerators (no window to attach AccelGroup)
|
|
212
|
-
# Show the shortcut hint in the label instead
|
|
213
|
-
refresh_item = Gtk.MenuItem(label="Refresh")
|
|
214
|
-
refresh_item.connect('activate', self._on_refresh_clicked)
|
|
215
|
-
menu.append(refresh_item)
|
|
216
|
-
|
|
217
|
-
# Add Settings submenu
|
|
218
|
-
settings_item = Gtk.MenuItem(label="Settings")
|
|
219
|
-
settings_submenu = Gtk.Menu()
|
|
220
|
-
|
|
221
|
-
# Pause Notifications checkbox
|
|
222
|
-
pause_item = Gtk.CheckMenuItem(label="Pause Notifications")
|
|
223
|
-
pause_item.set_active(self.config.pause_notifications)
|
|
224
|
-
pause_item.connect('activate', self._on_pause_toggled)
|
|
225
|
-
settings_submenu.append(pause_item)
|
|
226
|
-
|
|
227
|
-
# Autostart on Login checkbox
|
|
228
|
-
autostart_item = Gtk.CheckMenuItem(label="Autostart on Login")
|
|
229
|
-
autostart_item.set_active(is_autostart_enabled())
|
|
230
|
-
autostart_item.connect('activate', self._on_autostart_toggled)
|
|
231
|
-
settings_submenu.append(autostart_item)
|
|
232
|
-
|
|
233
|
-
# Separator
|
|
234
|
-
settings_submenu.append(Gtk.SeparatorMenuItem())
|
|
235
|
-
|
|
236
|
-
# Edit Config File item
|
|
237
|
-
edit_config_item = Gtk.MenuItem(label="Edit Config File...")
|
|
238
|
-
edit_config_item.connect('activate', self._on_edit_config_clicked)
|
|
239
|
-
settings_submenu.append(edit_config_item)
|
|
240
|
-
|
|
241
|
-
settings_item.set_submenu(settings_submenu)
|
|
242
|
-
menu.append(settings_item)
|
|
243
|
-
|
|
244
|
-
# Add separator
|
|
245
|
-
menu.append(Gtk.SeparatorMenuItem())
|
|
246
|
-
|
|
247
|
-
# Add Quit item
|
|
248
|
-
quit_item = Gtk.MenuItem(label="Quit")
|
|
249
|
-
quit_item.connect('activate', self._on_quit_clicked)
|
|
250
|
-
menu.append(quit_item)
|
|
251
|
-
|
|
252
|
-
# Show all menu items
|
|
253
|
-
menu.show_all()
|
|
254
|
-
|
|
255
|
-
# Update instance menu and indicator
|
|
256
|
-
self.menu = menu
|
|
257
|
-
self.indicator.set_menu(menu)
|
|
258
|
-
|
|
259
|
-
return menu
|
|
260
|
-
|
|
261
|
-
def _on_refresh_clicked(self, widget):
|
|
262
|
-
"""Handle Refresh menu item click.
|
|
263
|
-
|
|
264
|
-
Uses GLib.idle_add to defer the update until after the menu closes,
|
|
265
|
-
avoiding GTK crashes from rebuilding the menu during event handling.
|
|
266
|
-
"""
|
|
267
|
-
def do_refresh():
|
|
175
|
+
# Periodic updates
|
|
176
|
+
while not self._stop_event.wait(timeout=self.config.polling_interval):
|
|
268
177
|
self._update_usage()
|
|
269
|
-
return GLib.SOURCE_REMOVE # Run only once, don't repeat
|
|
270
|
-
GLib.idle_add(do_refresh)
|
|
271
178
|
|
|
272
|
-
def
|
|
179
|
+
def _on_refresh_clicked(self, icon=None, item=None):
|
|
180
|
+
"""Handle Refresh menu item click."""
|
|
181
|
+
# Run update in background thread to avoid blocking UI
|
|
182
|
+
threading.Thread(target=self._update_usage, daemon=True).start()
|
|
183
|
+
|
|
184
|
+
def _on_pause_toggled(self, icon=None, item=None):
|
|
273
185
|
"""Handle Pause Notifications toggle."""
|
|
274
|
-
self.config.pause_notifications =
|
|
186
|
+
self.config.pause_notifications = not self.config.pause_notifications
|
|
275
187
|
self.config.save()
|
|
276
188
|
self.notifier.pause_notifications = self.config.pause_notifications
|
|
277
189
|
|
|
278
|
-
def _on_autostart_toggled(self,
|
|
190
|
+
def _on_autostart_toggled(self, icon=None, item=None):
|
|
279
191
|
"""Handle Autostart toggle."""
|
|
280
|
-
if
|
|
281
|
-
create_autostart_entry(True)
|
|
282
|
-
else:
|
|
192
|
+
if is_autostart_enabled():
|
|
283
193
|
remove_autostart_entry()
|
|
284
|
-
|
|
194
|
+
self.config.autostart_enabled = False
|
|
195
|
+
else:
|
|
196
|
+
create_autostart_entry(True)
|
|
197
|
+
self.config.autostart_enabled = True
|
|
285
198
|
self.config.save()
|
|
286
199
|
|
|
287
|
-
def _on_edit_config_clicked(self,
|
|
288
|
-
"""Open config file in default editor."""
|
|
200
|
+
def _on_edit_config_clicked(self, icon=None, item=None):
|
|
201
|
+
"""Open config file in default editor/viewer."""
|
|
202
|
+
import os
|
|
289
203
|
import subprocess
|
|
204
|
+
|
|
290
205
|
config_path = get_config_path()
|
|
291
206
|
# Ensure file exists with defaults
|
|
292
207
|
if not config_path.exists():
|
|
293
208
|
self.config.save()
|
|
294
|
-
subprocess.Popen(["/usr/bin/xdg-open", str(config_path)])
|
|
295
209
|
|
|
296
|
-
|
|
210
|
+
# Platform-specific file opening
|
|
211
|
+
if sys.platform == 'win32':
|
|
212
|
+
os.startfile(config_path)
|
|
213
|
+
elif sys.platform == 'darwin':
|
|
214
|
+
subprocess.run(['open', str(config_path)])
|
|
215
|
+
else:
|
|
216
|
+
subprocess.run(['xdg-open', str(config_path)])
|
|
217
|
+
|
|
218
|
+
def _on_quit_clicked(self, icon=None, item=None):
|
|
297
219
|
"""Handle Quit menu item click."""
|
|
298
|
-
|
|
220
|
+
self._stop_event.set()
|
|
221
|
+
if self.icon:
|
|
222
|
+
self.icon.stop()
|
|
299
223
|
|
|
300
224
|
def run(self):
|
|
301
|
-
"""Start the
|
|
302
|
-
|
|
225
|
+
"""Start the tray indicator."""
|
|
226
|
+
# Start background update thread
|
|
227
|
+
self._update_thread = threading.Thread(target=self._update_loop, daemon=True)
|
|
228
|
+
self._update_thread.start()
|
|
229
|
+
|
|
230
|
+
# Run pystray main loop (blocks until icon.stop() is called)
|
|
231
|
+
self.icon.run()
|
|
@@ -1,15 +0,0 @@
|
|
|
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,,
|
|
File without changes
|
|
File without changes
|