Adding GPU & CPU Temperature to Zebar
I’ve been using Zebar as my desktop status bar on Windows as part of a GlazeWM + Tokyo Night rice setup. One thing it was missing: hardware temperature monitoring. There was an open issue (#232) requesting it, so I decided to build it.
The whole thing was vibecoded with Claude Code, from the Rust provider implementation to the frontend integration to debugging the Windows-specific quirks. Turns out AI pair programming works pretty well even for systems-level Rust code.
The Goal
Add two things to Zebar:
- A GPU provider to show GPU name, temperature, usage, and VRAM
- A temperature field on the existing CPU provider
Sounds straightforward. It was not.
GPU Provider: The Easy Part
The GPU side was relatively clean. I used the nvml-wrapper Rust crate, which wraps NVIDIA’s NVML library. On Windows, nvml.dll ships with the NVIDIA driver, so no extra install needed.
The provider exposes:
- GPU name
- Temperature (celsius)
- GPU usage percentage
- Memory used / total
Wrapped it in a #[cfg(windows)] block since NVML is Windows/Linux and this was focused on my Windows setup. The Rust side was a straightforward provider implementation following Zebar’s existing patterns.
CPU Temperature: The Hard Part
CPU temperature on Windows is where it gets interesting. Unlike Linux where you can just read /sys/class/thermal, Windows has no standard API for CPU temperature. It requires kernel-mode driver access.
The standard solution is to use LibreHardwareMonitor (LHM), which installs a kernel driver and exposes hardware data. But how you talk to LHM matters.
The Three-Tier Fallback
I implemented a fallback chain:
- LHM HTTP API (primary): LHM can run a web server on
localhost:8085that serves a JSON endpoint with all sensor data - WMI: Query LHM/OpenHardwareMonitor WMI namespaces
- sysinfo: The
sysinfoRust crate as a last resort
Why not just use WMI? Because LHM v0.9.5+ broke WMI namespace registration. The WMI approach that worked with older versions and OpenHardwareMonitor simply doesn’t work with current LHM releases. The HTTP API is the reliable path.
Setup Requirements
For CPU temperature to work, users need LibreHardwareMonitor running as admin with:
- Remote Web Server enabled (Options > Remote Web Server > Run)
- Run On Windows Startup
- Start Minimized
Not the most elegant UX, but it’s the reality of hardware monitoring on Windows.
Frontend Integration
Since my GPU provider wasn’t in the published zebar npm package yet, I had to use Tauri’s internal IPC directly:
const ti = (window as any).__TAURI_INTERNALS__;
await ti.invoke('plugin:event|listen', { event, target: { kind: 'Any' } });
This lets the frontend subscribe to the GPU provider’s events before the types ship in the official package.
The PR
All of this went into PR #257, “feat: add GPU provider and CPU temperature support”. In the meantime, I’m running a custom Zebar binary built from my fork so I can see my GPU and CPU temps in my bar.
Takeaway
The actual Rust code for querying hardware wasn’t complicated. The hard part was navigating Windows’ lack of a standard temperature API and the breakage in LHM’s WMI layer. Sometimes open source contributions are less about writing clever code and more about figuring out which approach actually works on real systems.
Having Claude Code as a pair programmer made the whole process significantly faster, especially for navigating unfamiliar Rust crates, figuring out WMI queries, and debugging the Tauri IPC integration. Vibe coding isn’t just for web apps.