Security & privacy · 01 macOS only

Local-only guarantee

Everything Halton Meter captures stays on your machine. No telemetry, no crash reports, no usage stats. The HTTP API is loopback-only and the CA private key never leaves disk.

macOS 12+ · Python 3.11+ Reading time 2 min Updated May 11, 2026

Halton Meter intercepts your LLM API traffic and keeps every captured byte on your machine. There is no upload, no telemetry, no crash report. The daemon’s only outbound connection is the original request to the LLM provider you were already calling — forwarded unchanged after parsing the usage metadata. This page is the precise contract.

What stays local

  • The SQLite database at ~/.halton-meter/db.sqlite — every captured request, project, pricing rate, audit event, and policy event. Never replicated anywhere.
  • Captured request and response bodies in the request_bodies table, when body capture is enabled. Redacted (Bearer tokens, API keys, recognised secrets stripped) before they hit disk.
  • Logs under ~/.halton-meter/*.err.log. Plain files, not syslog. Token counts and event names only — never prompt content. See Logs.
  • The mitmproxy CA at ~/.mitmproxy/. The public cert is added to your System keychain; the private key is 0600 and never read by anything except the daemon itself.

What does not stay local

The daemon forwards your original LLM request to the provider you were already calling. That single outbound flow — your machine to api.anthropic.com (or api.openai.com / generativelanguage.googleapis.com / api.x.ai / chatgpt.com / cloudcode-pa.googleapis.com) — is the only outbound traffic the daemon initiates.

The daemon does not phone home. There is no analytics endpoint. There is no crash-report endpoint. There is no version-check endpoint at runtime. The only network call from the daemon process is the provider call that was always going to happen.

The HTTP API is loopback only

The FastAPI server on port 8765 binds 127.0.0.1. CORS allows only http://localhost:3000 by default. There is no auth — the listener is bound to localhost as the access control. To confirm:

lsof -nP -iTCP:8765 -sTCP:LISTEN

The output should show 127.0.0.1:8765, never *:8765. If you ever see the latter, file an issue immediately.

The CA private key is locked down

~/.mitmproxy/mitmproxy-ca.pem (the combined cert + private key) is mode 0600. The parent directory ~/.mitmproxy/ is 0700. Both are re-asserted by tighten_mitmproxy_ca_permissions() in daemon/halton_meter/setup/_macos.py on every init. The daemon refuses to relax these.

Confirm:

~ — confirm CA permissions
$ stat -f "%Sp %N" ~/.mitmproxy
  drwx------ /Users/you/.mitmproxy
$ stat -f "%Sp %N" ~/.mitmproxy/mitmproxy-ca.pem
  -rw------- /Users/you/.mitmproxy/mitmproxy-ca.pem

Body capture defaults

Body capture is on by default (bodies.enabled = true in config.toml) and is the only place prompt content ever lands on disk. Two safeguards apply:

  1. Redaction. Every captured body passes through a redaction stack that strips Bearer tokens, API keys, and recognised secret shapes before the row is written. Per-category counts surface in halton-meter bodies stats.
  2. Size and time bounds. bodies.max_body_bytes = 524288 (512 KiB) per body; bodies.retention_days = 90. The daemon’s daily sweep purges rows older than the retention horizon.

To turn body capture off entirely:

~/.halton-meter/config.toml — disable body capture
# Disable all body capture, daemon-wide
[bodies]
enabled = false

To turn it off for a single project (overrides the daemon-wide setting):

halton-meter project set <slug> body-capture off

To force-purge old bodies:

halton-meter bodies purge --older-than 30d --vacuum

What you can verify

Halton Meter’s trust model rests on observable behaviour, not source inspection. Three checks anyone can run:

  1. Listening surface. lsof -nP -iTCP:8765 -sTCP:LISTEN should return only 127.0.0.1:8765. If it ever shows *:8765, file a security report.
  2. Outbound surface. Run the daemon under Little Snitch (or equivalent). The only outbound flows you should see from halton-meter are to the LLM provider hosts listed above. Specifically: nothing to haltonlabs.com, *.amazonaws.com, or any analytics host.
  3. CA private key. ~/.mitmproxy/mitmproxy-ca.pem is mode 0600, re-asserted by the daemon on every init. Confirm with the stat -f "%Sp %N" block above.

If any of those three checks fails, the daemon is misbehaving and we want to know. Use the Disclosure process.

What we ask of you in return

Nothing automatic. Halton Meter doesn’t fingerprint your install, check for updates, or open a feedback channel. If something breaks or surprises you, email operator@haltonlabs.com. For security reports, see Disclosure.

If you later opt in to Halton Meter Cloud, the contract widens — see what changes when Cloud is turned on for the exact field-level list and the regional / encryption posture.

What’s next

  • Disclosure — how to report a vulnerability
  • SQLite schema — the precise on-disk shape of what gets captured
  • Logs — what the daemon writes vs. what it refuses to