-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtracker.py
More file actions
executable file
·122 lines (98 loc) · 3.74 KB
/
tracker.py
File metadata and controls
executable file
·122 lines (98 loc) · 3.74 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#!/usr/bin/env python3
"""
Claude Usage Tracker - macOS Menu Bar App
"""
import rumps
from datetime import datetime
from config import get_api_key, set_keychain_key
from anthropic_api import get_oauth_usage, format_reset_time
class ClaudeUsageTracker(rumps.App):
def __init__(self):
super().__init__(name="Claude Usage", title="...", quit_button=None)
self.usage = None
self.last_refresh = None
self._build_menu()
self._refresh_data(None)
def _build_menu(self):
self.menu.clear()
# Session limits
self.menu_5hr = rumps.MenuItem("5-hour: ...")
self.menu_7day = rumps.MenuItem("Weekly: ...")
self.menu_sonnet = rumps.MenuItem("Sonnet: ...")
self.menu_extra = rumps.MenuItem("Extra: ...")
self.menu.add(self.menu_5hr)
self.menu.add(self.menu_7day)
self.menu.add(self.menu_sonnet)
self.menu.add(None)
self.menu.add(self.menu_extra)
self.menu.add(None)
# Refresh
self.menu_updated = rumps.MenuItem("Updated: Never")
self.menu.add(self.menu_updated)
refresh_btn = rumps.MenuItem("Refresh")
refresh_btn.set_callback(self._refresh_data)
self.menu.add(refresh_btn)
self.menu.add(None)
quit_btn = rumps.MenuItem("Quit")
quit_btn.set_callback(lambda _: rumps.quit_application())
self.menu.add(quit_btn)
@rumps.timer(60) # Refresh every minute
def _auto_refresh(self, _):
self._refresh_data(None)
def _refresh_data(self, _):
self.title = "..."
try:
self.usage = get_oauth_usage()
self.last_refresh = datetime.now()
self._update_display()
except Exception as e:
self.title = "Err"
print(f"Error: {e}")
def _update_display(self):
if not self.usage:
self.title = "?"
return
# Menu bar title: show 5-hour percentage
five_hr = self.usage.get("five_hour")
if five_hr:
pct = int(five_hr.get("utilization", 0))
self.title = f"{pct}%"
else:
self.title = "0%"
# 5-hour session
if five_hr:
pct = int(five_hr.get("utilization", 0))
reset = format_reset_time(five_hr.get("resets_at", ""))
self.menu_5hr.title = f"5-hour: {pct}% (resets {reset})"
else:
self.menu_5hr.title = "5-hour: --"
# 7-day
seven_day = self.usage.get("seven_day")
if seven_day:
pct = int(seven_day.get("utilization", 0))
reset = format_reset_time(seven_day.get("resets_at", ""))
self.menu_7day.title = f"Weekly: {pct}% (resets {reset})"
else:
self.menu_7day.title = "Weekly: --"
# Sonnet weekly
sonnet = self.usage.get("seven_day_sonnet")
if sonnet:
pct = int(sonnet.get("utilization", 0))
reset = format_reset_time(sonnet.get("resets_at", ""))
self.menu_sonnet.title = f"Sonnet: {pct}% (resets {reset})"
else:
self.menu_sonnet.title = "Sonnet: --"
# Extra usage
extra = self.usage.get("extra_usage")
if extra and extra.get("is_enabled"):
used = extra.get("used_credits", 0) / 100 # cents to dollars
limit = extra.get("monthly_limit", 0) / 100
pct = int(extra.get("utilization", 0))
self.menu_extra.title = f"Extra: ${used:.2f}/${limit:.0f} ({pct}%)"
else:
self.menu_extra.title = "Extra: disabled"
# Updated time
if self.last_refresh:
self.menu_updated.title = f"Updated: {self.last_refresh.strftime('%H:%M:%S')}"
if __name__ == "__main__":
ClaudeUsageTracker().run()