Rewrite in Go: static binaries, zero runtime dependencies
Some checks failed
Release / build (push) Failing after 21s

Replace Node.js + Python codebase with three Go binaries:
- claude-statusline: CLI status bar for Claude Code
- claude-fetcher: standalone cron job for API usage
- claude-widget: system tray icon (fyne-io/systray + fogleman/gg)

All CGO-free for trivial cross-compilation. Add nfpm .deb packaging
with autostart and cron. CI pipeline produces Linux + Windows binaries,
.deb, .tar.gz, and .zip release assets.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Axel Meyer
2026-02-26 15:27:10 +00:00
parent 59afabd65a
commit 7f17a40b7c
33 changed files with 1275 additions and 1512 deletions

243
README.md
View File

@@ -5,9 +5,9 @@
</p>
<p align="center">
<img src="https://img.shields.io/badge/Node.js-18+-339933?logo=node.js&logoColor=white" alt="Node.js 18+" />
<img src="https://img.shields.io/badge/Python-3.9+-3776AB?logo=python&logoColor=white" alt="Python 3.9+" />
<img src="https://img.shields.io/badge/Platform-Linux%20|%20macOS%20|%20Windows-informational" alt="Platform: Linux | macOS | Windows" />
<img src="https://img.shields.io/badge/Go-1.21+-00ADD8?logo=go&logoColor=white" alt="Go 1.21+" />
<img src="https://img.shields.io/badge/Platform-Linux%20|%20Windows-informational" alt="Platform: Linux | Windows" />
<img src="https://img.shields.io/badge/Dependencies-zero-brightgreen" alt="Zero dependencies" />
<img src="https://img.shields.io/badge/license-MIT-green" alt="MIT License" />
<br />
<a href="https://git.davoryn.de/calic/claude-statusline/releases"><img src="https://img.shields.io/badge/releases-Gitea-blue?logo=gitea&logoColor=white" alt="Releases" /></a>
@@ -17,156 +17,90 @@
## Overview
Both components share the same session key and fetcher logic. Install one or both depending on your setup.
Three static binaries built from one Go codebase. No runtime dependencies — no Node.js, Python, or system packages needed.
### CLI Statusline (Node.js)
### CLI Statusline
A headless-friendly status bar for Claude Code. Shows context window utilization and token usage as text progress bars, piped into the Claude Code statusline slot.
Headless status bar for Claude Code. Shows context window utilization and token usage as text progress bars.
```
Context ▓▓▓▓░░░░░░ 40% | Token ▓▓░░░░░░░░ 19% 78M
```
### Usage Fetcher (Node.js)
### Usage Fetcher
Standalone cron job that fetches token usage from the Claude API and writes a JSON cache file. The CLI statusline reads this cache. Runs independently — no browser or GUI needed.
Standalone binary for cron. Fetches token usage from the Claude API and writes a shared JSON cache.
### Desktop Widget (Python)
### Desktop Widget
Cross-platform system tray icon that shows the 5-hour usage window as a circular progress bar overlaid on a Claude starburst logo. Color shifts from green through amber to red as usage increases. Right-click menu shows detailed usage stats, reset timers, and configuration.
System tray icon showing 5-hour usage as a circular progress bar on a Claude starburst logo. Color shifts from green through amber to red as usage increases. Right-click menu shows detailed stats and configuration.
## Topology
```mermaid
graph TD
API["claude.ai API"]
FetchJS["fetch-usage.js<br/>(cron / Node.js)"]
FetchPy["fetcher.py thread<br/>(Python / urllib)"]
Cache["/tmp/claude_usage.json<br/>(shared cache)"]
SL["statusline.js<br/>(Claude Code)"]
Widget["app.py<br/>(pystray tray icon)"]
CC["Claude Code status bar"]
Tray["System tray icon<br/>+ right-click menu"]
SK["~/.config/claude-statusline/session-key"]
API --> FetchJS
API --> FetchPy
FetchJS --> Cache
FetchPy --> Cache
Cache --> SL
Cache --> Widget
SL --> CC
Widget --> Tray
SK -.->|auth| FetchJS
SK -.->|auth| FetchPy
```
claude.ai API
├──► claude-fetcher (cron) ──► /tmp/claude_usage.json ──► claude-statusline (Claude Code)
│ │
└──► claude-widget (built-in fetcher) ──┘──► System tray icon
```
Only one fetcher needs to run. Either `fetch-usage.js` (via cron) or the widget's built-in fetcher thread writes to the shared cache at `/tmp/claude_usage.json`. Both consumers read from it:
- **CLI statusline** reads the cache on every Claude Code render cycle
- **Desktop widget** reads the cache on startup for instant display, then either fetches itself (writing back to cache) or detects that the cache is already fresh (from cron) and skips the API call
If both fetchers happen to run, they write the same format — last writer wins, no conflicts.
Only one fetcher needs to run. The widget has a built-in fetcher; the standalone `claude-fetcher` is for headless/cron setups. Both write the same cache format.
## Installation
### Quick Install (from release)
Download the latest archive from the [Releases page](https://git.davoryn.de/calic/claude-statusline/releases) for your platform:
| Platform | Download | Install |
|----------|----------|---------|
| **Linux** | `.tar.gz` source archive | Extract, then `bash install.sh` |
| **macOS** | `.tar.gz` source archive | Extract, then `bash install.sh` |
| **Windows** | `.zip` source archive | Extract, then run `install.ps1` (see [Windows Quick Start](#windows-quick-start) below) |
> **Planned:** Native installers (`.deb`, `.msi`) are on the roadmap. For now, releases contain source archives.
### Developer Install (from source)
Clone the repository and run the installer wizard:
**Linux / macOS:**
```bash
git clone https://git.davoryn.de/calic/claude-statusline.git
cd claude-statusline
bash install.sh
```
**Windows (PowerShell):**
```powershell
git clone https://git.davoryn.de/calic/claude-statusline.git
cd claude-statusline
powershell -ExecutionPolicy Bypass -File install.ps1
```
### What the wizard does
1. Asks which components to install (CLI statusline, desktop widget, or both)
2. Guides you through session key setup
3. Configures autostart (widget) or cron (CLI fetcher) as applicable
4. Sets up the Claude Code statusline integration
### Windows Quick Start
If you're new to the command line, follow these steps:
1. Go to the [Releases page](https://git.davoryn.de/calic/claude-statusline/releases) and download the latest `.zip` file
2. Extract the zip to any folder (e.g. `C:\Users\YourName\claude-statusline`)
3. Open the extracted folder in File Explorer
4. Right-click `install.ps1` and select **Run with PowerShell**
- If you see a security prompt, choose **Run anyway** or **Open**
- Alternatively, open PowerShell manually and run:
```powershell
powershell -ExecutionPolicy Bypass -File install.ps1
```
5. The wizard will walk you through component selection and session key setup
6. To find your session key, see [Session Key](#session-key) below
### Prerequisites
| Component | Requires |
|-----------|----------|
| CLI Statusline + Fetcher | Node.js 18+ |
| Desktop Widget | Python 3.9+, pip |
| Desktop Widget (Linux) | `python3-gi`, `gir1.2-ayatanaappindicator3-0.1` (installed by wizard) |
## Session Key
Both components authenticate via a session cookie from claude.ai.
```mermaid
sequenceDiagram
participant User
participant Browser
participant Installer
participant Config
User->>Browser: Log into claude.ai
User->>Browser: DevTools → Cookies → sessionKey
User->>Installer: Paste session key when prompted
Installer->>Config: ~/.config/claude-statusline/session-key
```
**Step by step:**
1. Log into [claude.ai](https://claude.ai) in any browser
2. Open DevTools (press `F12`), go to **Application** → **Cookies** → `https://claude.ai`
3. Copy the value of the `sessionKey` cookie (it starts with `sk-ant-`)
4. The installer will prompt you to enter it, or set it manually:
### Debian/Ubuntu (.deb)
```bash
sudo dpkg -i claude-statusline_0.3.0_amd64.deb
```
Installs all three binaries to `/usr/bin/`, sets up autostart for the widget, and adds a cron job for the fetcher.
### Linux (tar.gz)
```bash
tar xzf claude-statusline_0.3.0_linux_amd64.tar.gz
sudo cp claude-statusline-0.3.0/claude-{statusline,fetcher,widget} /usr/local/bin/
```
### Windows
Extract the `.zip` and place the `.exe` files anywhere on your PATH.
### Session Key Setup
After installing, paste your claude.ai session key:
```bash
mkdir -p ~/.config/claude-statusline
echo "sk-ant-..." > ~/.config/claude-statusline/session-key
chmod 600 ~/.config/claude-statusline/session-key
```
Alternatively, set the `CLAUDE_SESSION_KEY` environment variable.
**To find your session key:**
1. Log into [claude.ai](https://claude.ai)
2. Open DevTools (`F12`) → **Application****Cookies**`https://claude.ai`
3. Copy the `sessionKey` cookie value
Or set `CLAUDE_SESSION_KEY` as an environment variable.
### Claude Code Integration
Add to your Claude Code settings (`~/.claude/settings.json`):
```json
{
"statusLine": {
"type": "command",
"command": "claude-statusline"
}
}
```
## Configuration
### CLI Statusline
Environment variables:
### Environment Variables
| Variable | Default | Description |
|----------|---------|-------------|
@@ -174,22 +108,17 @@ Environment variables:
| `CLAUDE_USAGE_MAX_AGE` | `900` | Max cache age in seconds |
| `CLAUDE_SESSION_KEY` | — | Session key (alternative to config file) |
| `CLAUDE_STATUSLINE_CONFIG` | `~/.config/claude-statusline` | Config directory |
| `CLAUDE_ORG_ID` | — | Organization ID (auto-discovered) |
### Desktop Widget
### Widget Menu
Right-click the tray icon to access:
- **Usage stats** — 5-hour and 7-day utilization with reset timers
- **Refresh Now** — trigger an immediate fetch
- **Refresh Interval** — 1 / 5 / 15 / 30 minutes
- **Session Key...** — update the session key via dialog
Widget settings are stored in `~/.config/claude-statusline/widget-config.json`.
- **Session Key...** — open session key file in editor
### Icon Color Scale
The tray icon arc color indicates usage severity at 10% increments:
| Range | Color |
|-------|-------|
| 010% | Green |
@@ -203,35 +132,37 @@ The tray icon arc color indicates usage severity at 10% increments:
| 8090% | Deep orange |
| 90100% | Red |
## Releases
## Building from Source
Tagged releases are published on [Gitea](https://git.davoryn.de/calic/claude-statusline/releases) following semver (`v0.2.0`, `v0.3.0`, etc.). Each release includes per-OS source archives.
```bash
# All binaries
go build ./cmd/statusline && go build ./cmd/fetcher && go build ./cmd/widget
**Planned future additions:**
- `.deb` package for Debian/Ubuntu
- `.msi` / `.exe` installer for Windows
- Homebrew tap for macOS
# Cross-compile for Windows
GOOS=windows GOARCH=amd64 go build -ldflags "-H=windowsgui" -o claude-widget.exe ./cmd/widget
GOOS=windows GOARCH=amd64 go build -o claude-statusline.exe ./cmd/statusline
GOOS=windows GOARCH=amd64 go build -o claude-fetcher.exe ./cmd/fetcher
# Build .deb
VERSION=0.3.0 nfpm package --config packaging/nfpm.yaml --packager deb
```
## Project Structure
```
claude-statusline/
├── statusline.js # CLI status bar (reads stdin + cache)
├── fetch-usage.js # Cron-based usage fetcher (writes cache)
├── install.sh # Linux/macOS installer wrapper
├── install.ps1 # Windows installer wrapper
├── install_wizard.py # Cross-platform installer wizard
├── package.json
├── requirements.txt # Python deps (widget only)
├── claude_usage_widget/
│ ├── __init__.py
│ ├── __main__.py # Entry point: python -m claude_usage_widget
│ ├── app.py # Tray icon orchestrator
│ ├── config.py # Shared config (~/.config/claude-statusline/)
│ ├── fetcher.py # Python port of fetch-usage.js (urllib)
│ ├── menu.py # Right-click menu builder
│ └── renderer.py # Starburst logo + arc icon renderer
└── README.md
cmd/
statusline/main.go # CLI statusline (reads stdin + cache)
fetcher/main.go # Standalone cron fetcher (writes cache)
widget/main.go # Desktop tray widget entry point
internal/
config/config.go # Shared config (session key, org ID, intervals)
fetcher/fetcher.go # HTTP fetch logic (shared between widget + standalone)
fetcher/cache.go # JSON cache read/write (/tmp/claude_usage.json)
renderer/renderer.go # Icon rendering: starburst + arc (fogleman/gg)
tray/tray.go # System tray setup + menu (fyne-io/systray)
packaging/
nfpm.yaml # .deb packaging config
linux/ # .desktop file, cron, install scripts
```
## License