@evvyxan/envvault-cli
v0.1.0
Published
Encrypt .env files with AES-256-GCM and a single password so teams can safely commit environment templates to public repos
Maintainers
Readme
env-vault-cli
Encrypt local .env files with AES-256-GCM and a single password, so teams can
commit environment templates to public repos without leaking real secrets.
No runtime dependencies. Works on Node 18+.
Why
.env files hold real secrets — API keys, database passwords, tokens. You can't
commit them, so repos end up with stale .env.example files that drift from the
real thing, or worse, a real .env that gets committed by accident.
env-vault encrypts the actual file with a password. Commit the vault, decrypt
it locally, and the .env never has to touch git.
Install
npm install -g env-vault-cliOr clone the repo and link it locally:
git clone https://github.com/you/env-vault-cli.git
cd env-vault-cli
npm linkQuick start
cd your-project
env-vault init # creates .env if missing
env-vault encrypt # prompts for a password, writes .env.vault
env-vault decrypt # prompts, writes .env backThat's it. From now on you commit .env.vault and keep .env in .gitignore.
Commands
init
Creates .env if it doesn't exist and points you at the next step.
encrypt
Encrypts .env into .env.vault.
env-vault encrypt
env-vault encrypt -i secrets.env -o lockbox.vault
env-vault encrypt --force # overwrite an existing vaultRefuses to overwrite an existing vault unless --force is given. Prints the
size and sha256 of the vault so you can spot changes in git history.
decrypt
Decrypts .env.vault into .env. Refuses to overwrite an existing .env
unless --force is given — a real .env is almost always worth protecting.
env-vault decrypt
env-vault decrypt -o .env.local # different local file nametemplate
Writes .env.example from your .env — same keys, same comments, values
blanked. Handy for documenting the shape of the environment next to the vault.
env-vault templateverify
Checks that the password decrypts the vault and prints how much plaintext it holds. Exits non-zero on failure, which makes it a cheap CI gate.
env-vault verify && echo "vault is in sync with the password"Options
| Option | Description |
| --- | --- |
| -i, --input <file> | input file (defaults: .env, .env.vault) |
| -o, --output <file> | output file (defaults: .env.vault, .env, .env.example) |
| -p, --password <pass> | password on the command line — avoid, see below |
| -f, --force | overwrite the output if it exists |
| --iterations <n> | PBKDF2 rounds for encrypt (default 600000) |
| -h, --help | show help |
| -v, --version | print the version |
Passwords
The password is prompted interactively and never echoed. In scripts and CI, set it via the environment:
export ENV_VAULT_PASSWORD=... # or in your CI secrets
env-vault encrypt-p/--password also works but prints a warning: the value shows up in shell
history and process listings. There is no way to recover a forgotten password —
if you lose it, decrypt with the old password and re-encrypt with a new one:
env-vault decrypt --force
env-vault encrypt --forceHow it works
The vault is a binary file with the layout:
ENVVLT version iterations salt(16) iv(12) tag(16) ciphertext- The password is stretched with PBKDF2-SHA256 (600,000 iterations by default, stored in the file so future versions can raise it)
- Encryption is AES-256-GCM, an authenticated cipher — the file can't be tampered with undetected
- Salt and IV are random per run, so encrypting the same file twice produces different vaults; no metadata (key names, comments, file size) leaks from the ciphertext alone
encrypt and decrypt are the only commands that touch the password.
Git workflow
# .gitignore
.env
.env.exampleCommit .env.vault. The vault is not secret-sensitive — without the password
it's opaque bytes — so committing it to a public repo is the whole point.
For CI, verify the vault decrypts with the deploy secret:
# .github/workflows/check-vault.yml
name: check-vault
on: push
jobs:
verify:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npx env-vault-cli verify
env:
ENV_VAULT_PASSWORD: ${{ secrets.ENV_VAULT_PASSWORD }}Development
npm test # node --test, no dependenciesLicense
MIT
