npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

envradar

v0.1.0

Published

Inventory the environment variables your code expects and check them against every environment — surfacing missing vars, staging/production parity drift, and dead configuration.

Readme


The problem

"It works on staging but breaks in production" is one of the most common — and most avoidable — deployment failures, and environment misconfiguration is a leading cause. The problem is structural:

  • Your code declares what it needs: process.env.STRIPE_WEBHOOK_SECRET, os.environ["DATABASE_URL"].
  • Your infrastructure declares what it has: secrets in AWS, Vercel, Doppler, a .env file.
  • Nothing checks that the two lists agree.

So variables drift out of sync. One gets added to production at 3am during an incident and never backfilled to staging. One gets deleted from the code but lingers in every secrets manager for years. A new service ships to production missing a variable nobody knew to add.

Existing tools don't close this gap. Dotenv linters (dotenv-linter, dotenv-safe) only compare a single local .env against .env.example. Infrastructure drift tools (driftctl, Terragrunt) only compare cloud resources against Terraform state — not application-level variable usage. EnvRadar is the missing link between what the code reads and what every environment provides.

What it does

EnvRadar reduces the entire question — "is every environment configured correctly for this code?" — to one command, envradar scan, and one report with four verdicts:

| Status | Meaning | The failure it prevents | | :--- | :--- | :--- | | 🔴 MISSING | The code reads it, but no environment provides it. | A guaranteed crash the moment that code path runs. | | 🟡 PARITY | Present in some environments but not others. | The classic "works on staging, breaks in production" drift. | | ⚪ DEAD | Configured in an environment but no code reads it. | Secret sprawl and config rot — stale values that mislead. | | 🟢 OK | Read by the code and present everywhere. | Nothing to do. |

Run it locally before a deploy, or wire up the GitHub Action to post the report on every pull request and fail the build when something is missing or drifting.

How it works

EnvRadar is a three-stage pipeline. It performs pure static analysis — your code is never executed, so the scan is fast and safe to run anywhere, including untrusted CI.

flowchart LR
    src["Source code"] --> scan["Scanner<br/>language-aware patterns"]
    scan --> expected["Expected vars<br/>what the code reads"]
    envs["Environments<br/>.env files · secrets managers"] --> resolve["Resolver<br/>source adapters"]
    resolve --> provided["Provided vars<br/>what each env has"]
    expected --> compare{"Compare"}
    provided --> compare
    compare --> report["Report<br/>MISSING · PARITY · DEAD · OK"]

1. Scan — build the manifest of what the code expects. EnvRadar walks your source tree and applies a set of language-aware patterns to every supported file, extracting each environment-variable reference together with its file and line number. There's no build step and nothing is run; it simply reads source. The output is the expected manifest — the complete set of variables your code depends on.

2. Resolve — find out what each environment provides. For every environment you configure, a source adapter reports the set of variable names that environment supplies. The built-in dotenv adapter reads the keys from a .env file; planned adapters query secrets managers like AWS SSM, Vercel, and Doppler. EnvRadar only ever reads variable names — never secret values. With no configuration at all, it auto-discovers local .env.* files and treats each as an environment.

3. Compare — cross-reference and classify. EnvRadar builds a matrix of what the code needs against what each environment has and assigns every variable a status. ignore rules in your config demote intentional cases (an environment-specific flag, an allowed legacy var) to OK, and the failOn setting decides which statuses cause a non-zero exit so CI can gate on them.

Each variable lands in exactly one bucket:

flowchart TD
    start["Each variable"] --> incode{"Read by<br/>any code?"}
    incode -- no --> dead["DEAD<br/>configured but unused"]
    incode -- yes --> provided{"Provided by<br/>environments?"}
    provided -- "none of them" --> missing["MISSING<br/>code needs it, nothing has it"]
    provided -- "some, not all" --> parity["PARITY<br/>drift across environments"]
    provided -- "all of them" --> ok["OK"]

The report is then rendered three ways — a colored terminal table for humans, JSON for tooling, and Markdown for pull-request comments.

Runs entirely on your machine

EnvRadar is local-first: no hosted service, no account, no telemetry. The envradar CLI makes no network calls — it reads your source and .env files from disk, analyzes them in-process, and writes a report. Nothing about your code or configuration is uploaded anywhere, because there's no reason for it to be.

flowchart LR
    subgraph local["Your machine / CI runner — everything happens here"]
        direction LR
        code["Source files"] --> eg["envradar CLI"]
        cfg[".env files and envradar.yml"] --> eg
        eg --> report["Report:<br/>terminal · JSON · Markdown"]
    end
    eg x--x net(["External servers · telemetry"])
  • Only names, never values. EnvRadar compares variable names. It never reads, stores, or prints the secret values inside your .env files.
  • Future cloud sources stay direct. Planned adapters (AWS SSM, Vercel, Doppler, …) will talk directly to your own provider with your own credentials to list variable names — still no third-party server in the middle, and still names only.

Install

npm install -g envradar

…or run it without installing:

npx envradar scan

Requires Node.js 18 or newer.

Quick start

From a project that has .env.staging and .env.production files, EnvRadar works with zero configuration — it discovers them automatically:

envradar scan

Point it at a specific directory and/or config file:

envradar scan ./services/api --config envradar.yml

Try the bundled demo

The repository ships a demo with source files in all five supported languages and two diverging environments:

git clone https://github.com/rinorhatashi/EnvRadar
cd EnvRadar
npm install && npm run build
node dist/index.js scan examples/demo

Example output

EnvRadar  ·  scanned 5 files  ·  2 environments (staging, production)

VARIABLE               CODE  staging  production  STATUS
STRIPE_WEBHOOK_SECRET   ✓       ✗         ✗       MISSING
API_KEY                 ✓       ✓         ✗       PARITY
DEBUG                   –       ✓         ✗       DEAD
LEGACY_TOKEN            –       ✓         ✓       DEAD
DATABASE_URL            ✓       ✓         ✓       OK
REDIS_URL               ✓       ✓         ✓       OK
SENDGRID_API_KEY        ✓       ✓         ✓       OK

  1 missing · 1 parity · 2 dead · 3 ok

  MISSING  STRIPE_WEBHOOK_SECRET — read at src/billing.ts:3, not set in any environment
  PARITY   API_KEY — set in staging; missing in production (read at app/server.py:5)
  DEAD     DEBUG — set in staging but not read by any scanned file
  DEAD     LEGACY_TOKEN — set in staging, production but not read by any scanned file

The same report, as machine-readable JSON or as a Markdown PR comment:

envradar scan --format json
envradar scan --format markdown

Supported languages

Each language is matched with its own idiomatic access patterns. Adding a language is a small, self-contained change to src/scan/patterns.ts.

| Language | Extensions | Detected forms | | :--- | :--- | :--- | | Node.js / TypeScript | .js .jsx .mjs .cjs .ts .tsx .mts .cts | process.env.X, process.env['X'], import.meta.env.X | | Python | .py | os.environ['X'], os.environ.get('X'), os.getenv('X') | | Ruby | .rb .erb .rake | ENV['X'], ENV.fetch('X') | | Go | .go | os.Getenv("X"), os.LookupEnv("X") | | Rust | .rs | std::env::var("X"), env::var("X"), std::env::var_os("X") |

Configuration

EnvRadar runs with zero config, but an envradar.yml at your project root unlocks declared environments, ignore rules, and CI behavior. Every field is optional.

# Which environments to compare, and where to read each one's variable names.
environments:
  staging:
    source: dotenv
    path: .env.staging
  production:
    source: dotenv
    path: .env.production

# Statuses that make `envradar scan` exit non-zero. Defaults to MISSING + PARITY.
failOn:
  - MISSING
  - PARITY

# Silence intentional findings by listing variable names.
ignore:
  parity:
    - DEBUG          # intentionally environment-specific — don't flag drift
  dead:
    - LEGACY_TOKEN   # allowed legacy var during a cleanup sprint
  missing:
    - OPTIONAL_VAR   # read by code but not required in any environment

# Narrow what gets scanned. Defaults to every supported file under the root.
scan:
  include:
    - "src/**"
    - "app/**"
  exclude:
    - "**/*.test.ts"

If environments is omitted, EnvRadar auto-discovers them from local .env.* files (.envlocal, .env.stagingstaging, …), skipping .example, .sample, and .local files.

Sources

A source answers a single question: "which variables does this environment provide?" Adapters implement one small interface (src/sources/types.ts) and only ever read variable names, never secret values — so coverage grows without touching the core.

| Source | Status | Configuration | | :--- | :--- | :--- | | dotenv — local .env files | ✅ Available | path: .env.<environment> | | AWS SSM Parameter Store | 🔜 Planned | — | | GitHub Actions secrets | 🔜 Planned | — | | Vercel | 🔜 Planned | — | | Doppler | 🔜 Planned | — | | Railway / Render | 🔜 Planned | — |

CLI reference

envradar scan [path]

Arguments:
  path                    directory to scan (default: ".")

Options:
  -c, --config <file>     path to an envradar.yml config file
  -f, --format <format>   output format: table | json | markdown (default: table)
  -o, --output <file>     write the report to a file instead of stdout
  --fail-on <list>        statuses that cause a non-zero exit:
                          missing, parity, dead, none (default: missing,parity)
  --no-color              disable colored output
  -v, --version           print the EnvRadar version
  -h, --help              show help

Exit codes

EnvRadar is built to gate a pipeline:

| Code | Meaning | | :---: | :--- | | 0 | No findings in the fail-on set. | | 1 | At least one finding in the fail-on set (e.g. a MISSING or PARITY variable). | | 2 | EnvRadar errored (bad config, unreadable path, …). |

GitHub Action

Run EnvRadar on every pull request. It posts the report as a comment that updates in place on each push:

sequenceDiagram
    participant PR as Pull request
    participant CI as GitHub Actions
    participant EG as envradar CLI
    PR->>CI: push / open PR
    CI->>EG: envradar scan
    EG-->>CI: report + exit code
    CI->>PR: create or update the report comment
    CI-->>CI: fail the check if MISSING / PARITY

Copy examples/github-workflow.yml to .github/workflows/envradar.yml:

name: EnvRadar
on:
  pull_request:
  push:
    branches: [main]

jobs:
  envradar:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      pull-requests: write # required to post the report comment
    steps:
      - uses: actions/checkout@v4
      - uses: rinorhatashi/EnvRadar@v1
        with:
          working-directory: .
          # config: envradar.yml
          # fail-on: missing,parity

When a fail-on status is present, the job fails — turning environment drift into a red check instead of a 3am page.

| Input | Description | Default | | :--- | :--- | :--- | | working-directory | Directory to scan. | . | | config | Path to an envradar.yml. | (auto) | | fail-on | Statuses that fail the job. | (from config / defaults) | | comment | Post/update the PR comment. | true | | version | envradar npm version to run. | latest | | github-token | Token used to post the comment. | ${{ github.token }} |

Roadmap

  • Source adapters for AWS SSM, GitHub Actions secrets, Vercel, Doppler, Railway, and Render.
  • Destructuring (const { FOO } = process.env) and comment-aware scanning.
  • SARIF output for GitHub code scanning, and a --baseline file to accept existing findings.
  • More languages (Java, PHP, .NET, Elixir).

Contributing

EnvRadar is designed to be extended in small, isolated pieces:

npm install
npm test                            # run the test suite
npm run build                       # compile to dist/
npm run dev -- scan examples/demo   # run straight from source

License

MIT © Rinor Hatashi