Tomas Vik

Fish shell has different PATH than neovim

TL;DR: neovim triggers shell commands in a non-interactive subshell that is initialised from scratch from your fish.confg (or other shell setup script). Ensure you set the $PATH the same way for both the interactive and the non-interactive shell.

Today, I found a strange thing. I added a yaml formatter to my neovim config (I use mhartington/formatter.nvim). The formatter runs python3 -m pyaml to format the file. So I installed pip3 install pyaml to have the module.

When I ran the formatter from within neovim, I saw an error Failed to run formatter python3: /opt/homebrew/python3... no module named pyaml.

That is strange because I don’t use homebrew python3. I install python using the asdf VM.

It seems that my fish shell and my neovim have a different path

  • Fish: which python3 returns /Users/tomas/.asdf/shims/python3
  • neovim: !:which python3 returns /opt/homebrew/bin/python3
  • and the echo $PATH (in fish) and :!echo $PATH (in neovim) also return different value.

How could this be?

I looked through fish and neovim documentation, trying to find evidence that fish doesn’t send the $PATH variable to its subprocess or that neovim ignores it.

In the end, I found the issue by running :echo $PATH and :!echo $PATH in neovim and noticing that the value is different. The first command returns the same value as the fish shell, and the second returns a different path.

Learning: When you run :! in neovim, it creates a subshell. It’s still fish :!echo $SHELL returns /opt/homebrew/bin/fish but the initialisation is different (non-interactive).

See, I tried to be smart and efficient and guarded most of my shell setup with if status is-interactive. That means I don’t set up autocompletion and other interactive-only features when I run scripts. But one of the setup steps in this interactive-only section was to initialise asdf. When I moved the asdf setup from the interactive-only section, the :echo $PATH and :!echo $PATH commands in neovim had identical output.

This is the fix commit in my dotfiles.