envelope: a SQLite-backed manager for environment variables
An environment variables cli tool backed by SQLite
At a glance
- What is it?
- envelope is a Rust command line tool that keeps named sets of environment variables in a local SQLite database, so a project can hold dev, staging and prod configurations side by side and run a command against one of them. It encrypts the whole database with a passphrase when locked, and it records history so a deleted variable can be reverted.
- Who is it for?
- envelope fits a developer working across several environments who wants one file instead of scattered .env files, and who wants a record of what a variable used to be, since deletes are soft and reversible. It does not fit a team that needs a shared, synchronised secret store, because the database is a local file with no remote component, and it does not fit a deployment pipeline that expects variables to arrive from the environment rather than be pulled from a store.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository last received commits 97 days ago.
- What is it written in?
- Mainly Rust, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 24, 2026, and from our analysis. They are not legal advice.
Editorial analysis
One SQLite file holding every environment
envelope is described as a modern environment variables manager, and the design decision that shapes everything else is that the store is a local SQLite database. Running envelope init in a directory creates a .envelope database file, and the documentation insists on a step that follows immediately: you must run envelope init before using any other commands, and the .envelope file should be added to your .gitignore to avoid committing sensitive environment variables. That is a different shape from the .env file convention. Instead of one file per environment, named by convention, you have one database with a row per variable per environment, which is what makes the rest of the command set possible. The tool is written in Rust, the project is a single crate, and the SQL layer is sqlx with the sqlite feature alongside tokio for the async runtime. The author is Mattia Righetti.
Four install routes, including one from the AUR
The install options are unusually broad for a small tool. Homebrew is first, from homebrew-core.
$ brew install envelopeThen a release binary, which you download from the latest release page and copy to a folder in your $PATH. Then cargo, and the README asks you to make sure your ~/.cargo folder is in your $PATH.
$ cargo install --git https://github.com/mattrighetti/envelope
$ envelope --version
envelope 0.3.11The AUR package is called envelope-bin, since it packages the binary rather than building from source.
yay -S envelope-binBuilding from source needs the Rust compiler, and the three commands are clone, build and check the version.
$ git clone https://github.com/mattrighetti/envelope
$ cd envelope
$ cargo build --release
$ ./target/release/envelope --version
envelope 0.7.1Note the version numbers printed in those two examples differ, 0.3.11 for the cargo install and 0.7.1 for the source build, because the README was written at different times. The current crate version is 0.8.0, with the Cargo.toml requiring a rust-version of 1.97.1 on edition 2024.
Importing a .env file and listing what you stored
The import command takes an environment name and a file, and you can also pipe a file in from stdin.
$ envelope import dev .env
$ cat .env | envelope import prodThe list command shows saved environments and the variables inside one of them.
$ envelope list
dev
staging
prod$ envelope list dev
API_KEY=your_api_key
DATABASE_URL=postgres://user:password@localhost:5432/mydb
DEBUG_MODE=true
SECRET_KEY=mysecretkey123
SMTP_HOST=smtp.example.comA pretty print mode renders the same data as a table, and a truncate option shortens long values, which matters because a database URL or a key in a terminal is easy to shoulder-surf or end up in a screenshot. Sorting is configurable with the --sort option, taking key, value or date in ascending form, the kd, vd and dd forms for descending, and dd as the default.
$ envelope list dev --pretty-print --truncateThere is also a standalone pretty print of a .env file by piping it in with no subcommand, which prints a two-column table of variables and values without touching the database at all.
Names are uppercased, and values can come from stdin
Adding a variable takes the environment, the name and the value, and the name is uppercased automatically.
$ envelope add dev api_key sk_test_123456789
$ envelope list dev
API_KEY=sk_test_123456789$ envelope add dev database_url postgres://localhost/mydb
$ envelope list dev
DATABASE_URL=postgres://localhost/mydbThe uppercasing is convenient and also quietly opinionated, since a tool that stores POSIX-style names will not hold a lower-case variable name verbatim. For sensitive values there is a --stdin flag, which prompts for the value rather than taking it as an argument.
$ envelope add dev secret_token --stdin
Enter value for env secret_token:
my-super-secret-tokenThat matters because a secret typed on the command line ends up in your shell history. The value can also be empty, which is how you record a variable that is present but unset.
$ envelope add dev optional_var
$ envelope list dev
OPTIONAL_VAR=Deletes are soft, and drop is the one that is not
The deletion semantics are the most interesting thing about the tool. Deleting a variable from an environment is a soft delete and can be reverted.
$ envelope delete --env dev --key API_KEY
$ envelope list dev
# API_KEY will no longer appearThe same command without an environment removes the variable from every environment where it exists.
$ envelope delete --key DEBUG_MODEAnd deleting an environment by name removes its variables.
$ envelope delete --env dev
$ envelope list
# dev will no longer appearThe note attached to this section is explicit: envelope always soft deletes environment variables, they are never actually removed from the database, which allows you to view the history and revert changes, and for a hard delete that permanently removes data you use the drop command. Drop takes an environment name and takes the history with it.
$ envelope drop dev
$ envelope list
# dev is permanently deleted, including all its historyThe cost of that design is that the database grows, since every deleted value stays in it, and a file that never forgets a secret is a different risk profile from a file that never had it.
The rest of the command set: history, revert, diff, run
The command list in the help output shows the shape of the tool, and several entries go beyond storing and printing. history displays the historical values of a specific key in a given environment, and revert reverts an environment variable, which together are the undo system for the soft deletes. diff compares two existing environments, which answers the question that comes up constantly in a multi-environment setup: what is different between staging and prod. duplicate creates a copy of another environment, which is the usual way to branch a configuration before a change. run executes a command with the environment variables from a specific environment, so the application starts with the right configuration without a shell export dance. check reports which environment is currently exported, and edit opens the environment variables in your editor, which is a nice touch for a tool that would otherwise force you back to the command line for a bulk edit. import brings in a .env file, list shows what you have, and init creates the database. The two remaining commands, `lock` and `unlock`, handle encryption.
Locking the whole database with a passphrase
The `lock` command encrypts envelope and the `unlock` command decrypts it, and the cryptography behind that is visible in the dependency list. The password handling is argon2, the cipher is chacha20poly1305, and the values that pass through memory are wiped with zeroize, so a passphrase and a secret value are not left lying in the process after use. The key derivation and the authenticated encryption together mean a wrong passphrase fails cleanly rather than producing a database full of garbage. What the README does not say is how the passphrase is supplied, whether the encrypted file is a separate artefact or replaces the .envelope file in place, or how the lock state is detected at startup, and those are exactly the questions a team needs answered before it puts production secrets in this format. The tool also has a man/ directory in the repository, so the reference documentation is generated rather than hand written.
Where a local database is the wrong shape
Two cases point elsewhere. The first is a team with more than one developer, where the environment configuration is shared and edited by several people. envelope's store is a file in your working directory, with no server, no sync and no access control, and the README does not mention any remote or shared mode. Sharing a .envelope file over a chat message and locking it before sending is possible in principle, but that is a workflow you are inventing rather than one the tool supports. The second is a deployment pipeline. On a build server the variables normally arrive from the environment, a secrets manager or the platform, and reading them from a local SQLite file means shipping a database to the runner and distributing a passphrase to it, which is more moving parts than the problem deserves.
There is a smaller operational point too. The .envelope file holds every environment's variables, including development and staging, in one place next to the code. A per-environment .env file keeps the blast radius of a mistake to one file. Envelope gives you history and diffing in exchange for that concentration, and for a solo developer on one project the trade is usually worth it. For a machine that holds production credentials, the question deserves more than a default answer.
Editorial conclusion
envelope fits a developer working across several environments who wants one file instead of scattered .env files, and who wants a record of what a variable used to be, since deletes are soft and reversible. It does not fit a team that needs a shared, synchronised secret store, because the database is a local file with no remote component, and it does not fit a deployment pipeline that expects variables to arrive from the environment rather than be pulled from a store. Before you adopt it, run envelope init in the project directory and add the .envelope file to .gitignore as the documentation asks, and decide where the passphrase lives, because the `lock` and `unlock` commands are where the security story of the whole tool rests.
Frequently asked questions
What is envelope and where does it store environment variables?
envelope is a Rust command line tool described as a modern environment variables manager, and it is backed by SQLite. Running envelope init in a directory creates a .envelope database file, and the README notes that you must run init before any other command and should add the .envelope file to your .gitignore.
How do I install envelope?
There are four documented routes: brew install envelope from homebrew-core, a release binary you copy into a folder in your $PATH, cargo install --git https://github.com/mattrighetti/envelope, and the AUR package envelope-bin installed with yay -S envelope-bin. Building from source needs the Rust compiler and a cargo build --release.
Can I undo a delete in envelope?
Yes. The README states that envelope always soft deletes environment variables and never actually removes them from the database, which lets you view the history and revert changes, and the revert and history commands exist for that. A permanent removal is done with drop, which takes an environment name and deletes its history too.
How do I keep a secret out of my shell history in envelope?
Add the variable with the --stdin flag, so envelope prompts for the value instead of taking it as an argument, as in envelope add dev secret_token --stdin. The dependency list also shows argon2 for passphrase derivation, chacha20poly1305 for the cipher and zeroize to wipe sensitive values from memory.
What is the difference between the delete and drop commands?
delete removes a variable, or an environment, but only as a soft delete, so the data stays in the database and can be reverted. drop is the hard delete, and the README says it permanently removes an environment and all of its variables, including all its history.
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/mattrighetti-envelope)Was this useful?