npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

dotswitch

v1.3.0

Published

Quickly switch between .env files

Downloads

783

Readme

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

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):

  1. dotswitch.config.ts
  2. dotswitch.config.js
  3. dotswitch.config.mjs
  4. dotswitch.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

  1. Add branch mappings to your config:
// dotswitch.config.ts
import { defineConfig } from "dotswitch";

export default defineConfig({
  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 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/hooks

Explicit --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 --root

This 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:

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