vim-illuminate: highlighting every use of the word under the cursor
illuminate.vim - (Neo)Vim plugin for automatically highlighting other uses of the word under the cursor using either LSP, Tree-sitter, or regex matching.
At a glance
- What is it?
- RRethy/vim-illuminate highlights other occurrences of the identifier under the cursor in Neovim, using LSP, Tree-sitter or regex matching in that order of priority. It is a small plugin with a real configuration surface, and the interesting part is how it degrades when a provider is missing.
- Who is it for?
- vim-illuminate is worth installing if you already run Neovim with a language server or Tree-sitter parser for the filetypes you edit, because the LSP and Tree-sitter providers give you read and write highlighting that a plain search cannot.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 39 days ago.
- What is it written in?
- Mainly Lua, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 2, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The problem vim-illuminate solves for Neovim users
Reading code means tracking one name across a screenful of lines. Vim's built-in search can do that, but it is a manual gesture: type the pattern, press n, press n again, and the search register now holds a pattern you have to clear before the next search. vim-illuminate removes the gesture. The word under the cursor is highlighted everywhere else it appears in the buffer, and the highlighting updates as you move. The README describes the plugin as highlighting other uses of the word under the cursor using either LSP, Tree-sitter, or regex matching. That list is ordered, and the order matters.
The audience is narrow but well defined. It is people editing code in Neovim who want reference context without opening a separate symbol list, and who are willing to accept that the quality of the highlighting depends on what tooling is attached to the buffer. If you edit prose or configuration files with no parser, the plugin still runs, but through the regex provider, which has no idea what a comment is unless you tell it.
How the provider chain decides what gets highlighted
The mechanism is a priority-ordered provider list. The default configuration sets providers = { 'lsp', 'treesitter', 'regex' }, and the README calls these the providers used to get references in the buffer, ordered by priority. So when a language server is attached and answers a references request, that answer wins. If no server is attached, the plugin falls back to Tree-sitter, which resolves the identifier against the syntax tree. If there is no parser either, it falls back to regex matching over the buffer text.
The practical consequence is that two people running the same plugin on the same file can see different results, depending on whether their LSP client is attached. That is a design choice with a cost: the plugin's behaviour is not self-contained. It is also why the README exposes providers_regex_syntax_allowlist and providers_regex_syntax_denylist, which apply only to the regex provider. The README suggests running :echom synIDattr(synIDtrans(synID(line('.'), col('.'), 1)), 'name') to find the syntax name at the cursor, which is a concrete way to discover what to put in those lists. Without that tuning, regex matching will happily underline a variable name inside a string literal.
Highlighting is also kind-aware where the provider supplies that information. There are three highlight groups: IlluminatedWordText for references where no kind information is available, IlluminatedWordRead for read references, and IlluminatedWordWrite for write references. All three default to underline. That read/write split is the part a plain search cannot reproduce.
Installing vim-illuminate and a first real use
The README's quickstart is short: install the plugin and things work, with no configuration needed. The repository does not ship a plugin manager, so installation goes through whatever manager you already use. The README does not give a package name for any registry, so the safest path is to point your manager at the repository. With lazy.nvim the usual form is a spec table naming the repository, which the plugin's own README does not spell out; check your manager's documentation for the exact syntax.
Once installed, the defaults are already active. The README states you get <a-n> and <a-p> as keymaps to move between references, and <a-i> as a textobject for the reference illuminated under the cursor. To confirm the plugin is running, put the cursor on an identifier in a file with a language server attached and look for the underline on other occurrences.
If you want to change behaviour, the configuration call takes a table. This is the default provider order and delay, and it is the shape every other option follows:
require('illuminate').configure({
providers = {
'lsp',
'treesitter',
'regex',
},
delay = 100,
})The delay key is in milliseconds and defaults to 100. The README explains the delay exists to avoid the jarring experience of things illuminating too fast, and notes that for Vim users the equivalent variable is g:Illuminate_delay, defaulting to 0 milliseconds there.
For per-filetype tuning, filetype_overrides takes a table keyed by filetype whose values accept the same keys as configure, except filetypes_denylist and filetypes_allowlist. If you want to silence the plugin in a specific filetype, filetypes_denylist is the list to edit, and the defaults already include dirbuf, dirvish and fugitive. Note the README's warning that filetypes_denylist overrides filetypes_allowlist, so an allowlist only takes effect once you set filetypes_denylist = {}.
There are also commands for turning the plugin off without touching the configuration. :IlluminatePause, :IlluminateResume and :IlluminateToggle work globally, while :IlluminatePauseBuf, :IlluminateResumeBuf and :IlluminateToggleBuf are buffer-local. The Lua functions mirror them, including freeze_buf, which the README says freezes the illumination on the buffer without clearing the highlights, and invisible_buf, which turns off highlighting for the buffer without stopping the engine so the reference navigation keys still work.
Where vim-illuminate gets in the way
The largest file in your project is the most likely to misbehave. The README exposes large_file_cutoff, defaulting to 10000 lines, and states that the under_cursor option is disabled once that cutoff is hit. It also exposes large_file_overrides, described as the config to use for large files based on that cutoff, and notes that if it is nil, vim-illuminate is disabled for large files. So the default behaviour on a 10001-line file is to stop highlighting under the cursor, and if you have not set large_file_overrides, the plugin effectively goes quiet. That is a reasonable default, but it is silent, and a user who does not know the key exists will read it as a bug.
The regex provider is the other rough edge. It matches text, not symbols, and the only defence the plugin offers is the syntax allow and deny lists, which you have to populate by hand using the synIDattr expression from the README. If you never populate them, string literals and comments are fair game.
Finally, the Vim path is explicitly deprecated. The README's Vim Users section is marked as deprecated for Neovim users, and Neovim users can force the old implementation by setting let g:Illuminate_useDeprecated = 1 in init.vim. If you are on Vim rather than Neovim, you are on the older Vimscript implementation, and the README points to the docs section for it rather than treating it as the primary path. That is a signal about where maintenance attention goes.
How vim-illuminate differs from a search-based highlighter
The obvious alternative is vim-searchindex or any plugin that highlights the current search pattern, and the difference is not cosmetic. A search highlighter works from a text pattern. It has no concept of a reference, no notion of read versus write, and no ability to ask a language server which occurrences are semantically related to the one under the cursor. vim-illuminate's LSP provider does exactly that, which is why the read and write highlight groups exist at all.
The trade-off runs the other way too. A search highlighter has no provider chain, so it behaves identically in every buffer and never silently degrades. vim-illuminate's results depend on what is attached to the buffer, and the README does not document a way to see which provider answered for the current match. If predictability matters more to you than semantic accuracy, a search-based approach is the simpler tool. If you want the LSP's read/write distinction, vim-illuminate is the one that provides it.
Maintenance, licence and upgrade cost
The repository is not archived, and the last push was on 2026-08-25, which is roughly a month before this writing. The repository does not list any releases, so there is no changelog to read before upgrading. Upgrades therefore mean pulling the current master and reading the README diff yourself. The configuration surface is a single Lua table with named keys, which is a stable shape, but the README does not document a deprecation policy or a versioning scheme, so a key rename would arrive without a migration note.
The licence is MIT. That permits use, modification and redistribution provided the copyright notice and permission notice are retained, and it comes with no warranty. It is a permissive licence with no copyleft obligation, so embedding the plugin in a larger configuration or a distribution does not force you to publish your own configuration under the same terms. This is a description of the licence text, not legal advice; read the LICENSE file in the repository if the distinction matters to your organisation.
Editorial conclusion
vim-illuminate is worth installing if you already run Neovim with a language server or Tree-sitter parser for the filetypes you edit, because the LSP and Tree-sitter providers give you read and write highlighting that a plain search cannot. Skip it if you work mostly in filetypes with no parser and no server attached, since the regex provider will highlight string literals and comments alongside real code, and skip it on very large files unless you tune large_file_cutoff and large_file_overrides. Before adopting, check three things in your own setup: which providers actually resolve for your main filetype, whether the default <a-n>, <a-p> and <a-i> mappings collide with anything you already use, and what :IlluminateToggle does in a buffer where you have not configured a filetype override.
Frequently asked questions
Is Vim still being developed?
The material for vim-illuminate cannot answer this. What it does show is that the plugin's own Vim Users section is marked deprecated for Neovim users, and that Neovim users can force the older implementation with let g:Illuminate_useDeprecated = 1.
Is vim better than neovim?
The material for vim-illuminate cannot settle this comparison. What it does say is that the README treats Neovim as the primary target and marks the Vimscript implementation as deprecated, with a separate docs section for Vim users.
How do I highlight multiple lines of text in Vim?
vim-illuminate highlights other occurrences of the word under the cursor, not arbitrary selections of lines. If you want to silence it in a particular filetype instead, edit filetypes_denylist, whose defaults already include dirbuf, dirvish and fugitive.
What does Ctrl+B do in Vim?
The material for vim-illuminate does not describe Ctrl+B. The keymaps the README does document for this plugin are <a-n> and <a-p> to move between references and <a-i> as a textobject for the illuminated reference.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/rrethy-vim-illuminate)