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
.envrconcdinto a directory and unloads them oncdout - Provides a stdlib of layout helpers, including
layout python,layout python3,layout pyenv, andlayout pipenv - Supports bash, zsh, fish, tcsh, elvish, and PowerShell
- Requires explicit per-directory authorization with
direnv allowbefore any new.envrcruns
Installation
direnv is distributed through most package managers:
brew install direnv # macOS / Linux
sudo apt install direnv # Debian / Ubuntu
nix-env -i direnv # NixAfter 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 | sourceThe 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:
source .venv/bin/activateThe built-in layout python helper goes one step further and creates the environment if it does not exist:
layout python python3.12This 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:
source .venv/bin/activateThe second sets the project environment path explicitly so activation works under any layout:
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
sourceorunset - 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
.envrcmust be authorized withdirenv allowbefore it loads - No native uv layout yet; uv users rely on
source .venv/bin/activateorUV_PROJECT_ENVIRONMENT