Background

Its almost given that for any Python project I have build in the past 2 year I have been using uv as a way to manage dependencies and virtual environments. Using uv has drastically improved my development experience and as an added bonus improved my development speed.

That being I was tired of running the same command over and over again:

source .venv/bin/acttivate

This is not a big problem but a problem none the less, for each project, multiple times a day I was manually running this command, either auto filling the terminal shell or looking it the past history and running it. On multiple occasional I forgot to run it and it broke the magical zoned-it-zone.

Until recently when I learnt about autoenv.

Virtual Environments

Anyone who has worked with Python knows how hard it is to easily setup a virtual environments with the correct version of Python runtime installed and activated in the current active shell. This problem has plagued Python ecosystem for decades and was recently solved elegantly by uv Still it didn’t solve the problem of requiring to manually run the command to active the virtual environment each time you open a terminal and start running the code in that virtual environment.

ZSH Solution

I have installed zsh in my terminal without even thinking about it, for me its the default shell. Within zsh there lies a function that runs a set of commands when the directory is changed. The function is call chpwd.

So anytime you jump into a new directory, zsh runs certain commands and if the conditions are met in the directory that the user has changed to then the commands are run in the current shell.

While this approach is zsh native and has no other dependencies, it is still not an ideal solution.

autoload

This where I prefer using autoload, this tool does one thing and one thing well, which is to run commands when the directory is changed.

All the commands are located in the .env file at the root of the project directory. This allows me to simple add the command source .venv/bin/activate and just like that my problem of manually triggering the Python Virtual Environments is now over.

Pros

  • Its quite declarative on which commands are going to be running
  • Transparency, I know which commands are going to run in this project as I live to limit the exposure of this tool to a limited to per project.

Cons

  • Whole teams need to onboarded to this new way of working
  • If the .env file already exists like in js and go environment, then a consensus needs to be made on what is contained within the .env file.

Extra pointers

You can add pretty much any commands to the autoenv. Since I’m already a user of the package direnv, managing the environment variables has been simple and effective. But you can add commands like ls or cat. On changing directory running the cat command on TODO list or progress.md can and does make it easier to bootstrap memory and start working on the project.

Implantation Images