> ## Documentation Index
> Fetch the complete documentation index at: https://hitspec.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Environments

> Configure variables for dev, staging, and production with hitspec.yaml, .env files, and system variables.

hitspec supports environment-specific configuration so you can run the same tests against different servers, credentials, and settings without modifying your test files.

## Overview

There are four ways to provide variables:

1. **Inline variables** -- `@var = value` in `.http` files (same for all environments)
2. **Config file** -- `hitspec.yaml` with an `environments` section (per-environment values)
3. **`.env` files** -- standard dotenv files injected with `--env-file`
4. **System environment variables** -- accessed via `{{$VAR}}` or the `$env()` function

<Note>
  Per-environment variables live in **`hitspec.yaml`** under the `environments:`
  key. There is no separate JSON environment file -- `hitspec.yaml` and `.env`
  files are the supported sources.
</Note>

## Inline Variables

Define variables directly in your test file:

```http theme={null}
@baseUrl = https://api.example.com
@token = your-api-token
@timeout = 5000

GET {{baseUrl}}/users
Authorization: Bearer {{token}}
```

This is simple but limited:

* Values are the same regardless of environment
* Secrets are visible in the test file
* Switching environments requires editing the file

Inline variables are best for values that do not change between environments, such as API version paths or test data.

## Config File (hitspec.yaml)

The `hitspec.yaml` config file combines global settings with per-environment
variable sets under the `environments:` key:

```yaml theme={null}
# Global settings
defaultEnvironment: dev
timeout: 30000        # milliseconds (integer)
retries: 0
followRedirects: true
validateSSL: true
verbose: false
headers:
  User-Agent: hitspec/1.0

# Per-environment variables
environments:
  dev:
    baseUrl: https://api-dev.example.com
    token: dev-token
  staging:
    baseUrl: https://api-staging.example.com
    token: "${STAGING_TOKEN}"   # expands from the OS environment
  prod:
    baseUrl: https://api.example.com
    token: "${PROD_TOKEN}"
```

Select the environment with the `--env` flag (defaults to `dev`):

```bash theme={null}
# Uses the default environment
hitspec run tests/

# Use staging
hitspec run tests/ --env staging

# Use production
hitspec run tests/ --env prod
```

Your test files reference variables without knowing which environment is active:

```http theme={null}
GET {{baseUrl}}/users
Authorization: Bearer {{token}}

>>>
expect duration < {{timeout}}
<<<
```

hitspec searches for config files in this order:

1. `hitspec.yaml`
2. `hitspec.yml`

You can also specify a config file explicitly:

```bash theme={null}
hitspec run tests/ --config ./config/hitspec.yaml
```

<Note>
  Inside `hitspec.yaml`, environment values can reference OS environment variables
  with shell-style `${VAR}` syntax -- ideal for keeping secrets out of the file
  and injecting them from CI secrets.
</Note>

## .env Files

Pass a standard dotenv file with the `--env-file` flag to inject additional variables:

```bash theme={null}
hitspec run tests/ --env staging --env-file .env.staging
```

The `.env` file uses standard `KEY=VALUE` format:

```
API_TOKEN=staging-secret-token
DB_PASSWORD=staging-db-pass
```

These values are exported to the process environment, so they're available via
`${VAR}` in `hitspec.yaml` and via `{{$VAR}}` / `{{$env(VAR)}}` in your requests.

## System Environment Variables

Reference system environment variables in your test files. Two forms are supported:

```http theme={null}
# Simple form -- direct lookup
@token = {{$API_TOKEN}}

# Function form -- supports an optional default value
@token = {{$env(API_TOKEN)}}
@dbUrl = {{$env(DATABASE_URL, sqlite://./test.db)}}
```

The second argument to `$env()` is an optional fallback used when the variable is unset.

<Warning>
  The dotted form `{{$env.VAR}}` is **not** supported. Use `{{$VAR}}` or
  `{{$env(VAR)}}`.
</Warning>

In `hitspec.yaml`, use shell-style `${VAR}` syntax instead:

```yaml theme={null}
environments:
  prod:
    token: "${PROD_TOKEN}"
```

## HITSPEC\_ Environment Variables

All major CLI flags can be set via environment variables with the `HITSPEC_` prefix, which is useful in CI/CD pipelines:

| Environment Variable  | CLI Flag        | Description                            |
| --------------------- | --------------- | -------------------------------------- |
| `HITSPEC_ENV`         | `--env`         | Environment to use                     |
| `HITSPEC_ENV_FILE`    | `--env-file`    | Path to .env file                      |
| `HITSPEC_CONFIG`      | `--config`      | Path to config file                    |
| `HITSPEC_TIMEOUT`     | `--timeout`     | Request timeout (duration, e.g. `30s`) |
| `HITSPEC_TAGS`        | `--tags`        | Filter by tags                         |
| `HITSPEC_OUTPUT`      | `--output`      | Output format                          |
| `HITSPEC_OUTPUT_FILE` | `--output-file` | Output file path                       |
| `HITSPEC_BAIL`        | `--bail`        | Stop on first failure                  |
| `HITSPEC_PARALLEL`    | `--parallel`    | Run in parallel                        |
| `HITSPEC_CONCURRENCY` | `--concurrency` | Concurrent requests                    |
| `HITSPEC_QUIET`       | `--quiet`       | Suppress output                        |
| `HITSPEC_NO_COLOR`    | `--no-color`    | Disable colors                         |
| `HITSPEC_PROXY`       | `--proxy`       | Proxy URL                              |
| `HITSPEC_INSECURE`    | `--insecure`    | Skip SSL verification                  |

```bash theme={null}
export HITSPEC_ENV=staging
export HITSPEC_TIMEOUT=60s
export HITSPEC_BAIL=true
hitspec run tests/
```

## Variable Resolution Order

When the same variable name comes from multiple sources, hitspec resolves it in this order (later sources override earlier ones):

1. **`hitspec.yaml` environment** -- values for the active `--env`
2. **Inline variables** -- `@variable = value` in the `.http` file
3. **Captured values** -- `{{requestName.captureName}}` from prior responses

Built-in functions (`$uuid()`, `$timestamp()`, `$env()`, …) and system variables
(`{{$VAR}}`) are evaluated wherever they appear.

<Note>
  Inline variables override `hitspec.yaml` environment values. A `@baseUrl = ...` in
  your `.http` file takes precedence over the `baseUrl` defined for the active
  environment -- remove the inline definition when you want environment-specific
  values to apply.
</Note>

## Best Practices

### Keep Secrets Out of Version Control

Keep secrets in a `.env` file (or your CI secret store) and reference them with
`${VAR}` in `hitspec.yaml`, rather than committing tokens. Add the `.env` file to
`.gitignore`:

```gitignore theme={null}
.env
.env.*
```

Commit a template instead:

```
# .env.example
API_TOKEN=YOUR_TOKEN_HERE
DB_PASSWORD=YOUR_DB_PASSWORD_HERE
```

```yaml theme={null}
# hitspec.yaml (committed -- no secrets)
environments:
  staging:
    baseUrl: https://staging.api.example.com
    token: "${API_TOKEN}"
```

### Use System Variables in CI/CD

<Tabs>
  <Tab title="GitHub Actions">
    ```yaml theme={null}
    env:
      API_BASE_URL: https://staging.api.example.com
      API_TOKEN: ${{ secrets.API_TOKEN }}

    steps:
      - uses: abdul-hamid-achik/hitspec@v1
        with:
          files: tests/
          env: ci
          env-file: .env.ci
    ```
  </Tab>

  <Tab title="Shell">
    ```bash theme={null}
    # Set variables inline
    API_TOKEN=secret hitspec run tests/ --env staging

    # Or export them
    export API_TOKEN=secret
    export DB_PASSWORD=dbpass
    hitspec run tests/ --env staging
    ```
  </Tab>
</Tabs>

### Shared Base Configuration

Reuse YAML anchors in `hitspec.yaml` to share values across environments:

```yaml theme={null}
environments:
  dev:
    baseUrl: http://localhost:3000
    apiVersion: &apiVersion v1
  prod:
    baseUrl: https://api.example.com
    apiVersion: *apiVersion
```

### Environment-Specific Test Behavior

Drive timeouts, retry settings, and other behavioral differences from
environment variables:

```yaml theme={null}
environments:
  dev:
    baseUrl: http://localhost:3000
    timeout: "30000"
    retries: "3"
  prod:
    baseUrl: https://api.example.com
    timeout: "5000"
    retries: "0"
```

```http theme={null}
# @timeout {{timeout}}
# @retry {{retries}}

GET {{baseUrl}}/slow-endpoint

>>>
expect status 200
<<<
```

## Recommended Project Structure

```
my-api-tests/
├── hitspec.yaml        # Global config and environment definitions (committed)
├── .env                # Secret values (gitignored)
├── .env.example        # Template for team members (committed)
├── .gitignore
├── tests/
│   ├── auth.http
│   ├── users.http
│   └── orders.http
└── schemas/
    └── user.json
```

## Troubleshooting

<Accordion title="Variable not found">
  ```
  Error: variable "baseUrl" not found
  ```

  1. Check that `hitspec.yaml` defines the variable under the active environment.
  2. Verify the `--env` flag matches an environment key: `hitspec run tests/ --env dev`.
  3. Check for typos in variable names (they are case-sensitive).
</Accordion>

<Accordion title="Environment not found">
  ```
  Error: environment "staging" not found
  ```

  1. Add a `staging:` key under `environments:` in `hitspec.yaml`.
  2. Check for typos in the environment name.
</Accordion>

<Accordion title="System variable not set">
  ```
  Error: environment variable "API_TOKEN" not set
  ```

  1. Export the variable: `export API_TOKEN=xxx`
  2. Set it inline: `API_TOKEN=xxx hitspec run tests/`
  3. Pass it via a dotenv file: `hitspec run tests/ --env-file .env`
  4. In CI/CD, add it to your secrets and pass it to the workflow.
  5. Use a default value: `{{$env(API_TOKEN, fallback-value)}}`
</Accordion>
