This question already has an answer here:

I think it would be useful/convenient if the current directory determined one's shell environment. This would mean that the command

cd /my/projects/foo

..., for example, would not only set the current working directory (and update $PWD, $OLDPWD, $dirstack, etc.), but would also adjust a host of other environment elements (shell options, variables, functions, aliases, etc.) in a manner appropriate to the contents of the new PWD.

At first blush this seems like a relatively simple thing to implement, especially with zsh, since it already supports a chpwd hook, and the $chpwd_functions array. But, as they say, the devil is in the details1.

Therefore, before plunging into rolling my own, I thought I'd ask: is anyone aware of a mature implementation of this idea?

Alternatively, besides chpwd et al., does zsh provide other tools that would be helpful towards implementing such a thing? In particular, does it provide any support for encapsulating/saving/restoring environments? (I'm thinking of something in the vein of R's environment objects, but encompassing not only variables, but also, e.g., aliases, options, etc.)

FWIW, I am aware of Python's virtualenv, which shares some features with the idea described in this post, but of course, this is limited to Python-related settings, however. Furthermore, it creates a new "state variable", if you will, the "current virtual environment", orthogonal (rather subsumed under) the "current working directory" state variable.

1 Once one looks into the matter more carefully one quickly meets some non-trivial questions. For example: if cd'ing to /my/projects/foo activates a custom environment, what exactly happens after cd /my/projects/foo/modules/bar? Can we have nested custom environments, demarcated by the filesystem's tree structure? What about symlinks? E.g., what if /my/projects/foo/modules/bar is actually a symlink to /my/shared/modules/bar? Or, if I execute /my/projects/foo/some_program while $PWD is /tmp, say, what should be the environment of the resulting process? Etc., etc., etc. I don't find these questions necessarily intractable, but I do find them at least not-totally-trivial.

marked as duplicate by muru, Kusalananda Jul 20 at 6:57

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.


There're mature tools designed to set environment variables for a specific directory.

Compared with other tools designed for this, direnv is the best of them. One of the main benefit is that it supports unloading the environment variables when you exit from that directory.

direnv is an environment switcher for the shell. It knows how to hook into bash, zsh, tcsh, fish shell and elvish to load or unload environment variables depending on the current directory. This allows project-specific environment variables without cluttering the ~/.profile file.

What makes direnv distinct between other similar tools:

  • direnv is written in Go, faster compared with its counterpart written in Python
  • direnv supports unloading environment variables when you quit from the specific dir
  • direnv covers many shells

Similar projects

  • Environment Modules - one of the oldest (in a good way) environment-loading systems
  • autoenv - lightweight; doesn't support unloads; slow written in Python
  • zsh-autoenv - a feature-rich mixture of autoenv and smartcd: enter/leave events, nesting, stashing (Zsh-only).
  • asdf - a pure bash solution that has a plugin system
  • You posted this exact same answer on the duplicate question (which is how I found out that they were duplicates). The appropriate action would have been to post the answer on one of the questions and to flag the other question as a duplicate for review. – Kusalananda Jul 20 at 11:46

Not the answer you're looking for? Browse other questions tagged or ask your own question.