flash.nvim: Label-Based Jumps, Enhanced f/t Motions and Treesitter Selection in Neovim
Navigate your code with search labels, enhanced character motions and Treesitter integration
At a glance
- What is it?
- flash.nvim replaces Neovim's built-in jump workflow with labelled targets for search, character motions and Treesitter nodes. It is a Lua plugin for Neovim 0.8.0 and later built with LuaJIT, and its default keymaps are the fastest way to judge whether it fits your config.
- Who is it for?
- Adopt flash.nvim if you already use lazy.nvim or another Lua-based plugin manager on Neovim 0.8.0 or newer with LuaJIT, and you want one plugin to cover searching, f/t/F/T motions and Treesitter node selection. Skip it if you are on an older Neovim build without LuaJIT, or if you have no appetite for remapping s, S, r and R, since the README's own example binds those keys.
- Can I use it commercially?
- Yes. Apache-2.0 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 September 30, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The problem flash.nvim solves for Neovim users
Neovim's built-in navigation is precise but slow at distance. To reach a visible token you either type /pattern and press Enter, or you count characters and use f, t, F or T. Both approaches assume the target is close enough to count or unique enough to search. On a screen with twenty occurrences of the same identifier, neither is pleasant.
flash.nvim targets that gap. The README describes it as navigating code with search labels, enhanced character motions and Treesitter integration. The audience is Neovim users who already live in the editor and want to move by sight rather than by counting. The plugin is Lua, licensed Apache-2.0, and the README states it requires Neovim 0.8.0 or later, built with LuaJIT. That LuaJIT requirement is not incidental: the plugin is a Lua module loaded through require, and the documented keymap form is a Lua function call.
It is not a file finder, not a fuzzy picker for buffers, and not a replacement for your search plugin in the sense of index building. It operates on what is already on screen, in one or several windows, and turns the matches into labelled targets.
How labels, search modes and Treesitter integration actually work
The core mechanism is label assignment. When you trigger a jump, flash.nvim finds matches for your pattern and draws a label next to each one, using extmarks. The default label alphabet is not the plain alphabet: the configuration shows labels = "asdfghjklqwertyuiopzxcvbnm", a home-row-first ordering. Labels are placed according to the label.style setting, whose documented values are "eol", "overlay", "right_align" and "inline". By default, label.after is true and label.before is false, so the label renders after the match.
Search integration is the part that differs from a plain jump mode. The README states that when you search with / or ?, labels appear next to the matches, and that labels are guaranteed not to exist as a continuation of the search pattern. That guarantee matters: if you type abc and a match is labelled with d, then abcd would be an ambiguity, so the plugin avoids that label. You can keep typing characters before using a label.
There are three documented search modes under search.mode: exact, search (regex) and fuzzy. The README also allows a custom function returning a pattern, with the example mode = function(str) return "\\<" .. str end to match only at the beginning of a word. Direction and wrapping are separate settings: search.forward defaults to true and search.wrap defaults to true, and the README notes that when wrap is false, only matches in the given direction are found.
The Treesitter side is a different entry point. According to the README, all parents of the Treesitter node under the cursor are highlighted with a label, so you can select a specific node rather than a text range. The label.rainbow option, disabled by default, is described as useful for visualising Treesitter ranges. Remote actions and multi-window jumping are listed as features, with search.multi_window defaulting to true. Dot-repeatability is claimed for jumps, and the README warns explicitly that creating keymaps with :lua breaks dot-repeat; you must use a Lua function or a <cmd>lua ...<cr> string.
Installing flash.nvim with lazy.nvim and making the first jump
The README gives one installation path, for lazy.nvim. The plugin spec sets event = "VeryLazy", an empty opts table, and five keymaps. Note the modes: s and S are bound in normal, visual and operator-pending mode, r only in operator-pending, R in operator-pending and visual, and <c-s> in command mode.
{
"folke/flash.nvim",
event = "VeryLazy",
---@type Flash.Config
opts = {},
keys = {
{ "s", mode = { "n", "x", "o" }, function() require("flash").jump() end, desc = "Flash" },
{ "S", mode = { "n", "x", "o" }, function() require("flash").treesitter() end, desc = "Flash Treesitter" },
{ "r", mode = "o", function() require("flash").remote() end, desc = "Remote Flash" },
{ "R", mode = { "o", "x" }, function() require("flash").treesitter_search() end, desc = "Treesitter Search" },
{ "<c-s>", mode = { "c" }, function() require("flash").toggle() end, desc = "Toggle Flash Search" },
},
}After restarting Neovim, pressing s in normal mode should open the jump prompt. Type a few characters, and labels should appear next to the matches. Press the label character to jump. Pressing S instead calls treesitter(), which should label the Treesitter parents of the node under the cursor.
If you build keymaps yourself, the README is explicit about the right-hand side. Use a Lua function, or a string such as <cmd>lua require("flash").jump()<cr>. Do not use :lua, because the README says that breaks dot-repeat.
Configuration is a single opts table. The documented defaults are worth reading before you change anything, because several defaults are conservative. jump.autojump is false, so a single match does not jump for you. jump.history and jump.register are false, so patterns are not written to search history or the search register. jump.nohlsearch is false, so highlights are not cleared after a jump. search.incremental is false, meaning it does not behave like incsearch out of the box.
Where flash.nvim gets in the way
The keymap choices are the first friction point. The README's own example binds s, which many Neovim users rely on as a substitute for the clunky default cc behaviour, and it binds r in operator-pending mode. If you adopt the documented spec unchanged, you are giving up those keys. The README does not discuss conflicts with other plugins that claim s or S.
The LuaJIT requirement is a hard boundary. The README states Neovim 0.8.0 or later, built with LuaJIT. A build without LuaJIT is outside the documented support, and there is no fallback path described.
The search.exclude list defaults to "notify", "cmp_menu", "noice", "flash_prompt", plus a function that excludes windows where nvim_win_get_config(win).focusable is false. That list is a snapshot of common plugins. If you run a completion menu or notification plugin under a different filetype, the README does not describe an automatic way to detect it, so you would add the filetype yourself.
The search.trigger option exists but the README advises against setting it: "It's NOT recommended to set this, unless you know what you're doing." That is a rare piece of direct guidance in the documentation, and it suggests the trigger path has sharp edges the README does not enumerate.
Finally, the release list is older than the repository's activity. The most recent release shown is v2.1.0 from 2024-07-07, while the last push to the default branch was on 2026-08-22. Anyone pinning to a tagged release is running code that predates two years of commits, and the README does not document what changed in between.
flash.nvim compared with leap.nvim and Neovim's built-in motions
The closest comparison people search for is leap.nvim. Both assign labels to on-screen targets, but the trigger model differs. flash.nvim is designed to hook into Neovim's own search: the README describes labels appearing next to matches when you use / or ?, with the guarantee that labels never continue the pattern. It also exposes jump(), treesitter(), remote() and treesitter_search() as separate entry points, and search.mode gives you exact, regex and fuzzy variants.
A plain f or t motion has no label layer at all. It is one keystroke plus a character, and it fails when the character is far away or repeated. flash.nvim's enhanced f, t, F and T are listed as a feature, but the README does not document the exact keymap needed to replace the built-ins, so that is something to work out from the plugin's own examples rather than the README text.
The Treesitter entry point has no equivalent in a plain motion or in a label-only jumper. Selecting a function body or an argument list by node is a different kind of operation from selecting text, and it depends on a working Treesitter parser for the filetype. The README does not state what happens when no parser is installed.
Maintenance, licence and the cost of staying current
The repository is not archived, and the last push to the default branch was on 2026-08-22. That is recent enough that the project is receiving changes, but the tagged releases tell a different story: v2.1.0 dates from 2024-07-07, v2.0.0 from 2024-07-05, and v1.18.3 from 2024-05-03. A user who tracks the default branch gets newer code than a user who pins to v2.1.0, and the README does not describe a release cadence or a stability policy. If you pin, pin deliberately.
The licence is Apache-2.0, which is a permissive licence with an explicit patent grant and a requirement to preserve notices. That is a general description of the licence text, not legal advice; check the LICENSE file in the repository and your own organisation's policy.
The upgrade cost is mostly configuration surface. The default settings block in the README is long, covering search, jump, label, prompt, modes, config and highlight groups. Option names such as search.max_length, label.reuse and label.min_pattern_length are the kind of settings that change meaning between minor versions. There is a CHANGELOG.md at the repository root, and that is the place to check before bumping, since the README itself is written as current-state documentation rather than a versioned migration guide.
Editorial conclusion
Adopt flash.nvim if you already use lazy.nvim or another Lua-based plugin manager on Neovim 0.8.0 or newer with LuaJIT, and you want one plugin to cover searching, f/t/F/T motions and Treesitter node selection. Skip it if you are on an older Neovim build without LuaJIT, or if you have no appetite for remapping s, S, r and R, since the README's own example binds those keys. Before committing, verify that your Neovim reports LuaJIT support, and check that the default exclude list (notify, cmp_menu, noice, flash_prompt) does not conflict with completion or notification plugins you run.
Frequently asked questions
What is flash.nvim and what does it do?
It is a Neovim plugin that lets you navigate code with search labels, enhanced character motions and Treesitter integration. The README describes label-based jumping for search matches, for f, t, F and T motions, and for Treesitter nodes.
What does flash.nvim do?
It assigns labels to on-screen targets so you can jump to one by pressing its label. The documented entry points are jump, treesitter, remote and treesitter_search, and search supports exact, regex and fuzzy modes.
How do I use flash.nvim?
The README's lazy.nvim spec binds s to require("flash").jump(), S to treesitter(), r to remote() in operator-pending mode, R to treesitter_search(), and <c-s> to toggle() in command mode. Press s, type a few characters, then press a label to jump.
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/folke-flash-nvim)