Open-source project
HeyOkay/HaloBattery avatar
HeyOkay/HaloBattery

HaloBattery: one tray icon per wireless device, no vendor software

Unified battery level indicators for 2.4GHz mice, headsets and Bluetooth devices in the Windows tray

679 stars64 forksPythonMIT

At a glance

What is it?
Halo Battery is a Windows tray utility that reads battery levels for 2.4GHz mice, keyboards, headsets and controllers over a receiver, a cable or Bluetooth, and draws a ring per device. It replaces the vendor utilities that hold the receiver, and it accepts that the raw device protocols come from other open projects.
Who is it for?
Halo Battery suits a Windows user with several wireless peripherals who wants a single readable battery indicator instead of a folder of vendor utilities that fight over the USB receiver. It does not suit macOS or Linux users, since the project targets Windows 10 and 11, and it does not suit someone who needs a signed installer, because the file is not code signed and SmartScreen will warn.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 10 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A tray icon per device, drawn as a ring that fills

Halo Battery is a small Windows program that puts a battery indicator for every wireless peripheral you own into the system tray, one icon per device. The description is blunt about the pitch: battery levels of your wireless mouse, keyboard, headset and controller, right in the Windows tray, with no vendor software.

The visual design is doing real work here. Each device gets a ring that fills with its charge level, turns amber near the alert level you set, and turns red below it. While a device is charging, the ring breathes green, and the project ships an animated GIF of exactly that arc moving slowly. The icon set covers headsets, mice, keyboards, controllers and generic Bluetooth, and the asset documentation states the range is from 100 percent down to 15 percent, plus charging and asleep states.

The menu is described as a Windows 11 style menu that stays sharp at any display scale, in light or dark. Right-clicking any icon opens the device name, an option to rename the device, hide it, set its alert level, change preferences, or take a diagnostics report. A separate settings entry adds portable mode and running from source.

The project ships the whole thing as a Python application. The repository root holds halo_battery.pyw as the entry point, a halo/ directory, a providers/ directory, a scripts/ directory, a tools/ directory and a tests/ directory, and the dependencies are pinned in a requirements.txt at the root listing hidapi 0.14 or newer, pystray 0.19 or newer and pillow 10 or newer.

The point is to get rid of the vendor apps, not to sit next to them

The main competitor for this utility is not another battery tool, it is the vendor's own software, and the project is explicit about that. The feature list says to close Synapse, G HUB, NGENUITY and the rest, because Halo Battery talks to the receiver, the cable or Windows Bluetooth itself.

That framing also explains the polling behaviour, which is unusual enough to mention. Alerts wait until your full-screen game closes, and devices are polled less often while you play. A background process that wakes a USB receiver every few seconds is a good way to get a stutter or a wake from sleep, so the utility backs off while it detects that you are playing.

The device coverage is broad, with 30 or more brands named, including Razer, Logitech, SteelSeries, HyperX, Corsair, ASUS ROG, Sony, Xbox, Nintendo, 8BitDo, Pulsar and Keychron, and the documentation points to docs/devices.md for the full list. That file is the part to read before you buy the tool rather than after, because it shows the connection method for each device and, importantly, whether each device has been tested on real hardware. The distinction matters: a device can be listed as supported by protocol while still being unverified in practice.

The connection methods are a receiver over 2.4 GHz, a USB cable, or Bluetooth. So the same utility covers a gaming mouse on its dongle, a headset charged over USB, and a pair of Bluetooth earbuds, which is a wider surface area than most single-purpose battery tools attempt.

Installing means extracting a zip, and the folder has to stay intact

There is no installer. The installation is three steps, and the second one has a condition that is easy to get wrong.

If you prefer to run it from source instead of the packaged build, the runtime dependencies are declared in the requirements.txt at the repository root:

bash
hidapi>=0.14
pystray>=0.19
pillow>=10

First, download the HaloBattery-<version>.zip archive from the latest release page. Second, extract it to a folder of its own, for example C:\Tools, and run HaloBattery\HaloBattery.exe. The documentation is emphatic that you keep the folder together, because the executable needs the _internal folder next to it. Third, right-click a tray icon and choose Start with Windows.

That _internal folder holds the bundled Python runtime, which explains the troubleshooting entry further down: if you see python312.dll was not found, or if Start with Windows says the app runs from a temporary folder, then the app was started straight from the ZIP, or only HaloBattery.exe was copied out of it. The fix is to extract the whole archive and run the executable from there.

Windows SmartScreen will warn about an unrecognized app, because the file is not code signed. The documented path is More info then Run anyway. The project argues for this by pointing out that the release is built by GitHub Actions straight from the repository, with public build logs, so the artefact can be traced to the source even though it carries no signature.

The autoupdate feature is described as installing a new release from the tray menu in one click, so the manual update path is a fallback rather than the normal routine. The release history shows how often that matters: v1.13.0 on 2026-09-29, v1.14.0 on 2026-10-05 and v1.15.0 on 2026-10-12, three releases in a fortnight. The last push to the repository was on 2026-10-12, and the project is MIT licensed with the licence file in the repository root.

The device protocols are borrowed, and the credits say so

Here is the honest limitation of the project, stated by the project itself. The credits section says the device protocols come from OpenRazer, HeadsetControl, Solaar, rivalcfg, G-Helper and other open projects, and from captures and test runs sent by the community. The full list is in docs/credits.md.

That is the right way to build a tool like this, because reverse engineering hundreds of receiver protocols from scratch would be a waste of effort when the work already exists under open licences. It also defines where the risk lies. When a vendor ships a firmware update that changes a protocol, the fix arrives when one of the upstream projects figures it out and this project picks it up. A device that stops reporting a level is more likely a regression in an upstream protocol implementation than a bug in the tray icon layer.

The same upstream lineage shows up in the requirement list. hidapi is the cross platform HID access library, which is what makes talking to a USB receiver directly possible without writing vendor specific drivers, and pystray is the system tray framework, with pillow handling the icon rendering.

The division of work inside the repository reflects that design. The providers/ directory is where the device protocol handling sits, separated from the halo/ directory that holds the application itself, and scripts/ and tools/ hold the packaging and helper work. A contributor adding a device is adding to a provider rather than touching the user interface.

The diagnostics report is the way to add a device, and it needs sanitising

Adding an unsupported device is a documented procedure rather than a request in the issue tracker. If a device is not detected or shows a wrong level, you send a diagnostics report, which takes about a minute to produce.

The first step is to close the maker's software, meaning Synapse, G HUB, the web driver and similar, and wake the device by moving the mouse or pressing a key. Then you right-click a Halo Battery icon and choose Diagnostics, an option that is also present on the No devices found icon. The report opens in Notepad as diagnostics.txt, and you open an issue using the device issue template, write the device name and how it is connected, and drag the file into the comment box. The file lives in %APPDATA%\HaloBattery, or in the app's own folder in portable mode, and the first line of the report shows which folder is used.

One line in that procedure deserves emphasis. The report contains Bluetooth MAC addresses and device serial numbers, and you can replace them with xx before you post. That is a real consideration when you are about to paste a file that identifies your hardware into a public issue thread, and the documentation gives you the tool to do it.

The troubleshooting section repeats the same theme from a different angle: close Synapse, the WLmouse web driver and other battery tools, because they may hold the receiver. This is the single most common failure, and the fix is to uninstall the competitor rather than to configure Halo Battery around it. The contributing guide also covers how to record a USB capture of the maker's own app, which is the way a new protocol gets reverse engineered in the first place.

Editorial conclusion

Halo Battery suits a Windows user with several wireless peripherals who wants a single readable battery indicator instead of a folder of vendor utilities that fight over the USB receiver. It does not suit macOS or Linux users, since the project targets Windows 10 and 11, and it does not suit someone who needs a signed installer, because the file is not code signed and SmartScreen will warn. Before you rely on it, check docs/devices.md for whether your exact model has been tested on real hardware, and note the file layout requirement: the executable needs its _internal folder beside it, or it will start from a temporary location and fail to find python312.dll.

Frequently asked questions

How do I install Halo Battery on Windows?

Download the HaloBattery-<version>.zip from the latest release, extract it to a folder of its own such as C:\Tools, and run HaloBattery\HaloBattery.exe. Keep the whole folder together, because the executable needs the _internal folder next to it.

Does Halo Battery need the vendor software for my mouse or headset?

No, and in fact the vendor software has to be closed. Halo Battery talks to the receiver, the cable or Windows Bluetooth itself, and the troubleshooting notes say other battery tools may hold the receiver, so Synapse, G HUB and similar should be closed or uninstalled.

How do I report a device that Halo Battery does not detect?

Close the maker's software, wake the device, then choose Diagnostics from the right-click menu of a Halo Battery icon. The report opens as diagnostics.txt, and you attach it to an issue along with the device name and connection type. Replace the Bluetooth MAC addresses and serial numbers with xx before posting.

Will Windows SmartScreen block the Halo Battery download?

It may warn about an unrecognized app, because the file is not code-signed, and the documented path is More info then Run anyway. The release is built by GitHub Actions from the repository with public build logs.

Official sources

  1. HeyOkay/HaloBattery on GitHub
  2. Issues
  3. License: MIT
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/heyokay-halobattery.svg)](https://hysenlabs.com/projects/heyokay-halobattery)

Was this useful?