# vim-lsp: Async Language Server Protocol Plugin for Vim 8 and Neovim

> vim-lsp brings LSP-driven code intelligence to Vim 8 and Neovim through an asynchronous Vim Script layer that requires manual server registration but ships with over thirty ready-to-use commands. It is the only LSP client that covers both Vim 8 and Neovim under a single plugin.

**prabirshrestha/vim-lsp** — async language server protocol plugin for vim and neovim

- Repository: https://github.com/prabirshrestha/vim-lsp
- Stars: 3,420 · Forks: 325
- Language: Vim Script
- License: MIT
- Published: 2026-09-23 · Updated: 2026-09-23 · Language: en
- Canonical page: https://hysenlabs.com/projects/prabirshrestha-vim-lsp

## LSP Features for Vim 8 and Neovim Without the Built-In Client

The Language Server Protocol defines a standard wire format for editors to query language tooling: go-to-definition, symbol search, inline diagnostics, rename, hover documentation, and more. Vim 8 gained async job control in 2016 but never shipped a native LSP client. Neovim added one in version 0.5.0, but it covers only Neovim and requires Lua-based configuration. vim-lsp fills the gap for Vim 8 users and provides a Vim Script alternative for Neovim users who prefer not to write Lua.

The plugin targets engineers who already have a Vim Script-based configuration and want code intelligence without switching to a different editor or learning a new configuration language. It registers as an autocmd-based system: servers attach per-buffer when the filetype matches, and keybindings are set inside the lsp_buffer_enabled event.

## The Async Architecture and the Lua Performance Path

vim-lsp submits language server requests through Vim's asynchronous job mechanism, so the editor does not block while the server processes large codebases. JSON-RPC messages travel over stdin/stdout to the language server process. Responses arrive as callbacks that update the buffer, the quickfix list, or the sign column.

Certain bottlenecks in the Vim Script layer have been reimplemented in Lua. The README states that to take advantage of these gains, you need Vim compiled with Lua support or Neovim v0.4.0 or later. Without Lua, vim-lsp falls back to the pure Vim Script path, which is functional but slower on files with dense completions or large diagnostic payloads.

Server registration uses a callable definition. The cmd key takes a funcref that receives a server_info dictionary and returns a list of command-line arguments, giving you full control over how the process launches and what flags it receives.

## Installing vim-lsp and Connecting a Language Server

Add vim-lsp using vim-plug:

```viml
Plug 'prabirshrestha/vim-lsp'
```

For automatic server installation and configuration, the README recommends adding vim-lsp-settings alongside it:

```viml
Plug 'prabirshrestha/vim-lsp'
Plug 'mattn/vim-lsp-settings'
```

Without vim-lsp-settings, each server requires a manual registration block. The README shows a Python example using pylsp:

```viml
if executable('pylsp')
    " pip install python-lsp-server
    au User lsp_setup call lsp#register_server({
        \ 'name': 'pylsp',
        \ 'cmd': {server_info->['pylsp']},
        \ 'allowlist': ['python'],
        \ })
endif
```

The executable() guard means the server only activates when the binary is present on PATH. The allowlist restricts the server to matching filetypes. Buffer-level setup (omnifunc, keymaps, tagfunc) is typically placed in a function triggered by the lsp_buffer_enabled autocmd event.

After setup, run :LspStatus to confirm the server attached to the current buffer. A server that fails the executable() check is silently skipped.

## Thirty-Plus Commands from Jump-to-Definition to Call Hierarchy

vim-lsp maps LSP capabilities to named commands. Navigation includes :LspDefinition, :LspDeclaration, and :LspTypeDefinition. Each has a Peek variant (for example :LspPeekDefinition) that opens the result in a preview window rather than the current window. :LspReferences finds all usages of the symbol under the cursor. :LspRename performs a workspace-wide rename.

Diagnostic commands let you step through problems without leaving the keyboard: :LspNextError, :LspPreviousError, :LspNextWarning, and :LspNextDiagnostic, which covers all severity levels. :LspDocumentDiagnostics dumps diagnostics for the current file.

Call hierarchy is available through :LspCallHierarchyIncoming and :LspCallHierarchyOutgoing. :LspTypeHierarchy shows type relationships. :LspCodeAction presents a list of quick fixes the server can apply. :LspCodeLens lists executable commands on the current document.

One important constraint documented in the README: when multiple servers are registered for the same filetype, commands like :LspRename and :LspDocumentFormat use only the first server that reports support for that capability. There is no mechanism to pick a different server for a specific operation.

## Features That Require Companion Plugins

Snippet expansion is not built into vim-lsp. Three integration paths exist, each requiring two plugins. The README lists them: vim-vsnip paired with vim-vsnip-integ, UltiSnips paired with vim-lsp-ultisnips, or neosnippet paired with vim-lsp-neosnippet.

Completion comes from setting omnifunc=lsp#complete in a buffer setup function, which routes LSP completions through Vim's native omnicompletion trigger. For automatic popup completion, asyncomplete.vim is the documented companion.

Diagnostics are enabled by default and appear in the sign column. Teams that already use ALE or Neomake for diagnostics can disable vim-lsp's output to avoid duplicate signs:

```viml
let g:lsp_diagnostics_enabled = 0         " disable diagnostics support
```

Reference highlighting (marking all occurrences of the symbol under the cursor) is also on by default. The highlight group that controls its appearance is lspReference.

## Folding, Semantic Highlighting, and Debugging Configuration

LSP-driven folding uses Vim's fold expression system. The README gives the configuration:

```vim
set foldmethod=expr
  \ foldexpr=lsp#ui#vim#folding#foldexpr()
  \ foldtext=lsp#ui#vim#folding#foldtext()
```

To disable it globally: `let g:lsp_fold_enabled = 0`.

Semantic highlighting is supported through an unofficial protocol extension. The README notes explicitly that this feature is based on a draft extension in the vscode-languageserver-node repository. It requires Neovim highlights or Vim compiled with the textprop feature. Support varies by language server and could break as the draft evolves.

When a server misbehaves, verbose logging is available:

```vim
let g:lsp_log_verbose = 1
let g:lsp_log_file = expand('~/vim-lsp.log')
```

The `:CheckHealth` command can report server status when a compatible health-check plugin is present.

## Where vim-lsp Falls Short and When to Use nvim-lspconfig Instead

Snippets and popup completion both require additional plugins, while Neovim's native client handles both through nvim-lspconfig and a companion completion plugin. The manual lsp#register_server approach is also more verbose than nvim-lspconfig, which ships pre-written server configurations for dozens of language servers and requires only a single function call per server.

nvim-lspconfig is Neovim-only and written in Lua. It is the more ergonomic choice for developers who use only Neovim. vim-lsp remains the only option for Vim 8 users and remains a valid choice for Neovim users who prefer to configure everything in Vim Script.

The semantic highlighting feature depends on a draft protocol extension, which is a concrete risk for projects that need predictable highlighting behavior across server updates. The multi-server-per-filetype limitation (only the first capable server handles rename and format) is also a constraint for mixed-language or polyglot projects.

## Maintenance Status and License

The last push to the repository was on 2026-09-02. The repository is not archived. Dependency updates are managed through Renovate, whose configuration lives at the repository root. The codebase includes a test/ directory and a .vintrc.yaml file for Vim Script linting.

The project is released under the MIT license. A separate LICENSE-THIRD-PARTY file covers other code included in the repository. There are no GitHub releases; the plugin is installed directly from the master branch via a plugin manager.

## Conclusion

vim-lsp is the right choice for Vim 8 users and for teams that mix Vim 8 and Neovim. Developers on Neovim only who prefer Lua configuration will find nvim-lspconfig more concise, since it ships pre-written server definitions and does not require a lsp#register_server block per language. Before relying on :LspDefinition or :LspRename in a project, confirm the language server is attached by running :LspStatus and verify that the allowlist entry matches the filetype Vim assigns to your files.

## FAQ

### What is vim-lsp?

vim-lsp is an asynchronous Language Server Protocol plugin for Vim 8 and Neovim, written in Vim Script. It connects editors to language servers over JSON-RPC and exposes capabilities like go-to-definition, rename, hover, and diagnostics through a set of :Lsp* commands.

### How do I install vim-lsp?

Add `Plug 'prabirshrestha/vim-lsp'` to your vim-plug configuration and run :PlugInstall. For automatic server setup, also add `Plug 'mattn/vim-lsp-settings'`. Without vim-lsp-settings, each language server must be registered manually with lsp#register_server.

### Can I use a Python language server with vim-lsp?

Yes. The README shows registering pylsp (python-lsp-server) using an executable() guard and an lsp#register_server call with 'allowlist': ['python']. The server only activates for Python filetypes when pylsp is on PATH.

### How does vim-lsp compare to coc.nvim?

vim-lsp is a lighter plugin that delegates completion and snippets to separate plugins, while coc.nvim is a full IDE-like framework with built-in completion, snippet, and extension support. vim-lsp works on Vim 8 and Neovim; coc.nvim targets both but requires Node.js.

### What is the difference between vim-lsp and nvim-lspconfig?

vim-lsp is a Vim Script plugin that supports Vim 8 and Neovim, requiring you to write lsp#register_server blocks for each server. nvim-lspconfig is Lua-based, works only in Neovim, and ships pre-written per-server configurations that reduce setup to a single function call.

## Sources

- [Issues](https://github.com/prabirshrestha/vim-lsp/issues)
- [License: MIT](https://github.com/prabirshrestha/vim-lsp/blob/master/LICENSE)
- [prabirshrestha/vim-lsp on GitHub](https://github.com/prabirshrestha/vim-lsp)
- [README](https://github.com/prabirshrestha/vim-lsp/blob/master/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/prabirshrestha-vim-lsp
