msamgan/laravel-env-keys-checker
Laravel Env Keys Checker compares your .env and .env.example files to spot missing or extra environment variables. Run a simple Artisan command to keep configs in sync and catch deployment issues before they happen.
composer require msamgan/laravel-env-keys-checker --dev. This is a development/CI guardrail, not a runtime dependency, so keep it out of production require.php artisan vendor:publish --tag="env-keys-checker-config".config/env-keys-checker.php — it is the single place that defines which files are compared and which keys are ignored. Everything else is convention..env and .env.example have drifted, and use the reported diff to either add missing keys to .env.example or remove stale ones. This is the fastest way to understand the package's output format before wiring it into CI.v2.0.0 note: the major version bump is driven by Laravel 13 compatibility. Treat the Laravel/PHP version constraints in composer.json as the thing to verify — a major bump here almost certainly means older Laravel (and possibly PHP) versions are no longer supported. Check the constraints before upgrading an app that is not yet on the latest Laravel line.
Local pre-commit / manual check. Run the checker command as part of your normal dev loop after adding a new config value. The package is cheap to run and catches the common failure of adding env('FOO') usage without documenting FOO in .env.example.
CI gate. The highest-value pattern is a dedicated CI step that fails the build when keys drift. Put it in the same job as your test suite but as a separate step so the failure reason is unambiguous:
- run: composer install --no-interaction --prefer-dist
- run: php artisan env:keys:check
Pin the major version (^2.0) in composer.json so a future major bump does not silently land in CI via composer update.
Pair it with config-cache / fresh-install checks. A pattern that works well is running the checker once on a clean checkout (where .env is generated from .env.example) — that validates .env.example is actually sufficient to boot the app, which is a stronger guarantee than a diff of two files.
Composer script hook. Add a composer check script that chains the checker with Pint/PHPStan so contributors run it without remembering the command:
"scripts": {
"check": ["@php artisan env:keys:check", "pint --test", "phpstan analyse"]
}
Multi-environment awareness. Keep the default .env / .env.example comparison for the main check, and use the config's path/exclusion options for repos that also ship .env.testing or .env.ci. Do not try to make one invocation cover every environment — separate invocations with separate config overrides are more readable.
Exclusion discipline. When a key legitimately differs (secrets, local-only overrides, keys injected by the host platform), add it to the exclusion list with a comment explaining why. Treat the exclusion list as technical debt: review it each time you bump the package.
composer update that resolves fine locally but drops support for a Laravel version another service in your monorepo is still on. Read the composer.json constraints after upgrading rather than trusting the changelog summary..env is usually gitignored. In CI there is often no .env at all, so the checker can fail for the wrong reason. Either generate .env from .env.example as a CI step, or scope the check to the environment where both files exist. This is the number-one source of confusing failures..env.example may or may not be treated as present depending on the implementation. If you rely on commented placeholders as documentation, verify the checker's behaviour on your own files before gating CI on it..gitattributes before blaming the package.config/*.php must be documented"), write a small custom command that wraps or complements this one rather than forking the package..env rather than a freshly generated one). Re-run in a clean checkout to confirm.require-dev. Adding it to production require bloats your deploy artifacts and, on platforms that run composer install --no-dev, means it silently disappears from the environment where you most want consistency guarantees.^2.0 is appropriate; * is not. If your CI is sensitive to surprise breakage, composer.lock plus scheduled, reviewed updates is the safer posture than auto-merging Dependabot PRs for a tool that gates your build.How can I help you explore Laravel packages today?