feat(telemetry): opt-in, anonymous CLI usage telemetry to PostHog - #460
Merged
Conversation
Off by default. The setup wizard asks once on its interactive path (default No); --yes never asks. A telemetry on/off/status command group, plus DO_NOT_TRACK, DOBERMAN_TELEMETRY=0 and CI as kill switches. Five allowlisted events (enable, disable, setup_completed, cli_command by name, a once-a-day usage_summary from the device rollup); every property value is a bounded scalar so a path, prompt, or secret cannot travel. No person profile, no GeoIP, random uuid4 id in the user-level state file. Stdlib transport in a daemon thread with a 1 s exit budget; never raises. The hook and proxy hot paths never import the module (new import-linter contract). The project key is a placeholder, which keeps the module a no-op until the real public key is committed. Documented in docs/TELEMETRY.md.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Opt-in, anonymous CLI usage telemetry to PostHog, so we can see which commands and modes people use and whether they keep using Doberman. Off by default; nothing leaves the machine unless the user says yes.
doberman setup(interactive path only) asks once, default No;doberman setup --yesnever asks and stays off.doberman telemetry on|off|status. Kill switches that override the local file:DO_NOT_TRACK,DOBERMAN_TELEMETRY=0,CI. State lives in<DOBERMAN_HOME or ~>/.doberman/telemetry.json(0600) with a random uuid4 distinct id (not derived from hardware, user, hostname, or repo).telemetry_enabled,telemetry_disabled,setup_completed(mode,host,hooks_installed,global_install,source),cli_command(command name only, e.g.taint.clear; never args),usage_summary(lifetime PASS/AUTH/BLOCK counts from the existing device rollup, at most once per 24 h).docs/TELEMETRY.md(exact event table, what is never sent, opt-out), README one-liner,docs/CLI.mdrows, CHANGELOG bullet.main.pyhunk is 9 lines (import,register_cli_telemetry, callback context, two calls insetup); the rest lives insrc/doberman/telemetry.pyandsrc/doberman/cli/telemetry_cmd.py. #447 and #414 also touchmain.py; same landing order as #458 (fu351, 2026-08-25): merge this first, re-apply their deltas when they land.Test plan
pytest tests/unit/test_telemetry.py tests/unit/test_setup_wizard.py tests/unit/test_device_metrics.py(default off means no HTTP; enabled means one POST with the exact key set; disallowed keys dropped and a synthetic path/token absent from the body; kill switches; placeholder key; transport failure; 24 h summary gate; wizard y/n/--yes;hook preemits nothing; atexit join stays under ~1.5 s)ruff check,ruff format --check,lint-imports(5 contracts kept, including the new telemetry vs proxy/hosthooks one)