halton-meter doctor is the one command to run when something feels off.
It walks every diagnostic signal — cert trust, port binding, env vars,
launchd / systemd / Task Scheduler health, certifi patch state, cloud
pairing state, dependency versions — and prints a concrete next-action
for each failure.
It is read-only by default: doctor never modifies state unless you
pass --fix (and even then it only applies the named, safe fixes).
Synopsis
halton-meter doctor [--curl] [--json] [--fix] [--apply] | Flag | Purpose |
|---|---|
--curl | Add a live curl probe through the proxy to a known endpoint. Useful when “everything looks healthy” but captures aren’t landing — pinpoints whether the daemon path is actually reachable. |
--json | Emit the diagnostic as a single structured JSON blob. Attach this to support tickets — every row appears as {name, status, evidence, next_action}. |
--fix | Print the fixes that would be applied without applying them. Pair with --apply to execute. Safe fixes only: re-run init steps, clear stale launchctl env, re-patch certifi. Will not touch the SQLite store, will not regenerate the CA cert, will not re-pair cloud. |
--apply | Apply the fixes. Combine with --fix (--fix --apply). Without --fix, --apply is a no-op. |
What doctor checks
The reference is daemon/halton_meter/doctor.py. The check list below
mirrors the actual rows; failures print a copy-pasteable next step.
| Section | Signals |
|---|---|
| Install | CLI on PATH; correct binary path; daemon version vs latest PyPI; install channel (uv tool / pipx / pip-in-venv); Python interpreter version inside the venv. |
| Cert | ~/.mitmproxy/mitmproxy-ca-cert.pem exists; permissions are 0700/0600; the cert is trusted in the OS trust store; the certifi bundle inside the daemon’s venv carries the cert. |
| Supervisor | macOS launchd: com.haltonlabs.meter plus (in apps/full mode) meter.watchdog, meter.edge, and meter.userenv registered and healthy. Linux systemd: halton-meter.service and halton-meter-edge.service enabled and active. Windows Task Scheduler: halton-meter and halton-meter-edge tasks registered, scheduled ONLOGON, last-run-result 0. |
| Ports | edge :8081 (or its renegotiated fallback) is bound, mitm :8090 is bound, FastAPI :8765 is bound, and the bound process is the daemon (not a stale residual). |
| Env | HTTPS_PROXY, HTTP_PROXY, NO_PROXY, SSL_CERT_FILE, NODE_EXTRA_CA_CERTS, REQUESTS_CA_BUNDLE, CURL_CA_BUNDLE, GIT_SSL_CAINFO, AWS_CA_BUNDLE set correctly. On macOS apps-mode: launchctl user-domain env mirrors the shell rc. On Linux: rc-file entries detected. On Windows: HKCU env entries present. |
| System proxy | macOS full-mode: networksetup -getsecurewebproxy <interface> reports 127.0.0.1:8081 enabled on every active interface. Linux: not applicable (apps mode only). Windows apps-mode: HKCU Internet Settings\ProxyEnable=1, ProxyServer=127.0.0.1:8081, ProxyOverride=<local>. |
| Sentinels | ~/.halton-meter/proxy-managed reflects the actual mode. system_state.json snapshot is intact (uninstall can restore from it). |
| Loopback bind guard | listen_host and api_host resolve to loopback (or HALTON_METER_ALLOW_NON_LOOPBACK=1 is set with a warning). v0.2.9+. |
| Cloud | If paired: token file at ~/.halton-meter/cloud-credentials.json is 0600; cloud_state row in SQLite matches; base_url is not a placeholder TLD; last sync timestamp is sensible; paused_reason (if any) and the recovery path. |
| Capture path | --curl only: a live request through the proxy to https://api.anthropic.com/ returns a captured row in the SQLite store within 5 s. |
Reading the output
Each row is STATUS signal evidence → next action. Statuses:
OK— green. No action needed.WARN— amber. Working but degraded; doctor explains what’s missing.FAIL— red. Broken. Doctor names the fix;--fix --applyapplies the safe ones.
$ halton-meter doctor
OK install:cli-on-path /opt/homebrew/bin/halton-meter
OK install:version 0.2.11 (latest on PyPI)
OK install:channel uv-tool
OK cert:file ~/.mitmproxy/mitmproxy-ca-cert.pem (0600)
OK cert:keychain-trust SecTrust evaluation pass
OK cert:certifi-patch marker present
OK supervisor:daemon com.haltonlabs.meter PID 94318
OK supervisor:watchdog com.haltonlabs.meter.watchdog
OK supervisor:edge com.haltonlabs.meter.edge
OK ports:edge :8081 bound by daemon
OK ports:mitm :8090 bound by daemon
OK ports:api :8765 bound by daemon
WARN env:HTTPS_PROXY empty in this shell
→ Open a new terminal so the rc block is sourced, or run: source ~/.zshrc
OK loopback-bind-guard listen_host=127.0.0.1
OK cloud:state ACTIVE last sync 3s ago
(1 warning) Exit codes
| Code | Meaning |
|---|---|
0 | All rows OK. |
1 | One or more FAIL rows. Doctor printed at least one next-action. |
2 | One or more WARN rows (no FAILs). Operator may want to act; daemon still works. |
3 | --fix --apply mode: at least one fix could not be applied automatically (e.g. requires admin elevation). |
Common follow-ups
- A FAIL on
cert:keychain-trust→ re-runhalton-meter initand approve the password dialog. - A FAIL on
cloud:base_urlfor a placeholder TLD → v0.2.7+ auto-heals on next start.halton-meter stop && halton-meter start. - A FAIL on
ports:edge :8081withheld by PID <pid>→ another process owns the port. See Port already in use. - A FAIL on
loopback-bind-guard→ Daemon exits immediately with loopback bind guard. - A WARN on
env:HTTPS_PROXY→ open a new terminal so the rc block sources; or, for GUI apps, quit and relaunch from Spotlight/Dock (macOS) or the Windows tray (afterWM_SETTINGCHANGEpropagates).
See also
halton-meter status— quick HEALTHY / BROKEN summaryhalton-meter rescue— wheninitanddoctor --fixaren’t enough- Troubleshooting — symptom-driven recovery