apvarun/no-telemetry

Detect JS/TS libraries with telemetry and set opt-out env vars in one command

5

stars

15

commits

TypeScript

primary language

Aug 22, 2026

updated

README

no-telemetry

Detect telemetry in your JS/TS dependencies and disable it in one command.

npm version npm downloads CI License: MIT Node.js 18+

The name applies to the CLI, too: no-telemetry collects no telemetry, has zero production dependencies, and makes no runtime network requests.

Terminal demo of no-telemetry finding dependencies and disabling their telemetry

Contents

Why no-telemetry?

  • Keep project activity private. Disable supported analytics at the source with each tool's documented environment variable.
  • Keep telemetry out of CI. Apply the same opt-outs locally, in automation, and in air-gapped environments without maintaining a pile of one-off scripts.
  • Make policy auditable. Store explicit opt-outs in a dotenv file and enforce them with a CI-friendly exit code.
  • Stop hunting through vendor docs. Use one curated registry for vendor-specific flags and the DO_NOT_TRACK convention.

Quick start

Run these commands from the directory containing your package.json:

npx no-telemetry init -y   # add missing opt-out variables to .env
npx no-telemetry doctor    # show telemetry status
npx no-telemetry check     # same report; exit 1 if anything is still enabled

Want to inspect the change first?

npx no-telemetry init --dry-run

Agents and CI can use structured output:

npx no-telemetry init -y --json
npx no-telemetry check --json=compact   # one-line JSON for pipes
npx no-telemetry list --json            # registry coverage; no project needed
npx no-telemetry why next --json        # env variable and docs for one tool

What it looks like

After init, doctor prints a per-tool status table:

Library     Status      Variable
────────────────────────────────────────────
Next.js     ✓ disabled  NEXT_TELEMETRY_DISABLED=1
Turborepo   ✓ disabled  TURBO_TELEMETRY_DISABLED=1
Prisma      ✓ disabled  CHECKPOINT_DISABLE=1

3 of 3 applicable libraries have telemetry disabled.

doctor always exits 0. Use check when enabled telemetry should fail a build.

Coverage

The bundled registry currently knows about 43 tools: 34 documented environment-variable opt-outs, 2 opt-in checks, and 7 config-only tools that are detected and reported without being changed.

That includes Next.js, Prisma, Vercel CLI, Turborepo, Storybook, Expo, Wrangler, Supabase CLI, GitHub CLI, Claude Code, and more.

npx no-telemetry list        # show every registry entry
npx no-telemetry why turbo   # show Turbo's variables, notes, and official docs

Is your tool missing? Adding a registry entry is a small, data-only contribution.

Unlike manually grepping documentation or maintaining a broad list such as toptout, no-telemetry detects the tools in the current project, applies their documented dotenv opt-outs, and can enforce the result in CI.

How it works and stays safe

  1. Reads the dependencies and devDependencies from the current directory's package.json.
  2. Matches those direct dependencies against the registry bundled with the package.
  3. Adds the documented opt-out variables to .env or another target you choose.
  4. Resolves the effective values from the process environment, .env.local, and .env, then reports whether telemetry is disabled.

The CLI is deliberately narrow:

  • It makes no runtime network requests and never downloads a registry. (npx may download the package itself when it is not already cached.)
  • It never overwrites a non-empty value. Conflicts are reported for you to resolve.
  • It fills empty KEY= placeholders in place and keeps new variables in one marker-delimited block.
  • It writes only dotenv-style assignments and its audit marker comments to the selected target; the default is .env.
  • It does not edit shell profiles, tool config files, lockfiles, or package.json.
  • It always includes DO_NOT_TRACK=1 alongside any tool-specific variables.
  • Re-running init is idempotent.

Scope

no-telemetry scans one package.json in the current directory. It does not currently scan workspaces or transitive dependencies.

The registry focuses on environment-variable opt-outs. Tools that require config files or saved CLI state are reported as unsupported and left untouched.

doctor and check resolve values in this precedence order: process environment, .env.local, then .env.

CI

Pin the version so your policy does not change unexpectedly:

- name: Telemetry opt-out check
  run: npx --yes no-telemetry@0.2.0 check --json=compact

To apply opt-outs after scaffolding and then verify them:

- run: npx --yes no-telemetry@0.2.0 init -y
- run: npx --yes no-telemetry@0.2.0 check --json=compact

The first --yes accepts the npx install. The -y after init accepts the file write.

Command reference

init

Reads package.json, matches direct dependencies against the built-in registry, and adds missing opt-out variables to the write target. The default target is .env.

FlagMeaning
--yes / -ySkip confirmation (required when non-TTY or CI=true)
--dry-runShow what would be written; do not write
--jsonMachine-readable report (version: 1)
--target <path>Any env-file path, or stdout (default: .env)
--exampleShorthand for --target .env.example (commit-safe opt-out template)

init does not accept --only, --ignore, or --all; those flags belong to doctor and check.

  • Creates the target file if needed (except for stdout)
  • Skips variables already set correctly
  • Fills empty KEY= placeholders in place
  • Warns instead of overwriting a different value
  • Always includes DO_NOT_TRACK=1
  • Keeps generated variables in one marker-delimited section with a versioned creation header
  • In stdout mode, writes pure KEY=VALUE lines to stdout and diagnostics to stderr
  • With --target stdout --json, keeps dotenv lines on stdout and sends the JSON report to stderr
  • Treats --example / .env.example like any other dotenv target; generated values contain no secrets

doctor

Prints a per-library table and always exits 0. Installed libraries determine the summary. The human-readable table hides not found rows unless you pass --all.

FlagMeaning
--jsonFull machine-readable report
--only <filter>installed or failing
--ignore <value>Omit by id, display name, or package; repeatable
--allInclude not-found rows in the human table

doctor and check do not accept --yes, --dry-run, or --target.

--only filters libraries[] in JSON; summary retains the full post---ignore policy counts.

check

Produces the same output as doctor, but exits 1 if any installed, applicable library still has telemetry enabled after --ignore.

npx no-telemetry check

list

Dumps the full registry without reading package.json. Use it to discover coverage or feed registry data to another tool.

npx no-telemetry list
npx no-telemetry list --json

why <id>

Explains one registry entry: environment variables, official docs, notes, and alternate satisfaction signals.

npx no-telemetry why next
npx no-telemetry why turbo --json

Shared flags

FlagMeaning
--jsonPretty-printed JSON report (version: 1)
--json=compactOne-line JSON for pipes
--quiet / -qSuppress human diagnostics; with --json, also selects compact output
--version / -VPrint version
--help / -hShow help

Color

Environment variableEffect
NO_COLORDisable ANSI colors when set to any non-empty value
FORCE_COLORForce colors outside a TTY (0 disables them)

Exit codes

CodeMeaning
0Success; doctor always, check when policy passes, or init completes
1Policy failure; check found enabled telemetry, or interactive init was aborted
2Tool or usage error; bad flags, missing package.json, or unconfirmed non-TTY init

Registry details

Library definitions live in src/registry.ts, the single source of truth. Each has a stable id such as next, prisma, or vercel for --ignore, why, and JSON output. Every environment variable is curated against official documentation.

Some tools honor a proprietary opt-out or DO_NOT_TRACK (for example, Turbo, Railway, and Supabase). Alternate signals use OR semantics by default. Entries with alternatePolicy: "fallback" use alternates only when the primary key is unset; this models tools such as GitHub CLI, where GH_TELEMETRY takes precedence. init still writes the primary tool-specific key plus DO_NOT_TRACK=1.

Registry entries are a discriminated union:

kindMeaning
opt-outTelemetry is on by default; set env to disable it
opt-inTelemetry is off by default; enableWhen values mean it is on
unsupportedNo environment-variable opt-out; config or CLI action is required

opt-out bindings may include accepts for multiple accepted values or non-empty semantics. Entries can also include alsoSatisfiedBy and alternatePolicy for additional signals.

Programmatic API

The stable API is ESM-only and supports Node.js 18+:

import { scan, planInit, applyInit, failsCheck, buildReport, REGISTRY } from "no-telemetry";

const cwd = process.cwd();
const results = scan(cwd);
const failing = results.filter(failsCheck);
const report = buildReport(cwd, results);
ExportRole
scan / evaluateDetect dependencies and evaluate status
planInit / applyInitPlan and apply idempotent dotenv writes
failsCheckApply the check policy
buildReport / buildErrorReportBuild the JSON DTO (version: 1)
REGISTRYRead the curated library data
filterResultsApply presentation filters

LibraryResult.status uses machine-stable tokens: disabled, enabled, not_applicable, not_found, and unsupported. The CLI maps these to human labels such as ✓ disabled and - n/a.

Target-specific plans must be applied to the same target:

const target = ".env.local";
const plan = planInit(cwd, { target });
applyInit(cwd, plan, { target });

scan(cwd, process.env, { envFiles: [".env", ".env.local"] });

Contributing

The easiest way to expand coverage is to add a typed entry to src/registry.ts:

  1. Find the tool's official telemetry documentation.
  2. Add its package match, stable id, opt-out variable, docs URL, and any notes.
  3. Run the tests; registry entries receive automatic golden-test coverage.

Special matching or precedence rules should include a focused test. Config-only tools are welcome as unsupported entries so doctor can still surface them without changing user files.

See CONTRIBUTING.md for the full registry schema, development workflow, and pull request checklist.

Development

pnpm install
pnpm run check
pnpm test
pnpm run build

The development toolchain runs on Node.js 22. The packed CLI and programmatic API are smoke-tested on Node.js 18, 20, and 22:

mkdir -p artifacts
pnpm pack --pack-destination artifacts
TARBALL=$(find artifacts -name '*.tgz' -type f -print -quit)
pnpm run test:package "$TARBALL" --tsc node_modules/.bin/tsc

Zero production dependencies. Runtime support: Node.js 18+.

License

MIT

Contributors

apvarun

15 commits

apvarun/no-telemetry

Detect JS/TS libraries with telemetry and set opt-out env vars in one command

5

stars

15

commits

TypeScript

primary language

Aug 22, 2026

updated

README

no-telemetry

Detect telemetry in your JS/TS dependencies and disable it in one command.

npm version npm downloads CI License: MIT Node.js 18+

The name applies to the CLI, too: no-telemetry collects no telemetry, has zero production dependencies, and makes no runtime network requests.

Terminal demo of no-telemetry finding dependencies and disabling their telemetry

Contents

Why no-telemetry?

  • Keep project activity private. Disable supported analytics at the source with each tool's documented environment variable.
  • Keep telemetry out of CI. Apply the same opt-outs locally, in automation, and in air-gapped environments without maintaining a pile of one-off scripts.
  • Make policy auditable. Store explicit opt-outs in a dotenv file and enforce them with a CI-friendly exit code.
  • Stop hunting through vendor docs. Use one curated registry for vendor-specific flags and the DO_NOT_TRACK convention.

Quick start

Run these commands from the directory containing your package.json:

npx no-telemetry init -y   # add missing opt-out variables to .env
npx no-telemetry doctor    # show telemetry status
npx no-telemetry check     # same report; exit 1 if anything is still enabled

Want to inspect the change first?

npx no-telemetry init --dry-run

Agents and CI can use structured output:

npx no-telemetry init -y --json
npx no-telemetry check --json=compact   # one-line JSON for pipes
npx no-telemetry list --json            # registry coverage; no project needed
npx no-telemetry why next --json        # env variable and docs for one tool

What it looks like

After init, doctor prints a per-tool status table:

Library     Status      Variable
────────────────────────────────────────────
Next.js     ✓ disabled  NEXT_TELEMETRY_DISABLED=1
Turborepo   ✓ disabled  TURBO_TELEMETRY_DISABLED=1
Prisma      ✓ disabled  CHECKPOINT_DISABLE=1

3 of 3 applicable libraries have telemetry disabled.

doctor always exits 0. Use check when enabled telemetry should fail a build.

Coverage

The bundled registry currently knows about 43 tools: 34 documented environment-variable opt-outs, 2 opt-in checks, and 7 config-only tools that are detected and reported without being changed.

That includes Next.js, Prisma, Vercel CLI, Turborepo, Storybook, Expo, Wrangler, Supabase CLI, GitHub CLI, Claude Code, and more.

npx no-telemetry list        # show every registry entry
npx no-telemetry why turbo   # show Turbo's variables, notes, and official docs

Is your tool missing? Adding a registry entry is a small, data-only contribution.

Unlike manually grepping documentation or maintaining a broad list such as toptout, no-telemetry detects the tools in the current project, applies their documented dotenv opt-outs, and can enforce the result in CI.

How it works and stays safe

  1. Reads the dependencies and devDependencies from the current directory's package.json.
  2. Matches those direct dependencies against the registry bundled with the package.
  3. Adds the documented opt-out variables to .env or another target you choose.
  4. Resolves the effective values from the process environment, .env.local, and .env, then reports whether telemetry is disabled.

The CLI is deliberately narrow:

  • It makes no runtime network requests and never downloads a registry. (npx may download the package itself when it is not already cached.)
  • It never overwrites a non-empty value. Conflicts are reported for you to resolve.
  • It fills empty KEY= placeholders in place and keeps new variables in one marker-delimited block.
  • It writes only dotenv-style assignments and its audit marker comments to the selected target; the default is .env.
  • It does not edit shell profiles, tool config files, lockfiles, or package.json.
  • It always includes DO_NOT_TRACK=1 alongside any tool-specific variables.
  • Re-running init is idempotent.

Scope

no-telemetry scans one package.json in the current directory. It does not currently scan workspaces or transitive dependencies.

The registry focuses on environment-variable opt-outs. Tools that require config files or saved CLI state are reported as unsupported and left untouched.

doctor and check resolve values in this precedence order: process environment, .env.local, then .env.

CI

Pin the version so your policy does not change unexpectedly:

- name: Telemetry opt-out check
  run: npx --yes no-telemetry@0.2.0 check --json=compact

To apply opt-outs after scaffolding and then verify them:

- run: npx --yes no-telemetry@0.2.0 init -y
- run: npx --yes no-telemetry@0.2.0 check --json=compact

The first --yes accepts the npx install. The -y after init accepts the file write.

Command reference

init

Reads package.json, matches direct dependencies against the built-in registry, and adds missing opt-out variables to the write target. The default target is .env.

FlagMeaning
--yes / -ySkip confirmation (required when non-TTY or CI=true)
--dry-runShow what would be written; do not write
--jsonMachine-readable report (version: 1)
--target <path>Any env-file path, or stdout (default: .env)
--exampleShorthand for --target .env.example (commit-safe opt-out template)

init does not accept --only, --ignore, or --all; those flags belong to doctor and check.

  • Creates the target file if needed (except for stdout)
  • Skips variables already set correctly
  • Fills empty KEY= placeholders in place
  • Warns instead of overwriting a different value
  • Always includes DO_NOT_TRACK=1
  • Keeps generated variables in one marker-delimited section with a versioned creation header
  • In stdout mode, writes pure KEY=VALUE lines to stdout and diagnostics to stderr
  • With --target stdout --json, keeps dotenv lines on stdout and sends the JSON report to stderr
  • Treats --example / .env.example like any other dotenv target; generated values contain no secrets

doctor

Prints a per-library table and always exits 0. Installed libraries determine the summary. The human-readable table hides not found rows unless you pass --all.

FlagMeaning
--jsonFull machine-readable report
--only <filter>installed or failing
--ignore <value>Omit by id, display name, or package; repeatable
--allInclude not-found rows in the human table

doctor and check do not accept --yes, --dry-run, or --target.

--only filters libraries[] in JSON; summary retains the full post---ignore policy counts.

check

Produces the same output as doctor, but exits 1 if any installed, applicable library still has telemetry enabled after --ignore.

npx no-telemetry check

list

Dumps the full registry without reading package.json. Use it to discover coverage or feed registry data to another tool.

npx no-telemetry list
npx no-telemetry list --json

why <id>

Explains one registry entry: environment variables, official docs, notes, and alternate satisfaction signals.

npx no-telemetry why next
npx no-telemetry why turbo --json

Shared flags

FlagMeaning
--jsonPretty-printed JSON report (version: 1)
--json=compactOne-line JSON for pipes
--quiet / -qSuppress human diagnostics; with --json, also selects compact output
--version / -VPrint version
--help / -hShow help

Color

Environment variableEffect
NO_COLORDisable ANSI colors when set to any non-empty value
FORCE_COLORForce colors outside a TTY (0 disables them)

Exit codes

CodeMeaning
0Success; doctor always, check when policy passes, or init completes
1Policy failure; check found enabled telemetry, or interactive init was aborted
2Tool or usage error; bad flags, missing package.json, or unconfirmed non-TTY init

Registry details

Library definitions live in src/registry.ts, the single source of truth. Each has a stable id such as next, prisma, or vercel for --ignore, why, and JSON output. Every environment variable is curated against official documentation.

Some tools honor a proprietary opt-out or DO_NOT_TRACK (for example, Turbo, Railway, and Supabase). Alternate signals use OR semantics by default. Entries with alternatePolicy: "fallback" use alternates only when the primary key is unset; this models tools such as GitHub CLI, where GH_TELEMETRY takes precedence. init still writes the primary tool-specific key plus DO_NOT_TRACK=1.

Registry entries are a discriminated union:

kindMeaning
opt-outTelemetry is on by default; set env to disable it
opt-inTelemetry is off by default; enableWhen values mean it is on
unsupportedNo environment-variable opt-out; config or CLI action is required

opt-out bindings may include accepts for multiple accepted values or non-empty semantics. Entries can also include alsoSatisfiedBy and alternatePolicy for additional signals.

Programmatic API

The stable API is ESM-only and supports Node.js 18+:

import { scan, planInit, applyInit, failsCheck, buildReport, REGISTRY } from "no-telemetry";

const cwd = process.cwd();
const results = scan(cwd);
const failing = results.filter(failsCheck);
const report = buildReport(cwd, results);
ExportRole
scan / evaluateDetect dependencies and evaluate status
planInit / applyInitPlan and apply idempotent dotenv writes
failsCheckApply the check policy
buildReport / buildErrorReportBuild the JSON DTO (version: 1)
REGISTRYRead the curated library data
filterResultsApply presentation filters

LibraryResult.status uses machine-stable tokens: disabled, enabled, not_applicable, not_found, and unsupported. The CLI maps these to human labels such as ✓ disabled and - n/a.

Target-specific plans must be applied to the same target:

const target = ".env.local";
const plan = planInit(cwd, { target });
applyInit(cwd, plan, { target });

scan(cwd, process.env, { envFiles: [".env", ".env.local"] });

Contributing

The easiest way to expand coverage is to add a typed entry to src/registry.ts:

  1. Find the tool's official telemetry documentation.
  2. Add its package match, stable id, opt-out variable, docs URL, and any notes.
  3. Run the tests; registry entries receive automatic golden-test coverage.

Special matching or precedence rules should include a focused test. Config-only tools are welcome as unsupported entries so doctor can still surface them without changing user files.

See CONTRIBUTING.md for the full registry schema, development workflow, and pull request checklist.

Development

pnpm install
pnpm run check
pnpm test
pnpm run build

The development toolchain runs on Node.js 22. The packed CLI and programmatic API are smoke-tested on Node.js 18, 20, and 22:

mkdir -p artifacts
pnpm pack --pack-destination artifacts
TARBALL=$(find artifacts -name '*.tgz' -type f -print -quit)
pnpm run test:package "$TARBALL" --tsc node_modules/.bin/tsc

Zero production dependencies. Runtime support: Node.js 18+.

License

MIT

Contributors

apvarun

15 commits

Languages

TypeScript

73.7%

JavaScript

26.3%