CLI reference · 01

halton-meter init

First-run setup for Halton Meter — generates the mitmproxy CA, trusts it in the OS trust store, patches the certifi bundle, and installs the supervisor (launchd on macOS, systemd --user on Linux, Task Scheduler on Windows). Idempotent and reconciliable.

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

halton-meter init is the command that wires Halton Meter into your machine. It generates a mitmproxy CA, trusts it in the System keychain, patches the running Python’s certifi bundle, installs the four launchd LaunchAgents, and runs a self-test. It is idempotent — running it twice does no harm — and it reconciles state in every direction, so switching modes does not require an uninstall first.

Synopsis

halton-meter init [--apps|--full] [--non-interactive] [--no-shell-rc] [--clean]

Modes

ModeFlagWhat it touches
env-only (default)halton-meter initCert + plists + supervisor only. No shell rc edits, no launchctl env, no system proxy. Use halton-meter run <cmd> to meter explicitly.
appshalton-meter init --appsAbove + writes env vars to ~/.zshrc / ~/.bashrc + launchctl setenv user domain so Spotlight / Dock-spawned apps inherit HTTPS_PROXY. Does not touch the system proxy.
fullhalton-meter init --fullAbove + flips the macOS system proxy (networksetup -setsecurewebproxy + -setwebproxy per active interface). Catches browsers and GUI apps that ignore env. May break HSTS sites if cert trust is incomplete.

--apps is the recommended default for most developers. See Install for the mode decision tree.

Flags

FlagPurpose
--appsApps mode (see table above).
--fullFull mode (see table above).
--non-interactiveSkip the live-daemon prompt; assume yes. Requires osascript or pre-cached sudo for the keychain step.
--no-shell-rcSkip the shell-rc edit. Apps and full modes only.
--cleanForce destructive rollback if the post-install self-test fails. Default behaviour repairs in place.
--guiDeprecated alias for --full.

onboard is a friendly alias that defaults to init --apps.

What init actually does, in order

The reference is daemon/halton_meter/setup/_macos.py::run_setup(). The order is fixed; the doc-drift on the landing’s old install walkthrough was that this order was misreported:

  1. Generate mitmproxy-ca-cert.pem under ~/.mitmproxy/ via mitmproxy.certs.CertStore.create_store(..., 2048). Skipped if the file already exists. Permissions are tightened to 0700 (dir) and 0600 (private key) on every init.
  2. Trust the CA in the System keychain. A macOS GUI password dialog appears, prompted by osascript wrapping security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain. The verification probe is security verify-cert -c <cert> -p ssl with no -r <self> flag — that flag would tautologically verify any self-signed cert.
  3. Patch the certifi bundle. The Anthropic Python SDK and most requests/httpx-based clients consult certifi, not the macOS keychain. The certifi bundle in the running Python is appended with the marker # halton-meter mitmproxy CA cert appended by halton-meter setup followed by the PEM. If the bundle is not writable, init prints the manual sudo command to run.

After the cert work, init installs the four launchd plists (com.haltonlabs.meter, com.haltonlabs.meter.edge, com.haltonlabs.meter.watchdog, com.haltonlabs.meter.userenv), starts the daemon and watchdog, runs a 30-second self-test, and prints the final mode summary.

A typical run

~ — halton-meter init --apps
$ halton-meter init --apps
  1/8  Generating mitmproxy CA certificate…
       cert written      ~/.mitmproxy/mitmproxy-ca-cert.pem
  2/8  Trusting cert in macOS Keychain (admin password required)…
        ── macOS dialog appears — type your password and click OK ──
       keychain trusted
  3/8  Patching certifi bundle so Python clients trust the cert…
       certifi patched
  4/8  Installing launchd plist for daemon auto-start…
       launchd registered  com.haltonlabs.meter
  5/8  Writing env vars to shell rc and launchctl user domain…
       shell rc updated    ~/.zshrc
  6/8  (skipped — system proxy unchanged in --apps mode)
  7/8  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

Switching modes without uninstalling

init is the reconciler. Run it with the new mode and it cleans up prior-mode state — stale launchctl env vars, shell rc blocks, system proxy settings — so the new mode is the sole source of truth:

~ — switch install mode
$ halton-meter init             # switch to env-only
$ halton-meter init --apps      # switch to apps
$ halton-meter init --full      # switch to full

You do not need to run uninstall first.

What’s next