---
sidebar_position: 1
title: Variables and Environments
description: Declare scalar inputs, prompt placeholders, arrays, and named environment overrides.
---
## Variables
```hen
$ variable_name = value
$ variable_name = $(command)
$ variable_name = secret.env("NAME")
$ variable_name = secret.file("./path/to/value.txt")
$ variable_name = [[ prompt_name ]]
$ variable_name = [[ prompt_name = default_value ]]
$ variable_name = [foo, bar]
```
- Scalars are the default building block for reusable values.
- `$(...)` runs a shell command at preparation time.
- Prompt placeholders can declare defaults.
- Arrays expand a request once per value.
Prompt defaults are plain text up to the closing `]]`, so URL-shaped values such as
`[[ ws_origin = wss://example.com ]]` are valid.
## Array Expansion
```hen
$ USER = [alice,bob]
---
Fetch profile
GET https://api.example.com/users/{{ USER }}
^ & status == 200
```
Hen turns that single request block into mapped requests, one per array value. In this example, the
planner creates `Fetch profile [USER=alice]` and `Fetch profile [USER=bob]`.
When a request references two array variables, Hen creates mapped requests for the Cartesian
product of those values.
Arrays are intentionally constrained:
- values must stay simple scalars
- no nested arrays
- no whitespace inside array items
- up to two array variables per request and 128 total combinations
Generated requests are suffixed with the chosen values, such as `[USER=foo]`.
If a mapped request fails, Hen aborts the remaining iterations. Exports from each iteration are
suffixed with the same selected-value label.
Mapped requests may depend on the matching expanded iteration of another mapped request when they
share compatible iteration bindings. Unmapped requests still cannot depend on a mapped request, and
ambiguous mapped matches still fail. If multiple downstream requests need the same unmapped setup,
move that setup into an unmapped helper request.
## Named Environments
```hen
$ API_ORIGIN = https://api.example.com
$ CLIENT_ID = [[ client_id ]]
env local
$ API_ORIGIN = http://localhost:3000
$ CLIENT_ID = hen-local
env staging
$ API_ORIGIN = https://staging.example.com
```
- Environment blocks are valid only in the collection preamble.
- Environment overrides may only target previously declared scalar variables.
- Environment values must stay scalar.
- Arrays, shell substitutions, and nested environment syntax are rejected inside environment blocks.
## Selection Order
Resolution order is:
1. Collection preamble scalar assignments
2. Selected named environment
3. Explicit CLI `--input key=value` values
4. Prompt defaults declared with `[[ name = default ]]`
5. Runtime captures and callback exports
## Run-Time Selection
Use:
```bash
hen run ./collection.hen 0 --env local --input client_id=demo --non-interactive
```
If no environment is selected, Hen uses the collection defaults.
For secret-backed values, continue to [Secrets and redaction](./secrets-and-redaction.md).