How to make cursor agent to pick up direnv environment?

I’m using direnv for every project to configure its environments like compiler versions and other build dependencies. It’s configured in my .zshrc via eval $(direnv hook zsh). I run cursor from command-line from inside of the project with direnv loaded before launching cursor.

Neither built-in terminal nor cursor agent don’t load direnv environment (while loading other zsh configurations such as prompt, colors etc). How to make cursor actually run enter direnv shell in agent terminal calls?

It’s tough to diagnose your issue without seeing more details, but I use direnv a lot on my Mac and I’ve never had this problem.

My setup might be a bit different because I changed my Mac’s default shell to the latest version of Bash (installed with Homebrew because MacOS’s default bash version is very outdated), so I use .bashrc instead of .zshrc. I doubt that’s the reason, but I do think it’s noteworthy.

The direnv VS Code extension is life-changing for any direnv users. Install it from here Open VSX Registry
It instantly shows a popup with a message like “direnv: /path/to/.envrc is blocked” and an “allow” button whenever the .envrc file is changed. This will make all direnv-related work 100x more efficient because you don’t have to run “direnv allow” in the terminal every time you modify the .envrc file and you’ll never forget to run “direnv allow” ever again. Most of my problems with direnv in the past have been simply due to forgetting to run “direnv allow” after modifying one line of the .envrc file.

All the .envrc files in my project roots tend to look something like this:

# *** Initialize direnv settings
# The "source_up_if_exists" is the important bit here. It tells direnv to search for and use other .envrc files in one or more parent directories.
source_up_if_exists

# *** Python
# Set python version with pyenv
layout pyenv 3.13.2

# *** Direnv VSCode extension setup
# export EDITOR="code --wait"; # In the past, this fixed a problem I had with the direnv VSCode extension. It doesn't seem to be an issue anymore, but try un-commenting this if you still have issues.

# *** Paths to project subdirectories
# Set the paths to the project subdirectories
export PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"; # This automatically creates the absolute path to the directory containing this .envrc file, regardless of location. All other paths for direnv are built off of this one.
export GIT_CLONES="$PROJECT_ROOT/git_clones"; # Base directory for all my cloned git repositories is here, organized by domain. For example, I clone the https://gitlab.com/graphviz/graphviz repository to "$GIT_CLONES/gitlab.com/graphviz/graphviz"
export DOCS="$PROJECT_ROOT/docs"; # Documentation for this project
export SETUP="$PROJECT_ROOT/setup"; # All my scripts for automatically managing this monorepo are in here.

I generally run all my scripts in the terminal using something like
source "$SETUP/git/setup_git_hooks.sh" instead of ./setup/git/setup_git_hooks.sh. Because the terminal considers all these paths to be absolute paths. This allows me to run any script from any working directory and never worry about crafting the proper relative paths from my terminal’s current location.

Also, make sure that you put export before any variables you want to access. The first line below will generally not work, but the second one will.

PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)";
export PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)";

Also, I have the following in my “User Rules” for Cursor because the agents would sometimes use the wrong shell instead of Bash. Adding something like this might help.

# Shell
* Always use Bash as the default shell

You can test this by entering Print the PROJECT_ROOT environment variable into Cursor’s Agent chat and see how it responds. For context, I’m currently using Claude 3.7 Sonnet. My chat responded with “I’ll help you print the PROJECT_ROOT environment variable. Let me run a command to display its value.”

echo $PROJECT_ROOT;

and it printed the correct path.

Hopefully this helps. Let me know if you have any other questions.

2 Likes