Withenv loads environment variables from YAML, JSON, scripts, directories, and aliases before running a command. It makes runtime configuration explicit and repeatable without permanently changing your shell.
brew install ionrock/tap/we
# or
go install github.com/ionrock/we/cmd/we@latestCreate devenv.yml:
---
APP_ENV: development
LOG_LEVEL: debug
DATABASE_URL: postgres://localhost/myappCreate .withenv.yml:
---
- file: devenv.ymlPrefix commands with we:
we printenv APP_ENV
# development
we ./my-app
we go test ./...Inspect exactly what withenv loads:
we --cleanUse a YAML list when ordering matters. Later entries can reference values from earlier entries, and later files or flags override earlier values.
# devenv.yml
---
- APP_ENV: development
- APP_HOST: localhost
- APP_PORT: "8080"
- BASE_URL: http://$APP_HOST:$APP_PORT
- LOG_LEVEL: debug# local.yml, optional and usually gitignored
---
- APP_PORT: "9000"
- LOG_LEVEL: trace# .withenv.yml
---
- file: devenv.yml
- file: local.ymlBecause sources are applied in order, local.yml overrides devenv.yml:
we --clean printenv APP_PORT
# 9000Explicit flags are applied after .withenv.yml, from left to right, so the final flag wins:
we -E APP_PORT=7000 -E APP_PORT=7100 --clean printenv APP_PORT
# 7100You can also render a simple config file before the command starts:
# app.conf.tmpl
env={{ .APP_ENV }}
url={{ .BASE_URL }}
log_level={{ .LOG_LEVEL }}
we --template app.conf.tmpl cat app.conf
# env=development
# url=http://localhost:8080
# log_level=traceBy default, app.conf.tmpl renders to app.conf. Use TEMPLATE:TARGET to choose an explicit output path.
The preferred way to use secrets is to keep them in a SOPS-encrypted YAML file. we decrypts SOPS YAML directly with the SOPS Go library and marks all values from encrypted files as secret, so inspection output redacts them by default.
Create a plaintext secrets file:
# secrets.yml
---
DATABASE_PASSWORD: super-secret
PAYMENTS_API_KEY: secret-tokenEncrypt it to an Age recipient:
we sops encrypt \
--age age1YOUR_PUBLIC_RECIPIENT_HERE \
--output secrets.enc.yml \
secrets.ymlLoad the encrypted file like any other withenv YAML source:
# .withenv.yml
---
- file: devenv.yml
- file: secrets.enc.ymlThen run commands normally:
we --clean printenv DATABASE_PASSWORD
# super-secret
we --clean
# DATABASE_PASSWORD=<redacted>
# PAYMENTS_API_KEY=<redacted>After verifying decryption works, remove the plaintext file:
rm secrets.ymlAge private keys are discovered using SOPS' standard locations, such as SOPS_AGE_KEY, SOPS_AGE_KEY_FILE, or the default key file under your user config directory.
The docs are organized into three sections:
- Quickstart: set up
.withenv.ymlanddevenv.yml. - Secrets: SOPS/Age encrypted YAML and secret provider references.
- Reference: every CLI flag and option.
- Advanced usage:
--agent, scripts, and templates.
Published docs: https://withenv.readthedocs.org