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

Laravel Env Sync Laravel Package

aranyasen/laravel-env-sync

A Laravel Artisan package for keeping .env files in sync across environments. Add missing keys from .env.example, compare and merge configuration values, and avoid manually copying variables during deployments or onboarding new developers.

View on GitHub
Deep Wiki
Context7

Getting Started

Install it as a dev dependency — this is a developer-machine/CI tool, not something your production app needs at runtime:

composer require --dev aranyasen/laravel-env-sync

The current release line is v3.x (v3.0.1 at time of writing), which supports PHP up to 8.5. That means the package is tracking modern PHP versions, but it also means if your app is still on an older PHP/Laravel combination, check composer.json for the actual constraint floor before blaming your own setup.

The service provider should be auto-discovered. Immediately after install, do two things:

  1. Discover the actual surface area. This is a small package (4 stars, no dependents), so don't assume the command names from the README are exhaustive or current:
    php artisan list | grep -i env
    php artisan <command> --help
    
  2. Publish the config, if one exists, so you can see what it controls:
    php artisan vendor:publish --provider="Aranyasen\EnvSync\EnvSyncServiceProvider"
    

First use case: you pull main, a teammate added STRIPE_WEBHOOK_SECRET to .env.example, and your local app now throws a confusing Missing required parameter error at runtime. Instead of diffing two files by hand, run the sync command and let it append the missing keys. Before you trust it, back up first:

cp .env .env.bak
php artisan env:sync      # or whatever the actual command is — check `list`
git diff --no-index .env.bak .env

If the diff looks correct (appended keys only, existing values untouched), delete .env.bak and make this a habit. If it rewrites or reorders your file, stop and read the config before going further.

Implementation Patterns

Treat .env.example as the contract, not .env. The workflow that makes this package pay off is a team rule: any PR that adds env('FOO') must add FOO= to .env.example. The sync tool then becomes the mechanism that propagates that contract, not a substitute for it.

Onboarding / post-pull loop. Add a Composer script so the step is muscle memory:

"scripts": {
    "post-pull": ["@php artisan env:sync"]
}

Or a simple shell alias: alias esync='php artisan env:sync && php artisan config:clear'.

CI parity gate. The highest-value use is catching drift in CI rather than on developer machines. In a pipeline job that has an .env built from secrets:

- run: cp .env.example .env   # baseline
- run: php artisan <sync-command> --check   # if a check/dry-run flag exists

If the package has no non-mutating mode, don't fight it — write the assertion yourself. A 20-line test is more reliable than a 4-star dependency:

it('keeps .env.example in sync with the app', function () {
    $example = collect(file(base_path('.env.example'), FILE_IGNORE_NEW_LINES))
        ->filter(fn ($l) => $l && !str_starts_with(trim($l), '#'))
        ->map(fn ($l) => explode('=', $l, 2)[0])
        ->filter();

    $missing = $example->diff(
        collect(file(base_path('.env'), FILE_IGNORE_NEW_LINES))
            ->map(fn ($l) => explode('=', $l, 2)[0])
    );

    expect($missing)->toBeEmpty("Missing from .env: {$missing->implode(', ')}");
});

Deploy hooks — think twice. The sync command writes files. On a read-only or container filesystem (or where .env is injected by the platform), this will either fail or create a stale file that shadows real environment variables. Gate it behind an environment check, and generally prefer php artisan config:cache with platform-injected env vars in production.

Multiple env files. Projects usually have .env, .env.testing, .env.ci. If the package only targets .env (likely), wrap it in a small script that syncs each file, or accept that .env.testing drift is caught by your test suite instead.

Gotchas and Tips

  • Never commit .env. The package's whole value proposition is editing .env; make absolutely sure nothing in your tooling stages it. Add .env and .env.* (except .env.example) to .gitignore and verify git status is clean before and after running the command.
  • Sync is one-directional in spirit. Adding example keys to .env is safe; the reverse (deleting keys from .env that aren't in the example) silently destroys local secrets and debugging overrides. Check the config for a "remove stale keys" option and leave it off unless you have a very disciplined team.
  • Empty vs. missing. FOO= is present-but-empty, which for Laravel's env() means '', not null. Sync tools frequently conflate these; if a key keeps reappearing after you "add" it, that's why.
  • Parser edge cases. Values containing #, spaces, quotes, or multi-line PEM blocks (very common with *_KEY secrets) are where hand-rolled .env parsers break. Test with a real-world .env before rollout, and keep a backup the first few runs.
  • ${VAR} interpolation and ordering. If your .env uses variable references, reordering or appending can change resolution. Prefer append-only behavior.
  • Clear the config cache after syncing. Laravel won't see new values until php artisan config:clear if you've ever run config:cache locally. Most "the sync didn't work" reports are this.
  • Actual environment variables win. A key synced into .env can still be overridden by an exported shell variable or Docker --env-file. When debugging, run php artisan tinker --execute="dump(env('FOO'));" and remember precedence.
  • Line endings and BOM. If your repo is on Windows or has core.autocrlf quirks, appended lines may mix CRLF/LF. Set .gitattributes (*.env* text eol=lf) to avoid noisy diffs.
  • Pin to the v3 line, and read the changelog before upgrading. v3.0.1 is a patch (CI workflow tidy-up plus PHP 8.5 support in the test matrix), but v3.0.0 was a major bump — if you have an older lockfile, treat the v2 → v3 jump as potentially breaking and check the release notes rather than assuming drop-in compatibility. Pin "aranyasen/laravel-env-sync": "^3.0" (or an exact tag if you want zero surprises), read the source (it's small) before wiring it into CI, and keep a manual fallback documented in your README: diff <(cut -d= -f1 .env.example | sort) <(cut -d= -f1 .env | sort). Extension points beyond the config file are unlikely to be stable, so avoid subclassing internals.
  • Maintenance signal is mildly positive, but don't over-read it. The 3.0.1 release shows the maintainer keeping the CI matrix current (PHP 8.5), which is a good sign for version compatibility. It is not a sign of ecosystem adoption — still 4 stars / no dependents, so keep the manual fallback and re-verify after every bump.
  • Watch for a Laravel version ceiling. Small packages often lag on illuminate/support constraints. The package supports PHP 8.5, but that says nothing about which Laravel majors are allowed — check the package's composer.json for the framework range before debugging your own setup.
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.
robertmarney/lara-hierarchial-collections
simonschaufi/rule-doc-generator
emissaoja/emissaoja
blackbricksoftware/gravityforms-civicrm-form-processor
al-rahabi/fancy-crud
jinas/dhivatar-component
mltstephane/laravel-quality
bernskiold/laravel-talentlms
bernskioldmedia/laravel-form-architect
youbar/easy-crud
c-point-labs/laravel-hostyourai
dbravoan/dbcms-admin-theme-dbcms
dbravoan/dbcms-theme-db-cyber
dbravoan/dbcms-blocks-basic
dbravoan/dbcms-module-content-audit
dbravoan/dbcms-module-ai-assistant
paygate-to/paygate-php
padosoft/askmydocs-connector-base
defstudio/supercharged-carbon
bernskioldmedia/laravel-matomo