Environment Overlays
Source file: examples/environment_overrides.hen
What It Demonstrates
- collection-level scalar defaults
- named
envblocks in the preamble - extending those
envblocks with per-environment dotenv layers - selecting an environment at run time with
--env - one request body reused across environment-specific IDs and headers
Key Pattern
$ API_ORIGIN = https://lorem-api.com/api
$ CLIENT_ID = hen-cli
$ AUDIENCE = public
$ USER_ID = abc1234
env local
$ API_ORIGIN = https://lorem-api.com/api
$ CLIENT_ID = hen-local
$ AUDIENCE = local
$ USER_ID = local-demo-user
env staging
$ API_ORIGIN = https://lorem-api.com/api
$ AUDIENCE = staging
$ USER_ID = staging-demo-user
This keeps one request body while swapping environment-specific scalar values at execution time.
The same overlay model can also preload dotenv files before those scalar bindings resolve:
dotenv .env
$ API_ORIGIN = env("API_ORIGIN")
env local
dotenv .env.local
env staging
dotenv .env.staging
That pattern keeps one request body while letting each selected environment add its own dotenv
layer on top of any shared top-level defaults. Use env(...) for ordinary values like origins,
and secret.env(...) only when the loaded value should be masked.
Run It
hen verify ./examples/environment_overrides.hen
hen run ./examples/environment_overrides.hen 0 --env local --non-interactive
hen run ./examples/environment_overrides.hen 0 --env staging --non-interactive
What To Notice
CLIENT_IDchanges inlocalwithout editing the request.USER_IDchanges with the selected environment while the request shape stays the same.- The default collection values still run with
--non-interactivewhen no environment is selected. - The same
env ...blocks can now adddotenvdirectives when the changing inputs live in local files instead of authored scalar overrides.
Related reference: Variables and environments