envy: a Laravel package that keeps .env.example in sync
Keep your .env.example file up to date
At a glance
- What is it?
- Envy is a Composer dev dependency for Laravel that scans your config files for env() calls and keeps your .env.example aligned with them, in both directions. It fits teams whose onboarding keeps breaking on a stale example file, and it only works if your env() calls actually live in config files.
- Who is it for?
- Adopt Envy if you run Laravel and your .env.example has drifted from the config directory, especially if you can add a CI step that runs php artisan envy:sync --dry and php artisan envy:prune --dry on every pull request. Do not adopt it for a non Laravel project, for env() calls that live outside config files, or if you need it to manage a real .env file in CI, which the README warns against.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 11 days ago.
- What is it written in?
- Mainly PHP, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The problem is a stale .env.example, not a missing .env
The README frames this plainly. Someone on a team has already spent hours debugging an onboarding because the project's .env.example file was wildly outdated. The variables listed in the example file no longer match the ones the application actually reads, so a new developer copies a file that is missing keys the code depends on.
Envy is the answer to that specific problem, and the scope is worth naming before anything else. It is a Laravel package, installed as a dev dependency, and it works by reading the configuration layer of your application. The README describes it as a way to sync your environment files with your project config, through a simple Artisan command.
The people who benefit are backend teams with more than one environment file and a shared repository, especially those where a missing variable only shows up as a null value deep in a request. The people who get nothing from it are teams that keep their configuration in one place already, and anyone outside the Laravel ecosystem, since the implementation is built around Laravel's env function and Artisan.
envy:sync finds env() calls and compares them to the example file
The first command, envy:sync, works in one direction. According to the README it combs through your project's config files for calls to Laravel's env function, then compares what it found against your configured environment files, which by default is just your .env.example, looking for missing entries.
When something is missing, the command does not just edit the file. You are given a choice: add the missing keys to your environment file, or add the missing keys to Envy's exclusion list. That second branch matters. Some env() calls are deliberately dynamic, a key assembled at runtime or a value that should not be in an example file, and the exclusion list is how you say so without silencing the whole check.
The mechanism is static scanning of the config directory, not runtime tracing. Envy never runs your application to discover which variables are read. That is why the location of env() calls determines whether the tool works at all.
envy:prune catches the opposite drift
The second command, envy:prune, does the reverse. The README says it searches your configured environment files for entries that could not be found in any of the configured config files, and if there are additional entries you choose between removing them from the environment file or adding them to Envy's inclusion list.
This is the half that most teams miss. An example file accumulates keys over time, and a key that no config file reads is either a leftover or a mistake, and either way it misleads the next person who sets up a local environment from it. The inclusion list is the counterpart to the exclusion list in sync, and it covers the case where a variable is genuinely required even though no config file references it directly.
Both commands take the same three options. The --path option points at a specific environment file instead of the configured set. The --dry option performs no updates, and fails if drift is found. The --force option skips the confirmation prompt, which is what you want in a bot that rewrites files without a human in the loop.
Installing is a composer require and one Artisan command
Installation is short because the package is a normal Composer dependency. The README recommends pulling it in as a dev dependency:
composer require worksome/envy --devIt also recommends publishing the package's own configuration file so you can fine tune the behaviour to your project, and that is done with the install command:
php artisan envy:installPublishing is worth doing rather than skipping, because the defaults are narrow. Out of the box Envy only makes changes to your .env.example file, and it only scans the config directory. Every other file or directory you care about has to be added to the published config.
After that the two Artisan commands are available, and the README points to the Configuration documentation for the details of the environment file list, the config file list and the exclusions.
A CI check that fails the build instead of rewriting files
The most valuable use of Envy is not the editing, it is the check. The README shows how to fail CI when .env.example is out of sync by running both commands in dry mode, and the recipe is a complete GitHub Actions workflow:
name: Envy Check
on:
pull_request:
push:
branches: [ main ]
jobs:
envy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: shivammathur/setup-php@v2
with:
php-version: '8.4'
coverage: none
- run: composer install --no-interaction --no-progress
- run: php artisan envy:sync --dry
- run: php artisan envy:prune --dryBoth dry runs fail the job when drift is detected, so a pull request that adds an env() call without updating the example file is caught before it reaches review. Note that the workflow installs dependencies but does not run envy:install, which means the check runs against the package defaults, so any non standard configuration has to be committed to the repository for CI to match your local run.
The complementary pattern is --force in an automation job that rewrites the example file and commits the result, which the README describes as useful for CI bots where no user input will be requested.
The config file decides which files are in scope
Everything tunable lives in the published envy.php file, and three keys decide the scope of a run.
The environment_files array holds the .env files Envy may change. By default it contains only .env.example. You can append .env.testing or .env.dusk, but the README explicitly warns against adding your .env file to this array because it could cause unwanted side effects, particularly in CI. That warning is the reason to keep the destructive mode out of the automated path.
The config_files array lists the files that are scanned for env() calls. By default Envy recursively scans everything in your project's config directory. If your project calls env() outside of config files, which the README calls an anti-pattern, you add those files or directories here. The array also solves a common package problem: if a package's config file was never published, you can point at the base config file inside the vendor directory instead. A directory entry includes everything under it recursively.
A third key, display_comments, controls whether a comment written next to a config key is converted into a comment above the matching environment variable, which is how the generated example file stays readable.
Where Envy stops working, and what it costs to maintain
The limitation that decides whether Envy works for you is the assumption that env() calls live in config files. The README states this directly: if your project calls env outside of config files, you must list those places in config_files. A project that reads environment variables in service providers, in bootstrap code or scattered through controllers will need those paths registered, and the tool's coverage of your application is then a configuration question rather than a given.
The second limitation is scope. Envy manages example and per environment files, not secret storage. It does not create .env values, it does not validate them, and it does not tell you whether a default in your example file matches what production expects. It checks that the set of names matches, nothing about the values.
On maintenance, the repository is not archived and the last push was on 2026-10-13, with tagged releases v1.5.0 on 2026-03-02, v1.4.0 on 2025-03-04 and v1.3.1 on 2025-02-19, so the release train is regular enough to depend on. The licence is MIT, which is the permissive end of the scale and means you can vendor the package or adapt it internally without disclosure obligations, which is not legal advice. The upgrade cost is a Composer version bump and a look at the changelog, since the configuration keys are few and stable.
Editorial conclusion
Adopt Envy if you run Laravel and your .env.example has drifted from the config directory, especially if you can add a CI step that runs php artisan envy:sync --dry and php artisan envy:prune --dry on every pull request. Do not adopt it for a non Laravel project, for env() calls that live outside config files, or if you need it to manage a real .env file in CI, which the README warns against. Verify first that your project keeps its env() calls inside config/ and that you have a configuration file published, since the default behaviour is to touch .env.example and nothing else.
Frequently asked questions
How do I install Envy for a Laravel project?
The README gives composer require worksome/envy --dev, then php artisan envy:install to publish the package configuration file. The install command is recommended so you can fine tune which environment and config files Envy works with.
What is the difference between envy:sync and envy:prune?
envy:sync scans your config files for env() calls and reports keys that are missing from your environment files, while envy:prune reports entries in your environment files that no config file references. Both let you either fix the file or record the key in an exclusion or inclusion list.
Can I use Envy to fail a CI build when .env.example is out of date?
Yes. The --dry option prevents updates and fails the command when drift is found, and the README shows a GitHub Actions job that runs php artisan envy:sync --dry and php artisan envy:prune --dry on pull requests.
Can Envy manage my real .env file in CI?
The README does not recommend adding your .env file to the environment_files array, because it could cause unwanted side effects, particularly in CI. The default scope is .env.example only.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/worksome-envy)Was this useful?