Perry sends no telemetry unless you accept the first-run prompt (or explicitly
set telemetry.enabled = true in ~/.perry/config.toml). This setting is the
master consent gate for every telemetry channel. If it is false or missing,
nothing is sent, even when compatibility_reports = "on". The environment
overrides PERRY_NO_TELEMETRY=1 and CI=true always win as well.
Counts perry compile, perry init, perry publish invocations on a
background HTTP POST. Sends: command name, platform (darwin/linux/...),
Perry version, success/error status, and an anonymous client UUID.
Additional opt-in for "I hit an unsupported TS/Node feature and bailed."
This channel is available only while the master enabled consent is true.
It sends a structured report when the compiler emits one of these diagnostic codes:
UnsupportedBinaryOp, UnsupportedExpression, UnsupportedStatement,
DynamicPropertyAccess, ImplicitCoercion, UnresolvedImport, NoOpStub.
Three modes:
off— never send. Sink isn't even installed; zero overhead.ask(default) — when a qualifying diagnostic fires, prompt once per session:[y] just this once / [a] always / [n] not this time / [N] never.on— always send (after dedup + redaction). No prompt.
What's sent (the entire payload schema):
{
"perry_version": "0.5.x",
"client_id": "uuid",
"code": "UnsupportedExpression",
"category": "gap-categorical",
"stage": "hir-lower",
"snippet_hash": "sha256:...",
"snippet_redacted": "let <id1> = await <id2>();",
"ts_feature": "decorator",
"node_api": "node:async_hooks.createHook",
"os": "darwin-arm64",
"node_target": "20"
}What's NEVER sent: raw source, file paths, project names, env vars, your
program's stdout/stderr, dependency tree, or anything tied to identity
beyond the existing anonymous client_id. Snippets are redacted before
hashing — string literals → "<str>", numbers → <num>, identifiers
(except built-ins like console, Math, Promise) → <id1>, <id2>,
capped at 200 chars, with a hard reject if any invariant fails.
A local 30-day dedup cache at ~/.perry/.report-cache prevents resending
the same snippet_hash on every reload.
perry doctor # shows current mode, sent/queued counts
perry doctor --show-pending-reports # print redacted payloads queued this run
perry doctor --clear-report-cache # wipe the 30-day dedup cacheTo opt out at the file level, edit ~/.perry/config.toml:
[telemetry]
enabled = false # all telemetry off
compatibility_reports = "off" # optional; master opt-out already winsSee also the PERRY_NO_TELEMETRY row in the perry.toml reference.