Telemetry
Elide ships a small, anonymous telemetry subsystem. It exists to answer operational questions -- which platforms run Elide, how often it crashes, how long runs take -- without collecting source code, file contents, arguments, or personally identifying information. This page documents exactly what is collected, how it travels, and every supported way to switch it off.
The subsystem lives in the elidetelemetry crate (crates/telemetry/). It is
designed to never affect your program: every emission path is wrapped in
catch_unwind, so a telemetry failure can never crash the binary, and a send
that cannot complete is dropped rather than retried.
What is collected
Telemetry is event-based. There are exactly four event types, defined by theEvent enum in crates/telemetry/src/model.rs:
| Event | When it fires | Payload |
|---|---|---|
| Program boot | At startup, before command dispatch | No fields |
| Program exit | Before normal exit | Run duration (ms), subcommand id, exit code, exit reason |
| Program crash | On a Rust panic or unhandled JVM exception | Crash origin (rust/kotlin), exception/panic type name, error message, stack trace, active subcommand id |
| Dependency install | After a dependency install completes | Ecosystem id (Maven/NPM), package count, bytes transferred, cached-package count, cache status, duration (ms) |
ProgramExitEvent serde rules in
model.rs). Boot and exit fire on every run so that runs and durations can be
counted; the crash event fires only on failure.
Crash payloads
The crash event carries the exception type, message, and stack trace so that
failures can be triaged. Both are bounded before transmission, in
packages/entry/bin/bridge.rs (event_crash):
- Error message -- truncated to 512 bytes (
truncate_utf8(message, 512)). - Stack trace -- truncated to 4096 bytes (
truncate_utf8(backtrace, 4096)).
No file paths beyond what appears in a stack trace, no command-line arguments, and no source code are included.
Per-run metadata
Every batch carries a small block of build/platform metadata
(EventMetadata in model.rs), all of it baked in at compile time:
- Elide release number and version.
- Target platform (one of
linux-amd64,linux-arm64,darwin-amd64,darwin-arm64,windows-amd64, orunknown). - Whether the build is a release build.
- Whether debug symbols are present.
- A feature bitmask.
Events are correlated within a single execution by a per-run identifier and a monotonic ordinal; timestamps are encoded relative to a fixed 2026 epoch to keep payloads small. No stable cross-run device or user identifier is part of the event model.
How it is transported
Telemetry has two transports. They are tried in order:
1. Sidecar (preferred, Linux only). A single background process per (user,
Elide version) aggregates events from concurrent Elide invocations over local
IPC, batches them, and uploads over HTTP/3. The sidecar is gated on Linux in
crates/sidecar/src/policy.rs (is_sidecar_supported); macOS and Windows do
not use it. See the sidecar source for
batching and idle-shutdown behavior.
2. UDP fallback. When the sidecar is unavailable -- or declines an event --
buffered events are flushed as fire-and-forget UDP datagrams to Elide's relay
(crates/telemetry/src/udp.rs). Datagrams are encrypted with AES-128-GCM-SIV
using a per-build ephemeral X25519 key exchange, and compressed with zstd
before encryption. The relay hostname is receiver.elide.events; datagrams
go to UDP port 9514. Because UDP is connectionless, the firewall-visible DNS
lookup for that hostname is the only network signal a tool like Little Snitch
will correlate.
The HTTP transport endpoint and API key are compiled in at build time from the
ELIDE_TELEMETRY_ENDPOINT and ELIDE_TELEMETRY_API_KEY build variables
(crates/base/build.rs); they are not configurable at runtime.
UDP events are flushed when a terminal event (program exit) is recorded, so a short-lived command still delivers its boot and exit events on the way out.
How to disable it
Any one of the following disables telemetry. They are checked in
crates/telemetry/src/lib.rs.
DO_NOT_TRACK environment variable
Elide honors the cross-vendor DO_NOT_TRACK
convention. If the variable is set to any value, telemetry is disabled for the
run (check_do_not_track, called from init_telemetry):
export DO_NOT_TRACK=1
elide ./script.ts--no-telemetry flag
A global flag, available on every command, disables telemetry for that
invocation (crates/cli/src/lib.rs):
elide --no-telemetry ./script.ts--no-sidecar flag
A global flag that disables the background sidecar process
(crates/cli/src/lib.rs). This does not disable telemetry on its own -- it
forces the UDP fallback transport on Linux:
elide --no-sidecar ./script.tsTo both skip the sidecar and stop telemetry entirely, combine --no-sidecar
with --no-telemetry, or set DO_NOT_TRACK.
should_use_sidecar returns false once telemetry is off
(crates/sidecar/src/policy.rs).EAP builds
Unlicensed Early Access ("EAP") builds always emit telemetry. On these builds
force_enable_telemetry is called at startup, after which --no-telemetry and
DO_NOT_TRACK become no-ops (packages/entry/bin/main.rs,
crates/telemetry/src/lib.rs). Licensed builds respect every opt-out above. The
--no-telemetry flag help text reflects this: *"Disallow telemetry; has no
effect if unlicensed."*
Sources
crates/telemetry/src/model.rs--Event,EventMetadata, event payloadscrates/telemetry/src/lib.rs--check_do_not_track,disable_telemetry,force_enable_telemetry,is_telemetry_enabled, flush/terminal-event logiccrates/telemetry/src/udp.rs-- UDP relay, encryption, compression,RELAY_PORTcrates/telemetry/src/emit.rs-- sidecar IPC emission pathcrates/sidecar/src/policy.rs--is_sidecar_supported,should_use_sidecarcrates/cli/src/lib.rs----no-telemetry,--no-sidecarglobal flagspackages/entry/bin/bridge.rs--event_boot/event_exit/event_crash, crash truncationcrates/base/build.rs--ELIDE_TELEMETRY_ENDPOINT,ELIDE_TELEMETRY_API_KEY