Skip to content

Quickly switch between .env files.

License

Notifications You must be signed in to change notification settings

natterstefan/dotswitch

Repository files navigation

dotswitch

dotswitch banner

CI npm version npm downloads node license

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 dotswitch

Or use directly without installing:

npx dotswitch use staging

Usage

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-run

List available environments

dotswitch ls
Available environments:

▸ staging (active)
  production
  preview

JSON output for scripts:

dotswitch ls --json
# [{"name":".env.staging","env":"staging","active":true},{"name":".env.production","env":"production","active":false}]

Show current environment

dotswitch current

JSON 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 restore

Compare 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 --json

Options

All commands support:

Flag Description
-p, --path <dir> Project directory (defaults to cwd)
--json Output as JSON (machine-readable)

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 .dotswitchrc.json in your project root to customize behavior. Everything is optional — dotswitch works out of the box without a config file.

{
  "target": ".env.local",
  "exclude": [".env.test"],
  "hooks": {
    "main": "production",
    "staging/*": "staging",
    "dev*": "development"
  }
}
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:

{
  "target": ".env"
}

Git hook auto-switching

Automatically switch environments when you check out a branch.

Setup

  1. Add branch mappings to .dotswitchrc.json:
{
  "hooks": {
    "main": "production",
    "staging/*": "staging",
    "develop": "development"
  }
}
  1. Install the git hook:
dotswitch hook install

Now git checkout staging/feat-login will automatically run dotswitch use staging.

Patterns

  • "main" — exact branch name match
  • "staging/*" — matches staging/ prefix (e.g., staging/feat-x)
  • "dev*" — matches any branch starting with dev

Remove the hook

dotswitch hook remove

Monorepo 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 .dotswitchrc.json 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/hooks

Explicit --path arguments are rebased automatically, so monorepo globs also work from worktrees:

dotswitch use staging --path "./apps/*"

How it works

When you run dotswitch use staging, it:

  1. Backs up your existing .env.local to .env.local.backup
  2. Copies .env.staging to .env.local
  3. Prepends a # dotswitch:staging header 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,
  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

About

Quickly switch between .env files.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors