Halton Meter is a local network proxy that sits between your LLM clients
(Claude Code, Cursor, the Anthropic SDK, the Gemini CLI, curl) and the
LLM provider APIs (Anthropic, OpenAI, Google Gemini, xAI). It intercepts
HTTPS calls via a local mitmproxy instance, parses request and response
bodies to extract model name, token counts, and cost, and writes one row
per LLM call into a local SQLite database at
%USERPROFILE%\.halton-meter\db.sqlite. It never modifies your code or
wraps SDKs. If the proxy fails, traffic falls through directly to the
provider — your tools keep working. Nothing about your development
workflow changes.
Requirements
- Windows 10 (build 19041+) or Windows 11
- PowerShell 5.1+ (preinstalled) or Windows Terminal
- One of:
uv(recommended — brings its own Python, no system Python required), orpipxwith system Python 3.11, 3.12, 3.13, or 3.14, orpipin a virtualenv
- No admin password required. Every step is per-user (
HKCU, user-level Task Scheduler, userRootcert store).
What ships on Windows today (phase 0)
Honest scope so you can decide before installing.
| Capability | Windows | macOS |
|---|---|---|
uvx halton-meter / uv tool install / pipx install | All work | All work |
halton-meter init (apps mode) | Works — per-user HKCU registry proxy, certutil user-store cert, Task Scheduler ONLOGON | Works |
halton-meter init --full (machine-wide HKLM proxy) | Not implemented. Deferred post-v1.0. | Works |
| WinINet / Electron apps pick up the proxy without restart | Works — WM_SETTINGCHANGE broadcast | n/a |
| WinHTTP clients (Windows Update, some .NET tools) | Not configured. Workaround: netsh winhttp import proxy source=ie after init. | n/a |
| Auto-trust mitmproxy CA in OS trust store | Works (per-user, certutil -user -addstore Root) | Works (Keychain, admin once) |
| Persistent daemon / edge supervisor across reboots | Works — Task Scheduler ONLOGON (user-level, no admin) | Works (launchd) |
| Watchdog process | Not installed in phase 0. ONLOGON re-starts on every interactive logon. | Works |
halton-meter rescue | Not implemented yet. Use halton-meter init --clean. | Works |
| WSL2 guest-traffic routing | Not supported. | n/a |
halton-meter doctor | Works | Works |
halton-meter report / cloud sync | Works (same SQLite + cloud path as macOS) | Works |
If anything in bold is a deal-breaker for your workflow, stay on macOS (or Linux for headless server cost capture) until the post-v1.0 push lands machine-wide proxy and WinHTTP.
Install
uvx runs the latest published wheel in an ephemeral environment — no install
step, no Python prerequisite, every invocation fetches the current release:
uvx halton-meter init For a persistent CLI on PATH:
uv tool install halton-meter pipx is still fully supported:
pipx install halton-meter Confirm the binary is on your PATH:
halton-meter --version You should see halton-meter, version 0.2.11 or later.
Run init
Phase 0 only supports apps mode — --full (machine-wide system proxy via
HKLM) is deferred post-v1.0.
PS> halton-meter init
1/7 Generating mitmproxy CA certificate…
✓ cert written %USERPROFILE%\.mitmproxy\mitmproxy-ca-cert.pem
2/7 Trusting cert in user Root store (certutil -user -addstore)…
✓ user Root store trusted
3/7 Snapshotting current proxy settings (HKCU)…
✓ snapshot written %USERPROFILE%\.halton-meter\system_state.json
4/7 Writing HTTPS_PROXY / HTTP_PROXY / NO_PROXY to HKCU\Environment…
✓ env vars written HTTPS_PROXY HTTP_PROXY NO_PROXY
✓ WM_SETTINGCHANGE broadcast (running apps will pick up env)
5/7 Setting per-user proxy (HKCU\…\Internet Settings)…
✓ ProxyEnable=1 ProxyServer=127.0.0.1:8081 ProxyOverride=<local>
✓ WM_SETTINGCHANGE broadcast (Electron/WinINet apps refresh)
6/7 Registering Task Scheduler ONLOGON tasks for daemon and edge…
✓ task registered halton-meter (ONLOGON, user)
✓ task registered halton-meter-edge (ONLOGON, user)
7/7 Starting daemon and running self-test (up to 30 s)…
✓ daemon healthy edge: 127.0.0.1:8081 api: 127.0.0.1:8765
✓ init complete mode: apps
What init does on Windows, idempotently:
- Generates a mitmproxy CA cert at
%USERPROFILE%\.mitmproxy\mitmproxy-ca-cert.pem. Per-user, no admin needed. - Trusts the cert in your user
Rootcertificate store viacertutil -user -addstore Root <cert_path>. No admin prompt — this is a per-user store. - Snapshots existing proxy settings to
%USERPROFILE%\.halton-meter\system_state.jsonsohalton-meter uninstallcan restore the prior state exactly. - Writes env vars to
HKCU\Environment:HTTPS_PROXY,HTTP_PROXY,NO_PROXY. BroadcastsWM_SETTINGCHANGE("Environment")so new shells inherit immediately. Apps already running won’t see the env until restarted — Windows bakes env into a process at exec time. - Sets per-user proxy via
HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings:ProxyEnable=1,ProxyServer=127.0.0.1:8081,ProxyOverride="<local>". BroadcastsWM_SETTINGCHANGEagain so Electron / WinINet apps refresh without restart. - Registers Task Scheduler
ONLOGONtasks at user level (halton-meter,halton-meter-edge). No admin required because user-level tasks don’t need it. Tasks re-launch the daemon + edge at every interactive logon, and survive reboot. - Starts the daemon and runs a self-test (up to 30 s) before returning.
init is idempotent. Running it again does no harm — the cert is detected
as already trusted, the registry block is diffed, and the tasks are
re-registered only if their XML definition has changed.
Apps that pick up the proxy without restart
Windows apps that use WinINet read the proxy directly from
HKCU\…\Internet Settings. They refresh on WM_SETTINGCHANGE. That covers:
- Edge, Chrome, Firefox — once you trust the user
Rootcert. - Electron apps (Cursor, VS Code, Windsurf, Slack, Notion, Discord) —
Chromium reads WinINet settings via
--proxy-server="<system>". - PowerShell
Invoke-WebRequest, curl, wget. - Most .NET applications using
HttpClientdefault handler.
Apps that use WinHTTP (separate stack from WinINet) do not see the HKCU proxy. That covers:
- Windows Update, Microsoft Store.
- Some .NET tools that explicitly use
WinHttpHandler. - PowerShell modules that route through
WinHttp(rare).
One-shot fallback to mirror WinINet → WinHTTP:
PS> netsh winhttp import proxy source=ie
Current WinHTTP proxy settings:
Proxy Server(s) : 127.0.0.1:8081
Bypass List : <local> This call needs an elevated PowerShell. Re-run it after halton-meter init
only if WinHTTP-only clients are part of your workflow.
Apps that need a restart
Apps already running when you ran halton-meter init will not see the new
HTTPS_PROXY env var until they’re restarted. Windows reads env vars from
HKCU\Environment at process creation; running processes get a snapshot.
The WinINet proxy itself takes effect immediately for Electron/WinINet
apps, but env-based clients (Python SDKs, Node CLIs, curl) need:
- A new PowerShell / Windows Terminal session, or
- For GUI apps: close the app from the system tray and re-launch it.
For Claude Code, Cursor, and Windsurf specifically: full app exit (right-click
tray icon → Quit, or taskkill /F /IM ...) and re-launch is required.
Reloading windows within an open app instance is not enough.
Verify the install
PS> halton-meter status
● HEALTHY daemon, edge, proxy registry, cert all green
PS> halton-meter run claude --print "Reply with exactly: pong"
pong
PS> halton-meter report
✓ 1 request · claude-opus-4-7 · $0.0023 If anything red, run halton-meter doctor for the full diagnostic. The
paused_unauthorised / paused_forbidden cloud states behave exactly as on
macOS — see Troubleshooting.
Where data goes on Windows
| Surface | Path |
|---|---|
| SQLite store | %USERPROFILE%\.halton-meter\db.sqlite |
| Config | %USERPROFILE%\.halton-meter\config.toml |
| Daemon logs | %USERPROFILE%\.halton-meter\daemon.out.log + daemon.err.log (100 MiB rotation, 5 backups since v0.2.9) |
| CA cert | %USERPROFILE%\.mitmproxy\mitmproxy-ca-cert.pem |
| Cert trust | HKCU\Software\Microsoft\SystemCertificates\Root\Certificates\… |
| Env vars | HKCU\Environment\HTTPS_PROXY (and HTTP_PROXY / NO_PROXY) |
| Proxy registry | HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings\ProxyServer |
| Pre-init snapshot | %USERPROFILE%\.halton-meter\system_state.json |
| Tasks | Task Scheduler → Task Scheduler Library → halton-meter, halton-meter-edge |
| Cloud credentials (if paired) | %USERPROFILE%\.halton-meter\cloud-credentials.json (file ACL: owner-only read) |
Nothing is written under HKLM or C:\Program Files. The entire footprint
lives under the current user.
Reinstall, upgrade, or switch install channels
halton-meter init is idempotent. To upgrade in place:
# Whichever channel you installed with — pick one:
PS> uv cache clean halton-meter; uvx halton-meter --version # uvx (force latest)
PS> uv tool upgrade halton-meter # uv tool
PS> pipx upgrade halton-meter # pipx
# Re-run init so the Task Scheduler XML points at the new binary:
PS> halton-meter init For a clean reinstall:
PS> pipx reinstall halton-meter # pipx path
PS> uv tool install --force halton-meter # uv tool path
# uvx has no "reinstall" — uv cache clean forces a fresh fetch:
PS> uv cache clean halton-meter; uvx halton-meter --version
PS> halton-meter init For a complete uninstall (removes Task Scheduler tasks, restores the prior
proxy registry from snapshot, removes the user-store cert) see
halton-meter uninstall.
What’s next
- Troubleshooting — the diagnostic tree shared with macOS; Windows-specific failures (cert-store, registry, Task Scheduler) are flagged inline.
halton-meter doctor— runs every signalinitchecks plus dependency probes, prints copy-paste fixes.- Cloud connect — pair this daemon to a team workspace later (entirely opt-in).
Found a Windows-specific failure not covered here? Email operator@haltonlabs.com with
[windows-beta]in the subject and the output ofhalton-meter doctor --json. We will fix the docs, not just answer the question.