Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Env Sync Laravel Package

dragon-code/env-sync

Synchronize Laravel .env files with .env.example using Dragon Code Env Sync. It detects missing or outdated variables, updates environment files safely, and helps keep local, staging, and team configurations consistent. Run it locally or in CI to prevent config drift.

View on GitHub
Deep Wiki
Context7

Getting Started

dragon-code/env-sync is a single-purpose utility: it reconciles .env.example against your real .env so the example file never drifts behind the keys your code actually reads. The whole package is one Artisan command, so onboarding is minutes, not hours.

Minimal setup:

composer require dragon-code/env-sync --dev

Pin to ^4.1 (or at least ^4.0 with a bump) if you are on Laravel 11 / Symfony 7 — 4.1.0 is the release that added Symfony 7 support. For Laravel 10 and earlier, any 4.x line works the same way; nothing in the command surface changed in this release.

There is nothing to publish or configure for the default case. Confirm the command name and any flags for your installed version with:

php artisan list | grep -i env

Then the first useful run is: add a key to your local .env (e.g. STRIPE_WEBHOOK_SECRET=whsec_...), run the sync command, and inspect the diff:

php artisan env:sync
git diff .env.example

Where to look first:

  • The README for the exact command signature, options, and the file paths it reads (it is a small package, so the README is the documentation).
  • The command class under src/ — it is short enough to read end-to-end, which matters because the package is a one-maintainer project and you may eventually need to patch or fork it.
  • Your config/ directory: any env('...') call there is the source of truth for which keys must exist in .env.example.

First use case to adopt: the "new env var" loop. Whenever a feature introduces a new env() lookup, run the sync command before committing so the example file gains the key in the same PR as the code that needs it.

Implementation Patterns

The per-change loop (the 90% case). Treat .env.example as a generated artifact that lives next to the code:

  1. Add the key to your local .env and to config/*.php (via env('KEY', default)).
  2. Run the sync command.
  3. Review the diff — replace any real value with a placeholder before committing.
  4. Commit code + .env.example together.

This keeps PR diffs self-documenting: reviewers see "this feature requires MAIL_FROM_ADDRESS" without reading the config file.

CI drift guard. Since the package modifies the file in place rather than offering a check mode, use git as the assertion:

- run: cp .env.example .env   # CI usually has no .env
- run: php artisan env:sync
- run: git diff --exit-code .env.example

If the job fails, someone added a key locally but forgot to commit the example. Note the bootstrap problem: the command needs a .env to compare against, so seed one from the example (or from your CI environment file) first.

Composer script. Make it a one-liner the team actually remembers:

"scripts": {
  "env:sync": "php artisan env:sync"
}

Then composer env:sync before pushing. A pre-commit hook (CaptainHook, Husky, or a plain .git/hooks/pre-commit) that runs the sync and git add .env.example is a reasonable escalation if the team keeps forgetting.

Onboarding and deployment checklists. Because .env.example becomes authoritative, new developers can cp .env.example .env && php artisan key:generate and get a complete, working skeleton. In deployment reviews, diff the key names (not values) between the example and each environment's real env file to catch missing production variables before a deploy.

Pair it with config validation. This package handles presence of documentation, not correctness of values. Combine it with a boot-time check (a small service provider that asserts required config() values are non-null, or a config-schema validation package) so a key that exists but is empty still fails loudly.

Multiple environment files. If your project uses .env.testing, .env.ci, or similar, check whether the installed version accepts file arguments or config for alternate paths. If it does not, wrap it: run it once per file, or fork the command — the logic is small enough that maintaining a local copy is realistic.

Gotchas and Tips

Thin maintenance, not abandonment. 4.1.0 is a dependency-compatibility release (Symfony 7 support, i.e. Laravel 11 era), which is a good sign the package is being kept alive against new framework majors — but it is a one-maintainer, single-command package with very low activity. Keep it in require-dev, pin it (^4.1), and be prepared to fork or replace it with ~30 lines of custom Artisan command if a future Laravel/PHP version breaks it. The upside: the scope is tiny, so the migration cost is low.

4.1.0 changes nothing about behaviour. Do not go looking for new flags or output formats — the release is purely a symfony/* constraint widening. If your CI pins exact dependency versions, re-run your lockfile bump and the drift-guard job before assuming nothing moved.

Never let real secrets reach .env.example. Whatever the command copies, verify the output before committing. If your installed version carries values across from .env, that is a leak waiting to happen — scrub to empty or placeholder values in the same commit, and consider a pre-commit grep for high-entropy strings in .env.example.

It only adds, never removes. Keys deleted from the codebase linger in both files forever. Periodically audit for dead keys yourself; the package has no dead-key detection.

Ordering, grouping, and comments are not preserved intelligently. Expect new keys appended at the end rather than placed beside related ones. Do the manual tidy-up in the same commit, or the file becomes an unsorted pile that developers stop reading. Hand-written comments in .env.example may also be displaced.

Quoted, multiline, and #-containing values round-trip poorly. If you have values with spaces, embedded #, or multiline certificates, check the generated output carefully — naive line-based parsing is the usual failure mode.

CI has no .env. The command will fail or no-op on a fresh checkout. Seed a .env from the example (or a checked-in CI env file) as shown above, and never point it at a production env file.

Do not confuse this with config caching. If you run php artisan config:cache while testing, env() calls outside config files return null and your mental model of "which keys are actually used" becomes wrong. Clear the cache (php artisan config:clear) before auditing keys.

Extension points are thin. There is likely a publishable config for file paths and exclusions — publish it (php artisan vendor:publish) and commit it so the whole team syncs the same files. Beyond that, the practical extension point is your own wrapper command that adds a --check (dry-run) mode, so CI can fail without mutating the working tree. Don't wait on upstream for that; the wrapper is a few lines and gives you a hedge if the package stalls again.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console