Release history
onWatch releases
Real-time API quota tracking across AI platforms
All releases
86 shown
- Structured JSON logging available through --log-format=json or ONWATCH_LOG_FORMAT=json
Full changelog
What's New
Structured JSON logging (#70)
You can now switch log output from the default key=value text format to JSON via CLI flag or environment variable:
# CLI flag
onwatch --log-format json
# Environment variable
ONWATCH_LOG_FORMAT=json onwatch
JSON output uses Go's native slog.JSONHandler, producing machine-readable logs ideal for container logging pipelines (Fluentd, Loki, CloudWatch, etc.).
- Accepts aliases:
text,txt,fmtfor text format;jsonfor JSON - Case-insensitive input
- Works in all modes: background,
--debug,--debugstdout, and Docker - Defaults to
textif unset or unrecognized
Full Changelog: https://github.com/onllm-dev/onWatch/compare/v2.11.45...v2.11.46
- After updating, re‑save each profile to restore correct tokens using `codex auth` followed by `onwatch codex profile refresh`.
- Auto-save settings in menubar apply changes immediately
- Menubar fetches live data from main daemon, eliminating stale displays
- Newly added providers appear automatically in the menubar
Full changelog
Bug Fix
Codex Team/Business workspace token cross-contamination (#69)
When multiple users from the same ChatGPT Team or Business workspace saved profiles, they shared the same account_id. The system credentials fallback only checked account_id match when picking up tokens from ~/.codex/auth.json - so one user's tokens would silently overwrite the other profile, causing both to poll with the same identity and show identical usage data.
The fallback now also checks user_id, rejecting system credentials that belong to a different user on the same workspace.
After updating, re-save your profiles to restore correct tokens:
# Log into first account
codex auth
onwatch codex profile refresh <profile1>
# Log into second account
codex auth
onwatch codex profile refresh <profile2>
Menubar Improvements
- Auto-save settings - changes apply immediately, no manual Save needed
- Fixed menubar showing stale data - companion now fetches from the main daemon instead of building its own snapshot
- New providers auto-visible - newly added providers appear in menubar without manual configuration
Full Changelog: https://github.com/onllm-dev/onWatch/compare/v2.11.44...v2.11.45
Routine maintenance release for onWatch.
Changelog
Full Changelog: https://github.com/onllm-dev/onWatch/compare/v2.11.43...v2.11.44
Fixed menubar to open the dashboard on the configured port rather than hardcoding port 9211.
Full changelog
What's Changed
- fix(menubar): open dashboard on configured port, not hardcoded 9211 by @prakersh in https://github.com/onllm-dev/onWatch/pull/66
Full Changelog: https://github.com/onllm-dev/onWatch/compare/v2.11.42...v2.11.43
- Add Cursor provider support
Full changelog
What's Changed
- Add Cursor provider support by @LeslieLeung in https://github.com/onllm-dev/onWatch/pull/59
New Contributors
- @LeslieLeung made their first contribution in https://github.com/onllm-dev/onWatch/pull/59
Full Changelog: https://github.com/onllm-dev/onWatch/compare/v2.11.41...v2.11.42
Routine maintenance release for onWatch.
Changelog
Full Changelog: https://github.com/onllm-dev/onWatch/compare/v2.11.40...v2.11.41
- Custom API Integrations
Full changelog
What's Changed
- Feat: Custom API Integrations by @sgogriff in https://github.com/onllm-dev/onWatch/pull/52
Full Changelog: https://github.com/onllm-dev/onWatch/compare/v2.11.39...v2.11.40
Routine maintenance release for onWatch.
Changelog
Full Changelog: https://github.com/onllm-dev/onWatch/compare/v2.11.38...v2.11.39
Routine maintenance release for onWatch.
Changelog
Full Changelog: https://github.com/onllm-dev/onWatch/compare/v2.11.37...v2.11.38
Routine maintenance release for onWatch.
Changelog
Full Changelog: https://github.com/onllm-dev/onWatch/compare/v2.11.36...v2.11.37
Routine maintenance release for onWatch.
Changelog
Full Changelog: https://github.com/onllm-dev/onWatch/compare/v2.11.35...v2.11.36
- Multi‑Account Support with full isolation and per‑account usage/history view in the dashboard
- Status bar API source badges now show timestamps for last quota update
Full changelog
v2.11.35 - MiniMax Multi-Account Support
Track multiple MiniMax accounts with full isolation. Switch accounts in the dashboard to view per-account usage and history.
Bug Fix - Fixed cycle overview showing blank data on shared MiniMax plans. Usage history now always displays correctly.
Improved Status Bar - API source badges now show timestamps for last quota update.
- Configurable quota display mode: toggle between usage (%) and available (%) for five_hour and seven_day quotas via `CODEX_SHOW_AVAILABLE` env var or Settings UI
- Consolidated Codex provider card in Settings now lists all sub-profiles with individual telemetry/dashboard toggles
- Beta Profile Management UI enables credential refresh and profile deletion directly from the Settings modal
Full changelog
Codex Display Mode Toggle
Toggle how you view Codex quotas - switch between "Usage" (utilization %) and "Available" (remaining %) for five_hour and seven_day quotas.
Configure via:
- Environment:
CODEX_SHOW_AVAILABLE=true(orfalsefor usage mode, which is default) - Settings UI: Settings → Providers → Configure Codex → Quota Display
Consolidated Codex Settings Card
The Codex provider card in Settings now shows ONE entry with all sub-profiles listed below it. Each sub-profile retains its own telemetry/dashboard toggles for granular control.
Profile Management UI (Beta)
Manage Codex profiles directly from the Settings modal - refresh credentials or delete profiles without needing the CLI.
Bug Fixes
- Added
display_modevalue validation (only accepts "usage" or "available") - CSS styling improvements for the consolidated Codex provider section
- All tests pass with race detection
Routine maintenance release for onWatch.
Changelog
Full Changelog: https://github.com/onllm-dev/onWatch/compare/v2.11.32...v2.11.33
- Use PDF vector icon for crisp menubar rendering
- Add OpenRouter provider for credit/usage monitoring
Full changelog
What's Changed
- feat: use PDF vector icon for crisp menubar rendering by @jinquan-shi in https://github.com/onllm-dev/onWatch/pull/43
- fix: add explicit expiry to login session cookie by @goldmar in https://github.com/onllm-dev/onWatch/pull/47
- Fix: Copilot quota tracking for free/limited plans by @sgogriff in https://github.com/onllm-dev/onWatch/pull/45
- feat: add OpenRouter provider for credit/usage monitoring by @omnissiah-comelse in https://github.com/onllm-dev/onWatch/pull/44
- fix: OpenRouter frontend + MiniMax zero-quota filter by @prakersh in https://github.com/onllm-dev/onWatch/pull/48
New Contributors
- @goldmar made their first contribution in https://github.com/onllm-dev/onWatch/pull/47
- @sgogriff made their first contribution in https://github.com/onllm-dev/onWatch/pull/45
- @omnissiah-comelse made their first contribution in https://github.com/onllm-dev/onWatch/pull/44
Full Changelog: https://github.com/onllm-dev/onWatch/compare/v2.11.31...v2.11.32
- Added MiniMax endpoint support for CN region
- Added ZHIPU (Z.ai) endpoint support for CN region
Full changelog
What's Changed
- feat: add MiniMax & ZHIPU(Z.ai) CN region endpoint support by @jinquan-shi in https://github.com/onllm-dev/onWatch/pull/41
New Contributors
- @jinquan-shi made their first contribution in https://github.com/onllm-dev/onWatch/pull/41
Full Changelog: https://github.com/onllm-dev/onWatch/compare/v2.11.30...v2.11.31
Routine maintenance release for onWatch.
Changelog
Full Changelog: https://github.com/onllm-dev/onWatch/compare/v2.11.29...v2.11.30
Routine maintenance release for onWatch.
Changelog
Full Changelog: https://github.com/onllm-dev/onWatch/compare/v2.11.28...v2.11.29
Routine maintenance release for onWatch.
Changelog
Full Changelog: https://github.com/onllm-dev/onWatch/compare/v2.11.27...v2.11.28
Routine maintenance release for onWatch.
Changelog
Full Changelog: https://github.com/onllm-dev/onWatch/compare/v2.11.26...v2.11.27
Routine maintenance release for onWatch.
Changelog
Full Changelog: https://github.com/onllm-dev/onWatch/compare/v2.11.25...v2.11.26
Routine maintenance release for onWatch.
Changelog
Full Changelog: https://github.com/onllm-dev/onWatch/compare/v2.11.24...v2.11.25
Routine maintenance release for onWatch.
Changelog
Full Changelog: https://github.com/onllm-dev/onWatch/compare/v2.11.23...v2.11.24
- Countdown timer on promo tags in dashboard and menubar displays time until next peak/off‑peak transition
- Timer updates every 30 seconds purely client‑side with no API calls
- Menubar promo now receives the promo end date for accurate countdown capping
Full changelog
What's New
Features
- Countdown timer on promo tags in both dashboard and menubar - shows time remaining until the next peak/off-peak transition (e.g. "2x limits till 14h 20m", "Peak hours till 1h 45m")
- Countdown updates every 30 seconds purely client-side with no API calls required
- Menubar promo now receives the promo end date for accurate countdown capping
Bug Fixes
- Fixed flaky CI test timeout in SetNotifier agent test by increasing wait deadlines for race-detected builds
Other
- Updated all dashboard and menubar screenshots with the new promo countdown tags
Full Changelog: https://github.com/onllm-dev/onWatch/compare/v2.11.22...v2.11.23
Menubar promo tag now dynamically reflects peak/off-peak status in real time.
Full changelog
What's New
Bug Fixes
- Menubar promo tag now dynamically shows peak/off-peak status based on current ET time without requiring a data refresh
Full Changelog: https://github.com/onllm-dev/onWatch/compare/v2.11.21...v2.11.22
- Anthropic March 2026 off‑peak 2x usage limits shown in dashboard quota cards and menubar provider header
- Dashboard toggles between "2x limits" during off‑peak hours and "Standard limits" during peak (8 AM–2 PM ET weekdays)
- Clickable promo tags link to the Claude help center article
Full changelog
What's New
Features
- Anthropic March 2026 off-peak 2x usage limits display in dashboard quota cards and menubar provider header
- Shows "2x limits" during off-peak hours and "Standard limits" during peak hours (8 AM - 2 PM ET weekdays)
- Clickable promo tags link to the Claude help center article
Full Changelog: https://github.com/onllm-dev/onWatch/compare/v2.11.20...v2.11.21
Minor fixes and improvements.
Full changelog
What's Changed
- fix(ci): switch macOS amd64 release runner to macos-14 by @prakersh in https://github.com/onllm-dev/onWatch/pull/29
Full Changelog: https://github.com/onllm-dev/onWatch/compare/v2.11.19...v2.11.20
- macOS menubar with three preset views
Full changelog
What's Changed
- fix: Docker container fails to start with misleading OOM error by @kapdon in https://github.com/onllm-dev/onWatch/pull/22
- fix: fail fast on unwritable Docker DB path by @prakersh in https://github.com/onllm-dev/onWatch/pull/28
- feat: Add macOS menubar with three preset views by @prakersh in https://github.com/onllm-dev/onWatch/pull/25
New Contributors
- @kapdon made their first contribution in https://github.com/onllm-dev/onWatch/pull/22
Full Changelog: https://github.com/onllm-dev/onWatch/compare/v2.11.18...v2.11.19
Stabilized SMTP email notification setup with automatic migration of legacy credential formats.
Full changelog
What's New
Bug Fixes
- Stabilized SMTP email notification setup with automatic migration of legacy credential formats
- Updated README badges and documentation
Full Changelog: https://github.com/onllm-dev/onWatch/compare/v2.11.17...v2.11.18
Minor fixes and improvements.
Full changelog
What's Changed
- test: achieve 90%+ code coverage for awesome-go eligibility by @prakersh in https://github.com/onllm-dev/onWatch/pull/24
Full Changelog: https://github.com/onllm-dev/onWatch/compare/v2.11.16...v2.11.17
- Added MiniMax to the landing page provider showcase
- Added Antigravity support to the summary endpoint
Full changelog
What's New
Features
- Added MiniMax to the landing page provider showcase
- Added Antigravity support to the summary endpoint
Bug Fixes
- Fixed cross-provider data leakage in the synthetic summary endpoint
- Fixed initial modal card render state not being populated
- Summary endpoint now returns 400 for unknown providers instead of silently failing
- Updated provider layout and documentation for all seven providers
Full Changelog: https://github.com/onllm-dev/onWatch/compare/v2.11.15...v2.11.16
- MiniMax provider integration
- Dynamic provider control
Full changelog
What's Changed
- feat: MiniMax provider integration + dynamic provider control by @prakersh in https://github.com/onllm-dev/onWatch/pull/21
Full Changelog: https://github.com/onllm-dev/onWatch/compare/v2.11.14...v2.11.15
- Configuration file loading changed from the current directory to ~/.onwatch/.env.
Full changelog
What's New
Bug Fixes
- Config now loads from ~/.onwatch/.env instead of the current directory, preventing config-not-found issues when running from different paths
Other
- Added multi-account Codex feature highlight to landing page
Full Changelog: https://github.com/onllm-dev/onWatch/compare/v2.11.13...v2.11.14
- Redesigned "All Providers" page with provider-centric cards
- Per-account Codex settings toggles for multi-account configurations
- Improved layout density across dashboard views
Full changelog
What's New
Features
- Redesigned "All Providers" page with provider-centric cards
- Per-account Codex settings toggles for multi-account configurations
- Improved layout density across dashboard views
Bug Fixes
- Fixed free-plan quota normalization display
- Scoped Codex cycle overview to the selected account
- Unified chart gap visualization with poll-aware thresholds
- Fixed dynamic provider card height - removed fixed chart space allocation
- Corrected layout density logic and centered insight cards
- Replaced em-dashes with hyphens and respected telemetry settings on All page
Full Changelog: https://github.com/onllm-dev/onWatch/compare/v2.11.12...v2.11.13
- Multi‑account Codex support (Beta) – track multiple Codex accounts with account‑tagged data and parallel polling
Full changelog
What's New
Features
- Multi-account Codex support (Beta) - track multiple Codex accounts and sessions simultaneously with account-tagged data and parallel polling
Full Changelog: https://github.com/onllm-dev/onWatch/compare/v2.11.11...v2.11.12
- Automatic bypass of Anthropic usage API rate limits via OAuth token refresh on 429 responses
- OAuth refresh tokens rotated per spec for added security
Full changelog
What's New
Features
- Automatic bypass of Anthropic's usage API rate limits via OAuth token refresh - when a 429 is encountered, onWatch refreshes the OAuth token for a fresh rate limit window and retries automatically
- Refresh tokens are rotated per OAuth spec for security
Full Changelog: https://github.com/onllm-dev/onWatch/compare/v2.11.10...v2.11.11
Fixed grid layout adaptation and improved chart gap visualization.
Full changelog
What's New
Bug Fixes
- Grid layouts now dynamically adapt to available providers instead of using hardcoded positions
- Improved chart gap visualization using poll-interval-based thresholds instead of hardcoded values
Full Changelog: https://github.com/onllm-dev/onWatch/compare/v2.11.9...v2.11.10
- Default poll interval increased to 120 seconds for better rate limit management
- Added Codecov coverage reporting to CI
Full changelog
What's New
Features
- Increased default poll interval to 120 seconds for better rate limit management
- Added Codecov coverage reporting to CI
Bug Fixes
- Replaced flaky subprocess tests with in-process tests for improved CI reliability
Full Changelog: https://github.com/onllm-dev/onWatch/compare/v2.11.8...v2.11.9
Fixed Windows process detection for Antigravity language server and corrected dashboard label display when no data is available.
Full changelog
What's New
Bug Fixes
- Windows Antigravity detection: Fixed process detection on Windows by using
Get-CimInstance(modern PowerShell) instead of deprecatedwmic. Now correctly finds thelanguage_server_windows_x64.exebinary, which runs as a separate process from the mainAntigravity.exeElectron app. - Dashboard chart labels: Fixed Antigravity dashboard showing incorrect "Subscription/Search/Tool Calls" labels (Synthetic provider defaults) when no data is available yet.
- Test stability: Fixed intermittent subprocess test failures under heavy parallel load.
Technical Details
- The Antigravity language server on Windows runs as
language_server_windows_x64.exewith--csrf_tokenand--extension_server_portarguments, not asAntigravity.exe. The detection pipeline now searches all processes by command line content and uses scoring to select the best candidate (language server scores highest due to CSRF token and LSP indicators).
Fixed tilde expansion in file paths.
Full changelog
What's New
Bug Fixes
- Proper handling of Anthropic 429 rate limiting with backoff
- Fixed tilde (~) expansion in file paths
- Improved daemon startup diagnostics
Full Changelog: https://github.com/onllm-dev/onWatch/compare/v2.11.6...v2.11.7
- Updated Go module path to v2 for compliance with the Go proxy, enabling `go install` support.
- Added Homebrew installation option on the landing page.
Full changelog
What's New
Features
- Updated Go module path to v2 for Go proxy compliance - enables
go installsupport - Added Homebrew install option to landing page
Other
- Applied gofmt formatting for Go Report Card A+ rating
Full Changelog: https://github.com/onllm-dev/onWatch/compare/v2.11.5...v2.11.6
- Homebrew tap support via `brew install onllm-dev/tap/onwatch`
- Guided first-time configuration with `onwatch setup` command
- CONTRIBUTING.md added for community contributors
Full changelog
What's New
Features
- Homebrew tap support - install with
brew install onllm-dev/tap/onwatch - New
onwatch setupcommand for guided first-time configuration - Added CONTRIBUTING.md for community contributors
Full Changelog: https://github.com/onllm-dev/onWatch/compare/v2.11.4...v2.11.5
- Removed hard 500‑record cap; logging history API scales up to 50,000 records per range
- Windows Defender false‑positive handling guidance added in documentation
- 'Cycle Overview' → 'Session History'
- Logging history added for Synthetic, Z.ai, Anthropic, Copilot, and Codex dashboards
- Dynamic time‑range filters (1h/3d/7d/15d/30d) now return correct data amounts without the previous ~3.3 hour cap
- QueryRange now returns most recent records instead of oldest
Full changelog
What's New
- Logging history for all providers — Session history now available for Synthetic, Z.ai, Anthropic, Copilot, and Codex dashboards
- Dynamic range support — 1h/3d/7d/15d/30d time range filters now return the correct amount of data (previously capped at ~3.3 hours)
- QueryRange fix — Historical queries now return most recent records instead of oldest
- Windows Defender guidance — Added docs for handling false positive detections on Windows
Fixes
- Logging history API now accepts
rangeparameter and calculates appropriate limits per time window - Removed hard 500-record cap for logging history — ranges scale up to 50,000 records as needed
- "Cycle Overview" renamed to "Session History" in dashboard
Full Changelog: https://github.com/onllm-dev/onWatch/compare/v2.11.2...v2.11.4
- PowerShell installer for Windows setup
- Windows installation guide
Full changelog
What's New
Features
- Windows support with PowerShell installer for easy setup
- Windows installation guide
Bug Fixes
- Fixed .env file encoding issue (UTF-8 BOM) on Windows
- Handle Windows Firewall prompt during first startup
Full Changelog: https://github.com/onllm-dev/onWatch/compare/v2.11.1...v2.11.2
- Added Antigravity provider to the landing page with chart data and usage legend
- Updated Antigravity model names to GPT OSS
Full changelog
What's New
Features
- Added Antigravity provider to the landing page with chart data and usage legend
Bug Fixes
- Fixed chart data ordering to display oldest-to-newest
- Updated Antigravity model names to GPT OSS
Full Changelog: https://github.com/onllm-dev/onWatch/compare/v2.11.0...v2.11.1
- Antigravity provider added with logging history support
Full changelog
What's Changed
- feat(antigravity): add Antigravity provider with logging history support by @prakersh in https://github.com/onllm-dev/onWatch/pull/12
Full Changelog: https://github.com/onllm-dev/onWatch/compare/v2.10.4...v2.11.0
- Added Codex OAuth provider support
Full changelog
What's Changed
- feat(codex): add Codex OAuth provider support by @iota31 in https://github.com/onllm-dev/onWatch/pull/9
- release: v2.10.4 codex fixes and screenshot refresh by @iota31 in https://github.com/onllm-dev/onWatch/pull/11
New Contributors
- @iota31 made their first contribution in https://github.com/onllm-dev/onWatch/pull/9
Full Changelog: https://github.com/onllm-dev/onWatch/compare/v2.10.1...v2.10.4
- Codex OAuth provider support - track Codex usage quotas with OAuth-based authentication
Full changelog
What's New
Features
- Codex OAuth provider support - track Codex usage quotas with OAuth-based authentication
Full Changelog: https://github.com/onllm-dev/onWatch/compare/v2.10.1...v2.10.3
- For older versions, add `--debug` to the container command or set environment variable `DOCKER_CONTAINER=1` as a workaround.
Full changelog
Bug Fixes
- Kubernetes container detection —
IsDockerEnvironment()now also detects Kubernetes environments by checking forKUBERNETES_SERVICE_HOSTenv var and/var/run/secrets/kubernetes.io/serviceaccountmount. This fixes the "permission denied" error when running in k8s clusters where containerd/CRI-O don't create/.dockerenvlike Docker does. (#7)
Download
| Platform | Architecture | Binary |
|----------|-------------|--------|
| macOS | Apple Silicon (M1/M2/M3) | onwatch-darwin-arm64 |
| macOS | Intel | onwatch-darwin-amd64 |
| Linux | x86_64 | onwatch-linux-amd64 |
| Linux | ARM64 | onwatch-linux-arm64 |
| Windows | x86_64 | onwatch-windows-amd64.exe |
Docker
docker pull ghcr.io/onllm-dev/onwatch:v2.10.1
Workaround (for users on older versions)
If you can't upgrade immediately, add --debug to your container command or set DOCKER_CONTAINER=1 in your pod's environment variables.
- Add COPILOT_TOKEN environment variable with a GitHub PAT that includes the `copilot` scope to enable the provider.
- Beta support for GitHub Copilot provider
- Premium Requests quota monitoring (300‑1500 per plan)
- Unlimited quotas displayed with ∞ badges
Full changelog
What's New
🚀 GitHub Copilot Provider (Beta)
onWatch now supports GitHub Copilot as a 4th provider! Track your Premium Requests, Chat, and Completions quotas alongside Synthetic, Z.ai, and Anthropic.
Features
- Premium Requests Tracking — Monitor your monthly premium model request quota (300-1500 depending on plan)
- Unlimited Quotas — Chat and Completions show ∞ badges for unlimited quotas
- Monthly Reset Detection — Automatic cycle tracking based on quota_reset_date_utc
- Purple Accent Colors — GitHub Copilot branding in dashboard UI
- Beta Badge — Clear indication that this feature uses an undocumented API
Configuration
Add your GitHub Personal Access Token (classic) with the copilot scope to .env:
COPILOT_TOKEN=ghp_your_token_here
Generate a token at github.com/settings/tokens with the copilot scope.
Technical Details
- Uses GitHub's internal API:
GET https://api.github.com/copilot_internal/user - Authorization: Bearer token (GitHub PAT with copilot scope)
- Full TDD implementation with comprehensive test coverage
- Follows same architecture as other providers
Other Changes
- Updated all provider screenshots
- Added Copilot section to landing page
- Updated documentation across all files
⚠️ Important Note
GitHub Copilot tracking uses an undocumented internal API. While it works today, GitHub may change or disable this API without notice. This feature is marked as Beta accordingly.
Full Changelog: https://github.com/onllm-dev/onwatch/compare/v2.9.0...v2.10.0
- Moved inline theme script to external file for CSP compliance
- Delta Display in Tables: quota columns show change between polling cycles
- Enhanced Polling History: quotas displayed in column format matching Cycle Overview
- Improved Cycle Overview: active cycles included with better sorting and styling
Full changelog
What's New in v2.9.0
Features
- Delta Display in Tables: All quota columns in Cycle Overview and Polling History now show delta values, making it easier to track usage changes between polling cycles
- Enhanced Polling History: Polling History table now displays all quotas in columns, matching the Cycle Overview layout for consistency
- Improved Cycle Overview: Active cycles are now included in the overview with improved sorting and visual styling
Fixes
- Session Tracking: Fixed quota order for Anthropic session tracking to ensure consistent display
- Security: Moved inline theme script to external file for CSP compliance
- Tracker: Fixed cycle detection to use hour precision for Synthetic provider and exclude reset snapshots from peak calculations
Changes
- Updated all dashboard screenshots for documentation
- Version bump to 2.9.0
Assets
| Platform | Binary |
|----------|--------|
| macOS ARM64 | onwatch-darwin-arm64 |
| macOS AMD64 | onwatch-darwin-amd64 |
| Linux AMD64 | onwatch-linux-amd64 |
| Linux ARM64 | onwatch-linux-arm64 |
| Windows AMD64 | onwatch-windows-amd64.exe |
Installation
curl -fsSL https://raw.githubusercontent.com/onllm-dev/onwatch/main/install.sh | bash
Or download the binary for your platform from the assets below.
- fix(security): Moved inline theme script to external file for CSP compliance
- Active cycles now appear at top of cycle overview with no end time
- Improved table sort styling with visual indicators
Full changelog
What's Changed
Bug Fixes
- fix(security): Move inline theme script to external file for CSP compliance
- fix(session): Use fixed quota order for Anthropic session tracking
- Ensures 5-Hour, Weekly, and Sonnet columns display correct data
- fix(tracker): Exclude reset snapshot from peak to match cross-quota query
- fix(tracker): Use hour precision for Synthetic cycle detection
- Prevents false cycle creation from minute-level API jitter
Features
- feat(cycle-overview): Include active cycles in cycle overview
- Active cycles now appear at top with no end time
- feat(ui): Improved table sort styling with visual indicators
Installation
Download the binary for your platform and run:
chmod +x onwatch-*
./onwatch-darwin-arm64 # or your platform binary
Or update an existing installation:
./onwatch update
- Run the new binary or `onwatch update` then restart; the push_subscriptions table is created automatically.
- In Settings → Notifications enable "Push Notifications" and grant browser permission when prompted.
- Use the "Send Test Push" button to verify delivery.
- Progressive Web App with standalone install, manifest.json, SW.js for push handling
- Browser push notifications via VAPID (RFC 8291/8292) without external services
- SMTP email alerts now documented and include per‑quota threshold overrides
Full changelog
Downloads
| Platform | Binary | Size |
|----------|--------|------|
| macOS (Apple Silicon) | onwatch-darwin-arm64 | 13 MB |
| macOS (Intel) | onwatch-darwin-amd64 | 14 MB |
| Linux (AMD64) | onwatch-linux-amd64 | 13 MB |
| Linux (ARM64) | onwatch-linux-arm64 | 13 MB |
| Windows (AMD64) | onwatch-windows-amd64.exe | 14 MB |
One-line install (macOS/Linux):
curl -fsSL https://raw.githubusercontent.com/onllm-dev/onwatch/main/install.sh | bash
Or upgrade an existing installation:
onwatch update
What's New in v2.7.0
PWA Support with Push Notifications (Beta)
onWatch is now a Progressive Web App — install it from your browser for a native app experience on desktop and mobile.
- Browser push notifications — Get system notifications when quotas cross warning or critical thresholds, or when quotas reset. No external push services required.
- Web Push protocol (VAPID) — Full RFC 8291 (content encryption) and RFC 8292 (VAPID JWT) implementation using only stdlib + existing
golang.org/x/crypto. Zero new Go dependencies. - VAPID keys auto-generated — ECDSA P-256 key pair created on first run and stored in the database. No configuration needed.
- Delivery channels — Choose email, push, or both in Settings → Notifications → Delivery Channels. Each channel can be toggled independently.
- Service worker — Minimal push-only service worker (no offline caching). Served from root
/sw.jsfor full scope. - PWA manifest —
manifest.jsonwith standalone display mode, teal theme color, and SVG icon. Browser shows "Install app" option. - Test push button — Send a test push notification from the settings page (30s rate limit, same pattern as SMTP test).
SMTP Email Alerts (Stable)
The notification system from v2.6.0 is now fully documented across all user-facing pages:
- Per-quota threshold overrides — Set custom warning/critical thresholds for individual quotas
- SMTP password encryption — AES-256-GCM encryption at rest, key derived from admin password
- Three alert types — Warning (configurable %), Critical (configurable %), and Reset notifications
Notification Deduplication Fix
- Once per cycle per event — Notifications are now sent exactly once per reset cycle per quota+type (warning, critical, reset). Previously, the cooldown-based approach could re-send alerts every 30 minutes while a quota remained above threshold.
- Automatic log clearing — Notification log entries are cleared when a quota resets, allowing fresh alerts in the new cycle.
Windows Cross-Compilation Fix
- Added missing
detectAnthropicCredentialsPlatform()andWriteAnthropicCredentials()toanthropic_token_windows.go— fixes the Windows build that broke after the OAuth token refresh feature in v2.6.0.
Backend Changes
| Component | Change |
|-----------|--------|
| internal/notify/push.go | New — Web Push sender: VAPID key generation, RFC 8291 content encryption, RFC 8292 JWT signing, HTTP delivery |
| internal/notify/push_test.go | New — Tests for VAPID generation, encryption round-trip, JWT signing, send with httptest |
| internal/web/static/sw.js | New — Service worker for push event handling and notification click |
| internal/web/static/manifest.json | New — PWA manifest with standalone display mode |
| internal/notify/notify.go | Extended — Dual-channel dispatch (email + push), channel config, once-per-cycle dedup |
| internal/store/store.go | Extended — push_subscriptions table, CRUD methods, ClearNotificationLog() |
| internal/web/handlers.go | Extended — Push API endpoints, extended Notifier interface |
| internal/web/server.go | Extended — Routes for /sw.js, /manifest.json, push API; CSP worker-src 'self' |
| internal/web/middleware.go | Updated — isStaticAsset() includes /sw.js and /manifest.json |
| internal/web/templates/layout.html | Updated — <link rel="manifest"> and <meta name="theme-color"> |
| internal/web/templates/settings.html | Extended — Delivery Channels section with email/push toggles |
| internal/web/static/app.js | Extended — SW registration, push subscription management, channel settings |
| internal/api/anthropic_token_windows.go | Fixed — Added missing OAuth credential detection and write stubs |
| main.go | Updated — notifier.ConfigurePush() call on startup |
Push Notification API Endpoints
| Endpoint | Method | Description |
|----------|--------|-------------|
| /api/push/vapid | GET | Returns VAPID public key for push subscription |
| /api/push/subscribe | POST | Subscribe a push endpoint |
| /api/push/subscribe | DELETE | Unsubscribe a push endpoint |
| /api/push/test | POST | Send test push notification (30s rate limit) |
Performance
No measurable impact on RAM. Push components add < 1 KB steady-state memory:
| Component | Cost |
|-----------|------|
| VAPID key pair in memory | ~200 bytes |
| Push subscriptions (1-3 devices) | ~500 bytes |
| sw.js + manifest.json (embed.FS) | ~1 KB (already in binary) |
| HTTP POST per push send | ~2 KB temp buffer |
Idle RSS remains ~28 MB with all three providers polling.
Dependency Impact
Zero new Go dependencies. Web Push uses:
crypto/ecdsa,crypto/ecdh,crypto/elliptic(stdlib)crypto/aes,crypto/cipher(stdlib)golang.org/x/crypto/hkdf(already a dependency)encoding/base64,net/http(stdlib)
Upgrade Guide
- Download the binary for your platform or run
onwatch update - Restart onWatch — the
push_subscriptionstable is created automatically - Open Settings → Notifications → Delivery Channels
- Enable "Push Notifications" and allow browser permission when prompted
- Click "Send Test Push" to verify
VAPID keys are generated automatically on first startup. No manual configuration required.
Full Changelog
Since v2.5.1:
feat: PWA support with push notifications (Beta) and SMTP email alertsfeat(anthropic): OAuth token refresh and auth failure rate limitingfeat(docker): Docker support with distroless base imagefeat(settings): Provider-grouped overrides, dual toggles, polling controlrefactor: Restructure project layout with docs/, tests/, app.sh entry pointrefactor(insights): Remove duplicate Avg Window Usage cards, add sublabel to statsux(insights): Improve analyzing state for insufficient datatest: Comprehensive E2E and integration testing suitedocs: Update dashboard screenshots, fix capture tool for missing providersfix: Windows cross-compilation for Anthropic OAuth stubsfix: Notification dedup — once per cycle per event instead of cooldown-based
- Replaced SHA-256 password hashing with bcrypt — critical upgrade to mitigate brute-force attacks
- Added comprehensive HTTP security headers (CSP, X-Frame-Options, etc.)
- Enhanced session cookie security with Secure and SameSite=Strict flags
Full changelog
onWatch v2.5.1 — Security & Stability Release
This release includes comprehensive security improvements and infrastructure enhancements to make onWatch production-ready.
🔒 Security Enhancements
Password Security Upgrade
- Migrated from SHA-256 to bcrypt for password hashing
- bcrypt provides superior protection against brute-force attacks with adaptive cost factor
- Backward compatible — existing SHA-256 password hashes continue to work
- Automatic migration to bcrypt on next login
HTTP Security Headers
Added comprehensive security headers to all responses:
X-Content-Type-Options: nosniff— Prevents MIME type sniffingX-Frame-Options: DENY— Blocks clickjacking attemptsX-XSS-Protection: 1; mode=block— Legacy XSS protectionReferrer-Policy: strict-origin-when-cross-origin— Controls referrer informationContent-Security-Policy— Comprehensive CSP restricting resources to trusted domains
Session Cookie Security
- Secure flag — Cookies only transmitted over HTTPS (auto-detected)
- SameSite=Strict — Protection against CSRF attacks
- HttpOnly — Prevents JavaScript access to session tokens
Rate Limiting Framework
- IP-based rate limiting with configurable windows
- Returns 429 Too Many Requests with Retry-After header
- Support for X-Forwarded-For headers (proxy-friendly)
IP Whitelist Middleware
- CIDR notation support for network ranges
- Single IP support
- Comprehensive logging of blocked attempts
📊 Backend Changes
| Component | Change | Impact |
|-----------|--------|--------|
| Password Hashing | SHA-256 → bcrypt | Critical security improvement |
| Session Cookies | Added Secure, SameSite=Strict | High security improvement |
| HTTP Headers | 5 new security headers | Medium security improvement |
| Rate Limiting | New framework | Infrastructure for DoS protection |
| IP Whitelist | New middleware | Infrastructure for access control |
🎯 Performance
- Binary size: ~13 MB (macOS/Linux), ~14 MB (Windows)
- RAM usage: Unchanged (~28 MB idle with all providers)
- Startup time: Unchanged (<100ms)
- All existing functionality: Preserved and tested
🔄 Upgrade Guide
Automatic Update (Recommended)
onwatch update
Manual Update
- Download the appropriate binary for your platform below
- Replace your existing onwatch binary
- Restart:
onwatch stop && onwatch
No Configuration Changes Required
- All settings and data are preserved
- Database schema unchanged
- Environment variables unchanged
📥 Downloads
| Platform | Architecture | Size | Download |
|----------|-------------|------|----------|
| macOS | Apple Silicon (ARM64) | 13 MB | onwatch-darwin-arm64 |
| macOS | Intel (AMD64) | 13 MB | onwatch-darwin-amd64 |
| Linux | AMD64 | 13 MB | onwatch-linux-amd64 |
| Linux | ARM64 | 13 MB | onwatch-linux-arm64 |
| Windows | AMD64 | 14 MB | onwatch-windows-amd64.exe |
One-line install:
curl -fsSL https://raw.githubusercontent.com/onllm-dev/onwatch/main/install.sh | bash
🧪 Testing
- All tests pass: 8 packages, 100+ test cases
- Race detector: Verified (no race conditions)
- End-to-end testing: Login, dashboard, settings, password change
- Cross-platform: Verified on macOS, Linux, Windows
- Backward compatibility: Legacy password hashes work
🛡️ Security Considerations for Production
While this release significantly improves security, please note:
- HTTPS Required: The Secure cookie flag requires HTTPS in production
- Reverse Proxy Recommended: Use nginx, Caddy, or Traefik with HTTPS
- Strong Passwords: bcrypt protects weak passwords, but use strong ones
- IP Whitelist: Consider enabling for public deployments
- Rate Limiting: Enable if exposing to public networks
See SECURITY.md for detailed deployment guidance.
📝 Full Changelog
Added:
- bcrypt password hashing with automatic migration
- 5 security headers (CSP, X-Frame-Options, etc.)
- Secure and SameSite=Strict cookie flags
- Rate limiting framework
- IP whitelist middleware
- Beta tag on Settings page
- Beta banner on landing page
Changed:
- Password hashing algorithm (SHA-256 → bcrypt)
- Cookie security flags enhanced
- README updated with beta notice
Deprecated:
- SHA-256 password hashes (still supported for backward compatibility)
Fixed:
- None (this is a security enhancement release)
Security:
- Critical: Replaced weak SHA-256 password hashing with bcrypt
- High: Added comprehensive HTTP security headers
- High: Enhanced session cookie security
- Medium: Added rate limiting infrastructure
- Medium: Added IP whitelist infrastructure
🤝 Contributors
Thanks to everyone who contributed to this release through testing, feedback, and security audits.
Full commit history: https://github.com/onllm-dev/onwatch/compare/v2.5.0...v2.5.1
- Cross-quota ratio insight card with updated documentation
- Settings page adding SMTP notification and provider control options
Full changelog
🚀 onWatch v2.5.0 Released
📥 Download
| Platform | Architecture | Binary | Size |
|----------|-------------|--------|------|
| macOS | Apple Silicon | onwatch-darwin-arm64 | 13 MB |
| macOS | Intel | onwatch-darwin-amd64 | 13 MB |
| Linux | x86_64 | onwatch-linux-amd64 | 13 MB |
| Linux | ARM64 | onwatch-linux-arm64 | 13 MB |
| Windows | x86_64 | onwatch-windows-amd64.exe | 14 MB |
✨ What's New
Anthropic Token Auto-Detection Improvements
This release significantly improves Anthropic (Claude Code) token detection, particularly for users running onWatch as a systemd service:
- Systemd Service Support: Fixed token detection when $HOME environment variable is not available (common in systemd services)
- Dual Home Directory Resolution: Now attempts both
os.UserHomeDir()(respects $HOME) anduser.Current().HomeDir(reads from passwd database) for maximum compatibility - Enhanced Debug Logging: Added detailed debug logs for credential file lookup failures to help diagnose detection issues
- Improved Error Handling: Better flow with explicit checks for empty tokens and credential parsing failures
Performance
- RAM Usage: Maintains ~28 MB idle footprint with all three providers polling
- Load Tested: 1,104 requests in 15 seconds with average response time of 2.58 ms
- Memory Efficient: No ORM, single SQLite connection, bounded buffers throughout
🔧 Backend Changes
| Change | File | Description |
|--------|------|-------------|
| Enhancement | internal/api/anthropic_token_unix.go | Improved token detection with fallback home directory resolution |
| Chore | .gitignore | Added perf-monitor artifacts to ignore list |
| Version | VERSION | Bumped to 2.5.0 |
⬆️ Upgrade Guide
macOS (Homebrew - coming soon)
brew upgrade onwatch
Manual Installation
- Download the appropriate binary for your platform above
- Stop the current onWatch instance:
./onwatch stop - Replace the binary:
mv onwatch-darwin-arm64 /usr/local/bin/onwatch - Restart:
./onwatch
Self-Update (v2.4.0+)
If running v2.4.0 or later:
./onwatch update
📝 Full Changelog
- dfe1e4c chore: bump version to 2.5.0
- 758dfd0 feat: improve Anthropic token detection for systemd services
- 6fecc10 feat: cross-quota ratio insight card + docs update
- edcb7b5 feat: settings page with SMTP notifications and provider controls
- 1723117 fix: insight card layout and cycle overview raw values for Synthetic/Z.ai
- 392e1b5 fix: show days in duration format and use 2-column Anthropic card grid
🙏 Thanks
Thanks to all users providing feedback and reporting issues. The systemd service improvements in this release were driven by community reports.
- Runtime memory tuning: GOMEMLIMIT=40MiB, GOGC=50, periodic FreeOSMemory goroutine
- SQLite connection pool limited to MaxOpenConns=2, MaxIdleConns=1 with reduced cache_size=-500 (512 KB)
- HTTP transport clients now use MaxIdleConns=1 and MaxIdleConnsPerHost=1
Full changelog
Downloads
| Platform | Binary | Architecture |
|----------|--------|-------------|
| macOS (Apple Silicon) | onwatch-darwin-arm64 | ARM64 (M1/M2/M3/M4) |
| macOS (Intel) | onwatch-darwin-amd64 | x86_64 |
| Linux | onwatch-linux-amd64 | x86_64 |
| Linux (ARM) | onwatch-linux-arm64 | ARM64 (Raspberry Pi 4+, AWS Graviton) |
| Windows | onwatch-windows-amd64.exe | x86_64 |
One-line install (macOS/Linux):
curl -fsSL https://raw.githubusercontent.com/onllm-dev/onwatch/main/install.sh | bash
Existing users: Click the update badge in the dashboard footer, or run onwatch update.
What's New
Runtime Memory Optimization
onWatch now actively manages its memory footprint through Go runtime tuning. Three techniques work together to keep RSS low:
| Technique | What It Does |
|-----------|-------------|
| GOMEMLIMIT=40MiB | Sets a soft heap limit that triggers MADV_DONTNEED on macOS/Linux, causing freed pages to actually be released back to the OS instead of being held as reclaimable (MADV_FREE) |
| GOGC=50 | Triggers garbage collection at 50% heap growth instead of the default 100%, running GC more frequently with negligible CPU cost for an I/O-bound daemon |
| FreeOSMemory() goroutine | Every 5 minutes, forces the Go runtime to return unused memory to the OS, preventing RSS from permanently ratcheting up after transient allocations |
This is a soft limit — it cannot crash the application. If the heap needs to exceed 40 MiB, Go simply exceeds the limit rather than OOM-killing.
SQLite Connection Pool Tuning
The default database/sql pool was creating multiple connections, each with its own 2 MB page cache. Now tuned to:
MaxOpenConns=2— allows one concurrent read + writeMaxIdleConns=1— keeps only one connection cached when idlecache_size=-500(512 KB) — reduced from 2 MB, sufficient for sequential inserts
HTTP Transport Optimization
All four HTTP clients (Synthetic, Z.ai, Anthropic, and the updater) now use MaxIdleConns=1, MaxIdleConnsPerHost=1. Each client only talks to a single host, so the default pool of 100 idle connections was wasteful.
Server-Side Chart Downsampling
History endpoints now downsample large datasets to a maximum of 500 data points before sending to the browser. This keeps chart rendering fast without truncating your data:
- Algorithm: Even step sampling that always preserves the first and last data points
- Threshold: Only activates when the dataset exceeds 500 points (e.g., 7-day view at 1-minute polling = ~10,080 points → 500)
- No data loss: The full dataset is still queried from SQLite; only the JSON response is thinned
- Time ranges unaffected: No artificial SQL LIMIT on chart/history endpoints — the time range remains the natural bound
Anthropic Query Optimization
The raw_json column (stored on every Anthropic snapshot INSERT for debugging) is no longer loaded on queries. This avoids unnecessary memory allocations when rendering the dashboard.
Bounded Cycle Table Queries
Cycle history endpoints now cap results at 200 per quota type, and insight cycle queries cap at 50. The frontend already paginates client-side, so this has zero visual impact while preventing unbounded memory growth as cycle history accumulates.
Performance
Measured with tools/perf-monitor while all three provider agents (Synthetic, Z.ai, Anthropic) ran in parallel:
| Metric | v2.3.4 | v2.4.0 | Budget |
|--------|--------|--------|--------|
| Idle RSS (avg) | 27.5 MB | 28.0 MB | 30 MB |
| Idle RSS (P95) | 27.5 MB | 28.0 MB | 30 MB |
| Load RSS (avg) | 28.5 MB | 35.1 MB | 50 MB |
| Load RSS (P95) | 29.0 MB | 35.9 MB | 50 MB |
| Load delta | +0.9 MB | +7.1 MB | <20 MB |
| Throughput | 1,160 reqs/15s | 1,104 reqs/15s | — |
| Avg API response | 0.28 ms | 0.75 ms | <5 ms |
| Avg dashboard | 0.69 ms | 2.58 ms | <10 ms |
Why is load RSS higher? The downsampling allocates temporary slices to process the full dataset before thinning. This is a deliberate tradeoff: the previous v2.3.4 numbers reflected hardcoded LIMIT 200 SQL queries that truncated 7-day charts. v2.4.0 queries the full time range and downsamples server-side, preserving data fidelity. Idle RSS (the number that matters for a background daemon) remains well within budget.
Backend Changes
| File | Change |
|------|--------|
| main.go | Added GOMEMLIMIT, GOGC, FreeOSMemory goroutine |
| internal/store/store.go | MaxOpenConns=2, MaxIdleConns=1, cache_size=-500 |
| internal/api/client.go | MaxIdleConns=1 on HTTP transport |
| internal/api/zai_client.go | MaxIdleConns=1 on HTTP transport |
| internal/api/anthropic_client.go | MaxIdleConns=1 on HTTP transport |
| internal/update/update.go | MaxIdleConns=1 on HTTP transport |
| internal/store/anthropic_store.go | Removed raw_json from SELECT queries |
| internal/web/handlers.go | Added downsampleStep() + maxChartPoints=500, applied to all 4 history handlers; cycle queries capped at 200, insight cycles at 50 |
Upgrade Guide
From v2.3.x: Update via dashboard or onwatch update. No configuration changes needed — all optimizations are internal.
From source:
git pull origin main
make build
./onwatch stop && ./onwatch
Full Changelog
https://github.com/onllm-dev/onWatch/compare/v2.3.4...v2.4.0
- If the service is stopped after a failed update from v2.3.1, manually start it with `systemctl start onwatch` to run the migration in v2.3.3 before triggering the v2.3.4 update.
Full changelog
Downloads
| Platform | Binary | Architecture |
|----------|--------|-------------|
| macOS (Apple Silicon) | onwatch-darwin-arm64 | ARM64 (M1/M2/M3/M4) |
| macOS (Intel) | onwatch-darwin-amd64 | x86_64 |
| Linux | onwatch-linux-amd64 | x86_64 |
| Linux (ARM) | onwatch-linux-arm64 | ARM64 (Raspberry Pi 4+, AWS Graviton) |
| Windows | onwatch-windows-amd64.exe | x86_64 |
What's Fixed
Apply()-Time systemd Migration
v2.3.3 added startup migration to fix the systemd unit file, but it only worked when the new binary got to execute (v2.3.0 → v2.3.3 path where the old binary spawns a child). For v2.3.1 → v2.3.3, the old binary's Restart() called os.Exit(0) without spawning anything, so the new binary's migration code never ran.
v2.3.4 fixes this by moving the migration into Apply() itself. Now the unit file is fixed while the current process is still alive, before Restart() is ever called. This means:
- Even if
Restart()doesos.Exit(0), the unit already hasRestart=always - systemd will auto-restart the service after the process exits
- The new binary starts and everything works
Three layers of protection (from v2.3.4+):
| When | What | Why |
|------|------|-----|
| Apply() | Fixes unit file before Restart() | Ensures Restart=always before any exit |
| Restart() | Runs systemctl restart | Proper systemd lifecycle management |
| Startup | MigrateSystemdUnit() before stopPreviousInstance() | Safety net for spawn-based upgrades |
Cumulative fixes (v2.3.1–v2.3.4)
- v2.3.1: Anthropic token auto-refresh, systemd detection
- v2.3.2:
systemctl restartin Restart(), Anthropic 401 retry - v2.3.3: Startup unit migration, service name auto-detection from cgroup
- v2.3.4: Apply()-time unit migration (this release)
Current State
If your service is stopped after a failed update from v2.3.1:
systemctl start onwatch
This starts v2.3.3 (already on disk from the previous update), which fixes the unit file. Then trigger the update to v2.3.4 from the dashboard — this time it will restart automatically.
Full Changelog
https://github.com/onllm-dev/onWatch/compare/v2.3.3...v2.3.4
- If the service is running, trigger update via dashboard – v2.3.3 handles restart automatically.
- If the service is stopped (e.g., after a failed v2.3.1 update), start it with `sudo systemctl start onwatch` to let the migration run.
- Fresh installations can continue using the existing install script.
- Automatic migration of systemd unit file: Restart=on-failure → always and RestartSec=10 → 5 on each startup
- Anthropic 401 token retry logic forces immediate credential re‑read and retries once
- Self‑update under systemd now uses `systemctl restart` instead of spawning a child process
Full changelog
Downloads
| Platform | Binary | Architecture |
|----------|--------|-------------|
| macOS (Apple Silicon) | onwatch-darwin-arm64 | ARM64 (M1/M2/M3/M4) |
| macOS (Intel) | onwatch-darwin-amd64 | x86_64 |
| Linux | onwatch-linux-amd64 | x86_64 |
| Linux (ARM) | onwatch-linux-arm64 | ARM64 (Raspberry Pi 4+, AWS Graviton) |
| Windows | onwatch-windows-amd64.exe | x86_64 |
What's New
Zero-Touch systemd Self-Update Migration
Previous versions had a chicken-and-egg problem with systemd self-updates: the old binary needed to restart the service, but its restart code was broken under systemd, and the systemd unit file had Restart=on-failure which doesn't restart on clean exits.
v2.3.3 solves this by having the new binary fix things itself. On every startup, onWatch checks its own systemd unit file and auto-migrates stale settings:
Restart=on-failure→Restart=alwaysRestartSec=10→RestartSec=5
The critical insight is when this runs. The migration executes before stopPreviousInstance() in the startup sequence. Here's why that matters:
Upgrade sequence (v2.3.0 → v2.3.3 under systemd):
1. Old binary (v2.3.0) downloads v2.3.3, replaces binary on disk
2. Old binary spawns new binary as child process (same cgroup)
3. New binary starts run():
a. Reads unit file, fixes Restart=on-failure → Restart=always
b. Runs systemctl daemon-reload (synchronous, completes while parent alive)
c. Calls stopPreviousInstance() → sends SIGTERM to parent
4. Parent dies (exit 0)
5. systemd starts cgroup cleanup → kills child too
6. systemd checks restart policy → now Restart=always → auto-restarts
7. Fresh v2.3.3 starts under systemd. Done!
Zero manual intervention. The child process is ephemeral — it fixes the unit file, triggers the kill chain, and lets systemd handle the rest.
This is idempotent: on subsequent starts, the unit file is already correct and nothing changes.
Also included (from v2.3.2)
- Anthropic 401 token retry: On unauthorized response, forces immediate credential re-read and retries once
- systemctl restart: Under systemd, self-update uses
systemctl restartinstead of spawning a child
Backend Changes
| File | Change |
|------|--------|
| internal/update/update.go | Added MigrateSystemdUnit() — reads/fixes/reloads systemd unit on startup |
| internal/update/update.go | Added findUnitFile() — locates system-level or user-level unit |
| main.go | Calls MigrateSystemdUnit() before stopPreviousInstance() |
Upgrade
If your service is currently running (any version)
Trigger the update from the dashboard — v2.3.3 handles the restart automatically.
If your service is currently stopped (from a failed v2.3.1 update)
sudo systemctl start onwatch
# v2.3.3 fixes the unit file on startup, future updates work automatically
Fresh install
curl -fsSL https://onwatch.onllm.dev/install.sh | bash
Full Changelog
https://github.com/onllm-dev/onWatch/compare/v2.3.2...v2.3.3
- If using v2.3.0 or v2.3.1, edit `/etc/systemd/system/onwatch.service` to set `Restart=always` and `RestartSec=5`, then run `sudo systemctl daemon-reload`
- Follow the provided upgrade steps when moving from v2.3.0/v2.3.1 to ensure systemd restarts correctly
- Systemd unit defaults changed to Restart=always with RestartSec=5 for safer restarts
- Anthropic API client retries once after a 401 by re‑reading the token
Full changelog
Downloads
| Platform | Binary | Architecture |
|----------|--------|-------------|
| macOS (Apple Silicon) | onwatch-darwin-arm64 | ARM64 (M1/M2/M3/M4) |
| macOS (Intel) | onwatch-darwin-amd64 | x86_64 |
| Linux | onwatch-linux-amd64 | x86_64 |
| Linux (ARM) | onwatch-linux-arm64 | ARM64 (Raspberry Pi 4+, AWS Graviton) |
| Windows | onwatch-windows-amd64.exe | x86_64 |
What's Fixed
systemd Self-Update Now Restarts Properly
v2.3.1 issue: The systemd fix used os.Exit(0) to let systemd restart the service. However, most installations use Restart=on-failure in their systemd unit, which does not restart on a clean exit (code 0). Result: the service stopped and never came back.
v2.3.2 fix: Instead of exiting, onWatch now runs systemctl restart <service> directly. The service name is auto-detected from /proc/self/cgroup (falls back to onwatch.service). systemd handles the full stop→start lifecycle, so the service restarts reliably regardless of the Restart= setting.
Additionally, install.sh now creates systemd units with Restart=always and RestartSec=5 (previously on-failure / 10s) as a safety net.
If you're on v2.3.0 or v2.3.1 and experienced the restart issue, update your systemd unit:
# Edit the unit file
sudo nano /etc/systemd/system/onwatch.service
# Change: Restart=on-failure → Restart=always
# Change: RestartSec=10 → RestartSec=5
# Then reload:
sudo systemctl daemon-reload
Anthropic 401 Token Retry
v2.3.1 issue: Token auto-refresh re-reads credentials before each poll, but if the stored token is expired and gets a 401, onWatch just logged the error and waited 60s for the next poll — even if Claude Code had already refreshed the token on disk between the read and the API call.
v2.3.2 fix: On a 401 response, onWatch immediately:
- Clears the cached token (forces a fresh file/keychain read)
- Re-reads credentials from disk
- Retries the API call once with the new token
This handles the race condition where Claude Code rotates the token between our file read and API call. If the retry also fails, it logs the error and waits for the next poll cycle.
Backend Changes
| File | Change |
|------|--------|
| internal/update/update.go | Restart() now uses systemctl restart under systemd; added detectServiceName() from /proc/self/cgroup |
| internal/agent/anthropic_agent.go | poll() retries on 401 with forced token re-read |
| install.sh | systemd units now use Restart=always, RestartSec=5 |
Upgrade
From v2.3.0 or v2.3.1 (manual — recommended for this release)
sudo systemctl stop onwatch
curl -fsSL https://github.com/onllm-dev/onWatch/releases/download/v2.3.2/onwatch-linux-amd64 -o /root/.onwatch/bin/onwatch
chmod +x /root/.onwatch/bin/onwatch
sudo systemctl start onwatch
Dashboard self-update
If you're on v2.3.1 and your service is running, the update button will work — v2.3.2 will use systemctl restart for a clean restart.
Install script (fresh install)
curl -fsSL https://onwatch.onllm.dev/install.sh | bash
Full Changelog
https://github.com/onllm-dev/onWatch/compare/v2.3.1...v2.3.2
- Systemd-aware self‑update restart exits cleanly, avoiding delayed service recovery
Full changelog
Downloads
| Platform | Binary | Architecture |
|----------|--------|-------------|
| macOS (Apple Silicon) | onwatch-darwin-arm64 | ARM64 (M1/M2/M3/M4) |
| macOS (Intel) | onwatch-darwin-amd64 | x86_64 |
| Linux | onwatch-linux-amd64 | x86_64 |
| Linux (ARM) | onwatch-linux-arm64 | ARM64 (Raspberry Pi 4+, AWS Graviton) |
| Windows | onwatch-windows-amd64.exe | x86_64 |
What's Fixed
Anthropic OAuth Token Auto-Refresh
Previously, the Anthropic OAuth token was read once at startup and never updated. If the token expired (which happens regularly — Claude Code rotates them), onWatch would log "anthropic: unauthorized - invalid API key" on every poll until manually restarted.
Now: The Anthropic agent re-reads the token from the credentials source (macOS Keychain, Linux keyring, or ~/.claude/.credentials.json) before each poll. When Claude Code rotates the token, onWatch picks it up automatically within 60 seconds. A log message "Anthropic token refreshed from credentials" confirms when a rotation is detected.
This works automatically — no configuration changes needed. Users upgrading from any previous version get this fix immediately.
systemd-Aware Self-Update Restart
Previously, the self-update (/api/update/apply) spawned a child process to replace the old one. Under systemd, this caused the tracked PID to die, making systemd think the service crashed. The result was a ~70-second gap (systemd's RestartSec delay) before the service came back.
Now: onWatch detects if it's running under systemd (via the INVOCATION_ID environment variable). If so, after replacing the binary it simply exits cleanly — systemd restarts the service instantly with the new binary. Standalone (non-systemd) mode continues to use the spawn-and-replace approach.
Backend Changes
| File | Change |
|------|--------|
| internal/api/anthropic_client.go | Added SetToken() method for runtime token updates |
| internal/agent/anthropic_agent.go | Added TokenRefreshFunc — re-detects credentials before each poll |
| internal/update/update.go | Added IsSystemd() detection; Restart() now exits cleanly under systemd |
| main.go | Wired token refresh to DetectAnthropicToken() for auto-detected tokens |
Upgrade
From v2.3.0 (dashboard self-update)
Click the update badge in the dashboard footer. Under systemd, the restart will now be instant instead of delayed.
From v2.2.x (manual)
# systemd
sudo systemctl stop onwatch
# Download new binary for your platform
sudo cp onwatch-linux-amd64 /root/.onwatch/bin/onwatch
sudo chmod +x /root/.onwatch/bin/onwatch
sudo systemctl start onwatch
Install script
curl -fsSL https://onwatch.onllm.dev/install.sh | bash
Full Changelog
https://github.com/onllm-dev/onWatch/compare/v2.3.0...v2.3.1
- All HTTP responses are gzip‑compressed (BestSpeed) using sync.Pool for writer reuse
- Static files served with Cache-Control: public, max-age=31536000, immutable and versioned URLs
Full changelog
Downloads
| Platform | Binary | Architecture |
|----------|--------|-------------|
| macOS (Apple Silicon) | onwatch-darwin-arm64 | ARM64 (M1/M2/M3/M4) |
| macOS (Intel) | onwatch-darwin-amd64 | x86_64 |
| Linux | onwatch-linux-amd64 | x86_64 |
| Linux (ARM) | onwatch-linux-arm64 | ARM64 (Raspberry Pi 4+, AWS Graviton) |
| Windows | onwatch-windows-amd64.exe | x86_64 |
What's New
Gzip Compression
All HTTP responses are now gzip-compressed, reducing transfer sizes by 60–70%. The dashboard's JS + CSS payload drops from ~170 KB to ~50 KB over the wire. Uses sync.Pool for writer reuse with BestSpeed level — minimal CPU overhead.
Immutable Static Asset Caching
Static files (app.js, style.css, favicon.svg) are now served with Cache-Control: public, max-age=31536000, immutable. URLs are versioned via ?v=2.3.0 query params for automatic cache busting on upgrades. Repeat visits load instantly — zero network requests for cached assets.
Parallel API Fetches
The dashboard's 4 critical above-fold API calls (/api/current, /api/history, /api/insights, /api/settings) now fire in parallel via Promise.all() instead of sequentially. Saves 300–400ms on initial render.
Lazy Loading for Below-Fold Sections
Cycles table, Cycle Overview, and Sessions table are now loaded on-demand via IntersectionObserver when they scroll into view (with 200px pre-fetch margin). Auto-refresh only refreshes sections that have been loaded. 3 fewer API calls on initial page load.
Font Optimization
- Google Fonts reduced from 11 weights (Inter 5 + JetBrains Mono 3) to 5 weights (Inter 3 + JetBrains Mono 2)
- Added
preconnectforcdn.jsdelivr.net(Chart.js CDN) - Added
<link rel="preload">hints for critical CSS and JS - Moved scripts to end of
<body>withdefer— no longer render-blocking
Production Cleanup
All 17 console.log/warn/error statements removed from app.js. Error handling still works — UI shows fallback states on failure — but the browser console is clean.
Performance Impact
| Metric | Before | After | Improvement |
|--------|--------|-------|-------------|
| Transfer size (JS+CSS) | ~170 KB | ~50 KB | -70% |
| Initial API calls | 7 sequential | 4 parallel + 3 lazy | -400ms |
| Repeat visit asset load | ~170 KB | 0 KB (cached) | -100% |
| Font payload | 11 weights | 5 weights | -55% |
| Console noise | 17 statements | 0 | Clean |
Estimated total improvement: 1.5–2.5 seconds faster initial dashboard load.
RAM budget remains unchanged — idle ~28 MB, load ~29 MB (all 3 agents polling).
Backend Changes
| File | Change |
|------|--------|
| internal/web/server.go | Gzip middleware, Cache-Control headers, sync.Pool writer |
| internal/web/templates/layout.html | Versioned URLs, preload hints, font reduction, deferred scripts |
| internal/web/static/app.js | Promise.all, IntersectionObserver lazy loading, console removal |
Upgrade
Existing users (binary)
onwatch stop
# Download new binary for your platform from assets below
chmod +x onwatch-*
./onwatch
Existing users (install script)
curl -fsSL https://onwatch.onllm.dev/install.sh | bash
Self-update (v2.2.0+)
If running v2.2.0 or later, click the update badge in the dashboard footer.
Full Changelog
https://github.com/onllm-dev/onWatch/compare/v2.2.5...v2.3.0
- Self‑update command `onwatch update` works from v2.2.1+; use one‑line install script for fresh installs.
- Manual updates require downloading the binary, making it executable (`chmod +x`), and replacing the existing binary.
- Self‑update robustness: binary replacement uses os.Remove + os.Rename on Unix and fallback backup‑rename on Windows.
- Truncated pagination UI shows compact `1 … n … last` format for tables with many pages.
- Dashboard HTML now served with Cache-Control: no-store to prevent stale content.
Full changelog
Downloads
| Platform | Binary |
|----------|--------|
| macOS (Apple Silicon) | onwatch-darwin-arm64 |
| macOS (Intel) | onwatch-darwin-amd64 |
| Linux (x86_64) | onwatch-linux-amd64 |
| Linux (ARM64) | onwatch-linux-arm64 |
| Windows (x86_64) | onwatch-windows-amd64.exe |
What's New
Self-Update Robustness (3 bugs fixed)
- Binary replacement: Uses
os.Remove+os.Renameon Unix (avoidslstat .old: no such file or directoryerrors on Linux). Falls back to backup-rename on Windows. - Update badge visibility: Fixed CSS where
display: inline-flexoverrode the HTMLhiddenattribute — badge now properly hides when no update is available. - Server restart after dashboard update: Fixed
pollForRestart()to detect server downtime before reloading, and uses cache-busting URL to prevent stale page from browser cache. Fixed/proc/self/exeresolution on Linux after binary replacement.
Mobile Dashboard Fix
- Truncated pagination: Tables with many pages now show compact
1 … 4 5 6 7 … 31format instead of all page buttons. - No horizontal overflow: Added
flex-wrapandoverflow-x: hidden.
Other Improvements
- Apply() forces a fresh GitHub API check (bypasses stale 1-hour cache)
- Version comparison handles pre-release suffixes (e.g.,
2.2.5-test) - Dashboard HTML served with
Cache-Control: no-store - Download timeout increased from 30s to 2min for slow connections
- 4 new unit tests for replaceBinary and filterArgs
E2E Tested
Full update flow verified with browser automation:
- Dashboard shows "Update to vX.Y.Z" badge when update available
- Click update → binary downloaded, validated, replaced
- Server restarts → page reloads with new version
- Badge correctly hidden after update (no update available)
Upgrade
One-line install (Linux/macOS)
curl -fsSL https://raw.githubusercontent.com/onllm-dev/onwatch/main/install.sh | bash
Self-update (v2.2.1+)
onwatch update
Or click the update button in the dashboard footer.
Manual
Download the binary for your platform, chmod +x, and replace the existing binary.
Full Changelog
https://github.com/onllm-dev/onWatch/compare/v2.2.4...v2.2.5
- Install script now downloads to /tmp then moves into place to avoid `ETXTBSY` errors on Linux upgrades
- Enhanced error logging in install.sh includes curl exit codes, download size, URL and destination path
- Sanity check rejects downloads under 1 MB; `stop_existing()` polls up to 5 seconds with pgrep
- CLI command `onwatch update` checks GitHub, downloads latest binary atomically and restarts the daemon
- Dashboard footer button triggers automatic server update when a newer version is available
Full changelog
Downloads
| Platform | Binary |
|----------|--------|
| macOS (Apple Silicon) | onwatch-darwin-arm64 |
| macOS (Intel) | onwatch-darwin-amd64 |
| Linux (x86_64) | onwatch-linux-amd64 |
| Linux (ARM64) | onwatch-linux-arm64 |
| Windows (x86_64) | onwatch-windows-amd64.exe |
What's New (v2.2.1 – v2.2.4)
Self-Update Feature
onWatch can now update itself — no more manual downloads or re-running install.sh:
- CLI:
onwatch update— checks GitHub for the latest release, downloads the binary, replaces itself atomically, and restarts the daemon if running - Dashboard: A footer button appears when a newer version is available. Click to update and the server restarts automatically.
Technical details:
- GitHub release check cached for 1 hour (respects API rate limits)
- Streaming download via
io.Copy— no buffering entire binary in RAM - Atomic binary swap via rename (backup → swap → cleanup)
- Magic byte validation (ELF, Mach-O, PE) before replacing
- ~200 bytes idle RAM overhead, zero new dependencies
Install Script Improvements
- Downloads to
/tmpfirst, then moves into place — avoidsETXTBSY(text file busy) errors on Linux when upgrading a running binary - Detailed error logging: curl exit codes, download size, URL, and destination path
- Sanity check rejects downloads under 1MB
stop_existing()now polls up to 5 seconds withpgrepinstead of a fixed 1-second sleep
Bug Fixes
- Fixed CLI
onwatch updatedaemon restart (v2.2.3): was re-running the update command instead of starting a fresh daemon - Fixed
fail()in install.sh:\nin error messages now renders as actual newlines
Upgrade
# From any previous version with self-update:
onwatch update
# Fresh install:
curl -fsSL https://raw.githubusercontent.com/onllm-dev/onwatch/main/install.sh | bash
# Manual download:
curl -fsSL https://github.com/onllm-dev/onWatch/releases/download/v2.2.4/onwatch-$(uname -s | tr '[:upper:]' '[:lower:]')-$(uname -m | sed 's/x86_64/amd64/' | sed 's/aarch64/arm64/') -o /usr/local/bin/onwatch
chmod +x /usr/local/bin/onwatch
Full Changelog
v2.2.1— Self-update feature (CLI + dashboard API + footer button)v2.2.2— Version bumpv2.2.3— Fix CLI update daemon restartv2.2.4— Version bump + install.sh fixes (download to /tmp, error logging)
Fixed `onwatch update` CLI command to properly stop the old daemon and spawn a fresh one.
Full changelog
Downloads
| Platform | Binary |
|----------|--------|
| macOS (Apple Silicon) | onwatch-darwin-arm64 |
| macOS (Intel) | onwatch-darwin-amd64 |
| Linux (x86_64) | onwatch-linux-amd64 |
| Linux (ARM64) | onwatch-linux-arm64 |
| Windows (x86_64) | onwatch-windows-amd64.exe |
Changes
- Fixed
onwatch updateCLI command not properly restarting the daemon after update — was re-running the update command instead of spawning a fresh daemon - The old daemon is now stopped via SIGTERM and a fresh daemon process is spawned
Upgrade
onwatch update
Note: v2.2.4 is the latest release with additional install.sh fixes.
Minor fixes and improvements.
Full changelog
Downloads
| Platform | Binary |
|----------|--------|
| macOS (Apple Silicon) | onwatch-darwin-arm64 |
| macOS (Intel) | onwatch-darwin-amd64 |
| Linux (x86_64) | onwatch-linux-amd64 |
| Linux (ARM64) | onwatch-linux-arm64 |
| Windows (x86_64) | onwatch-windows-amd64.exe |
Changes
- Version bump (includes self-update feature from v2.2.1)
Upgrade
onwatch update
Note: v2.2.4 is the latest release with daemon restart and install.sh fixes.
- Run `onwatch update` to upgrade; note that v2.2.4 contains additional daemon restart fixes
- CLI command `onwatch update` for automatic self‑update with atomic binary swap and daemon restart
- Dashboard footer button triggers server self‑update when a newer version is available
Full changelog
Downloads
| Platform | Binary |
|----------|--------|
| macOS (Apple Silicon) | onwatch-darwin-arm64 |
| macOS (Intel) | onwatch-darwin-amd64 |
| Linux (x86_64) | onwatch-linux-amd64 |
| Linux (ARM64) | onwatch-linux-arm64 |
| Windows (x86_64) | onwatch-windows-amd64.exe |
What's New
Self-Update Feature
onWatch can now update itself! Two interfaces:
- CLI:
onwatch update— checks GitHub for the latest release, downloads the binary, replaces itself atomically, and restarts the daemon if running - Dashboard: A footer button appears when a newer version is available. Click to update and the server restarts automatically.
Technical Details
- GitHub release check cached for 1 hour (respects rate limits)
- Streaming download — no buffering entire binary in RAM
- Atomic binary swap via rename (backup + swap + cleanup)
- Magic byte validation (ELF, Mach-O, PE) before replacing
- ~200 bytes idle RAM overhead
- Zero new dependencies
- 19 unit tests covering version comparison, cache TTL, error cases, binary validation
Upgrade
onwatch update
Note: v2.2.4 is the latest release with daemon restart and install.sh fixes.
- Drop‑in binary replacement; no config or database changes required. The stale connection issue will stop occurring immediately upon upgrade.
- Removed `/robots.txt` and `/llms.txt` route handlers and associated files from the app binary.
- Custom `http.Transport` with ResponseHeaderTimeout, IdleConnTimeout, TLSHandshakeTimeout, and increased client Timeout for Anthropic API clients.
- Per-request context timeout of 30 s added to all agent goroutines.
- Panic recovery (`defer/recover`) implemented on all three agent goroutines.
Full changelog
Download
| Platform | Binary |
|----------|--------|
| macOS (Apple Silicon) | onwatch-darwin-arm64 |
| macOS (Intel) | onwatch-darwin-amd64 |
| Linux (x86_64) | onwatch-linux-amd64 |
| Linux (ARM64) | onwatch-linux-arm64 |
| Windows (x86_64) | onwatch-windows-amd64.exe |
What's New
Fixed: Anthropic API connection stale hang
The Anthropic polling agent would occasionally stop updating because the HTTP connection to api.anthropic.com entered a stale ESTABLISHED state — the TCP connection was alive but no data flowed. The http.Client.Timeout of 10s failed to fire due to an HTTP/2 dead-stream edge case on a "live" TCP connection, blocking the polling goroutine indefinitely.
Symptoms:
- Synthetic and Z.ai snapshots stayed fresh (< 1 min old)
- Anthropic snapshots became 50+ minutes stale
lsofshowed a hung ESTABLISHED connection toapi.anthropic.com- Process was alive, but the Anthropic goroutine was blocked on
httpClient.Do(req)
Root cause: All three API clients used http.Client{Timeout: 10s} with no custom Transport — they shared http.DefaultTransport which lacks ResponseHeaderTimeout and has a 90s IdleConnTimeout that doesn't prevent this issue.
Fix Details
Custom http.Transport for all API clients — each client now uses a dedicated transport with:
ResponseHeaderTimeout: 30s— fires if server accepts connection but doesn't send response headers (the key fix)IdleConnTimeout: 30s— closes idle keep-alive connections between 60s pollsTLSHandshakeTimeout: 10s— prevents TLS negotiation hangsForceAttemptHTTP2: true— keeps HTTP/2 with proper timeouts- Client-level
Timeoutraised from 10s to 30s to match
Per-request context timeout — belt-and-suspenders context.WithTimeout(ctx, 30s) in every FetchQuotas() method, ensuring requests have a hard deadline even if the client timeout fails to fire.
Panic recovery on agent goroutines — all three agent goroutines now have defer/recover to log and surface panics instead of silently dying.
Removed: robots.txt and llms.txt
Removed robots.txt and llms.txt from the app binary. These belong on the landing page (onwatch.onllm.dev), not the dashboard. The v2.1.2 release that added them has been deleted.
Changes
| File | Change |
|------|--------|
| internal/api/anthropic_client.go | Custom Transport + per-request context timeout |
| internal/api/client.go | Custom Transport + per-request context timeout |
| internal/api/zai_client.go | Custom Transport + per-request context timeout |
| internal/api/client_test.go | Updated timeout assertion (10s → 30s) |
| internal/api/zai_client_test.go | Updated timeout assertion (10s → 30s) |
| main.go | Panic recovery on all 3 agent goroutines |
| internal/web/server.go | Removed /robots.txt and /llms.txt route handlers |
| internal/web/middleware.go | Removed isPublicFile() auth bypass |
| internal/web/static/robots.txt | Deleted |
| internal/web/static/llms.txt | Deleted |
| static/robots.txt | Deleted |
| static/llms.txt | Deleted |
| VERSION | 2.1.2 → 2.2.0 |
Performance
No impact on RAM or response times — this is a networking reliability fix only.
| Metric | Value | Budget |
|--------|-------|--------|
| Idle RSS (avg) | 27.5 MB | 30 MB |
| Load RSS (P95) | 29.0 MB | 50 MB |
| Avg API response | 0.28 ms | < 5 ms |
| Avg dashboard response | 0.69 ms | < 10 ms |
Upgrade
Drop-in binary replacement — no config or database changes needed. The stale connection issue will stop occurring immediately.
# One-line upgrade (macOS/Linux)
curl -fsSL https://raw.githubusercontent.com/onllm-dev/onwatch/main/install.sh | bash
# Or manual: download binary, replace, restart
onwatch stop
# replace binary
onwatch
Full changelog: https://github.com/onllm-dev/onWatch/compare/v2.1.1...v2.2.0
- Header controls (change password, theme toggle, logout) wrapped in .header-controls with a compact 6px gap
Full changelog
Download
| Platform | Binary |
|----------|--------|
| macOS (Apple Silicon) | onwatch-darwin-arm64 |
| macOS (Intel) | onwatch-darwin-amd64 |
| Linux (x86_64) | onwatch-linux-amd64 |
| Linux (ARM64) | onwatch-linux-arm64 |
| Windows (x86_64) | onwatch-windows-amd64.exe |
What's New
Header controls spacing fix — The change password, theme toggle, and logout buttons in the dashboard header are now grouped tightly together in the top-right corner. Previously, these three buttons were spread apart by the header's space-between flex layout, creating an awkward gap between them. They are now wrapped in a .header-controls container with a compact 6px gap for a cleaner, more polished look.
Changes
| File | Change |
|------|--------|
| internal/web/templates/dashboard.html | Wrap 3 header buttons in .header-controls div |
| internal/web/static/style.css | Add .header-controls flexbox container (6px gap) |
| static/style.css | Sync copy |
| VERSION | Bump to 2.1.1 |
Upgrade
Replace your existing binary with the one for your platform — no config or database changes needed.
Full changelog: https://github.com/onllm-dev/onWatch/compare/v2.1.0...v2.1.1
- No database migration required; new tables auto‑create on startup.
- Run the install script `curl -fsSL https://raw.githubusercontent.com/onllm-dev/onwatch/main/install.sh | bash` for fresh installations.
- Dynamic Y‑axis scaling zooms to actual data range with 30% headroom
- Per‑minute Anthropic cycle history with burn rate and time‑to‑exhaustion projections
- Stable key‑based chart colors mapped by quota key
Full changelog
onWatch v2.1.0 — Stable Anthropic Support, Dynamic Charts, Comprehensive Screenshots
onWatch v2.1.0 solidifies Anthropic (Claude Code) as a first-class provider with production-ready tracking, dynamic chart scaling, per-minute cycle granularity, and a polished dashboard experience across all three providers.
Download
| Platform | Binary |
|----------|--------|
| macOS ARM64 (Apple Silicon) | onwatch-darwin-arm64 |
| macOS AMD64 (Intel) | onwatch-darwin-amd64 |
| Linux AMD64 | onwatch-linux-amd64 |
| Linux ARM64 | onwatch-linux-arm64 |
| Windows AMD64 | onwatch-windows-amd64.exe |
Or install with one command (macOS/Linux):
curl -fsSL https://raw.githubusercontent.com/onllm-dev/onwatch/main/install.sh | bash
What's New
Dynamic Y-Axis Scaling
- Charts now zoom into the actual data range instead of always showing 0-100%
- Peak data value + 30% headroom, rounded to clean tick marks
- Example: if your 5-Hour Limit peaks at 45%, the chart Y-axis scales to ~60% — making trends and variations far more visible
- Works on all views: single-provider, "All Providers" multi-chart, and modal mini-charts
Per-Minute Anthropic Cycle History
- Cycle History table now shows per-minute polled snapshots instead of coarse reset cycles (which only had 1 row per 5-hour window)
- Grouping controls (1m, 5m, 30m, 1h) now work properly — aggregate multiple snapshots into rows
- Each row shows: utilization peak, delta from previous snapshot, and burn rate (delta/hr)
- Range filters (1h, 3d, 7d, 15d, 30d) limit the time window naturally
Burn Rate Insights for Anthropic
- Current burn rate calculated from recent utilization deltas
- Time to exhaustion projection based on current consumption rate
- Average window usage across recent 5-hour cycles
- Provider-specific insight cards with severity coloring (positive/warning/negative)
Key-Based Chart Colors (Stable)
- Anthropic chart colors are now mapped by quota key, not array index:
five_hour→ Coral (#D97757)seven_day→ Emerald (#10B981)seven_day_sonnet→ Blue (#3B82F6)monthly_limit→ Violet (#A855F7)extra_usage→ Amber (#F59E0B)
- Colors remain stable regardless of quota sort order or dynamic addition/removal
Consistent Display Names
- Anthropic display names synchronized across Go backend and JS frontend:
five_hour→ "5-Hour Limit"seven_day→ "Weekly All-Model"seven_day_sonnet→ "Weekly Sonnet"monthly_limit→ "Monthly Limit"extra_usage→ "Extra Usage"
Provider Tab Reordering
- Default tab order changed to: Anthropic → Synthetic → Z.ai → All
- Anthropic is now the default selected provider on dashboard load
Session Manager Extraction
- Shared session lifecycle logic (create, heartbeat, close) extracted into
session_manager.go - All three agents (Synthetic, Z.ai, Anthropic) now use the same clean session management
- Reduced code duplication across agent files by ~300 lines
Comprehensive Dashboard Screenshots
- 8 new screenshots captured: all 4 provider views × light/dark mode
- Cropped to top half for gallery readability (quota cards + charts + cycle history)
- Landing page gallery updated with Anthropic-first filter, provider + theme toggles
- Login page screenshot removed from gallery
Dashboard Screenshots
| Provider | Light | Dark |
|----------|-------|------|
| Anthropic | anthropic-light.png | anthropic-dark.png |
| Synthetic | synthetic-light.png | synthetic-dark.png |
| Z.ai | zai-light.png | zai-dark.png |
| All Providers | all-light.png | all-dark.png |
Performance
Measured with all three agents (Anthropic + Synthetic + Z.ai) polling in parallel:
| Metric | Value |
|--------|-------|
| Idle RSS | ~30 MB avg |
| Load RSS (under sustained HTTP traffic) | ~30 MB avg |
| Load delta | +0.4 MB (+1.3%) |
| Avg API response | 0.28 ms |
| Avg dashboard response | 0.61 ms |
| Throughput | 1,160+ reqs/15s |
Backend Changes
| Component | File(s) | Change |
|-----------|---------|--------|
| Session Manager | internal/agent/session_manager.go | New — shared session lifecycle for all agents |
| Anthropic Agent | internal/agent/anthropic_agent.go | Refactored to use session manager |
| Synthetic Agent | internal/agent/agent.go | Refactored to use session manager |
| Z.ai Agent | internal/agent/zai_agent.go | Refactored to use session manager |
| Store | internal/store/store.go | Added QueryAnthropicUtilizationSeries, session manager support |
| Handlers | internal/web/handlers.go | Rewrote cyclesAnthropic() for per-minute data, added burn rate insights |
| Config | internal/config/config.go | Anthropic-first provider ordering |
| Frontend | app.js, style.css | Dynamic Y-axis, key-based colors, display names, removed height hacks |
Upgrade Guide
For existing users: Just replace the binary. No database migration needed — all new tables auto-create on startup.
For new users:
curl -fsSL https://raw.githubusercontent.com/onllm-dev/onwatch/main/install.sh | bash
Full Changelog
31 files changed: +1,359 lines, -720 lines
| Category | Count |
|----------|-------|
| New Go files | 2 (session_manager.go + test) |
| Modified Go files | 11 |
| Frontend | app.js, style.css, dashboard.html |
| Screenshots | 8 new PNGs |
| Docs | README, CLAUDE.md, DEVELOPMENT.md, INDEX.md, landing page |
Full diff: v2.0.0...v2.1.0
- Upgrade guide: update binary; onWatch will auto‑detect Claude Code credentials and prompt to enable tracking during upgrade
- Installer (`install.sh`) now offers five provider options (Synthetic only, Z.ai only, Anthropic only, Multiple – choose one at a time, or All) with 20 bash test cases validating all flows
- Auto‑detection of Claude Code credentials from macOS Keychain, Linux keyring, and fallback JSON file
- Dynamic quota tracking for Anthropic with utilization percentages, reset cycle detection, and detailed modal charts
- Dashboard enhancements: amber‑themed Anthropic tab, 'All' view auto‑fit grid for up to three providers, per‑quota history modals
Full changelog
onWatch v2.0.0 — Anthropic (Claude Code) Provider
onWatch now tracks three providers: Anthropic (Claude Code), Synthetic, and Z.ai — all running in parallel with a unified dashboard.
This is a major release that adds comprehensive Anthropic/Claude Code support with auto-detection of credentials, dynamic quota tracking, and a beautiful amber-themed dashboard experience.
Download
| Platform | Binary |
|----------|--------|
| macOS ARM64 (Apple Silicon) | onwatch-darwin-arm64 |
| macOS AMD64 (Intel) | onwatch-darwin-amd64 |
| Linux AMD64 | onwatch-linux-amd64 |
| Linux ARM64 | onwatch-linux-arm64 |
| Windows AMD64 | onwatch-windows-amd64.exe |
Or install with one command (macOS/Linux):
curl -fsSL https://raw.githubusercontent.com/onllm-dev/onwatch/main/install.sh | bash
What's New
Anthropic (Claude Code) Provider
- Auto-detection of Claude Code credentials — onWatch automatically finds your token from:
- macOS Keychain (
Claude Code-credentials) - Linux keyring via
secret-tool - File fallback:
~/.claude/.credentials.json
- macOS Keychain (
- Dynamic quota tracking — Anthropic quotas (5-Hour, 7-Day, 7-Day Sonnet, Monthly, Extra Usage) are variable and change over time. onWatch handles this dynamically instead of hardcoding quota types.
- Utilization-based display — Anthropic reports quotas as utilization percentages (0-100%), displayed with the same progress bars, countdowns, and status badges as other providers.
- Full reset cycle tracking — Detects quota resets via
resets_attimestamp changes, tracks peak utilization and deltas per cycle.
Dashboard Updates
- Anthropic tab with amber/orange accent color (#D97706) and dynamically rendered quota cards
- "All" view (formerly "Both") — auto-fit grid that adapts to 2 or 3 providers
- Per-quota modal with chart history and cycle details for each Anthropic quota
- Chart.js datasets created dynamically from the active quotas in each API response
Install Script Improvements
- New "Multiple" option in provider selection — choose providers one at a time instead of all-or-nothing
- Anthropic auto-detection during install — if Claude Code is installed, the installer offers to enable tracking automatically
- Cross-platform token help — shows macOS, Linux, and Windows commands for retrieving Claude Code credentials regardless of the current OS (useful for VPS setups)
- Upgrade flow — existing installations are offered Anthropic tracking when upgrading
- Fixed color rendering — escape codes now render correctly in all terminal contexts
- 20 bash test cases validating all install flows
Bug Fixes
- Fixed SQLite BUSY on 3-provider startup — agents now start with staggered delays to prevent concurrent session creation contention
- Fixed installer color codes — ANSI escape sequences now render correctly when piped through
curl | bash
Backend Architecture
| Component | File(s) |
|-----------|---------|
| API Types | internal/api/anthropic_types.go — Dynamic quota response parsing with null filtering |
| HTTP Client | internal/api/anthropic_client.go — OAuth usage API with anthropic-beta header |
| Token Detection | internal/api/anthropic_token.go + platform files — Build-tagged for unix/windows |
| DB Schema | internal/store/store.go — 3 new tables: anthropic_snapshots, anthropic_quota_values, anthropic_reset_cycles |
| Store | internal/store/anthropic_store.go — Normalized key-value queries for dynamic quotas |
| Tracker | internal/tracker/anthropic_tracker.go — Reset detection, cycle management, utilization deltas |
| Agent | internal/agent/anthropic_agent.go — Background polling loop |
| Config | internal/config/config.go — ANTHROPIC_TOKEN env var, HasMultipleProviders() |
| Handlers | internal/web/handlers.go — All API endpoints extended with anthropic provider case |
Configuration
# Auto-detected from Claude Code (no manual setup needed if Claude Code is installed)
ANTHROPIC_TOKEN=your_token_here
# Existing providers unchanged
SYNTHETIC_API_KEY=syn_your_key_here
ZAI_API_KEY=your_zai_key_here
At least one provider is required. All three can run simultaneously.
Upgrade Guide
For existing users: Just update the binary. On next start, onWatch will:
- Auto-detect Claude Code credentials if present
- Log that Anthropic tracking is available
- The installer (
install.sh) will prompt to enable Anthropic during upgrade
For new users: Run the one-liner:
curl -fsSL https://raw.githubusercontent.com/onllm-dev/onwatch/main/install.sh | bash
The installer now offers 5 provider options: Synthetic only, Z.ai only, Anthropic only, Multiple (choose one at a time), or All available.
Full Changelog
Files changed: 27 files, +4,800 lines
| Category | Changes |
|----------|---------|
| New Go files | 9 (types, client, token detection, store, tracker, agent) |
| Modified Go files | 7 (config, store schema, handlers, server, main) |
| Frontend | dashboard.html, app.js, style.css updated |
| Install | install.sh with 5 provider options + test suite |
| Docs | README.md, CLAUDE.md, .env.example updated |
- `SYNTRACK_*` environment variables still work as fallback during transition period
- Process detection recognizes both `onwatch` and `syntrack` binaries temporarily
- Automatic migration script provided for standalone binary users before upgrading
- Binary renamed from `syntrack` to `onwatch`
- Go module changed to `github.com/onllm-dev/onwatch`
- Default data directory moved to `~/.onwatch/data/onwatch.db`
- Interactive installer with guided provider setup and key collection
- Detect missing providers in `.env` and offer to add them
- Compact insight cards into single-line layout
Full changelog
onWatch v1.8.0 — The Rebrand Release
SynTrack is now onWatch by onLLM. Same tool, new identity — reflecting multi-provider support and the onLLM ecosystem.
What Changed
Full Rebrand: SynTrack → onWatch
- Binary renamed from
syntracktoonwatch - Go module:
github.com/onllm-dev/onwatch - Domain: onwatch.onllm.dev
- GitHub: github.com/onllm-dev/onWatch
- Default data directory:
~/.onwatch/data/onwatch.db - All environment variables renamed to
ONWATCH_*(e.g.ONWATCH_PORT,ONWATCH_POLL_INTERVAL) - Session cookie, HTTP Basic Auth realm, User-Agent headers all updated
- Dashboard branding, localStorage keys, page titles updated
Backward Compatibility
SYNTRACK_*environment variables still work as fallback — no need to update your.envimmediately- Process detection recognizes both
onwatchandsyntrackbinaries during the transition period
Automatic Migration
Two migration paths for existing users:
Installer users — just re-run the installer:
curl -fsSL https://raw.githubusercontent.com/onllm-dev/onWatch/main/install.sh | bash
The installer detects ~/.syntrack/ and automatically migrates your config, database, and systemd service.
Standalone binary users — run the migration script before upgrading:
curl -fsSL https://raw.githubusercontent.com/onllm-dev/onWatch/main/scripts/migrate-from-syntrack.sh | bash
This moves ~/.syntrack/ → ~/.onwatch/, renames env vars in .env, migrates the database, updates PATH in shell rc files, and cleans up old systemd services.
Also Included (since v1.7.0)
- refactor: Compact insight cards into single-line layout
- fix: KPI modal chart not loading due to range-selector misfire
- fix: Login page infinite refresh loop and systemd restart storm
- fix: Interactive prompts display correctly and handle all edge cases
- feat: Detect missing providers in existing
.envand offer to add them - feat: Interactive installer with guided provider setup and key collection
Platforms
| Platform | Binary |
|----------|--------|
| macOS (Apple Silicon) | onwatch-darwin-arm64 |
| macOS (Intel) | onwatch-darwin-amd64 |
| Linux (x86_64) | onwatch-linux-amd64 |
| Linux (ARM64) | onwatch-linux-arm64 |
| Windows (x86_64) | onwatch-windows-amd64.exe |
Upgrade
Via installer (recommended):
curl -fsSL https://raw.githubusercontent.com/onllm-dev/onWatch/main/install.sh | bash
Manual: Download the binary for your platform, replace the existing one, and restart.
- After upgrading, reload the systemd unit with `systemctl --user daemon-reload` or `systemctl daemon-reload` (as root) to apply the new restart rate‑limiting settings.
Full changelog
SynTrack v1.7.0
Bug Fixes
Login Page Infinite Refresh Loop (Critical)
The login page was constantly refreshing in an infinite loop after a fresh install. Root cause: loadHiddenInsights() was calling the /api/settings API endpoint on every page — including the login page. Since the user wasn't authenticated, the API returned 401, and the authFetch helper immediately redirected back to /login, creating:
/login → app.js loads → authFetch('/api/settings') → 401 → redirect to /login → repeat
Fixes applied:
- Moved
loadHiddenInsights()into the dashboard-only code block (only runs when authenticated on the dashboard) - Added a guard in
authFetch()to skip redirect when already on the/loginpage (safety net against future regressions)
Systemd Restart Storm (Linux)
On Linux systems using the installer, the systemd service had Restart=on-failure with no rate limiting. If the app failed to start due to a persistent issue (missing API key, port conflict, DB permission error), systemd would restart it infinitely every 10 seconds.
Fix: Added StartLimitBurst=3 and StartLimitIntervalSec=120 to both system-wide and user systemd service units. The service now stops after 3 failures within 2 minutes instead of looping forever.
Improvements
Auth Rejection Logging
Authentication rejections (401 API responses and login redirects) were previously completely silent on the server side — making it impossible to diagnose auth issues from server logs.
Fix: SessionAuthMiddleware now logs auth rejections at Debug level with path, method, and remote address. Enable debug logging (--debug or SYNTRACK_LOG_LEVEL=debug) to see these entries.
Platforms
| Platform | Binary |
|----------|--------|
| macOS (Apple Silicon) | syntrack-darwin-arm64 |
| macOS (Intel) | syntrack-darwin-amd64 |
| Linux (x86_64) | syntrack-linux-amd64 |
| Linux (ARM64) | syntrack-linux-arm64 |
| Windows (x86_64) | syntrack-windows-amd64.exe |
Upgrade
Via installer (recommended):
curl -fsSL https://raw.githubusercontent.com/onllm-dev/syntrack/main/install.sh | bash
Manual: Download the binary for your platform, replace the existing one, and restart.
Linux systemd users: After upgrading, reload the service unit to pick up the new rate-limiting config:
systemctl --user daemon-reload # user service
systemctl daemon-reload # system service (as root)
- Time range selector (1d/7d/30d) for insights with default 7 days
- Provider boxes in "Both" mode show distinct colored labels per provider
- Responsive stats grid and insight cards adapt from 4‑column to single column on mobile
Full changelog
What's New in v1.6.0
Usage Insights Redesign
Fixed grid layouts — no more orphan cards:
- Stats grid now always displays exactly 4 cards per provider in a single row
- Removed the 5th "Tracking Days" stat card that caused asymmetric 4+1 layouts
- Insight cards use a clean 2-column grid with last-odd-child spanning full width
Time range selector for insights:
- New 1d / 7d / 30d range pills in the insights section header
- Stats (Requests, API Calls, Tool Calls, Sessions) recalculate for the selected range
- Default range is 7 days
"Both" mode provider boxes:
- Replaced ugly "(Syn)" / "(Z.ai)" suffix interleaving with visually separated provider boxes
- Each provider gets its own labeled box with distinct accent color (teal for Synthetic, peach for Z.ai)
- Stats and insight cards are fully independent per provider
Removed duplicate data:
- Eliminated
computeClientInsights()— live quota percentages were already displayed in KPI cards at the top of the dashboard - Session average stat moved server-side into the stats grid
Responsive Improvements
- Stats grid: 4 columns → 2 columns on tablet → 1 column on mobile
- Insight cards: 2 columns → 1 column on tablet/mobile
- Provider boxes in Both mode stack vertically on narrow screens
All Platforms
Binaries for all supported platforms:
- macOS ARM64 (Apple Silicon) —
syntrack-darwin-arm64 - macOS AMD64 (Intel) —
syntrack-darwin-amd64 - Linux AMD64 —
syntrack-linux-amd64 - Linux ARM64 —
syntrack-linux-arm64 - Windows AMD64 —
syntrack-windows-amd64.exe
Upgrade Notes
Drop-in replacement. No database migration or config changes required.
Full Changelog: https://github.com/onllm-dev/syntrack/compare/v1.5.1...v1.6.0
- Drop‑in replacement. No database migration or config changes required.
- Production landing page with Material Design 3, dark/light mode toggle, interactive dashboard mockup, one‑line install command, screenshots gallery, feature comparison tables, audience cards, FAQ accordion, alternatives comparison, Google Analytics integration, and SEO enhancements
- Header & footer redesign moving password change to header, updating footer links, removing version string from footer
- Version command (`syntrack version`, `--version`, `-v`) now reads embedded VERSION file, prints GitHub URL and attribution
Full changelog
What's New in v1.5.1
Landing Page
Production landing page at syntrack.onllm.dev:
- Material Design 3 with dark/light mode toggle
- Interactive dashboard mockup with provider tabs (Synthetic, Z.ai, Both)
- One-line install command with copy button
- Screenshots gallery with lightbox, filters, and scroll-based zoom
- Side-by-side comparison tables for Synthetic and Z.ai features
- "Who is SynTrack for?" section with 6 target audience cards
- FAQ accordion with 8 searchable Q&A items
- Alternatives comparison (SynTrack vs Quotio vs Helicone vs Langfuse)
- Google Analytics integration for traffic insights
- SEO: JSON-LD structured data (SoftwareApplication + FAQPage), Open Graph, Twitter Cards
Dashboard Improvements
Header & Footer:
- Password change button moved from footer to header for easier access
- Footer updated with project links and tech attribution
- Removed version string from dashboard footer for cleaner layout
Version Command
syntrack version,syntrack --version, andsyntrack -vall work- Version now reads from embedded VERSION file — no more "vdev" when built without ldflags
- Prints GitHub URL and attribution alongside version number
README Overhaul
- Complete rewrite — 35% smaller, focused on value proposition
- Added "Who Is SynTrack For?" section targeting 6 audience segments
- Added FAQ section with 5 LLM-targeted Q&A pairs for AI discoverability
- Keyword-rich intro mentioning compatible tools (Cline, Roo Code, Kilo Code, Claude Code, Cursor, Windsurf)
- Added badges (License, Go, Platform) and landing page link
Bug Fixes
- Fix version printing "vdev" when built with plain
go build - Fix install cards not centering due to grid overflow
- Fix feature card icons and text alignment
- Show all 3 install cards at tablet widths
- Correct license references from MIT to GPL-3.0
Install Script
- One-line install:
curl -fsSL https://raw.githubusercontent.com/onllm-dev/syntrack/main/install.sh | bash - Auto-detects root/sudo for systemd service type
- Downloads binary to
~/.syntrack/, sets up PATH and service
All Platforms
Binaries for all supported platforms:
- macOS ARM64 (Apple Silicon) —
syntrack-darwin-arm64 - macOS AMD64 (Intel) —
syntrack-darwin-amd64 - Linux AMD64 —
syntrack-linux-amd64 - Linux ARM64 —
syntrack-linux-arm64 - Windows AMD64 —
syntrack-windows-amd64.exe
Upgrade Notes
Drop-in replacement. No database migration or config changes required.
Full Changelog: https://github.com/onllm-dev/syntrack/compare/v1.5.0...v1.5.1
- --stop and --status now accept both subcommand (syntrack stop) and flag (--stop) syntax
- New --test flag provides isolated PID and log files for development/CI without affecting production
- Dashboard gains SVG favicon and header logout button
Full changelog
What's New in v1.5.0
CLI Improvements
--stop and --status Aliases:
- Support both subcommand and flag syntax:
syntrack stoporsyntrack --stop - Same for status:
syntrack statusorsyntrack --status - Improves discoverability for users who prefer flag-style commands
--test Mode Isolation:
- New
--testflag for complete process isolation - Uses separate PID file (
.syntrack-test.pid) and log file (.syntrack-test.log) - Test instances never interfere with production — no port scanning or PID killing
- Ideal for development and CI environments
Dashboard Enhancements
Favicon:
- Added SVG favicon (teal circle with brand icon) for browser tab identification
- Shows in bookmarks, browser tabs, and mobile home screen
Logout Button:
- New logout button in the dashboard header (arrow-right icon)
- Red hover indicator for visual clarity
- Clears session and redirects to login page
All Platforms
Binaries for all supported platforms:
- macOS ARM64 (Apple Silicon) —
syntrack-darwin-arm64 - macOS AMD64 (Intel) —
syntrack-darwin-amd64 - Linux AMD64 —
syntrack-linux-amd64 - Linux ARM64 —
syntrack-linux-arm64 - Windows AMD64 —
syntrack-windows-amd64.exe
Upgrade Notes
Drop-in replacement. No database migration or config changes required.
Full Changelog: https://github.com/onllm-dev/syntrack/compare/v1.3.0...v1.5.0
- Update any scripts or configurations referencing port 8932 to use the new default port 9211.
- If using Z.ai, add `ZAI_API_KEY` and optionally `ZAI_POLL_INTERVAL` entries to your `.env` file.
- Default listening port changed from 8932 to 9211
- Unified "Both" view showing Synthetic and Z.ai usage side‑by‑side with combined insights panel
- Tab‑based provider selector replacing dropdown for faster switching
- Quota visibility toggle on quota cards with persistent localStorage state and dynamic Y‑axis scaling
Full changelog
What's New in v1.3.0
Multi-Provider Support: Z.ai Integration
SynTrack now tracks both Synthetic API and Z.ai usage in a single dashboard. This is a major expansion beyond Synthetic-only tracking.
Z.ai Support:
- Full quota tracking for Z.ai's token-based and time-based limits
- Token usage tracking with 15B token monthly limit
- Time-based quota tracking (5 minutes/hour) with smart reset detection
- Per-tool token consumption breakdown
- Token efficiency metrics (tokens per tool call)
Z.ai Quota Tracking Features:
- Token Reset Detection: Tracks monthly token resets via
NextResetTimefield - Time Reset Detection: Smart value-drop detection for time-based quotas
- Rate Calculations: Usage rate and projection to limit
- Tool Breakdown: Per-tool token consumption with sortable table
New "Both" Provider View
A new unified view showing Synthetic and Z.ai side-by-side:
- Dual-column layout with independent quota cards for each provider
- Combined insights panel comparing usage across both services
- Dual charts: Separate time-series charts for Synthetic and Z.ai
- Merged sessions table: All sessions from both providers with provider badges
- Unified reset cycles: All cycles with provider identification
UI/UX Improvements
Tab-Based Provider Selector:
- Replaced dropdown with clean tab selector (Synthetic / Z.ai / Both)
- Faster provider switching with single click
- Visual indication of active provider
- Mobile-responsive horizontal scroll on small screens
Quota Visibility Toggle:
- New eye icon on each quota card to hide/show on graph
- Hidden quotas shown at 50% opacity for visual clarity
- Persistent state: Your visibility preferences saved in localStorage
- Dynamic Y-axis scaling: Automatically recomputes based only on visible datasets
- Supports both Synthetic (3 quotas) and Z.ai (2 quotas) providers
Improved Y-Axis Scaling:
- Renamed "Performance" section to "Usage Graphs" for clarity
- Dynamic scaling with 20% padding (was 100%) for better visual resolution
- Rounded to nearest 5 for cleaner axis labels
- Proper handling of zero values (shows max at 10%)
Performance & RAM Optimizations
Server-Side Pagination:
- Bounded queries for RAM efficiency on large datasets
- Configurable page sizes for sessions and cycles tables
- Prevents unbounded memory growth with long-running instances
Measured Performance (v1.3.0):
- Idle RAM: ~26-28 MB (stable)
- Dashboard Load: ~28-30 MB
- Both Provider View: Minimal overhead (~1-2 MB)
- Binary Size: ~12-13 MB per platform
Infrastructure Changes
Default Port Change: 9211
- New default port is 9211 (was 8932)
- Better mnemonic: "9211" = "SynTrack"
- Backwards compatible:
syntrack stopchecks both ports - All documentation updated
Documentation Updates
- Updated README with Z.ai configuration instructions
- Added Z.ai environment variables to
.env.example - New
zai_integration.mddocumenting Z.ai API specifics - Updated screenshots showing new UI features
Bug Fixes
- Fixed Y-axis computation when highest value dataset is hidden
- Fixed provider badge display in merged tables
- Improved reset detection accuracy for rapid polling scenarios
All Platforms
This release includes binaries for:
- macOS ARM64 (Apple Silicon) -
syntrack-darwin-arm64 - macOS AMD64 (Intel) -
syntrack-darwin-amd64 - Linux AMD64 -
syntrack-linux-amd64 - Linux ARM64 -
syntrack-linux-arm64 - Windows AMD64 -
syntrack-windows-amd64.exe
Upgrade Notes
-
Update your
.envfile to include Z.ai credentials (optional):ZAI_API_KEY=your_zai_key_here ZAI_POLL_INTERVAL=60 -
Port change: If you have scripts referencing port 8932, update them to 9211
-
Database: Existing Synthetic data is preserved; Z.ai tables created automatically
Known Limitations
- Z.ai API token usage shows aggregated values (API limitation)
- Time-based quota resets are detected via value-drop heuristic
- "Both" view requires at least one poll from each provider to show data
Full Changelog: https://github.com/onllm-dev/syntrack/compare/v1.2.0...v1.3.0
- New perf-monitor tool for tracking RAM and HTTP performance
- Performance metrics added to README
Full changelog
What's New in v1.2.0
Performance & Resource Usage
This release includes comprehensive performance testing and updated resource targets:
Measured Performance:
- Idle RAM: 26.3 MB (very stable baseline)
- Dashboard Load RAM: 28.3 MB (+2.0 MB / +7.7% overhead)
- API Response Times: 0.27-0.32 ms average
- Dashboard Response: 0.71 ms
- Request Throughput: ~77 requests/second
Updated RAM Targets:
- Idle: 30 MB max (was 10 MB)
- Load: 50 MB max (was 15 MB)
Performance Monitoring Tool
New developer tool for tracking RAM and HTTP performance:
cd tools/perf-monitor
go build -o perf-monitor .
./perf-monitor --restart # Test with clean baseline
See DEVELOPMENT.md for details.
Documentation Updates
- Added Performance section to README with measured metrics
- Updated CLAUDE.md with corrected RAM budgets
- Added performance monitoring documentation
All Platforms
This release includes binaries for:
- macOS ARM64 (Apple Silicon)
- macOS AMD64 (Intel)
- Linux AMD64
- Linux ARM64
- Windows AMD64
Full Changelog: https://github.com/onllm-dev/syntrack/compare/v1.0.0...v1.2.0