Skip to main content
Extension.js collects a tiny amount of anonymous telemetry to understand which commands you run and which fail. It never collects source code, file paths, URLs, or project content. The privacy bar is strict by design:
  • Two events total: command_executed and command_failed
  • Three properties per event: command, success, version
  • Opt-out with an environment variable, a CLI flag, or a persistent consent command
  • Extension.js samples and caps events to stay well inside the PostHog (open-source analytics) free tier

What Extension.js collects

Per CLI run, at most one of: The create command may add two more properties: template (the sanitized template name) and source (where the template came from). The create command is also exempt from sampling, so template usage numbers stay accurate. Common context attached to every event: os (darwin/linux/win32), arch, node_major, is_ci, is_source_build. Nothing else. is_source_build is a single boolean answering “was this a registry install or a repository checkout”. It is computed from the shape of the install path (whether a node_modules-style segment sits above the CLI). The path itself is never read into the event, sent, or hashed.

Volume controls

Three independent controls limit how much data leaves the machine:
  • Sampling: Extension.js samples command_executed at 20 % by default. Override with EXTENSION_TELEMETRY_SAMPLE_RATE (0.0–1.0). Failures are never sampled.
  • Per-run cap: at most 3 events per CLI process. Override with EXTENSION_TELEMETRY_MAX_EVENTS.
  • Debounce (duplicate suppression): Extension.js drops duplicate (event, command, success) tuples within 60 s. Override with EXTENSION_TELEMETRY_DEBOUNCE_MS.

What Extension.js never collects

The Extension.js telemetry contract explicitly excludes:
  • Source code, manifest contents, HTML output, or package.json contents
  • Repo names, Git remotes, GitHub org/user names, branch names, commit SHAs, or preview URLs
  • Dependency lists, permission lists, or freeform project identifiers
  • Environment variable values, filesystem paths, or machine-local URLs
  • Stack traces, error messages, or free-text error names
  • IP addresses (Extension.js sets $ip to null on every payload)

Opt out

Three ways to disable telemetry, listed in precedence order:
The consent file lives at $XDG_CONFIG_HOME/extensionjs/telemetry/consent (or the platform equivalent). When that location is not writable, storage falls back in order: the platform cache directory, then a folder under the system temp directory, then ./.cache/extensionjs in the working directory.

Default behavior

In an interactive terminal, telemetry is opt-out. On the first run where none of the overrides above apply, Extension.js prints a one-line notice explaining how to disable it. It also records an enabled consent marker so the notice does not repeat.

CI is off by default

In CI with nothing attached to stdout (a CI marker set and no TTY), telemetry is off by default and reports source: ci. A stored enabled consent does not carry into a pipeline: consent recorded by a person at a keyboard cannot cover a pipeline that inherited that home directory, so the stored opt-in is demoted below the CI gate. A stored disabled is a refusal, and a refusal always wins, in CI and everywhere else. To send telemetry from a pipeline on purpose, set EXTENSION_TELEMETRY=1. That explicit machine-level opt-in sits above the CI gate.

Local audit log

Extension.js appends every event it considers sending (whether or not it actually ships) to events.jsonl next to the consent file. Inspect it any time. Delete it freely. The audit log stays bounded. At 1 MiB it rolls to a single events.jsonl.1 backup, replacing any previous backup. Override the cap with EXTENSION_TELEMETRY_AUDIT_MAX_BYTES. A file grossly over the cap (10 times or more) is dropped instead of kept. If the audit write itself fails, Extension.js disables all further sends for that run: an event that cannot be audited locally is not sent.

Best practices

  • Use EXTENSION_TELEMETRY_DISABLED=1 in CI when policy requires no telemetry.
  • Treat privacy regressions as product regressions.
  • Read the repository-level contract for the exact event list.

Next steps

  • Review Global flags for --no-telemetry and environment variable overrides.
  • Use build and dev for release and automation workflows.
  • Read the repository-level docs/TELEMETRY.md contract for the exact event list.