Sitelet https://envstack.dev/

envstack logo

envstack is an environment variable composition and activation layer for tools and processes.

It is built for cases where environments are hierarchical, shared, and context-dependent, and where a flat .env file stops being enough.

export ENVPATH=/studio/project/foo/env:/studio/prod/env
envstack mytool

Why envstack

envstack is a lightweight CLI and Python library for composing, tracing, exporting, and reproducing environment variables using a PATH-like model called ENVPATH.

Compose

Explain

Export

ENVPATH

ENVPATH defines where environment fragments are discovered and in what order they apply, similar to PATH, but for full environments.

export ENVPATH=/studio/project/foo/env:/studio/prod/env
envstack mytool

ENVPATH is ordered; earlier paths have higher precedence than later ones.

That gives envstack a compact mental model:

Files identify stacks; directories identify scope; ENVPATH defines precedence.

For example:

/studio/prod/env/mytool.env
/studio/project/foo/env/mytool.env

mytool.env identifies the stack being configured. The containing directories describe scope. With:

export ENVPATH=/studio/project/foo/env:/studio/prod/env

the project-scoped mytool.env has higher priority because its directory comes first.

envstack is not

It is intentionally boring: explicit inputs, deterministic outputs, and tooling that tells you what it did.

Install

pip install -U envstack

Quickstart

Start with the repository’s baseline example:

curl -o default.env \
  https://raw.githubusercontent.com/rsgalloway/envstack/master/examples/default/default.env

Running envstack launches a shell with the resolved stack active:

$ envstack
🚀 Launching envstack shell... (CTRL+D or "exit" to quit)
(prod) ~$ echo $ENV
prod

Inspect the unresolved environment:

envstack -u

Typical output from examples/default/default.env looks like:

DEPLOY_ROOT=${ROOT}/${ENV}
ENV=prod
ENVPATH=${DEPLOY_ROOT}/env:${ENVPATH}
LOG_LEVEL=${LOG_LEVEL:=INFO}
PATH=${DEPLOY_ROOT}/bin:${PATH}
PYTHONPATH=${DEPLOY_ROOT}/lib/python:${PYTHONPATH}
ROOT=/mnt/pipe
STACK=default

Resolve a specific variable:

envstack -r DEPLOY_ROOT

Run a command inside the active stack:

envstack -- echo {VAR}

For example:

$ envstack -- echo {ENV}
prod

That makes it easy to inject configuration into subprocesses:

$ echo "console.log('Hello ' + process.env.ENV)" > index.js
$ node index.js
Hello undefined
$ envstack -- node index.js
Hello prod

Trace where a variable comes from:

envstack -t PATH

How envstack finds environments

ENVPATH tells envstack where environment fragments live and in what order they should be discovered, much like PATH for executables.

export ENVPATH=/path/to/prod/env:/path/to/dev/env

To give development overrides higher priority than shared production defaults, put the development directory first:

export ENVPATH=/path/to/dev/env:/path/to/prod/env

Because earlier ENVPATH entries have higher precedence, /path/to/dev/env takes precedence over /path/to/prod/env.

Converting .env files

You can convert an existing flat .env file into an envstack-compatible file:

cat .env | envstack --set -o out.env

Learn More