Add desktop tray widget + installer wizard
- 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>
This commit is contained in:
62
claude_usage_widget/config.py
Normal file
62
claude_usage_widget/config.py
Normal file
@@ -0,0 +1,62 @@
|
||||
"""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)
|
||||
Reference in New Issue
Block a user