---
title: direnv
description: Load validated environment variables into your shell with direnv and varlock
---

import { Steps } from "@astrojs/starlight/components";

[direnv](https://direnv.net/) is a shell extension that automatically loads and unloads environment variables when you enter and leave a directory. By combining it with varlock, you can get validated, schema-driven environment variables loaded directly into your shell session.

:::tip[Consider a deeper integration]
For projects where you control the codebase, using one of varlock's [framework integrations](/integrations/overview/) or the [JavaScript / Node.js integration](/integrations/javascript/) is usually a better fit than direnv. Those integrations wire validation, type safety, and leak protection directly into your build and runtime — rather than relying on shell-level injection. You can also use [`varlock run`](/reference/cli/#run) to inject env vars into any process without needing direnv. direnv is most useful when you need env vars available in your shell session itself, or when working with tools that cannot be launched via `varlock run`.
:::

## How it works

direnv works by executing a `.envrc` file in your project directory and capturing any exported variables into the current shell. Varlock's `--format shell` flag outputs your resolved env vars as `export KEY=VALUE` lines that direnv can capture via `eval`.

```bash
# .envrc
eval "$(varlock load --format shell)"
```

When you `cd` into your project, direnv runs this command and exports all your validated environment variables into the shell.

## Setup

<Steps>

1. **Install direnv**

   Follow the [official direnv installation guide](https://direnv.net/docs/installation.html) for your platform and shell, then hook it into your shell profile. For example, for bash:

   ```bash
   echo 'eval "$(direnv hook bash)"' >> ~/.bashrc
   ```

2. **Create a `.envrc` file** in your project root

   ```bash title=".envrc"
   watch_file .env .env.*
   eval "$(varlock load --format shell)"
   ```

   The `watch_file` line tells direnv to re-evaluate whenever any of your `.env` files change. Note that **new files added after the initial load will not be watched until you run `direnv reload`** — but this is rarely a concern since adding new env files is uncommon.

   :::caution[Imported files outside the project directory]
   If your `.env` files [import](/guides/import/) other files from outside the current directory, those external files will **not** be watched automatically. You would need to add additional `watch_file` entries for them, or run `direnv reload` manually after changing them.
   :::

3. **Allow the `.envrc` file**

   ```bash
   direnv allow
   ```

</Steps>

## How it looks

Once set up, when you `cd` into your project directory, direnv automatically loads your varlock-validated environment:

```bash
$ cd my-project
direnv: loading .envrc
direnv: export +API_URL +DB_PASS +PORT
```

And when you leave the directory, those variables are automatically unloaded.

## Skip undefined values

By default, varlock outputs an empty assignment for undefined optional variables (e.g. `OPTIONAL_VAR=""`). If you prefer to skip undefined values entirely, use the `--compact` flag:

```bash title=".envrc"
watch_file .env .env.*
eval "$(varlock load --format shell --compact)"
```

## Troubleshooting

:::caution[direnv strict mode]
Some shells or direnv configurations run `.envrc` files in strict mode (`set -euo pipefail`). If `varlock load` exits with a non-zero code (e.g. due to a validation error), direnv will halt and show an error. This is intentional — it prevents your shell from loading a broken environment.
:::

:::tip[Loading errors]
If your environment fails validation, run `varlock load` directly in your terminal to see the full colorized output and error details before direnv loads it.
:::
