Hacker News

mattrighetti
Show HN: Envelope – A modern environment variable cli tool github.com

Hey HN! I've built this cli tool to manage env variables of a project, but mostly for fun and to try out Rust and the clap crate.

I had this idea when I made a big mistake and broke some production stuff because I had a very messy .env file laying around in my project.

I was implementing new features for one of my projects and in my .env file I had the test database url commented out and the production one was not. Long story short, I applied migrations to the production database instead of my local test one and broke a lot of production APIs :')

I wanted a tool that could easily help me spot these issues before something bad happened, and so I built envelope for that reason.

Instead of a \.env(\..+)? file, I now use this tool to add variables to different configurations: dev, prod etc. and I feed them to the program I am executing on a one liner.

  $ envelope init
  $ envelope add dev db_url localhost:5432/postgres
  $ envelope add dev db_username username
  $ envelope add dev db_pwd pwd
  $ export $(envelope list dev)
  $ ./run.sh
This way I am explicitly exporting the dev environment without relying on the fact that everything is in order in my .env file (another approach would be to have a .env.dev file)

A very useful feature that I use quite a lot is the `check` command which is going to tell you which environment you have currently active

  $ export $(envelope list dev)
  $ envelope check
  > dev
I don't think this tool is going to be useful to anybody, but I wanted to share this with you in case there is someone that can make good use of it or find particular scenarios where this could be used instead of .env files, either way I had a lot of fun building it

leetrout3 months ago

A word of caution - this is a way to leak your secrets through your shell history:

  $ envelope add dev db_pwd pwd
There are settings such that a command that starts with a space will not be saved in the history which would help here but I would be very careful about how you use this.

mattrighettiop3 months ago

Mine was a bad example :) the command also lets you input stuff from stdin for that very case

bomewish3 months ago

What’s the threat model? If an attacker has access to your shell history then don’t they then already have access to basically everything else?

leetrout3 months ago

No, not necessarily. Compared to interactive prompts / processes, at a minimum ones that can help audit access (e.g. 1password), there is an immediate layer of defense missing when things are just sitting in plain text in the history. (Same extends to our beloved `.env` files.)

If you do a lot of remote pairing or screen sharing then you also remove the risk of sharing on accident by searching or walking up through your command history.

bloopernova3 months ago

Interesting!

Have you looked at mise-en-place at all? It's written in rust too, and might have some cool ideas to use: https://mise.jdx.dev/

breck3 months ago

I like it.

Env variables should be a solved problem but no one has made the simplest general solution yet. Seems like you are on track.

One suggestion: no need to use SQLite. Just develop a simple (and _lasting_), plain text DSL and save to a file.

Here's one I made using your example.

https://sdk.scroll.pub/designer/#parsers%0A%20valueCell%0A%2...

I'm happy to chat more to nail that design if that would be helpful.

cbarrick3 months ago

Seems like .env is already an ideal DSL here. It's just a subset of shell. Easy to parse and index too.

breck3 months ago

It's close to ideal, but not ideal.

eikenberry3 months ago

> Env variables should be a solved problem

I think the main problem is that this problem is 99% solved by the shell alone. Shells are very versatile and it is quite easy to setup different environments using your shell. I'd bet that the crossover of people good at manipulating environments on workstations and people good with shells is pretty big. That is, the people with good domain knowledge have little motivation to write tools to address this.

bloopernova3 months ago

A parser playground? Wow that is very cool.

breck3 months ago

Thanks. It is not "great" yet but it is pretty good and reliable and has served me well for many years.

At some point I may clean up the code so that it can really shine.

Higher priority though is getting support for this Parsers language in Sublime and VS Code.

gtirloni3 months ago

I was thinking the same because how do you version control SQLite in git?

mattrighettiop3 months ago

> how do you version control SQLite in git?

Interesting article just about that [0]

[0]: https://garrit.xyz/posts/2023-11-01-tracking-sqlite-database...

skeledrew3 months ago

I don't think you want your secrets committed...

gtirloni3 months ago

It's common for projects to have placeholder values for dev/local environments.

Environment variables aren't only for secrets (some say they should have never been).

skeledrew3 months ago

Sure, but we've seen time and again where someone got hacked because secrets got committed, whether accidentally or deliberately. Why tempt fate with something that encourages committing of any env vars?

The reason why we even pull these things out in the first place is because they're considered dynamic values. Otherwise we'd just hardcode them in a committed constants file.

gtirloni3 months ago

This is a tool to manage environment variables. People use .env files with dev/local env var values in Git repositories for a good reason. They won't stop doing this.

tomwphillips3 months ago

Of all the adjectives to use, why “modern”?

Very common these days. I don’t get it.

peter_l_downs3 months ago

I think a lot of new entrants to previously-well-explored spaces tend to label themselves as "modern" in order to signify that there is something new about their approach.

For instance, I have a migrations library that I descibre as "modern" because it is designed for a continuous deployment environment where you're automatically running migrations on container startup — there are tons of existing popular migrations libraries, but none of them work this way because they were written in the era that you'd manually run sql commands in prod. I say "modern" so that if anyone finds my library, they realize that it was created recently based on more recent dev/ops trends.

Maybe I should drop the "modern"? I do see a lot of people describe their code as "minimal" or "clean", which is pretty meaningless to me, so I get that "modern" could come across that way as well.

tomwphillips3 months ago

Interesting. My take is more negative than that: modern indicates they are unaware of prior art and the key challenges in the particular space, and consequently the software is buggy and/or fundamentally broken its approach.

I think you should drop “modern” for something like “designed for CI”, “CI-first” or “CI-native”. It’s more informative.

skeledrew3 months ago

Another issue with using such relative qualifiers IMO is that they become meaningless over time, as the namespace becomes polluted as every few years something addressing some problem with a potentially different approach is given a similar qualifier.

Aeolun3 months ago

Maybe? I think, everything else being equal, that “modern” is still a relatively positive signal to me.

bityard3 months ago

I've noticed it's something a lot of Rust programs describe themselves as. Implying that software written in other programming languages is somehow vintage or obsolete, I guess.

whateveracct3 months ago

Rust has a very pronounced hype/ marketing/PR culture.

rpigab3 months ago

Ripgrep is recent and written in Rust, but it does not describe itself as modern, even if some apects of it are.

Its interface is designed to be an almost drop-in replacement of grep, which makes it "old style".

I think software can be old style, modern, or neutral. Most software written today aims for modern, it seems logical.

Aeolun3 months ago

Ripgrep is definitely much more usable than legacy grep though.

keb_3 months ago

Same, except I take issue with the word "tool." Like a program? A library? A screwdriver? Very ambiguous. Very common these days as well. I don't get it.

looperhacks3 months ago

It's explicitly called a "cli tool", not very ambiguous imo

keb_3 months ago

Not quite. Could be Call Level Interface, Command Line Interface, Common Language Infrastructure, or Clintonville Municipal Airport which has the airport code of "CLI".

superb_dev3 months ago

At this point you’re being intentionally obtuse. “CLI tool” is pretty non-ambiguous given the context

RadiozRadioz3 months ago

Maybe it's a synonym for "Rust/Go instead of C/C++"

oopsallmagic3 months ago

[dead]

oopsallmagic3 months ago

[flagged]

mattrighettiop3 months ago

Quite the contrary, I think that env variables have been in this state for this long because they just works and I'm all in with the say "don't reinvent the wheel". I just used modern because it's a tool made in 2023-2024 with Rust, but yeah others may be right that it's just meaningless. I'll probably remove it.

Kwpolska3 months ago

The docs don’t make it very obvious how are the environment variables actually applied. And I think .env files are much easier to manage and share. `envelope check` could be replaced with a CURRENT_ENV environment variable in an .env file. I can’t see how it would help avoid environment confusion more than $CURRENT_ENV displayed in your prompt would. (Or even better, not having production credentials on developers’ machines…)

mattrighettiop3 months ago

> The docs don’t make it very obvious how are the environment variables actually applied.

Actually, they are not applied. This is a tool that helps you manage them, you can see it as a replacement of .env files.

> `envelope check` could be replaced with a CURRENT_ENV environment variable in an .env file

Can you elaborate more on this? I've never used that tbh and I'm interested

Kwpolska3 months ago

> Actually, they are not applied. This is a tool that helps you manage them, you can see it as a replacement of .env files.

The point of .env files is for tools (shells or libraries like dotenv) to read the file and actually use them. How do you do that with your tool, considering it uses a custom format?

> Can you elaborate more on this? I've never used that tbh and I'm interested

There is nothing special, just define a variable in .env, and then either echo it manually, or change your shell prompt to apply it.

globular-toast3 months ago

Seems neat, but direnv can do more despite this claiming to be "modern".

another-dave3 months ago

> This way I am explicitly exporting the dev environment without relying on the fact that everything is in order in my .env file (another approach would be to have a .env.dev file)

What did you find lacking with the .env.dev approach? (Or if some tool doesn't support .env.dev could always symlink .env → .env.dev)

mattrighettiop3 months ago

The cons of that is that sometime I'd end up with 3 different files for different scenarios and in one particular case my tool only cared about the .env file, so I had to do a lot of `mv .env.dev .env` every time I had to switch to another env configuration.

another-dave3 months ago

But running:

    ln -sf .env.dev .env
doesn't seem any worse than running:

    envelope export dev

?

Aeolun3 months ago

Well… one is just a tad more readable.

another-dave3 months ago

My personal approach is to favour more universal tools, so would prefer using symlinks & then adding a shell alias (or a package.json script) if I want to make it quicker to type.

To each their own, though!

stephenr3 months ago

> I had the test database url commented out and the production one was not.

I feel like this is a giant red flag. Why on earth is your production database accessible from anywhere (ie your PC) without some kind of extra layer of security like a VPN or SSH tunnel?

mattrighettiop3 months ago

The production database that I'm talking about is a Postgres instance that is only available to me in my house for my side projects, it contains random stuff that can be queried through APIs that me and my family use with an app that works only when we are connected to our home LAN. Therefore I'm not paying as much attention when I do stuff with it as I would on a database that thousands of users rely on. Still, it sucks because it took quite some time to bring it back to a working state. Lesson learned

skeledrew3 months ago

Hmm I fairly recently started saving variables which tend to be shared among multiple projects in a central location, grouped in sh files and sourcing as needed. This gives me an idea to improve that flow...

applgo4433 months ago

When i deploy a webapp on azure, it expects me to put env variables in a file or their own tool (key value fields) where you can add env variables one by one.

Is there a way to use envelope in places like those?

SeriousM3 months ago

envkey.com is also distributing environment variables

nodesocket3 months ago

Any plans to support encryption at rest?

cranberryturkey3 months ago

how do I install the damn thing??

mattrighettiop3 months ago

I'll copy the answer to a similar question in the issues:

> I used to have a `brew tap` for it but I've removed it temporarily. To install it you can download the binary file in the latest release[0] and move it to your `/usr/local/bin` folder (on macOS this is what I'd do) or any other folder that is in your `$PATH`.

[0]: https://github.com/mattrighetti/envelope/releases/latest

cranberryturkey3 months ago

Can we get an arch package?

i4k3 months ago

yep, do it!

mattrighettiop3 months ago

Added an aarch version to the release ci

cranberryturkey3 months ago

What's the package name?

twerkmonsta3 months ago

you probably don’t need sql

mattrighettiop3 months ago

Agreed, sqlite is definitely overkill for this kind of task but it's also lightweight and fast, so why not?

hn-front (c) 2024 voximity
source