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, Gemini Code Assist,
ChatGPT / Codex). It intercepts HTTPS 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
~/.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
- A systemd-based Linux distribution. Ubuntu 22.04+, Debian 11+, Fedora 36+, Arch, Pop!_OS, Manjaro all qualify. Headless server distros work — you don’t need a desktop environment.
- Python 3.11, 3.12, or 3.13. Ubuntu 24.04 ships 3.12 by default.
pipxrecommended, oruv tool, orpipinside a virtualenv.sudoaccess for one command:loginctl enable-linger <user>.sqlite3CLI (optional but recommended for inspecting captures).
You do not need: Docker, root for the daemon itself, NetworkManager,
an open inbound firewall port, a desktop session, or a graphical password
prompt. Everything binds to 127.0.0.1.
What ships on Linux today (v0.1.24 beta)
Honest scope so you can decide before installing.
| Capability | Linux | macOS |
|---|---|---|
uvx halton-meter / uv tool install halton-meter / pipx install halton-meter | All work | All work |
halton-meter init --apps (per-app proxy via env vars) | Works | Works |
halton-meter init --full (system-wide proxy enable) | Not implemented. Transparent-proxy via iptables/nftables REDIRECT is post-v1.0. | Works |
halton-meter init (env-only default) | Falls back to --apps. Env-only without launchctl-equivalent isn’t exposed yet. | Works |
| Cert auto-trust in the OS trust store | Not done. certifi bundle is patched; browser interception is not supported in apps mode. | Works (macOS Keychain) |
Shell rc auto-write of HTTPS_PROXY etc | Not done. Add the env vars to ~/.bashrc / ~/.zshrc yourself. | Works |
| systemd-user supervisor | halton-meter.service + halton-meter-edge.service — both Restart=always RestartSec=1. | n/a (launchd on macOS) |
| Watchdog | Not installed. The watchdog is a macOS-networksetup poller with no Linux counterpart. | Works |
halton-meter rescue | Not implemented. Manual equivalent documented under Troubleshooting. | Works |
If the items in bold are deal-breakers, stay on macOS for the v0.1.x line.
Install the package
uvx runs the latest published wheel in an ephemeral environment — no install
step, no system-Python prerequisite, every invocation fetches the current
release. It’s the canonical install:
uvx halton-meter init --apps --non-interactive For a persistent CLI on PATH:
uv tool install halton-meter pipx is still fully supported:
pipx install halton-meter If you’d rather use a virtualenv directly:
pip install halton-meter Confirm the binary is on your PATH:
halton-meter --version You should see halton-meter, version 0.2.11 or later.
Enable systemd-user persistence (one-time)
sudo loginctl enable-linger $USER This makes your --user systemd manager (user@$(id -u).service) come up
at boot regardless of whether you’re logged in, so the daemon and edge
survive logout and reboot. Verify:
$ loginctl show-user "$USER" --property=Linger
Linger=yes Run init
On Linux only apps mode is supported in v0.1.24.
$ halton-meter init --apps --non-interactive
1/6 Generating mitmproxy CA certificate…
✓ cert written ~/.mitmproxy/mitmproxy-ca-cert.pem
2/6 Trust cert in OS trust store…
✗ not yet supported on Linux — macOS only for Phase 0
3/6 Patching certifi bundle so Python clients trust the cert…
✓ certifi patched ~/.local/share/pipx/venvs/halton-meter/.../certifi/cacert.pem
4/6 Writing systemd --user units…
✓ unit installed ~/.config/systemd/user/halton-meter.service
✓ unit installed ~/.config/systemd/user/halton-meter-edge.service
5/6 Enabling units…
✓ daemon active edge: 127.0.0.1:8081 api: 127.0.0.1:8765
✓ edge active
6/6 Done.
✓ init complete mode: apps
What that runs, idempotently:
- Generates a mitmproxy CA cert at
~/.mitmproxy/mitmproxy-ca-cert.pem. Permissions tightened to0700(dir) /0600(private key) every init. - OS-trust-store step is skipped — intentional. See note below.
- Patches the certifi bundle in the running Python (the pipx venv). This is what your Python and Node LLM SDKs actually consult.
- Writes systemd units to
~/.config/systemd/user/. The watchdog unit is not written on Linux; any stale unit from a pre-v0.1.23 install is removed. - Reloads systemd and enables-now the daemon first, then the edge, so the API socket is up before the edge tries to chain into it.
- Writes sentinel files (
apps-managed,install-mode) under~/.halton-meter/.
The “Trust cert in OS trust store” row prints
✗ not yet supported on Linux — macOS only for Phase 0. This is intentional: the certifi-bundle patch is sufficient for every Python and Node LLM SDK we test against; system-trust-store install would mostly benefit browsers, which we don’t intercept in apps mode. Manual workaround for browsers documented in Troubleshooting.
Point your tools at the proxy
Halton Meter does not modify your shell rc on Linux in v0.1.24. Add the
following to ~/.bashrc or ~/.zshrc yourself, then open a new shell.
# Adjust the Python minor version in the path if pipx installed under a different one.
CERT=$HOME/.local/share/pipx/venvs/halton-meter/lib/python3.12/site-packages/certifi/cacert.pem
export HTTPS_PROXY=http://127.0.0.1:8081
export HTTP_PROXY=http://127.0.0.1:8081
export SSL_CERT_FILE=$CERT
export NODE_EXTRA_CA_CERTS=$CERT
export REQUESTS_CA_BUNDLE=$CERT
export CURL_CA_BUNDLE=$CERT If your pipx venv uses a different Python minor version, run
halton-meter run -- python3 -c "import certifi; print(certifi.where())"
to read the exact bundle path.
Per-tool trust mapping
| Client | What it trusts | Var to set |
|---|---|---|
curl (system) | /etc/ssl/certs/ca-certificates.crt | CURL_CA_BUNDLE |
Anthropic Python SDK, httpx, requests | certifi bundle of the running Python | SSL_CERT_FILE / REQUESTS_CA_BUNDLE |
| Claude Code (native binary) | NODE_EXTRA_CA_CERTS | NODE_EXTRA_CA_CERTS |
| Gemini CLI (Node-based) | Same as Claude Code | NODE_EXTRA_CA_CERTS |
| Browsers (Chrome, Firefox) | System trust store + own NSS DB | Not captured in apps mode |
If your project venv runs a different Python from the pipx venv, point
that Python’s SSL_CERT_FILE at the patched pipx bundle. Halton Meter
does not patch every Python on the system — only the one it’s installed
under.
Verify the install
halton-meter status Expected: the daemon and edge rows are green. The Watchdog row reads
✗ not installed — this is intentional on Linux (the watchdog is a
macOS-only role) but the row text doesn’t yet say so. Treat it as
informational, not a failure.
halton-meter doctor The edge-proxy row uses socket.connect_ex(("127.0.0.1", 8081)) to confirm
the port is bound — preferred over systemctl is-active because it works
inside containers and non-systemd shells without raising.
Inspect state from the shell
$ systemctl --user is-active halton-meter.service halton-meter-edge.service
active
active
$ systemctl --user status halton-meter.service --no-pager
● halton-meter.service - Halton Meter daemon
Loaded: loaded (~/.config/systemd/user/halton-meter.service; enabled)
Active: active (running) since Sun 2026-05-11 09:14:02 UTC
Main PID: 31427 (halton-meter)
Tasks: 9 (limit: 19097)
Memory: 142.8M If you get Failed to connect to bus: No medium found on a fresh SSH shell,
export XDG_RUNTIME_DIR:
export XDG_RUNTIME_DIR=/run/user/$(id -u) Test a capture
Open a new terminal (so the env vars in your shell rc are sourced) and run any real LLM call. Example with the Claude Code CLI:
claude --print "Reply with exactly: pong" Then check the report:
halton-meter report If you see “No captures yet” instead, walk the checklist in Troubleshooting → No captures.
What’s next
- First request — verify captures, understand the apps-mode flow, and learn how to extend metering to project venvs and editors.
- Troubleshooting — Linux-specific diagnoses for systemd, certifi, ports, and the bus.
If you’re stuck for more than five minutes, that’s a docs bug. Email operator@haltonlabs.com with
[linux-beta]in the subject and we’ll fix the page, not just answer the question.