dniccum/secret-stash-cli
A command-line companion for Laravel's secret stash, offering artisan commands to add, list, rotate, and remove encrypted secrets without leaving the terminal. Keep API keys and credentials organized, encrypted at rest, and easy to manage across environments.
dniccum/secret-stash-cli is a dev-dependency style CLI for committing your secrets to the repo in an encrypted "stash" that each team member/device can unlock independently. The v1.1.1 patch is a bug-fix release with no API or config changes — upgrading from 1.1.0 is safe.
Minimal path from zero to useful:
composer require --dev dniccum/secret-stash-cli
php artisan vendor:publish --tag="secret-stash-config"
php artisan secret-stash:install # or :init, depending on version
Where to look first, in this order:
config/secret-stash.php — the stash file path, keyring/envelope directory, and the cipher used. This is the file you will actually need to reason about.stash/ or .secret-stash/) — understand what gets committed versus what never leaves the machine.php artisan list secret-stash — the command surface is the real documentation; commands are grouped under a single namespace.First use case to validate the tool end-to-end: run the setup command, lock your existing .env, confirm the encrypted stash is diffable and readable in git, then immediately simulate a second developer by copying the repo to another directory (or a fresh clone with a different local key) and unlock there. If that round-trip works, the mental model is correct and everything else is workflow.
Bootstrap once, unlock per session. Treat lock/unlock as an explicit, deliberate action rather than something wired into composer install. Unlocking writes plaintext to disk; you want that to be a conscious step, not a side effect of dependency installation. A useful convention is a composer script ("stash:unlock": "@php artisan secret-stash:unlock") so the team shares the same invocation without it firing automatically.
Per-device envelopes, not a shared password. The architecture here is a data key wrapped into one envelope per authorized device. The practical pattern is:
Envelope repair as part of the add-a-device runbook (v1.1.1). The 1.1.1 fix — "repair missing envelopes for your other devices after unlocking" — directly addresses the most common failure in this model: a device is registered but its envelope never gets materialized, so it silently can't decrypt later. The pattern this enables is: unlock on any authorized device becomes a self-healing reconciliation pass. Bake it into onboarding docs as "after adding a teammate's device, run unlock once and commit the resulting envelope changes," rather than hand-managing envelope files.
CI/CD. Store the CI machine's key (or passphrase) in your platform's secret store, unlock non-interactively in a deploy step, write .env, run php artisan config:clear, then let the ephemeral runner die. Do not cache the unlocked plaintext between jobs, and do not commit the CI device's private key — only its public envelope.
Rotation. When someone leaves, remove their device entry and rotate the data key, then re-emit envelopes for remaining devices. Plan for this as a scripted, reviewed PR: the stash diff will be large and unreadable, which is expected. Pair it with an actual secret rotation for anything the departing person could have read.
Integration tip: keep the stash file checked in and treat it as the source of truth, but keep .env gitignored as usual. Any drift between the two is a workflow bug, not a tool bug — a lock immediately after editing .env keeps them in sync.
unlock from an authorized machine and commit the envelope changes.--help rather than piping stdin — prompts behave differently when there's no TTY.php artisan config:cache in a deploy pipeline will freeze the stash paths; run config:clear after any config edit and before debugging "it can't find the stash.".env. Values containing #, spaces, or multi-line PEMs often round-trip badly. Test the stash with your gnarliest secret (a private key) early, not with APP_NAME.How can I help you explore Laravel packages today?