Previously I have written about what I tried and what did and did not work while trying to satisfy neovim's :checkhealth command while detecting the Python provider on Mac M3.

Yeah, the solution worked but it was less than optimal, due to the use of --break-system-packages option, which should not be used. It is designed to sound scary in the first place. While I did not encounter any situations that would I classify as broken system packages I have since found a better, hopefully a proper way to install pynvim in a way that would satisfy neovim.

Introduction

At the beginning there was this message. It happens when Python is installed via Homebrew. It is very hard to use brew without it, as most really useful packages, at least the ones that I use, depend on Python.

However, trying to install something via homebrew's like so:

pip3 instal some_random_package

Leads to the following error:

error: externally-managed-environment
× This environment is externally managed
╰─> To install Python packages system-wide, try brew install
    xyz, where xyz is the package you are trying to
    install.

    If you wish to install a Python library that isn't in Homebrew,
    use a virtual environment:

    python3 -m venv path/to/venv
    source path/to/venv/bin/activate
    python3 -m pip install xyz

    If you wish to install a Python application that isn't in Homebrew,
    it may be easiest to use 'pipx install xyz', which will manage a
    virtual environment for you. You can install pipx with

    brew install pipx

    You may restore the old behavior of pip by passing
    the '--break-system-packages' flag to pip, or by adding
    'break-system-packages = true' to your pip.conf file. The latter
    will permanently disable this error.

    If you disable this error, we STRONGLY recommend that you additionally
    pass the '--user' flag to pip, or set 'user = true' in your pip.conf
    file. Failure to do this can result in a broken Homebrew installation.

    Read more about this behavior here: <https://peps.python.org/pep-0668/>
note: If you believe this is a mistake, please contact your Python installation or OS distribution provider. You can override this, at the risk of breaking your Python installation or OS, by passing --break-system-packages.
hint: See PEP 668 for the detailed specification.

I am sure I have read the log error message from above carefully back then, and that I even tried to use the venv, but I am sure I failed. Not remembering why. Anyway, for the record, making sure pip3 in this case is really the one installed via Homebrew:

which pip3 # /opt/homebrew/bin/pip3

But there is another pip3 on the system...

System wide Python

Note that it is possible to completely overcome the above error message by running the system-wide pip3:

/usr/bin/pip3 install some_random_package
# Defaulting to user installation because normal site-packages is not writeable

The above works but it is discouraged for at least two reasons:

  1. The Python there is older, 3.9 versus 3.13 at the time of writing
  2. It is better to leave system space as intact as possible

Moreover, since system space actually is not writable, the installation will store the files into user space under ~/Library/Python/3.9/, making it even harder to manage. So what is the proper way?

Reverting the damage

Before installing pynvim properly, first address the possible damage. Check if there are system-wide Python packages installed at all, hopefully not:

/usr/bin/pip3 list

If there are any, consider completely removing them too:

Warning: The following command might cause damage to your system, inspect carefully before use.

/usr/bin/pip3 uninstall -y (/usr/bin/pip3 list | tail -n +3 | string split -f1 ' ')

Packages removed this way should be replaced, as the long error above suggests, either via Homebrew's pipx or via Python virtual environment, which we are going to discuss here in this post.

Next, more certain step is to remove pynvim from Homebrew as we installed it incorrectly and we want to stop using this installation:

pip3 uninstall pynvim `--break-system-packages`

Note that that the --break-system-packages switch is again required here, even for removal, hopefully your system has no Homebrew packages depending on it, which is unlikely.

Using venv

Now read the long error message from the beginning. It actually writes the guidelines what to do to use the virtual environment, but not in an exact way an also missing the critical points. Here's a compacted list of commands that worked for me:

mkdir -p ~/.config/nvim/venv
/opt/homebrew/bin/python3 -m venv ~/.config/nvim/venv
source ~/.config/nvim/venv/bin/activate
pip install pynvim

# Leave virtual environment
deactivate

Note that when using fish shell, activation will fail with the error:

~/.config/nvim/venv/bin/activate (line 40): 'case' builtin not inside of switch block
case "$(uname)" in
^~~^
from sourcing file ~/.config/nvim/venv/bin/activate
source: Error while reading file '/Users/peterbabic/.config/nvim/venv/bin/activate'

In that case use the specialized activation script:

source ~/.config/nvim/venv/bin/activate.fish

Also note that the location for the environment is conveniently placed inside ~/.config/nvim/ where my other neovim related files reside, resulting in a neat and clean setup.

Configuring nvim

Last important thing to do is to locate and replace the python3_host_prog parameter from Homebrew to the venv like the your .vimrc or init.vim file:

let g:python3_host_prog = expand('~/.config/nvim/venv/bin/python')

Now run :checkhealth in neovim again. It should now not complain about missing Python provider. Here's how it could possibly look:

provider.python: require("provider.python.health").check()

Python 3 provider (optional) ~
- Using: g:python3_host_prog = "/Users/peterbabic/.config/nvim/venv/bin/python"
- Executable: /Users/peterbabic/.config/nvim/venv/bin/python
- Python version: 3.13.2
- pynvim version: 0.5.2
- OK Latest pynvim is installed.

Python virtualenv ~
- OK no $VIRTUAL_ENV

Enjoy!