cross-env
Cross-platform CLI for setting environment variables in npm scripts without worrying about Windows vs POSIX syntax.
Repository Health
Technical Analysis
cross-env solves a specific, annoying cross-platform problem: Windows command prompts choke on NODE_ENV=production node script.js-style variable assignment, and Windows uses %VAR% where POSIX shells use $VAR. Rather than maintaining separate win and posix npm scripts, or wrapping every script in a shell-detection hack, cross-env lets you write a single command that works identically everywhere.
It ships as a tiny CLI (cross-env and cross-env-shell) that parses KEY=value pairs off the front of a command, builds the right environment, and then hands the rest of the command off to cross-spawn for execution — translating $VAR/${VAR} references and PATH-style list delimiters to their Windows equivalents when needed. The maintainers consider the feature set complete: the README explicitly states cross-env is “done” and isn’t accepting new features, only maintenance.
What You Get
- A single
cross-envbinary that prefixes any command, parsing leadingKEY=valueassignments before spawning the real process - A
cross-env-shellvariant that runs the command through a shell, useful when the underlying script itself needs$VARsubstitution - Automatic
$VAR/${VAR}to%VAR%conversion so command bodies work undercmd.exewithout rewriting them - Bash-style default-value expansion (
${VAR:-default}) resolved before the command runs - PATH-like list-delimiter translation (
:to;) for whitelisted variables such asPATHandNODE_PATH - Correct signal forwarding (SIGTERM/SIGINT/SIGBREAK/SIGHUP) and exit-code propagation from the spawned child process
Common Use Cases
- Setting
NODE_ENV=production(or any other var) in apackage.jsonbuild/start script that has to run on both CI (Linux) and Windows developer machines - Chaining a variable-setting script into a downstream script via
cross-env-shellso the child script can still use$VARsyntax - Passing multiple environment variables to a single command without per-OS branching logic
- Normalizing PATH-style variables that use OS-specific list separators inside a script
Under The Hood
Architecture
cross-env is intentionally small and linear: src/bin/cross-env.ts and src/bin/cross-env-shell.ts are one-line entry points that call the single exported crossEnv() function in src/index.ts with process.argv. crossEnv() does all the real work in three phases — parseCommand() walks the argument list with a regex (envSetterRegex) to split leading KEY=value assignments from the actual command and its arguments (including careful handling of escaped quotes), getEnvVars() builds the child environment by running each assignment’s value through varValueConvert(), and the resulting command/args/env triple is handed to cross-spawn’s spawn() with stdio: 'inherit'. Platform-specific string rewriting is isolated in two small modules, command.ts (converts $VAR references and normalizes paths for Windows) and variable.ts (converts value-level $VAR references and PATH-style delimiters), both gated by the single isWindows() check in is-windows.ts. Nothing else in the codebase branches on platform, so the Windows/POSIX difference is fully contained to those two files.
Tech Stack
The project is plain TypeScript (type: module, ES modules only, no CommonJS build) with a single runtime dependency, cross-spawn, used for its more reliable cross-platform child-process spawning versus Node’s built-in child_process.spawn. It builds with zshy (a thin TypeScript-to-dual-output bundler), type-checks with tsc --noEmit, and targets Node.js 20+. Dev tooling is the @epic-web/config shared ESLint/Prettier config, and tests run under Vitest with @vitest/coverage-v8 for coverage and @vitest/ui for interactive runs.
Code Quality
The src/__tests__/ directory has dedicated unit-test files for every module (index, command, variable, is-windows, plus a focused command-default-values suite for the ${VAR:-default} expansion path) totaling roughly 600 lines of test code against ~250 lines of source — a high test-to-source ratio for a project this size. A separate e2e/ directory runs the built CLI end-to-end via plain Node scripts. CI (.github/workflows/validate.yml) runs the full validate script — build, typecheck, lint, format check, and test — and a second workflow auto-formats on push. Error handling is minimal but intentional (e.g. parseCommand throws a clear Error('Command is required') when no command is given); the small surface area means there’s little room for swallowed errors.
What Makes It Unique
cross-env doesn’t try to be a general shell-compatibility layer — it solves exactly one problem (environment variable assignment syntax differing between POSIX and Windows shells) and stops there, which is why the maintainers call it feature-complete. Its narrow scope is the differentiator: alternatives that try to emulate a full POSIX shell on Windows are heavier and slower, while cross-env’s regex-based rewriting of just the variable-reference syntax keeps it a near-zero-overhead prefix to any existing script.
Used by 115 apps in this directory
Actual
Invoicing Finance
Local-first personal finance with envelope budgeting, end-to-end encryption, and multi-device sync — no subscription required.
AFFiNE
Productivity · Project Management · Note Taking
Write, draw, and plan in one infinite canvas — the open-source alternative to Notion and Miro that keeps your data yours.
AionUi
AI Agents · Productivity
Free, open-source Cowork desktop app that unifies Claude Code, Codex, Gemini CLI, and 20+ AI agents into a single platform with multi-agent teams, 24/7 cron automation, and zero-config built-in agent.
APITable
Low Code Platforms · Databases
API-first collaborative spreadsheet-database platform that auto-generates REST APIs and lets teams build internal tools, CRMs, and dashboards without code.
Akaunting
Invoicing Finance
Open-source online accounting for small businesses and freelancers — invoices, expenses, and reporting without monthly fees or vendor lock-in.
Another Redis Desktop Manager
Developer Tools · Databases
Fast, stable Redis GUI with cluster, SSH, and massive key support
AnythingLLM
Developer Tools · Automation · AI Assistants
The all-in-one AI platform for private document chat, no-code agents, and local LLMs with zero setup friction.
anytype-ts
Knowledge Management · Note Taking · Collaboration
A local-first, end-to-end encrypted knowledge OS that lets you build notes, tasks, wikis, and entire apps — with your data stored offline and synced peer-to-peer.
argilla
AI Development · Data Engineering
Collaborate on high-quality AI training data with a self-hosted annotation platform built for LLMs, NLP, and multimodal models.