All case studies

Open source · developer tooling

devkit/env-profiles

Named .env profiles — save, switch with backups, diff drift, merge safely.

View on Packagist
01 — Packagist

01 — Packagist

Package listing — install, requirements, and README.

01

The brief

Laravel teams juggle .env, .env.staging, CI secrets, and half-remembered local tweaks — switching environments is copy-paste theatre, and nobody trusts a diff until something breaks in prod.

This tool gives you a small profile store under your repo, a predictable use workflow with backups and optional post-switch hooks, and a diff command to compare any set of env files side by side or as JSON.

02

What we shipped

Install as a dev dependency in the consuming application. Requires PHP 8.3+. Run from your application root — where composer.json and usually .env live.

Recommended entry point: ./vendor/bin/devkit-env --help. Alternatives: composer exec devkit-env -- --help or php vendor/bin/devkit-env --help.

Drop a .devkit-env.json in your project root to customise store paths and post-switch hooks — config:clear, cache:clear, migrate on profile switch.

03

Commands at a glance

  1. save — snapshot ./.env (or --from) into a named profile.
  2. use — apply a saved profile to your working .env, with automatic backup.
  3. list — print all saved profile names.
  4. delete — remove a profile from the store (does not touch your live .env).
  5. diff — compare profiles or files; missing keys, extra keys, and value drift.
  6. merge — merge two env files or profiles; interactive or scriptable.

05

Install & configuration

Install in the consuming application. Requires PHP 8.3+. The CLI resolves paths and .devkit-env.json relative to the directory you run it from.

Install
composer require --dev devkit/env-profiles
Run the CLI
./vendor/bin/devkit-env --help
composer exec devkit-env -- --help
.devkit-env.json
{
  "storeDir": "env",
  "backupDir": "env/backups",
  "defaultEnv": ".env",
  "afterSwitch": [
    "php artisan config:clear",
    "php artisan cache:clear"
  ],
  "afterSwitchProfiles": {
    "production": [
      "php artisan migrate --force --no-interaction"
    ]
  }
}

06

Switching environments

Snapshot each environment once, then switch with a single command — automatic backup, profile apply, and optional post-switch hooks.

One-time setup — snapshot profiles
./vendor/bin/devkit-env save local
./vendor/bin/devkit-env save staging
./vendor/bin/devkit-env save production
Switch to staging or production
./vendor/bin/devkit-env use staging
./vendor/bin/devkit-env use production
Diff drift between profiles
./vendor/bin/devkit-env diff local production --format side-by-side

07

Files and folders

Default layout: env/ holds saved profiles and registry.json; env/backups/ stores timestamped backups when use runs.

On first save, use, list, or delete, the store and backups directories are automatically appended to .gitignore.

You can safely commit .devkit-env.json (paths only) — keep secrets and env/ local.

08

Command reference

Representative examples from the README — save, use, diff, and merge:

save — snapshot a file into a named profile
./vendor/bin/devkit-env save staging
./vendor/bin/devkit-env save staging --from .env.staging
./vendor/bin/devkit-env save staging --force
use — apply a profile to your working env file
./vendor/bin/devkit-env use staging
./vendor/bin/devkit-env use staging --target .env.local
./vendor/bin/devkit-env use staging --skip-hooks
diff — drift between env files
./vendor/bin/devkit-env diff local staging
./vendor/bin/devkit-env diff local staging --format json
./vendor/bin/devkit-env diff local staging --mask-key 'APP_*' --mask-key 'STRIPE_*'
merge — combine two .env files
./vendor/bin/devkit-env merge local staging
./vendor/bin/devkit-env merge --left .env --right .env.staging --out merged.env
./vendor/bin/devkit-env merge --left .env --right .env.staging --dry-run

09

Version control and safety

Profiles live outside version control — auto-added to .gitignore so secrets never accidentally land in your repo.

diff exit codes: 0 = no drift, 1 = drift found, 2 = error. Use in CI to catch env drift before deploy.

merge supports non-interactive mode for scripts: --prefer right -n --out merged.env.

04

Screens from the build

Real UI captures — placeholders until assets are dropped in.

02 — README

02 — README

Why it exists — profile store, switching, drift reports.
03 — Use case

03 — Use case

Switching local → staging → production in seconds.
04 — Diff

04 — Diff

Side-by-side drift — keys, values, and missing vars.