I’ve used direnv for env variables forever. Just discovered layout python:

# .envrc
layout python python3.12

cd into the directory, direnv:

  • Creates a venv if one doesn’t exist (named .direnv/python-3.12).
  • Activates it.
  • Sets VIRTUAL_ENV and adjusts PATH.

cd out, direnv undoes all of it. No more source .venv/bin/activate. No more forgetting to deactivate and polluting the next project’s shell.

For Node: layout node (uses the system node). For Go: layout go (sets GOPATH to a project-local dir).

The catch: direnv layouts create dirs like .direnv/ that you should .gitignore. Also, if you use IDEs that do their own venv detection, they might not find the direnv-managed venv. My fix: symlink a top-level .venv to the direnv-managed one.

# .envrc
layout python python3.12
ln -sf "$VIRTUAL_ENV" .venv 2>/dev/null

Now the IDE finds .venv/bin/python and direnv keeps the shell sane. Best of both.