- Desktop widget (Python/pystray): system tray icon showing 5h usage as circular progress bar with Claude starburst logo, 10-step green-to-red color scale, right-click menu with usage stats and configuration - Shared cache: both widget and CLI statusline read/write the same /tmp/claude_usage.json — only one fetcher needs to run - Installer wizard (install_wizard.py): interactive cross-platform setup with component selection, session key prompt, cron/autostart config - OS wrappers: install.sh (Linux/macOS) and install.ps1 (Windows) find Python 3.9+ and launch the wizard - README with topology diagram, usage docs, and configuration reference Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
63 lines
1.8 KiB
Python
63 lines
1.8 KiB
Python
"""JSON config management for Claude Usage Widget."""
|
|
|
|
import json
|
|
import os
|
|
import sys
|
|
|
|
# All config lives under claude-statusline (shared with the CLI statusline)
|
|
if sys.platform == "win32":
|
|
_CONFIG_DIR = os.path.join(os.environ.get("LOCALAPPDATA", os.path.expanduser("~")), "claude-statusline")
|
|
else:
|
|
_CONFIG_DIR = os.environ.get("CLAUDE_STATUSLINE_CONFIG") or os.path.join(
|
|
os.environ.get("XDG_CONFIG_HOME", os.path.expanduser("~/.config")), "claude-statusline"
|
|
)
|
|
|
|
CONFIG_PATH = os.path.join(_CONFIG_DIR, "widget-config.json")
|
|
SESSION_KEY_PATH = os.path.join(_CONFIG_DIR, "session-key")
|
|
|
|
DEFAULTS = {
|
|
"refresh_interval": 300, # seconds
|
|
"org_id": "",
|
|
}
|
|
|
|
|
|
def load():
|
|
"""Load config, merging with defaults for missing keys."""
|
|
cfg = dict(DEFAULTS)
|
|
try:
|
|
with open(CONFIG_PATH, "r") as f:
|
|
cfg.update(json.load(f))
|
|
except (FileNotFoundError, json.JSONDecodeError):
|
|
pass
|
|
return cfg
|
|
|
|
|
|
def save(cfg):
|
|
"""Persist config to disk."""
|
|
os.makedirs(os.path.dirname(CONFIG_PATH), exist_ok=True)
|
|
with open(CONFIG_PATH, "w") as f:
|
|
json.dump(cfg, f, indent=2)
|
|
|
|
|
|
def get_session_key():
|
|
"""Return session key from env var or shared config file."""
|
|
key = os.environ.get("CLAUDE_SESSION_KEY", "").strip()
|
|
if key:
|
|
return key
|
|
try:
|
|
with open(SESSION_KEY_PATH, "r") as f:
|
|
key = f.read().strip()
|
|
if key and not key.startswith("#"):
|
|
return key
|
|
except FileNotFoundError:
|
|
pass
|
|
return ""
|
|
|
|
|
|
def set_session_key(key):
|
|
"""Write session key to shared config file."""
|
|
os.makedirs(os.path.dirname(SESSION_KEY_PATH), exist_ok=True)
|
|
with open(SESSION_KEY_PATH, "w") as f:
|
|
f.write(key.strip() + "\n")
|
|
os.chmod(SESSION_KEY_PATH, 0o600)
|