Last active
February 27, 2026 16:26
-
-
Save sky87/8aa6145080db4bcbe4df684a8a8896ad to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env python3 | |
| """Claude Code status line - shows 5-hour usage window, context %, and session cost.""" | |
| import json | |
| import os | |
| import sys | |
| import time | |
| import urllib.request | |
| from datetime import datetime, timezone | |
| CACHE_FILE = "/tmp/claude-usage-cache.json" | |
| CACHE_TTL = 120 # seconds between API calls | |
| CREDS_FILE = os.path.expanduser("~/.claude/.credentials.json") | |
| def get_cached_usage(): | |
| try: | |
| if os.path.exists(CACHE_FILE): | |
| age = time.time() - os.path.getmtime(CACHE_FILE) | |
| if age < CACHE_TTL: | |
| with open(CACHE_FILE) as f: | |
| return json.load(f) | |
| except Exception: | |
| pass | |
| return None | |
| def fetch_usage(): | |
| try: | |
| with open(CREDS_FILE) as f: | |
| creds = json.load(f) | |
| token = creds.get("claudeAiOauth", {}).get("accessToken") | |
| if not token: | |
| return None | |
| req = urllib.request.Request( | |
| "https://api.anthropic.com/api/oauth/usage", | |
| headers={ | |
| "Authorization": f"Bearer {token}", | |
| "anthropic-beta": "oauth-2025-04-20", | |
| }, | |
| ) | |
| with urllib.request.urlopen(req, timeout=3) as resp: | |
| data = json.loads(resp.read()) | |
| five_hour = data.get("five_hour", {}) | |
| result = { | |
| "five_hour_pct": five_hour.get("utilization"), | |
| "resets_at": five_hour.get("resets_at"), | |
| } | |
| with open(CACHE_FILE, "w") as f: | |
| json.dump(result, f) | |
| return result | |
| except Exception: | |
| return None | |
| def main(): | |
| stdin_data = json.loads(sys.stdin.read()) | |
| model = stdin_data.get("model", {}).get("display_name", "?") | |
| pct = stdin_data.get("context_window", {}).get("used_percentage", 0) | |
| cost = stdin_data.get("cost", {}).get("total_cost_usd", 0) | |
| cached = get_cached_usage() | |
| usage = cached if cached else fetch_usage() | |
| five_hour = "?" | |
| reset_str = "" | |
| if usage and usage.get("five_hour_pct") is not None: | |
| five_hour = f"{usage['five_hour_pct']:.0f}" | |
| resets_at = usage.get("resets_at") | |
| if resets_at: | |
| try: | |
| reset_time = datetime.fromisoformat(resets_at) | |
| remaining = reset_time - datetime.now(timezone.utc) | |
| secs = int(remaining.total_seconds()) | |
| if secs > 0: | |
| h, m = secs // 3600, (secs % 3600) // 60 | |
| reset_str = f" {h}h{m:02d}m" if h else f" {m}m" | |
| except Exception: | |
| pass | |
| print(f"[{model}] 5h: {five_hour}%{reset_str} | ctx: {int(pct)}% | ${cost:.2f}") | |
| if __name__ == "__main__": | |
| main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment