Telemetry
raid ships an opt-in, anonymous CLI telemetry pipeline so the team can prioritize features against real usage signal — which task types matter, which commands fail, which features go unused — without ever capturing what you actually run.
Off by default. A fresh install never sends anything to the telemetry endpoint until you explicitly run raid telemetry on (or accept the first-run prompt). The one narrow exception is the follow-up question: if you decline the first-run prompt and then explicitly answer yes to the follow-up, raid sends exactly one anonymous raid_telemetry_opt_out event and then stays off forever. Answering no to the follow-up (or skipping it for any reason) means raid still sends nothing. When opted out, raid makes zero further telemetry / PostHog requests, and there's an integration test that pins this contract. (raid still performs an unrelated GitHub release-version check on normal invocations regardless of telemetry state — that request is independent of this pipeline.)
What raid collects
| Event | Properties (sanitized) |
|---|---|
raid_first_run | os, arch, raid_version, install_method (best-effort) |
raid_command_executed | command_name, task_count, task_types[], duration_ms, success |
raid_command_failed | command_name, error_code (from the errors table), duration_ms |
raid_task_executed | task_type, duration_ms, success — sampled at ~10% to bound volume |
raid_telemetry_opt_out | reason — either "prompt-declined" (set automatically when you accept the follow-up question) or the free-text string from raid telemetry off --why "...". Optional; absent when neither path was used. |
Every event also carries: distinct_id (anonymous UUIDv4 from ~/.config/raid/telemetry-id), raid_version, os (e.g. darwin/linux/windows), arch (e.g. arm64/amd64).
What raid never collects
- Command bodies.
cmd:,path:,runner:,src:,dest:,url:— never sent. - Variable values. Anything set by a
Settask or passed in env vars. - Argument values.
RAID_ARG_*, declared args, declared flag values. The one exception is the explicit opt-out reason:raid telemetry off --why "..."sends the free-text string you typed as thereasonproperty onraid_telemetry_opt_out— and only on that event. raid never collects argument or flag values implicitly. - Stdout / stderr. Task output is never captured by the telemetry layer.
- Identifiers. Username, hostname, IP, MAC, OS version beyond
darwin/linux/windows, terminal emulator — none. - File paths beyond their kind.
task_types: ["shell", "shell", "print"]is fine; the actual paths are not.
The source of truth is the src/internal/telemetry package. Every event builder is a tiny pure function — read them yourself.
First-run consent
On your first interactive raid <command> invocation after install, raid prints the consent prompt to stderr:
raid would like to send anonymous usage telemetry to help prioritize features.
We never collect: file paths, command contents, env values, or anything that could identify you.
See: https://raidcli.dev/docs/telemetry
[y] yes, send telemetry [N] no, leave it off [?] what's collected
>
Default is no (capital N). [?] shows the long-form disclosure inline and re-asks.
Follow-up: may we record the denial?
If you decline the first prompt, raid asks one follow-up question:
Telemetry is off. May raid send a single anonymous event recording your decision?
This is the only event raid would ever send; it helps the project measure how
many users opt out vs. opt in. Same anonymity guarantees as above.
[y] yes, send once [N] no, send nothing at all
>
Default is no again. Answering yes fires exactly one raid_telemetry_opt_out event (with reason: "prompt-declined") and then leaves telemetry permanently off — that's the whole transaction. Answering no (or hitting Enter) skips the network entirely; raid touches zero endpoints for the remainder of the install.
The follow-up exists because opt-out rate is the most useful single signal for the project: without it, we can't tell whether a quiet user has opted out actively or just never finished setup. It's also why the follow-up exists only on the explicit-decline path — when you skip the first prompt for any other reason (non-TTY, headless, DO_NOT_TRACK, etc.), raid never asks anything further.
Non-interactive contexts skip the prompt entirely and leave telemetry off. Specifically, raid does not prompt when:
DO_NOT_TRACK=1is set in the environment (cross-tool standard — consoledonottrack.com).-y,--yes, or--headlessis on the command line (see Headless mode).--jsonis on the command line (machine-readable output mode).- stdin isn't a TTY (CI runners, pipes, agent hosts).
- This raid build wasn't compiled with a PostHog API key (dev builds — telemetry is dead code).
- The invocation is a
raid telemetry ...subcommand (so you can runraid telemetry onwithout being prompted to opt in first).
In each of these cases raid records the decision as off-by-default so it won't try to prompt later either. Switch back on explicitly with raid telemetry on.
Managing telemetry
raid telemetry on # opt in
raid telemetry off # opt out
raid telemetry off --why "ci runner" # opt out + record an anonymous reason
raid telemetry status # show current state, anonymous ID, ID file path
raid telemetry status --json # same, as JSON
raid telemetry purge # delete the anonymous ID file (breaks linkage to past events)
raid telemetry preview # render a sample event payload — does not send
raid telemetry preview is the recommended way to see exactly what raid would post before opting in. The API key is automatically redacted in the preview output so you can paste it anywhere.
Three ways to opt out
raid telemetry off— persists the choice; future runs stay off.DO_NOT_TRACK=1— env var; overrides the persisted state for the current process and any child it spawns. Honored on every run regardless oftelemetry on.- Never opt in. The first-run prompt defaults to off, and non-interactive contexts skip the prompt entirely.
You can purge the anonymous machine ID at any time with raid telemetry purge — that breaks linkage between future events and any sent before. Useful if you've been opted in for a while and want to reset.
Destination
- PostHog US Cloud, project
Raid(id403603). - Endpoint:
https://us.i.posthog.com/i/v0/e/. - The PostHog publishable project key is baked into release builds at compile time via a ldflag. Dev /
go runbuilds have no key and never send.
Network failures are always silent. A 2-second HTTP timeout, fire-and-forget goroutines, and a 1.5-second flush deadline at process exit mean a stuck network can't slow raid down or break a command.
Source code
The entire telemetry implementation is in src/internal/telemetry:
| File | Role |
|---|---|
telemetry.go | Capture, Flush, the HTTP send path, PreviewPayload |
consent.go | Consent state (read/write via viper) + DO_NOT_TRACK honor |
id.go | Anonymous UUIDv4 generation + persistence + purge |
events.go | Event builders. Every builder is a few lines — easy to audit. |
sampling.go | Per-task sample rate |
prompt.go | First-run consent prompt flow |
The test file telemetry_test.go pins the contracts above: zero network calls when opted out, zero network calls under DO_NOT_TRACK, sanitization of every event builder, UUIDv4 format of the anonymous ID, and the redacted-key preview output.