Plugins in `runtimepath` are misbehaving

:help plugins tells that nvim scans runtimepath and loads files from plugin/ subdirectories there. But when I clone vim-go into ~/.config/nvim/plugin/vim-go, something terrible happens.


Here is the docker/podman command to repeat this.

podman run -it --rm ubuntu sh -uec '
  apt-get update -y
  apt-get install -y neovim git
  git clone ~/.config/nvim/plugin/vim-go

When vim-go is cloned into ~/.config/nvim/somepath/vim-go, the plugin is not loaded at all. And when it is cloned into ~/.local/share/nvim/site/pack/plugins/start/vim-go, the plugin works as expected.

So why plugins just don’t work if dropped into documented plugin dir in runtimepath?

First of all, there is a difference between what the community calls a “plugin” and what the vim documentation calls a “plugin”. Long story short, in the vim documentation a plugin is a shareable script that adds new functionality to the editor, e.g. by adding new commands; on the other hand, in general parlance a plugin can include this, but also syntax highlighting, file-type specific settings, and more.

From the documentation at :help 'runtimepath' you’ll see that these all go in different subdirectories, because vim loads them at different times: not only there is plugin, but there are also ftplugin (for functions/settings that should only affect specifc file types), syntax (for syntax highlighting configurations), doc (for documentation), and more. If you now look at the file tree for GitHub - fatih/vim-go: Go development plugin for Vim, you’ll see that it includes all of these, and more.

Furthermore, many Lua-based plugins place their Lua code under lua and a glue vimscript file under plugin, because for a while neovim could only load Lua from lua (this is no longer the case).

All that said, I would strongly recommend using a plugin manager like GitHub - junegunn/vim-plug: Minimalist Vim Plugin Manager or GitHub - wbthomason/packer.nvim: A use-package inspired plugin manager for Neovim. Uses native packages, supports Luarocks dependencies, written in Lua, allows for expressive config, because not only they clone and keep up to date your plugin repositories, but most importantly they manage your runtimepath.

By the way, if you read the error messages you’re getting, vim-go is telling you that it cannot find in your system the binaries go (the Go compiler) and gopls (the Go language server), and it is instructing you to run :GoInstallBinaries to install them. So at least some of the plugin is indeed loading…

It looks like neovim treats plugin as a set of separate scripts if placed into ~/.config/nvim/plugin/, but it somehow able to treat it as a real plugin if placed into ~/.local/share/nvim/site/pack/plugins/start/vim-go.

Using plugin manager just to use plugins doesn’t seem like a “plug-in” experience to me. If neovim changed where the its plugin should reside, maybe it could also establish some firm terminology? Making a distinction between script (.vim or .lua file that could be autoloaded) and a plugin, which is a set of scripts that only work together.

You’ve discovered packages, which go under pack, as documented in :help runtimepath. This is also what packer uses under the hood. Note that ~/.local/share/nvim/ is the default user data directory, whereas ~/.config/nvim is the default user configuration directory – see :help base-directories for more information.

If you don’t need the extra features offered by plugin managers and are happy manually cloning and updating your plugins, packages are a good option.

Neovim does use a firm terminology, which it inherits from vim and which is defined in the documentation. Repurposing the plugin directory and introducing a script directory as you suggest would break compatibility with (almost) all existing vim plugins, for no good reason.

vim-go authors describe their software as “plugin for Vim”. Should they call it a package instead?

Instead of repurposing plugin directory, why it is not possible to have both scripts and packages there?

Packages are not configuration, you should not put them into ~/.config/nvim. In the very old days of Vim things used to be simple: one “plugin” was one file which you would dump into your ~/.vim/ directory under plugin or ftplugin or syntax or whatever. Over time people started making more complicated plugins that would span several files, but we did not have a separate word for them, we still called them “plugins”. I will call them compound plugins for clarity. If you wanted to uninstall such a compound plugin you would need to know all the files involved and delete them individually.

Then the package managers came along. Using some runtimepath hackery you could put your compound plugins into individual directories and the manager would keep them updated. Most importantly, you no longer had to intermingle your configuration and other people’s code. Later support for packages was added in Vim 8 which allowed Vim to find packages which were placed inside a standard directory. No more need for runtimepath hackery.

I don’t use a package manger, I have a Git repository where each package is a Git submodule. There is nothing wrong with using a package manger, but you don’t have to if you are willing to do a bit of extra work. If you don’t care about automatic updates and pinning versions you don’t even have to bother with Git submodules.

Here is how you can do it:

  • Create a directory ~/.local/share/nvim/site/pack/3rd-party/start/ (the name 3rd-party is arbitrary)
  • Download your compound package (e.g. vim-go) into the start directory, i.e. ~/.local/share/nvim/site/pack/3rd-party/start/vim-go

And that’s it. To make matters more confusing, the documentation uses the terms “plugin” and “package” ambiguously at times.

I appreciate the thorough explanation of the status quo. However, I’ve got a feeling that it still doesn’t answer the question. At least it doesn’t touch technical aspects if it is possible to reliably detect package directory among scripts.

You can probably add ~/.config/nvim/3rd-party/vim-go to the 'runtimepath',
but you really should not. This is essentially what the early package managers
were doing, except automatically.

First you would have to do that for every plugin individually, and second it
just makes things more complicated if you want to version-control your

  1. Why add another dir to runtimepath is there are already a plenty of dirs there?
  2. Why neovim will treat it as a package and not as a dir with scripts? Like it happened with ~/.config/nvim/plugin/vim-go.

For fine-grained version control of my config I surely need .gitignore to make sure no passwords are trapped in catch-all patterns. And also I can use git submodules for plugins-as-packages. I would say it is less complicated than managing plugins manually or learning additional plugin management tools.

Hi all,

I have decided not create new topic, so I will describe my issue here.

I would like to create my first module for nvim. I use windows 10 as my system.
I have created folder structure in my package folder.


but it is not loaded by neovim.

When I have run :lua vim.tbl_map(print, vim.api.nvim_list_runtime_paths()) above path is not visible.

How can I fix it?