Files
clawdmeter/daemon/README-windows.md
T
wenilandClaude Opus 4.8 ec8322fa21 v2: standalone Clawdmeter.exe — runs on any Win11 machine, no Python
Package the tray+daemon as a single PyInstaller onefile exe so it runs on a
fresh Windows 11 box with no Python and no pip install. Verified on hardware:
the frozen exe connects over BLE, reads the Windows media session, and pushes
now-playing (incl. Cyrillic) at the 3s / 60s cadence.

- clawdmeter.spec: onefile, windowed (no console; logs to daemon.log). collect_all
  for winrt + bleak is the key bit — bleak loads its WinRT backend dynamically and
  the winrt.windows.* projections are split distributions that PyInstaller's static
  analysis misses, so BLE and the media session would otherwise fail at runtime.
  upx off (lowers AV false-positive rate).
- build-exe.ps1: one-command build (venv + deps + pyinstaller + spec).
- tray_windows.py: resolve the brand-logo asset from sys._MEIPASS when frozen.
- autostart_windows.py: when frozen, the HKCU\Run "Start at login" value points at
  the exe itself (sys.executable), not pythonw + script.
- .gitignore: ignore /build, /dist, /.venv — the exe ships via a Gitea release.
- README-windows.md: document the standalone-exe path (download / run / build).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 09:58:26 +03:00

11 KiB
Raw Blame History

Windows Setup and Run Guide

This guide covers running the Clawdmeter Windows daemon on native Windows hardware. It includes the turnkey install-windows.ps1 bootstrap (tray icon + login autostart), the manual-run fallback, and how to manage or remove autostart.


Prerequisites

Requirement Details
Native Windows Must run on real Windows — not WSL. The script prints a warning and BLE will not work under WSL.
Python 3.11+ Download from python.org if not already installed. Ensure "Add python.exe to PATH" is checked during install.
Claude Code installed Install Claude Code and complete claude login so credentials exist on disk.
Clawdmeter powered on The device must be powered on and in range before the daemon starts.
Paired with Windows Bluetooth Pair the device once via Settings → Bluetooth & devices → Add device (see Pair the device). This is required — the device is a bonded BLE HID keyboard, so pairing enables its physical buttons and keeps a persistent connection that shows your last usage even when the daemon is stopped.

Where are my credentials?

claude login writes the OAuth token to (first match wins):

  1. %USERPROFILE%\.claude\.credentials.json — primary path (confirmed by Claude Code docs)
  2. %LOCALAPPDATA%\Claude\.credentials.json — fallback
  3. %APPDATA%\Claude\.credentials.json — fallback

The daemon probes these paths in order. You can also set CLAUDE_CREDENTIALS_PATH to an absolute path or CLAUDE_CONFIG_DIR to a directory to override the search entirely.

Security note: The credentials file contains your OAuth token. Never share its contents or embed it in scripts. The daemon reads it from disk and uses it only as the API Authorization header — the token is never written to any log, tooltip, or notification.


Pair the device (one time)

The Clawdmeter is a bonded BLE HID keyboard as well as a usage display — its firmware enables bonding (NimBLEDevice::setSecurityAuth) and advertises the HID service so its physical buttons act as a keyboard (Space / Shift+Tab). Pair it with Windows once, before running the daemon:

  1. Put the device on its Bluetooth waiting screen (powered on, not yet connected).
  2. Open Settings → Bluetooth & devices → Add device → Bluetooth.
  3. Select Claude Controller and complete pairing.

Why this is required:

  • Keyboard buttons — HID over BLE requires bonding on Windows. Without pairing, the device's buttons won't reach the PC.
  • Persistent point-in-time view — once paired, Windows maintains the BLE link and auto-reconnects the device whenever it is in range. This is intentional: the device keeps showing your last-synced usage even after you Quit the daemon, as a glanceable point-in-time view. Quitting the daemon releases only its data connection — it does not drop the Windows pairing, so the device stays connected to Windows.

To undo, use Settings → Bluetooth & devices → (device) → Remove device. Removing the pairing disables the keyboard buttons.


To run Clawdmeter on a machine without Python, use the single-file Clawdmeter.exe. It bundles its own Python, the WinRT BLE stack and the media-session reader, so nothing needs to be installed.

  1. Pair the device with Windows once (see Pair the device).
  2. Get Clawdmeter.exe — download it from the project's Gitea release, or build it yourself (below).
  3. Double-click Clawdmeter.exe. The tray icon appears and the watch starts updating within ~10 seconds.
  4. To launch it automatically at every logon, right-click the tray icon → Start at login. That registers the exe itself under HKCU\Software\Microsoft\Windows\CurrentVersion\Run — no Python, no console window.

There is no console window; the exe logs to %LOCALAPPDATA%\Clawdmeter\daemon.log.

Building the exe

On a machine that does have Python (e.g. your dev box), from the repo root:

powershell -ExecutionPolicy Bypass -File build-exe.ps1

This creates dist\Clawdmeter.exe (~3060 MB). The PyInstaller config lives in clawdmeter.spec. The exe is intentionally not committed to git — distribute it through a Gitea release.

SmartScreen / antivirus: unsigned PyInstaller executables are sometimes flagged by a generic heuristic (not a real detection). Until the exe is code-signed, you may need to allow it through SmartScreen ("More info → Run anyway"). Building from source sidesteps this entirely.


Setup from source (one time)

Use this if you prefer running from a Python checkout instead of the standalone exe above (e.g. on your dev box).

Open a PowerShell terminal and cd to the repository root.

1. Create a virtual environment

python -m venv .venv

2. Activate it

.venv\Scripts\Activate.ps1

If you see a scripts-execution-policy error, run:

Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned

Then repeat the Activate.ps1 step.

3. Install dependencies

pip install -r daemon\requirements-windows.txt

This installs bleak (WinRT BLE) and httpx (async HTTP for the Anthropic API).


Running the daemon

With the venv active and the Clawdmeter powered on:

python daemon\claude_usage_daemon_windows.py

Expected console output

[HH:MM:SS] === Claude Usage Tracker Daemon (BLE, Windows) ===
[HH:MM:SS] Poll interval: 60s
[HH:MM:SS] Scanning for 'Claude Controller' (8.0s)...
[HH:MM:SS] Found: XX:XX:XX:XX:XX:XX
[HH:MM:SS] Connecting to XX:XX:XX:XX:XX:XX...
[HH:MM:SS] Connected
[HH:MM:SS] Sending: {"s":42,"sr":180,"w":17,"wr":8820,"st":"active","ok":true}
  • The device must be paired with Windows first (see Pair the device). The daemon then connects over that existing link via BleakScanner + BleakClient; it does not pop its own pairing dialog.
  • After Connected, the daemon polls the Anthropic API immediately and sends the first payload within a few seconds of connect (warm token path). With a valid, non-expired token the device should leave its waiting screen and show session + weekly percentages within about 10 seconds of launch.
  • The daemon then re-polls the Anthropic API every 60 seconds while connected. If the device fires a refresh request (e.g., after a button press), an immediate re-poll occurs without waiting for the 60-second interval.
  • The Now Playing screen updates on a separate, faster cadence: the daemon reads the Windows media session every 3 seconds and pushes an update the moment the track or play/pause state changes — so the watch reflects a song change within a few seconds, not at the next 60-second API poll. The cached usage data is re-sent with each of these updates, so the rate-limit / token screens never blank between polls.
  • If the device disconnects or goes out of range, the daemon logs Device disconnected and re-scans automatically with exponential backoff (starting at 1 second, capped at 60 seconds).

Stopping

Press Ctrl+C in the terminal. The daemon logs Daemon stopping and exits cleanly.


Troubleshooting

Symptom Likely cause Fix
Warning: running under Linux/WSL Running in WSL, not native Windows Run from a native PowerShell or Command Prompt on Windows
Scanning for 'Claude Controller'… Device not found Clawdmeter is off, out of range, or showing a non-Bluetooth screen Power on the device and ensure it is on the Bluetooth waiting screen
No token; skipping poll No credentials file found at any candidate path Confirm claude login ran on this machine; check %USERPROFILE%\.claude\.credentials.json exists
API HTTP 401 Token expired Re-run claude login in a terminal to refresh the token, then restart the daemon
Connection failed WinRT BLE initialisation issue Ensure Windows Bluetooth is on; try toggling Bluetooth off/on in Windows Settings

Tray icon, login autostart, and turnkey install

Copy the repo to a native Windows path first. Clone or copy this repository to a Windows location such as %USERPROFILE%\Clawdmeternot a WSL share (\\wsl$\... or \\wsl.localhost\...). Installing from the WSL share would point the virtual environment and the login-autostart entry at a path that disappears when WSL shuts down, defeating the whole point of the Windows daemon. The installer detects a WSL path and refuses to run, telling you how to relocate.

Copy-Item -Recurse '\\wsl.localhost\Ubuntu\home\<you>\repos\Clawdmeter' "$env:USERPROFILE\Clawdmeter"
cd "$env:USERPROFILE\Clawdmeter"

Run this once from the repository root in PowerShell (a native Windows path):

powershell -ExecutionPolicy Bypass -File install-windows.ps1

The script does four things in order and logs progress at each step:

  1. Creates a Python virtual environment at .venv.
  2. Installs dependencies from daemon\requirements-windows.txt (bleak, httpx, pystray, Pillow).
  3. Registers the tray app to launch automatically at login via HKCU\Software\Microsoft\Windows\CurrentVersion\Run — per-user, no admin required.
  4. Launches the tray app immediately (headless — no console window).

The script downloads nothing from the internet. It only installs the packages listed in the in-repo daemon\requirements-windows.txt.

Tray icon and status

After install, the Clawdmeter icon appears in the Windows notification area:

State Icon bubble Tooltip
Connected green Connected · last update HH:MM
Scanning amber Scanning…
Error red Error: token expired — run claude login

Hover over the icon to see the current status tooltip. A notification fires once when the daemon first enters the Error state (e.g. after a token expiry).

Tray menu

Right-click the tray icon for the menu:

  • Status header (non-clickable) — live status + last data sync time.
  • Start at login (checkable toggle) — enables or disables autostart at runtime. Reflects the current registry state each time the menu opens.
  • Quit — stops the daemon cleanly and exits with no lingering process. It releases the daemon's own data connection but does not drop the Windows Bluetooth pairing — the device stays connected to Windows and keeps showing your last-synced usage (point-in-time view).

Disabling or removing autostart

Use the tray menu toggle, or remove the registry value manually:

reg delete "HKCU\Software\Microsoft\Windows\CurrentVersion\Run" /v Clawdmeter /f

WSL independence

The daemon operates fully independently of WSL. The token is read from native Windows credential paths (%USERPROFILE%\.claude\.credentials.json and fallbacks); BLE uses the WinRT stack directly. Running wsl --shutdown does not affect the BLE link, and the daemon starts correctly even in a fresh Windows session where WSL has never been launched.


What is NOT covered here

  • Code-signing the standalone .exe (to avoid SmartScreen/AV prompts) — future
  • MAC-address cache / sleep-wake reconnect hardening — Phase 3