direnv Cheat Sheet
Overview
direnv is an environment switcher for the shell that loads and unloads environment variables depending on the current directory. When you cd into a directory containing an .envrc file, direnv automatically loads the defined environment variables. When you leave the directory, it unloads them, restoring the previous environment state.
direnv supports bash, zsh, fish, tcsh, and elvish shells. It provides a security model where new or modified .envrc files must be explicitly approved before they are loaded. direnv integrates with Nix for reproducible development environments and supports loading .env files, PATH modifications, Python virtualenvs, and custom functions through its stdlib.
Installation
# macOS
brew install direnv
# Ubuntu/Debian
sudo apt install direnv
# Arch Linux
sudo pacman -S direnv
# Fedora
sudo dnf install direnv
# From source (Go)
go install github.com/direnv/direnv@latest
# Nix
nix-env -i direnv
# Verify
direnv version
Shell Hook Setup
# Bash - add to ~/.bashrc
eval "$(direnv hook bash)"
# Zsh - add to ~/.zshrc
eval "$(direnv hook zsh)"
# Fish - add to ~/.config/fish/config.fish
direnv hook fish | source
# Tcsh - add to ~/.cshrc
eval `direnv hook tcsh`
Core Commands
| Command | Description |
|---|---|
direnv allow | Approve the current .envrc file |
direnv deny | Deny the current .envrc |
direnv reload | Reload the current environment |
direnv status | Show direnv status and loaded files |
direnv edit | Open .envrc in editor and allow on save |
direnv prune | Remove old allowed entries |
direnv fetchurl <url> | Fetch and cache a URL |
direnv stdlib | Print the stdlib available in .envrc |
Basic Usage
# Create an .envrc file
echo 'export API_KEY="sk-abc123"' > .envrc
# Allow the file (required for security)
direnv allow
# Environment is now loaded
echo $API_KEY # sk-abc123
# Leave the directory - environment is unloaded
cd ..
echo $API_KEY # (empty)
# Edit .envrc (opens in $EDITOR, auto-allows on save)
direnv edit .
.envrc Examples
Basic Environment Variables
# .envrc
export DATABASE_URL="postgres://user:pass@localhost:5432/mydb"
export REDIS_URL="redis://localhost:6379"
export API_KEY="sk-abc123"
export NODE_ENV="development"
export DEBUG="app:*"
Loading .env Files
# .envrc
dotenv
# Or load a specific .env file
dotenv .env.development
# Or load from a specific path
dotenv_if_exists .env.local
PATH Modifications
# .envrc
# Add project bin to PATH
PATH_add bin
PATH_add node_modules/.bin
PATH_add .venv/bin
# Add absolute path
path_add PATH /opt/custom/bin
# Prepend to other variables
path_add LD_LIBRARY_PATH /opt/custom/lib
Python Virtual Environments
# .envrc - Auto-create and activate virtualenv
layout python3
# Specific Python version
layout python python3.12
# Use existing virtualenv
source .venv/bin/activate
# Or with pyenv
layout pyenv 3.12.3
# Poetry integration
layout poetry
Node.js
# .envrc
# Use project Node modules
layout node
# Use specific Node version with nvm
use nvm 20
# Use volta
use volta
Ruby
# .envrc
layout ruby
Stdlib Functions
# .envrc
# Check if a command exists
has docker && export USE_DOCKER=true
# Watch a file for changes (reload when it changes)
watch_file Gemfile.lock
watch_file package-lock.json
watch_file requirements.txt
# Source another file
source_env .envrc.local
source_env_if_exists .envrc.secrets
# Load env from URL
source_url "https://example.com/envrc" "sha256-HASH"
# Expand variables
expand_path ~/projects/lib
# Log messages
log_status "Loading development environment"
log_error "Missing required configuration"
# Strict mode
strict_env # Error on undefined variables
direnv_load # Load from a command's output
Security Model
# When .envrc is new or modified:
# direnv: error .envrc is blocked. Run `direnv allow` to approve its content.
# Allow current directory
direnv allow
# Allow specific path
direnv allow /path/to/.envrc
# Deny/block an .envrc
direnv deny
# Check what's allowed
direnv status
# Prune stale allowed entries
direnv prune
Advanced Usage
Nix Integration
# .envrc - Use Nix for reproducible dev environment
use nix
# Or with flakes
use flake
# Custom Nix shell
use nix -p nodejs python3 postgresql
Shared Team Configuration
# .envrc (committed to git)
dotenv_if_exists .env # Shared defaults
dotenv_if_exists .env.local # Personal overrides (gitignored)
source_env_if_exists .envrc.local # Personal extensions (gitignored)
# .gitignore
.env.local
.envrc.local
Docker Compose Integration
# .envrc
export COMPOSE_PROJECT_NAME="myproject"
export COMPOSE_FILE="docker-compose.yml:docker-compose.dev.yml"
export DOCKER_BUILDKIT=1
dotenv
AWS Profile Switching
# .envrc
export AWS_PROFILE="production"
export AWS_REGION="us-east-1"
export AWS_DEFAULT_REGION="us-east-1"
# Or load from AWS SSO
aws sso login --profile production 2>/dev/null || true
Terraform Workspace
# .envrc
export TF_WORKSPACE="production"
export TF_VAR_region="us-east-1"
export TF_VAR_environment="prod"
dotenv_if_exists .env.terraform
Conditional Loading
# .envrc
if [ "$(uname)" = "Darwin" ]; then
export OPENSSL_DIR=$(brew --prefix openssl@3)
fi
if has docker; then
export TESTCONTAINERS_DOCKER_SOCKET_OVERRIDE=/var/run/docker.sock
fi
Configuration
# direnv.toml (global config)
# Location: ~/.config/direnv/direnv.toml
# Allow all .envrc in trusted directories
[whitelist]
prefix = [ "/home/user/work" ]
exact = [ "/home/user/project/.envrc" ]
# Custom .envrc filename
[global]
load_dotenv = true # Auto-load .env files
strict_env = false # Don't error on undefined vars
warn_timeout = "5s" # Warn if loading takes too long
# ~/.config/direnv/lib/*.sh
# Custom stdlib extensions available in all .envrc files
# Example: ~/.config/direnv/lib/use_nvm.sh
use_nvm() {
local node_version=$1
nvm_sh=~/.nvm/nvm.sh
if [[ -s $nvm_sh ]]; then
source $nvm_sh
nvm use $node_version
fi
}
Troubleshooting
| Issue | Solution |
|---|---|
.envrc is blocked | Run direnv allow to approve the file |
| Variables not loading | Check shell hook is added; restart terminal |
| Slow loading | Minimize .envrc complexity; use watch_file sparingly |
Variables persist after cd | Ensure shell hook is properly installed |
.env not loading | Add dotenv to .envrc; run direnv allow |
| Editor not opening | Set $EDITOR environment variable |
| Nix integration fails | Install Nix first; ensure use nix syntax is correct |
| Virtualenv not activating | Use layout python3 instead of manual activation |