Yes. A CLI can write usage counters to a file on the user's own machine and never send them anywhere unless the user turns uploading on. The Go toolchain ships this way: collection is local by default, and upload is a separate, explicit choice. It is a useful pattern for any developer tool.
What a local-only mode is
Most CLIs treat telemetry as a switch with two positions, on or off. The Go team's documentation describes a third position. The telemetry mode can be local, on or off.
| Mode | Collected on the machine | Uploaded |
|---|---|---|
| local (default) | Yes | No |
| on | Yes | Yes, an approved subset, with sampling |
| off | No | No |
Go documents it this way: by default, telemetry data is kept only on the local computer, and users may opt in to uploading an approved subset. Setting the mode to off stops collection as well as upload.
Why this helps a security-minded team
The usual argument against telemetry in a developer tool is trust. People run your CLI in repositories that hold proprietary code and in CI jobs that hold credentials. A tool that quietly sends data out is a tool a security reviewer will block.
A local-only default changes the review. The reviewer can read the counter file, see exactly what it holds, and confirm nothing leaves the host. Upload becomes a decision a person makes with that evidence in front of them.
What Go actually collects
Go's design uses counters, which are lightweight counts of named events, such as how often a subcommand ran. Counters sit in a memory-mapped file, so a crash does not lose them. About once a week the counters are rolled into a report. Only counters on an approved upload list are ever sent, and the docs say the list changes only through a public proposal process. New charts cannot carry sensitive user information.
The documentation also notes that once enough people opt in, the upload process randomly skips some reports to reduce volume and add privacy while keeping the statistics useful.
Steps to copy the pattern
- Pick a counters-only data model. Count named events. Do not record arguments, paths, file contents or environment values.
- Store counters in a clearly documented directory under the user's config location, and say where it is.
- Ship three modes and a command to show and change the mode.
- Keep an allowlist of counters that may be uploaded, reviewed in public, separate from what is collected locally.
- Make a one-line command to wipe or inspect the local data.
- Say what happens in CI. If your tool runs unattended, default to the quietest mode there.
The cost to be honest about
Go's own docs call this the campaign cost of the opt-in model. If upload needs a choice, only a slice of users make it, and that slice skews toward experienced users. Go addresses this in the editor by asking users, in the language server, whether they want to opt in. Expect a smaller, biased sample and plan questions around it. Telemetry from a self-selected group answers some questions and not others.
Check your own tool
Check your own tool: run it once, then look in its config directory. If you cannot find what it recorded in under a minute, your users cannot either.
Quick check
Does local-only telemetry still count as telemetry for a security review?
Collection on the machine is still data your tool records, so document it. But when nothing is uploaded, the review shrinks to what is written on disk and who can read it.
Should upload be opt-in or opt-out?
That is a product and legal decision. Go chose local by default with upload as an opt-in. Whatever you choose, state it plainly and make the off switch one command.
If you are building a developer tool and want a dependency inventory of what your CLI ships, Safeguard offers a free scan at gold.safeguard.sh/scan.
Sources
Last reviewed: 19 October 2026.