dotswitch
v1.3.0
Published
Quickly switch between .env files
Downloads
783
Maintainers
Readme
dotswitch

Quickly switch between .env files. Copies
.env.<environment> to .env.local (or a custom target) and
tracks the active environment via a header comment. Works with
Next.js, Vite, Remix, and any project that uses .env files.
Install
npm install -g dotswitchOr use directly without installing:
npx dotswitch use stagingUsage
Switch environment
# Switch to .env.staging → .env.local
dotswitch use staging
# Interactive picker (when no env specified)
dotswitch use
# Skip backup of existing .env.local
dotswitch use production --no-backup
# Force switch even if already active
dotswitch use staging --force
# Preview what would happen without making changes
dotswitch use staging --dry-runList available environments
dotswitch lsAvailable environments:
▸ staging (active)
production
previewJSON output for scripts:
dotswitch ls --json
# [{"name":".env.staging","env":"staging","active":true},{"name":".env.production","env":"production","active":false}]Show current environment
dotswitch currentJSON output:
dotswitch current --json
# {"active":"staging"}Pipe-friendly — outputs the plain env name when not a TTY:
ENV=$(dotswitch current)Restore from backup
# Restore .env.local from .env.local.backup
dotswitch restoreCompare environments
# Compare current .env.local against .env.production
dotswitch diff production
# Compare two environments directly
dotswitch diff staging production
# Show actual values (not just key names)
dotswitch diff staging production --show-values
# JSON output
dotswitch diff staging production --jsonOptions
All commands support:
| Flag | Description |
|------|-------------|
| -p, --path <dir> | Project directory (defaults to cwd) |
| --json | Output as JSON (machine-readable) |
ls and use also support:
| Flag | Description |
|------|-------------|
| -r, --root | Source env files from the main repo root (worktree) |
use also supports:
| Flag | Description |
|------|-------------|
| -f, --force | Switch even if already active |
| --no-backup | Skip .env.local backup |
| -n, --dry-run | Preview what would happen |
Configuration
Create a dotswitch.config.ts (or .js/.mjs/.cjs) in your project
root to customize behavior. Everything is optional — dotswitch
works out of the box without a config file.
TypeScript (recommended)
// dotswitch.config.ts
import { defineConfig } from "dotswitch";
export default defineConfig({
target: ".env.local",
exclude: [".env.test"],
hooks: {
"main": "production",
"staging/*": "staging",
"dev*": "development",
},
});JavaScript (ESM)
// dotswitch.config.js
/** @type {import("dotswitch").DotswitchConfig} */
export default {
target: ".env.local",
exclude: [".env.test"],
hooks: {
"main": "production",
"staging/*": "staging",
},
};JavaScript (CommonJS)
// dotswitch.config.cjs
const { defineConfig } = require("dotswitch");
module.exports = defineConfig({
target: ".env.local",
exclude: [".env.test"],
});Config file resolution order
dotswitch searches for config files in this order (first match wins):
dotswitch.config.tsdotswitch.config.jsdotswitch.config.mjsdotswitch.config.cjs
Options
| Field | Default | Description |
|-------|---------|-------------|
| target | ".env.local" | File to write the active env to |
| exclude | [] | Additional env files to hide from ls |
| hooks | {} | Branch-to-env mappings for git hook auto-switching |
Custom target file
By default dotswitch writes to .env.local, but some
frameworks use .env directly. Set the target field to
change this:
// dotswitch.config.ts
import { defineConfig } from "dotswitch";
export default defineConfig({
target: ".env",
});Git hook auto-switching
Automatically switch environments when you check out a branch.
Setup
- Add branch mappings to your config:
// dotswitch.config.ts
import { defineConfig } from "dotswitch";
export default defineConfig({
hooks: {
"main": "production",
"staging/*": "staging",
"develop": "development",
},
});- Install the git hook:
dotswitch hook installNow git checkout staging/feat-login will automatically run
dotswitch use staging.
Patterns
"main"— exact branch name match"staging/*"— matchesstaging/prefix (e.g.,staging/feat-x)"dev*"— matches any branch starting withdev
Remove the hook
dotswitch hook removeMonorepo support
Switch environments across multiple packages at once using glob patterns:
# Switch all apps to staging
dotswitch use staging --path "./apps/*"
# Check status across packages
dotswitch ls --path "./packages/*"Each directory is processed independently with labeled output.
Git worktree support
dotswitch works transparently in
git worktrees. When
you run any command from a worktree, it automatically resolves
back to the main repo where your .env.* files and
config live.
# From a worktree, all commands operate on the main repo
cd /path/to/my-worktree
dotswitch ls # lists envs from the main repo
dotswitch use staging # switches in the main repo
dotswitch hook install # installs hook in the shared .git/hooksExplicit --path arguments are rebased automatically, so
monorepo globs also work from worktrees:
dotswitch use staging --path "./apps/*"Using main repo envs in a worktree
When a worktree has its own .env.* files, dotswitch operates
locally by default. Use --root / -r to source env files
from the main repo instead:
cd /path/to/my-worktree
# List envs from the main repo (even if the worktree has local ones)
dotswitch ls --root
# Copy .env.staging from the main repo into the worktree as .env.local
dotswitch use staging --rootThis is useful when you want to quickly pull an environment configuration from the main repo into your worktree without copying files manually.
How it works
When you run dotswitch use staging, it:
- Backs up your existing
.env.localto.env.local.backup - Copies
.env.stagingto.env.local - Prepends a
# dotswitch:stagingheader to track the active environment
The header comment is how dotswitch ls and
dotswitch current know which environment is active.
Programmatic API
dotswitch exports its core functions for use in scripts:
import {
listEnvFiles,
switchEnv,
getActiveEnv,
restoreEnvLocal,
loadConfig,
defineConfig,
parseEnvContent,
diffEnvMaps,
resolveProjectRoot,
} from "dotswitch";
const files = listEnvFiles(process.cwd());
const active = getActiveEnv(process.cwd());
switchEnv(process.cwd(), "staging", { backup: true });In worktree-aware scripts, resolve the project root first:
const projectRoot = resolveProjectRoot(process.cwd());
const files = listEnvFiles(projectRoot);
switchEnv(projectRoot, "staging", { backup: true });Requirements
- Node.js >= 20
License
MIT
