One command, one token, reversible.
Pairing connects a single machine’s halton-meter daemon to a Cloud
workspace. The pairing flow uses a six-character one-time code that the
daemon prints; you approve it in the browser, the backend mints a
single-shot hm_sync_… token, and the daemon writes it to a 0600 file.
Until you run cloud connect and approve in the browser, nothing
flows. The daemon ships with cloud.enabled = false.
Prerequisites
Before you pair, you need:
- A running daemon. Verify with
halton-meter status— the daemon row should be green andmitm boundon127.0.0.1:8090. If it is not, see Install Halton Meter. - A Halton Meter Cloud account. Sign up at
app.haltonmeter.com. - A workspace. Created automatically on first sign-up. Switch workspaces from the avatar menu in the dashboard if you have more than one.
- Daemon v0.2.0 or later. The
cloudCLI group is part of the Phase 2 cloud-sync arc. Upgrade withpipx upgrade halton-meter.
halton-meter cloud connect
Run the connect command on the machine that should be paired:
$ halton-meter cloud connect
# Output
⠇ Requesting pairing code from api.haltonmeter.com…
● Pairing code: WXJ4-9KLM
● Approve at: https://app.haltonmeter.com/connect?code=WXJ4-9KLM
⠇ Waiting for approval… (Ctrl-C to cancel) The daemon opens a long-poll against POST /v1/pairing/poll while you
approve in the browser. The pairing code is 8 characters, ambiguity-safe
(no 0/O, no I/l), and expires after 10 minutes.
When you approve at app.haltonmeter.com/connect?code=WXJ4-9KLM, the
backend mints a hm_sync_… token scoped to one workspace and one
machine, returns it on the poll, and the daemon writes:
| Path | Contents |
|---|---|
~/.halton-meter/cloud-credentials.json | Raw hm_sync_… token, chmod 0600, owner-readable only |
~/.halton-meter/cloud.key | Fernet symmetric key for the SQLite-mirror encrypted column |
~/.halton-meter/config.toml [cloud] block | enabled = true, base_url = "https://api.haltonmeter.com", workspace_id = "..." |
~/.halton-meter/db.sqlite cloud_state row | Encrypted api_key_ciphertext, workspace name, machine id, hostname snapshot |
The cloud worker spawns inside the daemon process on the next supervisor tick (≤ 15s) and starts batching unsynced rows.
Common flags
--base-url <url>— override the cloud endpoint. Default ishttps://api.haltonmeter.com. Use this only for self-hosted or development backends. As of v0.2.1 this flag persists toconfig.toml; earlier versions required a manual edit.--workspace <slug>— pre-select a workspace when you have more than one. Skips the disambiguation step in the browser.--no-browser— print the URL but do not open the browser. Useful on headless machines or over SSH.
Verifying the link
After approval, three commands confirm the link is healthy:
$ halton-meter cloud whoami
● Workspace: acme-co
● Machine id: dev-mbp-vk
● Hostname: vk.local
$ halton-meter cloud status
● State: ACTIVE
● Last sync: 3s ago
● Unsynced rows: 0
● Last reconcile: never
$ halton-meter cloud sync
● POST /v1/requests/batch → 200 OK (1247 rows accepted) cloud status reports one of four states:
- ACTIVE — sync is running, last sync recent, no errors.
- DEGRADED — sync is running but rows are accumulating faster than they upload (transport latency, large body queue).
- PAUSED — sync is intentionally paused via
halton-meter cloud pauseor automatically after a 401. Re-enable withcloud resumeorcloud connect. - NOT-CONFIGURED —
cloud.enabled = false. Nothing flowing.
Add --json for the machine-readable shape (useful in scripts).
Cross-check against the cloud side: open
app.haltonmeter.com/[workspace]/settings/devices
— the machine should appear with the hostname and the timestamp of its
last sync.
Pairing a second machine
Each developer’s laptop pairs once. Repeat the same flow on every machine. Cloud joins them into one workspace; the dashboard shows one view of every paired machine’s spend.
There is no “machine fingerprint” — the daemon picks a stable
machine_id from ~/.halton-meter/machine.json (random UUID, generated
on first init). If you re-image a laptop and want it to look like the
same machine in the dashboard, copy machine.json over before pairing;
otherwise it appears as a new device.
Disconnecting
$ halton-meter cloud disconnect
● Revoking token at api.haltonmeter.com…
● Token revoked.
● Local: cloud.enabled = false; credentials wiped. Disconnect is symmetric to connect:
- The daemon calls
POST /v1/pairing/revokeso the token is unusable immediately, even if the local files survive (stolen laptop case). ~/.halton-meter/cloud-credentials.jsonand~/.halton-meter/cloud.keyare removed.- The
[cloud]block inconfig.tomlhasenabledflipped tofalse. - The
cloud_staterow in SQLite is cleared.
After cloud disconnect, the daemon keeps capturing locally exactly as
before. halton-meter report keeps working. To re-pair, run
cloud connect again — the machine appears as a new device unless you
preserved machine.json.
To remove a machine from the workspace remotely (laptop lost, employee
left), use the workspace settings page at
app.haltonmeter.com/[workspace]/settings/devices.
Revoking from the dashboard immediately invalidates the token; the
daemon’s next sync attempt returns 401 and the worker transitions to
PAUSED with paused_reason="paused_unauthorised".
Troubleshooting
halton-meter cloud connect reports daemon not running. Run
halton-meter status and halton-meter start. Pairing requires the
mitm port to be bound because the supervisor that runs the cloud worker
is the same process.
Browser opens but /connect?code=... says “code not found”. The
code expired (10-minute window). Cancel the CLI with Ctrl-C and re-run
halton-meter cloud connect for a fresh code.
Pairing succeeds but cloud status shows PAUSED with
paused_unauthorised. The token was revoked. Re-run cloud connect.
cloud sync returns 422 with Field required. Upgrade the daemon
to v0.2.1 or later — the from/to → from_date/to_date query
parameter rename was fixed there.
See also
- Cloud overview — what the hosted cloud adds
- Workspaces — team workspaces, invitations, roles
- Sync and retention — what syncs, retention, opt-in body sync
- Cloud security — token storage, auth, encryption
halton-meter status— local daemon health- Install Halton Meter — required before pairing