Keeping environment variables local to a project directory on the terminal and with IntelliJ

Attention IntelliJ users:

  • Working on multiple projects?
  • Too many environment variables set globally?
  • Or maybe the environment variables for each project are clashing?

Then you need local environment variables!

Local environment variables are env vars that get set and unset as you change directories. They are super useful as they allow you to have environment variables only where they are needed. It also means you can use the same environment variable name for multiple projects and not have to manage the different values.

Local environment variables for the terminal

Two great CLI tools that enable local env vars are direnv and autoenv. The main difference between the two is that while both will set env vars for each directory, only direnv will unset the env vars when you exit out of the directory.

Here’s a quick demo (from install to usage) for direnv on a Mac.

First off, you need to install and setup some local env vars. Here I’m creating the env var foo=bar in the directory tmp.

$ brew install direnv

$ mkdir tmp && touch tmp/.envrc
$ echo "export foo=bar" > tmp/.envrc
$ cd tmp
direnv: error .envrc is blocked. Run `direnv allow` to approve its content.
tmp $ direnv allow
direnv: loading .envrc
direnv: export +foo
tmp $ cd ../

Now let’s prove that there is the env var foo=bar that only exists in the tmp directory:

$ echo $foo
$ cd tmp
direnv: loading .envrc
direnv: export +foo
tmp tmo2367$ echo $foo
tmp tmo2367$ cd ../
direnv: unloading
$ echo $foo

Phoar, how useful is that? But what about IntelliJ I hear you ponder.

Local environment variables for IntelliJ

Unfortunately when using IntelliJ to run applications, the local env vars set by direnv don’t get picked up. This is because of reasons I don’t understand (please explain below in the comments if you know why).

One of the really nice features I like regarding IntelliJ is the ability to extend its functionality with plugins. There is an IntelliJ plugin called EnvFile which will allow you to set environment variables at application runtime from an external file (an .env file).

// contents of .env

With the plugin installed you get this extra tab in the Application “edit configuration” modal window…

While this is useful for IntelliJ it’s still not great for the developer as we now have two different ways to store local environment variables. You could keep both dot env files up to date but that would be sub optimal.

If only there was a way to bridge these two solutions together…

One env file to rule them all

I’ve come up with a solution to this problem. A great feature about direnv is that it will allow you to execute bash in the .envrc file. So this means you can store a single instance of all your environment variables in the .env file, and then with the simple bit of bash script below, read them into the .envrc file.

// contents of .envrc
#!/usr/bin/env bash
for line in $(cat .env); do
eval “export $line”

And so there you have it. The power of local environment variables, but with the convenience of storing them in one place for both the terminal and IntelliJ.