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:
Axel Meyer
2026-02-26 12:54:32 +00:00
parent f308a8105e
commit 6a1b4bd022
14 changed files with 1241 additions and 71 deletions

View File

@@ -1,78 +1,28 @@
#!/usr/bin/env bash
# Install claude-statusline for the current user.
# Linux/macOS wrapper — launches the cross-platform installer wizard.
# Usage: bash install.sh
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
INSTALL_DIR="${HOME}/.local/share/claude-statusline"
CONFIG_DIR="${HOME}/.config/claude-statusline"
CLAUDE_DIR="${HOME}/.claude"
# --- Check Node.js version (need 18+ for built-in fetch) ---
NODE_BIN="$(which node 2>/dev/null || echo '')"
if [ -z "$NODE_BIN" ]; then
echo "ERROR: Node.js not found. Install Node.js 18+ first."
exit 1
fi
NODE_MAJOR=$("$NODE_BIN" -e "process.stdout.write(String(process.versions.node.split('.')[0]))")
if [ "$NODE_MAJOR" -lt 18 ]; then
echo "ERROR: Node.js $("$NODE_BIN" --version) found, but 18+ is required (built-in fetch)."
exit 1
fi
echo "==> Node.js v${NODE_MAJOR} found at $NODE_BIN"
echo "==> Installing claude-statusline..."
# Copy scripts
mkdir -p "$INSTALL_DIR"
cp "$SCRIPT_DIR/statusline.js" "$INSTALL_DIR/"
cp "$SCRIPT_DIR/fetch-usage.js" "$INSTALL_DIR/"
chmod +x "$INSTALL_DIR"/*.js
# Create config dir
mkdir -p "$CONFIG_DIR"
if [ ! -f "$CONFIG_DIR/session-key" ]; then
echo "# Paste your claude.ai sessionKey cookie value here" > "$CONFIG_DIR/session-key"
chmod 600 "$CONFIG_DIR/session-key"
echo " Created $CONFIG_DIR/session-key (edit with your session key)"
fi
# Configure Claude Code statusline
mkdir -p "$CLAUDE_DIR"
SETTINGS="$CLAUDE_DIR/settings.json"
if [ -f "$SETTINGS" ]; then
if grep -q '"statusLine"' "$SETTINGS" 2>/dev/null; then
echo " statusLine already configured in $SETTINGS — skipping"
else
"$NODE_BIN" -e "
const fs = require('fs');
const settings = JSON.parse(fs.readFileSync('$SETTINGS', 'utf8'));
settings.statusLine = {
type: 'command',
command: '$NODE_BIN --no-warnings $INSTALL_DIR/statusline.js'
};
fs.writeFileSync('$SETTINGS', JSON.stringify(settings, null, 2) + '\n');
"
echo " Added statusLine to $SETTINGS"
# Find Python 3.9+
PYTHON=""
for candidate in python3 python; do
if command -v "$candidate" &>/dev/null; then
major_minor=$("$candidate" -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')")
major=$("$candidate" -c "import sys; print(sys.version_info.major)")
minor=$("$candidate" -c "import sys; print(sys.version_info.minor)")
if [ "$major" -ge 3 ] && [ "$minor" -ge 9 ]; then
PYTHON="$candidate"
break
fi
fi
else
cat > "$SETTINGS" <<SEOF
{
"statusLine": {
"type": "command",
"command": "${NODE_BIN} --no-warnings ${INSTALL_DIR}/statusline.js"
}
}
SEOF
echo " Created $SETTINGS with statusLine config"
done
if [ -z "$PYTHON" ]; then
echo "ERROR: Python 3.9+ is required to run the installer."
echo "Install Python 3.9+ and try again."
exit 1
fi
# Offer cron setup
echo ""
echo "==> Optional: set up usage fetcher cron (every 5 min):"
echo " crontab -e"
echo " */5 * * * * ${NODE_BIN} ${INSTALL_DIR}/fetch-usage.js 2>/dev/null"
echo ""
echo "==> Done! Restart Claude Code to see the statusline."
echo " Don't forget to add your session key to: $CONFIG_DIR/session-key"
exec "$PYTHON" "$SCRIPT_DIR/install_wizard.py"