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

env-surgeon

v0.1.7

Published

CLI + library to diff, scan, check and validate .env files

Downloads

651

Readme

env-surgeon

Diff, scan, check and validate .env files — CLI + Node.js library.

npm version npm downloads license


Why

Every Node.js project suffers from the same .env problems:

  • App crashes in production because someone forgot to add a new variable
  • .env.example is months out of date
  • CI passes but deployment fails with Cannot read property of undefined
  • No one knows which variables are required vs optional

env-surgeon solves all of this with a handful of commands.


Install

npx env-surgeon <command>          # run without installing
npm install -D env-surgeon         # dev dependency (recommended)
npm install -g env-surgeon         # global

Commands

diff — Compare two .env files

env-surgeon diff .env .env.production

scan — Scan source code, generate .env.example

env-surgeon scan ./src --output .env.example

Finds process.env.X, import.meta.env.X, Deno.env.get('X'), Bun.env.X, and destructured const { FOO } = process.env.

check — CI check for missing variables

env-surgeon check
env-surgeon check --env .env --template .env.example --strict

validate — Validate types and rules

env-surgeon validate --env .env --schema .env.schema.json

Supports types: string, number, boolean, url, email, json, port, duration, secret, array.

Zod is supported out of the box — point --schema at a .js/.mjs file whose default export is a Zod object schema:

// env.schema.js
import { z } from 'zod'
export default z.object({
  PORT: z.coerce.number().min(1024),
  DATABASE_URL: z.string().url(),
  LOG_LEVEL: z.enum(['debug', 'info', 'warn', 'error']).optional(),
})
env-surgeon validate --env .env --schema env.schema.js

zod is an optional peer dependency — install it only if you use this path.

print — Inspect the effective merged env

env-surgeon print --env .env.local --env .env --expand
env-surgeon print --env .env --reveal          # actual values to stdout

unused — Find dead env keys

env-surgeon unused ./src --env .env

init — Generate schema from existing .env

env-surgeon init --env .env --output .env.schema.json

Infers types (number, boolean, URL, email, JSON, port, duration) from values.


Common options

| Option | Description | |--------|-------------| | --json | Output as JSON | | --reporter <fmt> | Output format: text, json, junit | | --silent | Exit code only, no output | | --expand | Expand ${VAR} references (dotenv-expand semantics) | | --watch | Re-run on file changes (check, validate) | | --strict | Fail on extra keys not in template/schema | | --auto-env | Auto-select .env files by NODE_ENV |


Library API

import { diff, scan, check, validate } from 'env-surgeon'

const result = await diff('.env', '.env.production')
const found = await scan('./src')
const status = await check({ template: '.env.example', env: '.env' })
const errors = await validate({
  env: '.env',
  schema: { PORT: { type: 'number', required: true } },
})

Low-level helpers

import {
  parseEnvFile, parseEnvString, readEnvCascade,
  defaultEnvCascade, UserError,
} from 'env-surgeon'

Recommended project setup

your-project/
├── .env              ← local, git-ignored
├── .env.example      ← committed, generated by `scan`
└── .env.schema.json  ← committed, generated by `init`
{
  "scripts": {
    "env:sync":  "env-surgeon scan ./src --output .env.example",
    "env:check": "env-surgeon check",
    "prestart":  "env-surgeon check",
    "prebuild":  "env-surgeon validate"
  }
}

GitHub Action

- uses: env-surgeon/env-surgeon@v1
  with:
    command: check
    env: .env.ci
    template: .env.example
    strict: true

Advanced

See docs/guide.md for:

  • Environment adaptation (stdin, cascades, Windows, Bun/Deno)
  • Config file reference
  • NestJS / dotenv-expand compatibility
  • .env.vault encrypted file support
  • Watch mode
  • CI reporters (JUnit XML)
  • Execution model and pitfalls

Requirements

  • Node.js >= 20

License

MIT