Run scripts that set and use environment variables across platforms
cross-env is a utility package that solves a fundamental cross-platform problem in Node.js development: setting environment variables in npm scripts. On Unix-based systems (macOS, Linux), you set variables inline like NODE_ENV=production node app.js, but Windows CMD requires set NODE_ENV=production && node app.js, and PowerShell uses yet another syntax. This inconsistency breaks team collaboration when developers use different operating systems.
With over 13 million weekly downloads, cross-env has become a standard tool in modern JavaScript projects. It works by wrapping your commands and detecting the host OS at runtime, automatically translating environment variable syntax to the correct format. This means you write your npm scripts once using Unix-style syntax, and cross-env ensures they execute correctly everywhere.
The package is particularly valuable for CI/CD pipelines, open-source projects with diverse contributors, and teams working across multiple platforms. It handles common variables like NODE_ENV, API endpoints, feature flags, and port configurations. While the package is now in maintenance mode and considered "finished," its stability and focused feature set make it a reliable choice for production environments.
Developers use cross-env to maintain clean, readable package.json scripts without conditional logic or platform-specific script files. It's a zero-configuration solution that requires no setup beyond installation, making it ideal for projects that prioritize simplicity and portability over complex build tool configurations.
// package.json
{
"name": "my-app",
"version": "1.0.0",
"config": {
"port": "3000",
"apiUrl": "http://localhost:4000"
},
"scripts": {
"start": "cross-env NODE_ENV=production PORT=8080 node server.js",
"dev": "cross-env NODE_ENV=development API_URL=$npm_package_config_apiUrl node server.js",
"test": "cross-env NODE_ENV=test ENABLE_LOGGING=false jest",
"build": "cross-env NODE_ENV=production ANALYZE_BUNDLE=true webpack --config webpack.prod.js"
},
"devDependencies": {
"cross-env": "^10.1.0"
}
}
// server.js
const express = require('express');
const app = express();
const NODE_ENV = process.env.NODE_ENV || 'development';
const PORT = process.env.PORT || process.env.npm_package_config_port || 3000;
const API_URL = process.env.API_URL || 'http://localhost:4000';
const ENABLE_LOGGING = process.env.ENABLE_LOGGING !== 'false';
if (ENABLE_LOGGING) {
console.log(`Starting server in ${NODE_ENV} mode`);
console.log(`API URL: ${API_URL}`);
}
app.get('/health', (req, res) => {
res.json({
status: 'ok',
environment: NODE_ENV,
apiEndpoint: API_URL
});
});
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});Build Environment Configuration: Set NODE_ENV to 'production' or 'development' to control webpack bundling behavior, minification, source maps, and debugging features without maintaining separate script files per platform.
API Endpoint Management: Configure different API URLs for local development, staging, and production environments. Teams can override these values without modifying code, enabling seamless transitions between environments during testing and deployment.
CI/CD Pipeline Consistency: Ensure GitHub Actions, CircleCI, Jenkins, and local dev environments execute identical npm scripts regardless of runner OS. This eliminates "works on my machine" issues caused by environment variable syntax differences.
Feature Flag Control: Toggle experimental features or A/B tests by setting boolean flags as environment variables. This allows runtime behavior changes without code deployments, particularly useful for gradual rollouts or emergency feature disabling.
Database and Port Configuration: Dynamically set database connection strings, Redis URLs, or server ports across different deployment contexts. Development teams can run multiple service instances locally on different ports without config file conflicts.
npm install cross-envpnpm add cross-envbun add cross-env