# env

The `env` global is a read-only dictionary of the environment values a step declares for its script. It holds
exactly the inputs you wrote in the step's `env:` map, after templates are resolved, so a script depends only on
values that are visible in the YAML.

## Usage

```python
env["NAME"]
env.get("NAME", "default")
```

## Contents

- Keys and values are strings.
- The dictionary contains the entries of the step's `env:` map, with templates rendered. Nothing else is added.
- The dictionary is frozen. Assigning to it, such as `env["REGION"] = "x"`, fails with
  `cannot insert into frozen hash table`.
- A standalone script has no step, so `env` is empty.

The dictionary is not a copy of the process environment, so `"HOME" in env` is `False` unless the step declares `HOME`.
Programs started with [`exec.run`](/functions/automation/exec.run) and the other process-running functions inherit the
effective execution environment on their own, including authentication and command environment settings. Pass
extra variables to one call with that function's `env` argument.

## Dictionary methods

The usual dictionary operations apply:

- **`env[name]`**
  The value of a declared input. A name that is not declared fails with a key error.
- **`env.get(name, default)`**
  The value of a declared input, or 
  `default`
   when it is not declared. Without 
  `default`
  , the fallback is 
  `None`
  .
- **`name in env`**
  Whether the input is declared.
- **`env.keys()`, `env.items()`, `len(env)`**
  Enumerate the declared inputs.

## Examples

### Read declared inputs in a custom command

```yaml
commands:
  - name: show-env
    description: Print declared env
    steps:
      - name: show
        type: script
        interpreter: starlark
        env:
          REGION: us-east-2
          NAME: "{{ \"demo\" | upper }}"
        script: |
          print(env["REGION"], env["NAME"])
          print(env.get("MISSING", "default-value"))
          print(sorted(env.keys()))
          print("HOME" in env)
```

```text
us-east-2 DEMO
default-value
["NAME", "REGION"]
False
```

### Choose a value from an input in a workflow

```yaml
workflows:
  deploy:
    steps:
      - name: choose
        type: script
        interpreter: starlark
        env:
          REGION: us-east-1
        script: |
          output = "blue" if env["REGION"] == "us-east-1" else "green"
```

### Declare the input once and use it in parallel tasks

```yaml
workflows:
  regions:
    steps:
      - name: fanout
        type: script
        interpreter: starlark
        env:
          REGION: us-east-1
        script: |
          def api():
              return {"service": "api", "region": env["REGION"]}

          def worker():
              return {"service": "worker", "region": env["REGION"]}

          output = steps.parallel(functions = [api, worker])
```

The dictionary is already frozen, so parallel tasks read it safely.

### Pass a value to a child process

```python
result = exec.run(
    ["printenv", "TARGET_REGION"],
    env = {"TARGET_REGION": env.get("REGION", "us-east-1")},
    output = "capture",
)
```

## Related

- [`exec.run`](/functions/automation/exec.run) accepts an `env` argument for one call.
- [`ctx.component`](/functions/automation/ctx.component) exposes the environment configured for a component.
- [`cli.flag`](/functions/automation/cli.flag) binds a flag to an environment variable in a standalone program.
- [Atmos Automation Language](/automation/language) and the [script step](/steps/type/script#working-directory-and-environment)
