I was setting up a new Python project with direnv to manage environment variables. Suddenly python wasn’t found, even though it was definitely installed. Here’s what happened and how I fixed it.

The problem Link to heading

I’d been using direnv happily for months, managing API keys and secrets per project. Then I added a custom PATH in my .envrc and broke everything:

# This was the problem
export PATH=/some/custom/path

Running which python returned nothing. Even python3 was gone. My shell couldn’t find Python at all.

Debugging the issue Link to heading

First, check what direnv is doing:

direnv status

This shows you:

  • Whether direnv is loaded for the current directory
  • What .envrc file it’s using
  • If there are any errors

In my case, it showed PATH had been completely replaced, not augmented.

My .envrc setup Link to heading

Here’s a proper .envrc that doesn’t break Python:

# Load Python virtual environment
layout python3

# Or if using uv (which I prefer now)
source .venv/bin/activate

# Add custom paths without clobbering existing PATH
PATH_add bin
PATH_add scripts

# Environment variables
export DATABASE_URL="postgresql://localhost/mydb"
export DEBUG=true
export API_KEY=secret-key-here

The key difference:

# Bad - replaces entire PATH
PATH=/some/path

# Good - appends to PATH
PATH_add /some/path

direnv + pyenv + uv interaction Link to heading

These three tools work well together if you load them in the right order. In ~/.zshrc:

# pyenv first (manages Python versions)
eval "$(pyenv init -)"

# direnv second (manages per-project env)
eval "$(direnv hook zsh)"

# uv doesn't need shell integration

When entering a project directory:

  1. pyenv sets the Python version (from .python-version)
  2. direnv loads .envrc (which might activate a venv)
  3. uv uses whatever Python is active

One gotcha: if you use layout python3 in .envrc, it will create a virtualenv using the Python on your PATH. Make sure that’s the right version before running direnv allow.

The fix Link to heading

After editing .envrc, you must allow it:

direnv allow

Verify Python is found:

which python
# Should show: /path/to/your/project/.venv/bin/python

python --version
# Should match what you expect

When direnv is the right tool Link to heading

direnv works well for:

  • Project-specific environment variables (API keys, database URLs)
  • Automatically activating virtual environments when I cd into a project
  • Setting up development vs production configs (via different .envrc files)

direnv is not ideal for:

  • Secrets that need rotation (use a secrets manager)
  • System-wide PATH changes (put those in your shell config)
  • Temporary variables (just export them in your current shell)

The brilliant thing about direnv is that it automatically unloads when you leave the directory. No more forgetting to deactivate virtual environments.

Further reading Link to heading