
Security News
The Hidden Blast Radius of the Axios Compromise
The Axios compromise shows how time-dependent dependency resolution makes exposure harder to detect and contain.
Grow and load your envs. Organically.
EnvTree is a smart environment variable loader that automatically discovers and loads .env files from your current directory up to your workspace root, following Next.js environment loading conventions. Execute any command with your environment variables loaded using the simple envtree -- command syntax.
.env files from workspace root down to current directoryenvtree -- command)npm install envtree
# or
pnpm add envtree
# or
yarn add envtree
EnvTree automatically:
Perfect for running development commands, build scripts, tests, or any tool that needs environment variables.
# Execute any command with loaded environment variables
npx envtree -- printenv DATABASE_URL
npx envtree -- npm run build
npx envtree -- node my-script.js
npx envtree -- python manage.py runserver
# With verbose output to see what's loaded
npx envtree --verbose -- npm start
# Different environments
npx envtree --node-env production -- npm run build
# Load and display .env files (default behavior)
npx envtree
# Load from specific directory
npx envtree /path/to/project
# Show detailed information about loaded files
npx envtree --verbose
# Get workspace detection info
npx envtree info
import { loadEnvTree } from 'envtree';
// Basic usage with defaults
const result = loadEnvTree();
// With custom options
const result = loadEnvTree({
convention: 'nextjs',
startDir: process.cwd(),
setEnv: true,
nodeEnv: 'development',
});
if (result) {
console.log(`Loaded ${Object.keys(result.envVars).length} variables`);
console.log('Files loaded:', result.filesLoaded);
console.log('Workspace root:', result.workspaceRoot);
}
EnvTree follows Next.js environment loading conventions with the following file types:
.env - Default environment variables.env.local - Local overrides (ignored in test environment).env.[NODE_ENV] - Environment-specific variables (e.g., .env.development, .env.production).env.[NODE_ENV].local - Environment-specific local overrides (e.g., .env.development.local, ignored in test environment)Loading Priority (lowest to highest):
.env (base configuration, loaded first).env.local (local overrides).env.[NODE_ENV] (environment-specific, overrides base and local).env.[NODE_ENV].local (environment-specific local overrides, highest priority)The loading happens from workspace root to current directory, with files in subdirectories taking precedence over parent directories.
Example file structure and loading order:
workspace-root/
├── .env # ← 1. Loaded first (lowest priority)
├── .env.development # ← 2. Loaded second
├── .env.local # ← 3. Loaded third
├── .env.development.local # ← 4. Loaded fourth
├── packages/
│ └── my-app/
│ ├── .env # ← 5. Loaded fifth
│ ├── .env.development # ← 6. Loaded sixth
│ ├── .env.local # ← 7. Loaded seventh
│ └── .env.development.local # ← 8. Loaded last (highest priority)
Usage: envtree [options] [dir] [-- command...]
Arguments:
dir Starting directory to search from (default: current directory)
Options:
-V, --version output the version number
-c, --convention <type> Environment loading strategy (nextjs) (default: "nextjs")
--node-env <env> Override NODE_ENV for nextjs convention (default: "development")
--verbose Show detailed information about loaded files
-h, --help display help for command
Commands:
info [dir] Show information about workspace detection
Command Execution:
envtree -- <command> Execute command with loaded environment variables
loadEnvTree(options?: EnvTreeOptions): EnvTreeResult | nullLoads environment variables from .env files in your workspace tree using Next.js conventions.
interface EnvTreeOptions {
/** Loading strategy: currently only 'nextjs' is supported */
convention?: 'nextjs';
/** Starting directory to search from */
startDir?: string;
/** Whether to set environment variables */
setEnv?: boolean;
/** Custom NODE_ENV for nextjs convention */
nodeEnv?: string;
}
interface EnvTreeResult {
/** Merged environment variables */
envVars: Record<string, string>;
/** List of files that were loaded */
filesLoaded: string[];
/** Detected workspace root */
workspaceRoot: string;
/** Detection method used */
method: 'lockfile' | 'workspace-indicators';
}
EnvTree automatically detects your workspace root using two methods:
Looks for common lockfiles:
package-lock.json (npm)yarn.lock (Yarn)pnpm-lock.yaml (pnpm)bun.lockb (Bun)Looks for workspace configuration files:
.git (Git repository)lerna.json (Lerna)nx.json (Nx)turbo.json (Turborepo)pnpm-workspace.yaml (pnpm workspaces)Use npx envtree info to see detailed workspace detection analysis.
Execute any command with loaded environment variables using the -- syntax:
# Common development commands
npx envtree -- npm run dev
npx envtree -- npm run build
npx envtree -- npm test
# Node.js scripts
npx envtree -- node server.js
npx envtree -- node scripts/migrate.js
# Other languages and tools
npx envtree -- python manage.py runserver
npx envtree -- cargo run
npx envtree -- go run main.go
# View environment variables
npx envtree -- printenv DATABASE_URL
npx envtree -- printenv API_URL
# Chain multiple commands
npx envtree -- sh -c 'printenv DATABASE_URL && npm run build'
# With verbose output to see loaded files and variables
npx envtree --verbose -- npm start
# Development mode (default)
npx envtree -- npm run dev
npx envtree --node-env development -- npm start
# Production mode
npx envtree --node-env production -- npm run build
# Staging mode
npx envtree --node-env staging -- npm run deploy
# From any package in a monorepo - finds workspace root automatically
npx envtree --verbose -- npm run build
# From specific package directory
cd packages/api && npx envtree -- npm start
# Run commands from workspace root for specific packages
npx envtree -- npm run build --workspace=packages/api
# Load and display environment variables (no command execution)
npx envtree
# From specific directory
npx envtree /path/to/my-project
# Show detailed information about loaded files
npx envtree --verbose
// In your application startup
import { loadEnvTree } from 'envtree';
// Load environment variables before anything else
const envResult = loadEnvTree({ setEnv: true });
if (!envResult) {
console.error('Failed to load environment variables');
process.exit(1);
}
console.log(`Loaded ${Object.keys(envResult.envVars).length} environment variables`);
// Your application code here
import './app';
import { loadEnvTree } from 'envtree';
const result = loadEnvTree({
startDir: '/path/to/project',
nodeEnv: 'production',
setEnv: false, // Don't set env vars, just return them
});
if (result) {
// Use result.envVars object manually
console.log('Environment variables:', result.envVars);
}
import { loadEnvTreeSync } from 'envtree';
import * as path from 'path';
const result = loadEnvTreeSync({
startDir: path.resolve(),
prefixFilter: 'NEXT_PUBLIC_',
});
console.log(result.envVars); // Only variables starting with NEXT_PUBLIC_
startDir: Directory to start searching for .env files.convention: Loading strategy (default: nextjs).setEnv: Whether to set variables in process.env (default: true).nodeEnv: Custom environment name (default: process.env.NODE_ENV).prefixFilter: Only include variables with this prefix.We welcome contributions!
Found a bug or have a feature request? Please open an issue.
# Clone the repository
git clone https://github.com/kiraki-io/envtree.git
cd envtree
# Install dependencies
pnpm install
# Build the package
pnpm build
# Run in development mode
pnpm dev
MIT
FAQs
Grow and load your envs. Organically.
We found that envtree demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
The Axios compromise shows how time-dependent dependency resolution makes exposure harder to detect and contain.

Research
A supply chain attack on Axios introduced a malicious dependency, plain-crypto-js@4.2.1, published minutes earlier and absent from the project’s GitHub releases.

Research
Malicious versions of the Telnyx Python SDK on PyPI delivered credential-stealing malware via a multi-stage supply chain attack.