Skip to content

direnv: Per-Directory Environment Variables for Python

direnv is a shell extension that loads and unloads environment variables based on the current working directory. It reads a per-directory .envrc file when entering a folder and reverts the environment when leaving. Although direnv is language-agnostic, it is widely used in Python projects to activate virtual environments and export project-specific settings without polluting the global shell.

Key Features

  • Loads variables from .envrc on cd into a directory and unloads them on cd out
  • Provides a stdlib of layout helpers, including layout python, layout python3, layout pyenv, and layout pipenv
  • Supports bash, zsh, fish, tcsh, elvish, and PowerShell
  • Requires explicit per-directory authorization with direnv allow before any new .envrc runs

Installation

direnv is distributed through most package managers:

brew install direnv     # macOS / Linux
sudo apt install direnv # Debian / Ubuntu
nix-env -i direnv       # Nix

After installation, add the hook to the shell startup file:

# bash (~/.bashrc)
eval "$(direnv hook bash)"

# zsh (~/.zshrc)
eval "$(direnv hook zsh)"

# fish (~/.config/fish/config.fish)
direnv hook fish | source

The hook runs on every prompt and applies any pending .envrc changes after the directory is authorized.

Activating a Python Virtual Environment

The simplest pattern sources an existing venv or virtualenv:

.envrc
source .venv/bin/activate

The built-in layout python helper goes one step further and creates the environment if it does not exist:

.envrc
layout python python3.12

This places the environment under .direnv/python-3.12/ and activates it whenever the directory is entered.

Using direnv with uv

direnv has no built-in layout_uv helper as of the current release, but two short patterns cover most projects.

The first activates the uv-managed .venv directly:

.envrc
source .venv/bin/activate

The second sets the project environment path explicitly so activation works under any layout:

.envrc
export UV_PROJECT_ENVIRONMENT="$PWD/.venv"
source "$UV_PROJECT_ENVIRONMENT/bin/activate"

For details on overriding the venv location, see How to customize uv’s virtual environment location.

Pros

  • Project-scoped variables without manual source or unset
  • Works with any shell and any tool, not just Python
  • Composes with venv, virtualenv, pyenv, conda, and uv

Cons

  • Requires a one-time shell hook installation
  • Each new or modified .envrc must be authorized with direnv allow before it loads
  • No native uv layout yet; uv users rely on source .venv/bin/activate or UV_PROJECT_ENVIRONMENT

Learn More

Last updated on