Solveddirenv fish: direnv is no longer triggered on shell creation

Describe the bug
direnv does not execute on creation of a new fish shell (or tmux pane or window, etc.) -- I have to hit 'enter' once to trigger it. Triggers fine when changing directories.

To Reproduce
Steps to reproduce the behavior:

  1. bash
  2. cd into a directory with a whitelisted .envrc file
  3. fish

Steps to reproduce the behaviour via tmux:

  1. Use fish
  2. Use tmux, with either of the recommended configurations from the wiki
  3. cd into a directory with a whitelisted .envrc file
  4. Create a new tmux pane or window

Expected behavior
direnv should immediately trigger and load the environment in the new fish shell / tmux pane/window. It does not.

Environment

  • OS: nixos 20.03.git.a21c2fa (Markhor)
  • Shell: fish 3.0.2
  • Direnv version: 2.21.2

Additional context
This issue was essentially caused by #512, which solved a smaller issue (direnv not un/loading when changing directories using alt-left/right), and then later this was not fixed by #549, which solved a larger issue cased by #512 (a general 1-command "lag" on direnv activation when using fish).

Incidentally: that first issue is also back after #549; direnv no longer un/loads when changing directories in fish using alt-left/right. I feel like you need regression tests, although unhelpfully I have no clue how you'd instrument them for something like this :P.

if fish_preexec is the only thing that fires on changing directories with alt-left/right, and fish_prompt is the only thing that fires on creation of a new shell, then it seems like perhaps both need to be hooked?

13 Answers

✔️Accepted Answer

I'm chiming in as a fish user, but I didn't know about the directory arrow shortcuts before reading this issue. I also would vote for option 2. My mental model of direnv has been "inside of this directory, I have this environment". I would even vote for 1, but I think consistency with other shells is desirable. In any case, using the directory history navigation feels like a shortcut for "cd", and so treating it just like that seems most consistent. The only case it seems like it would matter is if the prompt were derived from direnv-exported variables, in which case it feels like 2 is the right behavior and 3 is wrong.

That said, all options fix the thing I care about: we need to run direnv on shell load. Easy enough to work around in config.fish:

direnv hook fish | source
direnv export fish | source

Other Answers:

So looking at this in relation to #614, I think that probably the solution for this would be to change the fish hook so that it executes --on-event fish_prompt again, but also --on-variable PWD. In my experiments, this combination means that it will run when you use alt-arrows to change directory, as well as at the initial prompt.

It does have the slight downside of running the hook twice when you manually cd, (once when the directory changes, and once when it comes back to a prompt), but the prompt is needed for it to work the first time, when the new shell begins.

Now, that actually could be fixed by running the hook immediately upon hook installation, and perhaps that is what we should do for fish. That is, normally only run the hook when PWD changes, and just kick it once on installation to avoid the other issue(s).

One minor drawback to that is that you would no longer be able to pre-empt direnv in a compound command. That is, a command like cd /somedir; something would now load the correct direnv for /somedir before something ran, whereas now you only get the new environment after something ran.

Otherwise, the only way to get this working is to do something like a prompt hook that triggers a PWD hook (to handle alt-arrow history) and then a pre-exec hook that disables the PWD hook so that it doesn't run mid-commandline. (That's actually easier to make happen than it sounds; fish is actually pretty nice in this one area.)

Okay, so I've experimented a bit with two variations on this. In one, direnv acts like in any other shell, except that reloads are immediately triggered whenever you us the history arrows. In another, it's almost the same, except that if you use the history arrows you instead get the reload triggered once you actually enter a command (via pre-exec). In short, there are three possibly-viable ways to handle it:

  • Option 1: trigger any time the directory changes, plus first installation of the hook
    • Pros: seamless and simple
    • Cons: absolutely no escape from direnv, even in compounds; behavior is vastly different from other shells
  • Option 2: trigger at prompt, plus immediately during arrow-based directory changes
    • Pros: more like other shells, except for the added feature
    • Cons: if you have something complex and slow it might take a while??
  • Option 3: trigger at prompt, but also before executing a command if you've used the arrows to change directories
    • Pros: doesn't run direnv till you stop hopping around
    • Cons: seems prone to surprises if you arrow to a different directory, then have "surprise! you thought you were ready to run your command, but now it is I, direnv!" interrupt

I'm personally inclined to option 2, though you can argue that some of my cons could be considered pros and vice versa. I do have a draft version of option 2 working in my fish shell right now (as ~/.config/fish/conf.d/direnv.fish, that looks like this:

# Replaces 'eval (direnv hook fish)'

function __direnv_export_eval --on-event fish_prompt;
    # Run on each prompt to update the state
    /absolute/path/to/direnv export fish | source;

    # Handle cd history arrows between now and the next prompt
    function __direnv_cd_hook --on-variable PWD;
        # ensure any output overwrites the prompt instead of going after it
        echo -ne '\r'
        # run the outer function to apply any changes
        __direnv_export_eval
    end

    function __direnv_disable_cd --on-event fish_preexec;
        # Once we're running commands, stop monitoring cd changes
        # until we get to the prompt again
        functions --erase __direnv_cd_hook
    end
end

So it's something y'all can try out and see what you think. (If you want to see what option 1 is like, you can remove the __direnv_disable_cd function, and maybe the echo. Option 3 is harder to implement, though I did try it at one point.)

@zimbatm I'll work on a PR.

Related Issues:

12
direnv fish: direnv is no longer triggered on shell creation
I'm chiming in as a fish user but I didn't know about the directory arrow shortcuts before reading t...
752
nvm .nvmrc example?
If you're currently using the Node version you want for .nvmrc you can run this command: node -v > ....
744
nvm -bash: nvm: command not found
I had the same issue until I added the following lines to my .bash_profile Running terminal in Mac O...
627
nvm nvm install node fails to install on macOS Big Sur M1 Chip
For anything under v15 you will need to install node using Rosetta 2 You can do this by running the ...
294
rbenv 'find_spec_for_exe': can't find gem bundler (>= 0.a) with executable bundle (Gem::GemNotFoundException)
Can you try with gem i bundler -v 1.17.3 and bundle i on your project directory? ...
287
nvm How to uninstall nvm?
@mibamur There is no need for such emphasis in your comments And it is probably better to use the $N...
179
nvm NVM is not compatible with the npm config "prefix" option warning (OS X)
nvm unalias default worked for me! Much appreciated @MwumLi 🍻 Split off from #855 ; see that issue ...
132
powerline Update MacOS to Mojave, then vim get error with powerline
SOLUTION!! Figure out your current vim version Mine was not compiled with homebrew but was the defau...
130
nvm NVM fails to load within nested shell
For me Operating system and version: macOS High Sierra 10.13.1 (17B48) nvm debug output: nvm ls outp...
118
screenFetch awk: fatal: cannot open file `proc/fb' for reading on Ubuntu 18.04 for Windows 10
Downlode the latest version from here wget -O screenfetch-dev https://git.io/vaHfR Then sudo rm /usr...
100
nvm "nvm use" not persisting
nvm use isn't meant to persist - it's only for the lifetime of the shell Sorry I'm sure this is a du...
88
nvm nvm is not compatible with the "PREFIX" environment variable: currently set to "/usr/local"
No need to unset anything.. This behavior happens when you have more than 1 installation of npm/yarn...
65
wslu Cannot create directory "//.cache": Permission denied
Hello Here an improved version Background Information: Build: 17763 WSL: Ubuntu 18.04.03 Version: ws...
62
nvm How to update npm?
nvm install-latest-npm Attempt to upgrade to the latest working npm on the current node version ...
62
nvm nvm prefix error appears in VS Code terminal only when default alias is present
I think i see the problem - you don't have a system node installed Operating system and version: Mac...
44
rbenv yarn shim can't seem to find installed yarn
The yarn shim was added to rbenv because one of the Ruby versions has for some reason a yarn executa...
37
shelljs 0.8.3 high severity vuln
I'm in communication with Snyk right now Node version (or tell us if you're using electron or some o...
30
liquidprompt ERROR: Can't get value of subfeature temp1_input: Can't read
I sympathize with @dolmen but the proper fix is to fix the lm-senors so it ignores the troublesome c...
29
DietPi ping: socket: Operation not permitted
This seems to be working here ADMIN EDIT Solution Read more https://fedoraproject.org/wiki/Changes/E...
19
nvm nvm install fails complaining about prefix, despite not being set
I had this issue for the past week and I finally sat down and took two hours to fix this Here is wha...
18
nvm .nvmrc for projects
I would pay 2$ if somebody implements this feature. It would be nice if we had a .nvmrc file for a p...
17
shellcheck SC1090/SC1091: sourcing should find files relative to script
@koalaman I can see the argument that the behaviour as it stands could be useful in some edge cases ...
16
babashka clojure.core.match
Just chiming in to say I'm also interested in using clojure.core.match with babashka! ...
16
nvm sourcing nvm.sh is slow even with --no-use
I use this for zsh: I start up a lot of terminal windows on my Mac and for some reason the commands ...
16
gitstatus gitstatus failed to initialize
@romkatv Steps Taken: cd ~/.oh-my-zsh/custom/themes/powerlevel10k git stash git pull Opened new term...
14
shc Executable does not work...
The problem lies in chkenv This uses the address of itself to compose a name of an environment varia...
14
nvm NVM command not found after terminal restart.
I am still facing the issue pls help? run source ~/.nvm/nvm.sh and if it doesnt work after you close...
14
nvm nvm.sh:114: parse error near `done'
omg i found it I had set up an alias to connect to my digital ocean server: can't believe it didn't ...
13
nvm OSX Sierra node installation failed; Checksums does not match.
@PeterDaveHello thanks for taking a look just figured that out I just didn't copy the second line of...
13
nvm Manjaro: `nvm is not compatible with the npm config "prefix" option: currently set to ""`
I figured this out on my system For other Arch/Manjaro users here's how you can find the cause: Inst...
12
nvm bashrc NVM EACCES: permission denied upon switching user
I was struggling to find a fix for this error but as @ljharb mentionned you should cd ~ BEFORE the n...
12
rbenv Ruby 2.4.1 build failed on macOS High Sierra 10.13.2
I have had the same issue but I am able to fix it by doing the following steps: sudo mv /usr/local/i...
11
nvm NVM not adding node_modules to path
@Gerst20051 @ljharb Because https://nodejs.org/api/modules.html#modules_loading_from_the_global_fold...
11
nvm NVM installed, getting GLIBC err on node install
I got the exact same error while trying to install node with nvm Operating system and version: linux...
9
fzf Revising ranking algorithm
I just released 0.15.0 with --algo=[v1|v2] option where v2 is the default You can use v1 if the perf...
9
nvm Globally installed cli packages not available after NPM install
save-prefix is fine altho ^ (the default) is better - but prefix definitely needs to be deleted Now ...
9
powerline powerline-status crashes with ipython>=7.0.0
Until the changes are released checkout the develop branch to get them It may be less stable than ma...
5
DietPi DietPi-Software | Kodi on RPi Buster fails to start
some information: Kodi is back on official rpi repo ADMIN EDIT Bug does not apply anymore since Kodi...
5
dockerfiles Chrome 79 white screen
Issue-Label Bot is automatically applying the label bug to this issue with a confidence of 0.79 ...
5
nvm nvm install node not working on "ubuntu on windows"
Hey everyone.. just so you're all aware this isn't an nvm issue nor a Ubuntu issue nor a Windows iss...
4
yadm Can I use this to track system level files?
Managing files outside of your home directory isn't really within the standard use-case for yadm ...
4
bash language server Install error Failed at the tree-sitter@0.13.23 install script
Update: This fixed the issue here on Arch Linux along with --unsafe-perm: https://wiki.archlinux.org...
3
DietPi DietPi-Software | NextCloudPi convergence
Thanks both I just saw this thread comparing the two projects and see no reason you could not furthe...
3
DietPi Upgrade v6.25.3 -> v.6.30.0 fails: /DietPi/dietpi/func/dietpi-ramdisk: No such file or directory
Found it please do not do any of the mentioned steps the error can and should be ignored As can be s...
3
DietPi Image | Odroid HC4
Not partitioning just a mountpoint They created /media/boot as an empty folder and mount the bootfs ...
3
acme.sh Cloudflare DNS broken - is this really the fix?
I was about to open the exact same issue! 😅 I had been using an older acme.sh version; today I deci...
3
nvm `sort` command not found
Hi I actually found the source of the problem I'm using 'bash strict mode' The change of the field s...
3
m cli Installed but won't work
@Strandbummler I found out that my PATH is in .bash_profile not .profile So I changed @blahah 's com...
82
drupal vm Composer install fails without proper swap
or you can create a swap file sudo fallocate -l 2G /swapfile sudo chmod 600 /swapfile sudo mkswap /s...
30
cross env /bin/sh: cross-env: command not found
My guess you have your NODE_ENV set to production on CI and cross-env is in your devDependencies So ...