dotenv
Loads environment variables from a .env file into process.env for Node.js apps.
Repository Health
Technical Analysis
dotenv is a zero-dependency Node.js module that loads environment variables from a .env file into process.env, following the twelve-factor app methodology of keeping configuration separate from code. It has been the de facto standard for local environment configuration in the Node.js ecosystem since 2013, used by hundreds of thousands of projects to keep API keys, database URLs, and other secrets out of source control while still making them easy to access at runtime.
The library exposes a tiny, stable API: require('dotenv').config() (or import 'dotenv/config' for ESM) parses a .env file and populates process.env, plus a standalone parse() function for programmatic use and a dotenv run -- CLI for injecting variables into any child process without modifying application code.
What You Get
- A
config()function that reads.envand populatesprocess.envin one call - A standalone
parse()function for turning a string or Buffer of env-style text into a plain object without touchingprocess.env - A
populate()function for merging parsed values into any target object, with optional override behavior - A
dotenv run -- <command>CLI for injecting.envvariables into a child process without any code changes - Support for multiline values (e.g. PEM private keys), inline comments, quoted strings, and multiple
.envfiles via-f/options.path
Common Use Cases
- Loading local development secrets (API keys, database URLs) without committing them to version control
- Configuring 12-factor apps where the same codebase runs against different environments via different
.envfiles - Injecting environment variables into a script or test run with
dotenv run -- node script.jswithout editing the script - Parsing arbitrary env-formatted text (e.g. from a secrets manager) into a plain object with
dotenv.parse()
Under The Hood
Architecture dotenv’s execution path is deliberately linear: config() resolves a .env path (or array of paths), reads each file synchronously with fs.readFileSync, and hands the raw text to parse(), a single regex-driven state machine (lib/main.js) that walks each line, strips surrounding quotes, and expands escaped newlines only inside double-quoted values. The parsed key/value map is then merged onto process.env (or a caller-supplied processEnv) by populate(), which enforces the override-vs-preserve policy and returns only the keys it actually wrote. cli.js reuses parse()/populate() directly rather than duplicating logic, so the CLI and the library share one code path end to end.
Tech Stack The package is pure CommonJS JavaScript with a companion .d.ts for TypeScript consumers (lib/main.d.ts) and has zero runtime dependencies — fs, path, and os from Node core are the only imports. package.json declares engines.node >= 12 and ships dual entry points (require('dotenv') and dotenv/config for side-effect-style imports), with standard for linting and tap for the test runner in devDependencies.
Code Quality The tests/ directory contains six focused suites (test-parse.js, test-populate.js, test-config.js, test-config-import.js, test-parse-multiline.js, test-cli.js, ~950 lines total) covering the parser’s quoting/comment/multiline edge cases, override semantics in populate(), and CLI argument parsing including error paths like a missing -f value. Error handling is explicit and typed via err.code = 'OBJECT_REQUIRED' rather than throwing bare Errors, and the configDotenv() function accumulates lastError across multiple file paths instead of failing fast, favoring partial success over hard failure.
API Design The public surface is intentionally minimal — four functions (config, configDotenv, parse, populate) cover every use case, and the single most common call, require('dotenv').config(), requires no arguments and no boilerplate. Optional behavior (custom path, encoding, override, debug/quiet output) is exposed through a single options object rather than a proliferation of methods, and the same options can be set via DOTENV_CONFIG_* environment variables for zero-code CLI configuration, which keeps the day-to-day API surface small while still supporting advanced setups.
Used by 227 apps in this directory
Documenso
Digital Signiture
Self-hosted, open-source DocuSign alternative with legally binding PDF signatures, multi-party workflows, and a full REST and tRPC API.
Dokploy
Devops · Hosting Control Panel · Security
Self-hosted PaaS that deploys apps and databases on your own VPS using Docker, Traefik, and multi-build-system orchestration
drawio-desktop
Design Tools · Productivity
The offline-first diagram editor that puts security above all else — no account, no data leaving your machine, no compromises.
Dyad
AI Assistants · AI Code Assistants · AI Development
Build AI-powered apps locally with your own keys, your own models, and zero cloud lock-in.
Element Web
Collaboration · Team Chat
A polished, self-hostable Matrix client for secure, decentralized messaging and collaboration that puts your organization in full control of its data.
Enclosed
Security
Send end-to-end encrypted notes and files where the server never sees your content — true zero-knowledge sharing.
Enso
Analytics · Data Engineering · Low Code Platforms
A visual and textual programming platform for data prep and analysis where the node graph and the underlying Enso code are always perfectly in sync, built by an Alteryx co-founder on a GraalVM engine.
evidence
Analytics · Data Engineering
Turn SQL queries and markdown files into polished, interactive data apps and business intelligence reports — no drag-and-drop, no GUI, just code.
FastGPT
AI Agents · AI Development
Build, debug, and deploy knowledge-based AI agents with a visual workflow editor, RAG retrieval, and support for any OpenAI-compatible LLM.