TL;DR: Usage telemetry genuinely helps you build a better tool — but done the usual way, on-by-default and quietly hoovering up everything, it’s a betrayal of the people running your software. go-tool-base’s telemetry is built on three rules: it is never on unless the user explicitly turns it on; it collects no personally identifiable information, ever; and the tool author picks the backend, including the one that sends data precisely nowhere. There’s also a real deletion path, because “opt in” with no “and take it back” isn’t consent.
The data you want, and the line you shouldn’t cross
If you maintain a tool, you want to know how it’s actually used. Which commands matter and which are dead weight. Where the error rate spikes. Whether anyone touched the feature you spent a fortnight on. That information makes you a better maintainer, and wanting it is completely legitimate.
The trouble is the standard way of getting it. Telemetry on by default. An opt-out buried three levels down in a settings file nobody reads. And once it’s running, it quietly collects far more than it admitted to — the arguments people passed, the paths they were working in, an IP address for good measure.
Every one of those is a small betrayal of someone who installed your tool to get a job done, not to become a data point. And the cost when users notice isn’t a slap on the wrist. It’s trust, and trust in a developer tool does not grow back quickly. A tool that surprises you once with what it was collecting is a tool you uninstall and warn colleagues about.
So go-tool-base’s telemetry started from a different question. Not “how do we collect the most data” but “how do we collect useful data without ever putting the user in a position they didn’t choose.”
Rule one: it is off until you say otherwise
The foundation is the simplest possible rule, and it is absolute. Telemetry is never enabled by default. A freshly installed tool built on go-tool-base sends nothing. Not a heartbeat, not a ping, nothing.
It only starts collecting when the user makes an explicit, visible choice to let it. Three honest doors: they run telemetry enable, they say yes to a clear prompt during init, or they set TELEMETRY_ENABLED themselves. All three are deliberate acts. None of them is a pre-ticked box or a default they have to discover and undo.
This is opt-in, and the distinction from a well-hidden opt-out is the entire point. Opt-out telemetry treats consent as something to be assumed and grudgingly reversed. Opt-in treats it as something that must be given. Only one of those is actually consent.
Rule two: no personally identifiable information, full stop
Consent to “some telemetry” is not consent to “any telemetry,” so the second rule constrains what can ever be collected, even from a user who has opted in.
No personally identifiable information. The framework does not record command arguments — those routinely contain paths, hostnames, the occasional secret someone pasted. It does not record file contents. It does not record IP addresses.
It does need some notion of “distinct installations” for the numbers to mean anything, so it derives a machine ID from a handful of system signals and runs it through SHA-256. What leaves the machine is a hash. It tells you “this is the same install as last week” and tells you nothing about whose install it is, and the hash can’t be walked backwards into the signals it came from.
The events themselves are deliberately thin. Which command ran, roughly how long it took, whether it errored. The shape of usage, not a transcript of it.
Rule three: the author picks the destination
Even with consent given and PII excluded, there’s a third question: where does the data actually go? go-tool-base doesn’t answer that for you, because it can’t. A corporate internal tool, an open-source CLI and an air-gapped utility have completely different right answers.
So the backend is the tool author’s choice. The framework ships several — a noop backend, stdout, a file, plain HTTP, and OpenTelemetry over OTLP — and supports custom ones. The noop backend matters more than it looks: it lets a tool wire up the whole telemetry surface, commands and all, while sending data to nowhere. A perfectly reasonable, fully supported configuration.
Pluggable backends also mean the data never has to touch infrastructure I run. It goes where the tool’s author decides, on their terms. The framework provides the plumbing and stays out of the destination.
And a way back out
One last thing, because it’s the part that makes the opt-in real rather than decorative. A user who opted in can opt back out, and the package includes a GDPR-aligned deletion path so “stop, and remove what you have” is an actual supported request, not a polite fiction.
Consent you can’t withdraw isn’t consent. It’s a one-way door with a friendly sign on it. The deletion path is what keeps the front door a door.
Pulling it together
Telemetry is genuinely useful to a maintainer and genuinely dangerous to the trust of the people running the tool, and the usual implementation — on by default, opt-out buried, collecting everything — spends that trust recklessly. go-tool-base’s telemetry holds three lines: never enabled without an explicit user action, never collecting personally identifiable information even once enabled, and always sending data to a destination the tool’s author chose (up to and including nowhere). A real deletion path makes the opt-in something you can take back.
You can have your usage numbers. You just have to ask for them, like you would for anything else that wasn’t yours.