spotenv — scan a JavaScript/TypeScript codebase for environment variable usage and generate a safe
.env.sample-filenamefile.
- Automatically discover the environment variables your code expects — great for onboarding, PRs, CI checks and documentation.
- Avoids manual errors: keeps
.env.sample-filenamein sync with code. - Safer than naive tools: it uses AST-based extraction (Babel) for accurate detection rather than brittle regex-only scanning.
- Works with both JavaScript and TypeScript projects (parses TypeScript syntax via
@babel/parserplugin).
-
Scans source files (
.js,.ts,.jsx,.tsx,.mjs,.cjs). -
Two-pass strategy: fast text heuristics to find candidate files, then AST extraction for precision.
-
Detects:
process.env.FOOprocess.env['FOO']/process.env["FOO"]const { FOO } = process.env(with optional default values)import.meta.env.FOO(Vite)
-
Flags dynamic usages (
process.env[someVar]) for manual review. -
Avoids writing secrets or sensitive defaults to
sample-filename(heuristic: keys containingSECRET,TOKEN,KEY,PWD,PASSWORD,PRIVATEare treated as sensitive). -
Watch mode — auto-regenerate
sample-filenameon file changes. -
Merge mode — preserve keys in an existing
sample-filenamewhile adding newly detected keys. -
You can customize a
.spotenv.jsonfile - the main configuration file of spotenv - to enable you to use spotenv without the cli flags. -
Multiple output formats: Generate
sample-filenamein env, JSON, or YAML format.
- Create a
.spotenv.jsonfile in the root of your project. - Manually customize the individual flag options -
dir,out,watch,mergeandignore- wheredirrefers to the target project directory to scan using both relative and absolute paths,outrefers to the location of your.env,.env.example,.env.localfile, specified to the directory of choice, whilewatchmergeandignoreset the flags to watch, merge and list the directories to ignore scanning for environment variables respectively. In action, your configuration file should look like this:
{
"dir": "/home/ubuntu/projects/project1",
"out": ".env.example",
"watch": false,
"merge": false,
"format": "json",
"ignore": [
"**/node_modules/**",
"**/dist/**",
"**/build/**",
"**/.next/**",
"**/.turbo/**",
"**/.vercel/**",
"**/out/**"
]
}NOTE: When you reference the environment file as shown above, it creates a new one in the current project root directory.
- With a properly configured file set up, you can run sponenv without cli options for the options specifically entered.
- New developer onboarding — provide a reliable
.env.sample-filenamefor a repo. - Open-source projects — maintainers can guarantee contributors see required env keys without exposing secrets.
- CI validation — check that required env keys are documented before deploying or running builds.
- Refactor time — ensure renamed/removed env keys are reflected in the sample-filename file.
Install globally so the dotx command is available system-wide:
npm install -g spotenv
# or
yarn global add spotenvOr install as a project dependency and use with npx:
npm install --save-dev spotenv
# run
npx spotenvAfter installing globally, users can simply run
spotenv.
# run on current directory and write .env.example
spotenv -d . -o example
# Scan a specific project directory
spotenv -d /path/to/project
# Generate with custom filename (automatic extension handling)
spotenv -d . -o sample-filename
# Generate in different formats
spotenv -d . -f json -o env-config
spotenv -d . -f yml -o environment
# Watch and auto-regenerate (COMMING SOON!)
spotenv -w
# ➕ Generate TypeScript types (env.d.ts)
spotenv -d . -t
-d, --dir <dir>— project directory to scan (default:.)-o, --out <file>— output file path (default:sample-filename)-w, --watch— watch source files and auto-regenerate on change (COMMING SOON!)-m, --merge— merge results with an existing.env.sample-filename(keep existing keys)--ignore <patterns...>— additional glob ignore patterns-f, --format <extension>— output format for environment variables (env, json, yml) (default:env)-t, --types— generate TypeScript definition file (env.d.ts) Examples:
# scan 'my-app' and write examples in repo root
spotenv -d ./my-app -o ./my-app/sample-filename
# Generate JSON format with custom filename
spotenv -d ./my-app -f json -o env-vars
# Generate YAML format for configuration
spotenv -d ./my-app -f yml -o config
# watch updates into existing example (COMMING SOON!)
spotenv -w
# Generate TypeScript types (env.d.ts)
spotenv -d ./my-app -tspotenv supports multiple output formats to suit different use cases:
Generated .env.sample-filename looks like this:
# .env.sample-filename (generated)
# Add real values to .env — do NOT commit secrets to source control.
# used in: src/server.ts, src/config.ts
# default: 3000
PORT=
# used in: src/db.ts
DB_HOST=
# NOTE: dynamic keys detected (e.g. process.env[someVar]).
# Please review code and add any dynamic env keys manually.For programmatic consumption or integration with other tools:
[
{
"description": "used in: src/server.ts, src/config.ts, default: 3000",
"key": "PORT",
"value": ""
},
{
"description": "used in: src/db.ts",
"key": "DB_HOST",
"value": ""
}
]For configuration management or documentation:
# used in: src/server.ts, src/config.ts, default: 3000
PORT: ''
# used in: src/db.ts
DB_HOST: ''- Sensitive keys are shown but their defaults are omitted or redacted.
- If a key is detected multiple times, the file includes up to a few example source file locations.
- Custom filenames are automatically handled with appropriate extensions (
.env,.json,.yml).
- Never commit real secrets into source control.
sample-filenameis meant to document keys, not store values. - Spotenv will not write literal string defaults into the example if the key looks sensitive (heuristic by name). However, you should manually review keys flagged sensitive.
- The tool scans only source files; it does not inspect runtime environment or loaded
.envfiles, so you won't accidentally reveal live secrets. - Use
.env(listed in.gitignore) for real values and keep it out of version control.
If the tool reports dynamic keys (process.env[someVar]) it cannot statically resolve them — inspect those files manually and add keys to .env.sample-filename where appropriate.
- The tool uses a two-pass approach: a lightweight text-based filter to find candidate files followed by AST parsing via
@babel/parserand AST traversal (@babel/traverse) for accurate extraction. - Supported AST patterns include
MemberExpressionchecks forprocess.env,VariableDeclaratorfor destructured env imports, andMetaPropertyhandling forimport.meta.env. - The generator intentionally avoids writing secret values and uses heuristics to decide which detected defaults are safe to show in the example.
Ideas you can add later:
- Support framework-specific conventions:
NEXT_PUBLIC_*(Next.js),VITE_prefixes, dotenv-safe validation, etc. - Add more output formats (CSV, XML, etc.) for different use cases.
- Template customization for different project structures.
Contributions welcome! Please open issues for feature requests or bugs.
MIT — see LICENSE for details.
Built with ❤️ by Ali Nazari, for developers.
