This plugin allows you to easily update Neovim from source, with fully customizable options to define where the source is cloned, which branch is tracked, and the desired build type.
All without leaving Neovim.
nvim-updater.webm
The above video shows an example of the update workflow with the Neovim Updater plugin.
- A Linux system (macOS and Windows are not supported by this plugin)
- Neovim 0.9+ (earlier versions may work, but could encounter issues)
- Build prerequisites for your platform
Important
It is recommended to uninstall any distro-provided neovim packages after installing from source (with this plugin or manually) to prevent those distro-packaged updates from overwriting the locally-built neovim binary.
These plugins are not required but can be used to extend functionality.
- diffview.nvim This plugin can be used to show new commits in DiffView.
- telescope.nvim This plugin can be used to show new commits in Telescope.
To use the plugin with lazy.nvim:
{
"rootiest/nvim-updater.nvim",
version = "*", -- Pin to GitHub releases
config = function()
require("nvim_updater").setup({
source_dir = "~/.local/src/neovim", -- Custom target directory
build_type = "RelWithDebInfo", -- Set the desired build type
branch = "master", -- Track nightly branch
check_for_updates = true, -- Enable automatic update checks
notify_updates = true, -- Enables update notifications
default_keymaps = false, -- Disable default keymaps
})
end,
keys = { -- Custom keymappings
{ -- Custom Update Neovim
"<Leader>cuU",
function()
require('nvim_updater').update_neovim()
end,
desc = "Custom Update Neovim"
},
{ -- Debug Build Neovim
"<Leader>cuD",
function()
require('nvim_updater').update_neovim({ build_type = 'Debug' })
end,
desc = "Debug Build Neovim"
},
{ -- Remove Neovim Source
"<Leader>cRN",
":NVUpdateRemoveSource<CR>",
desc = "Remove Neovim Source Directory",
},
}
}Minimal example with defaults in lazy.nvim:
{
"rootiest/nvim-updater.nvim",
version = "*", -- Pin to GitHub releases
opts = {},
}Example with packer.nvim:
use {
"rootiest/nvim-updater.nvim",
tag = "*", -- Pin to GitHub releases
config = function()
require("nvim_updater").setup({
source_dir = "~/.local/src/neovim", -- Custom target directory
build_type = "RelWithDebInfo", -- Set the desired build type
branch = "master", -- Track nightly branch
check_for_updates = true, -- Enable automatic update checks
notify_updates = true, -- Enables update notifications
default_keymaps = false, -- Disable default keymaps
})
-- Define custom keymappings here
vim.keymap.set("n", "<Leader>cuU", function()
require('nvim_updater').update_neovim()
end, { desc = "Custom Update Neovim" })
vim.keymap.set("n", "<Leader>cuD", function()
require('nvim_updater').update_neovim({ build_type = 'Debug' })
end, { desc = "Debug Build Neovim" })
vim.keymap.set(
"n",
"<Leader>cRN",
":NVUpdateRemoveSource<CR>",
{ desc = "Remove Neovim Source Directory"
})
end,
}Example with vim-plug:
Plug "rootiest/nvim-updater.nvim"
lua << EOF
require("nvim_updater").setup({
source_dir = "~/.local/src/neovim", -- Custom target directory
build_type = "RelWithDebInfo", -- Set the desired build type
branch = "master", -- Track nightly branch
check_for_updates = true, -- Enable automatic update checks
notify_updates = true, -- Enables update notifications
default_keymaps = false, -- Disable default keymaps
})
-- Custom keybindings
vim.api.nvim_set_keymap("n", "<Leader>cuU",
":lua require('nvim_updater').update_neovim()<CR>",
{ noremap = true, silent = true, desc = "Custom Update Neovim" })
vim.api.nvim_set_keymap("n", "<Leader>cuD",
":lua require('nvim_updater').update_neovim({ build_type = 'Debug' })<CR>",
{ noremap = true, silent = true, desc = "Debug Build Neovim" })
vim.api.nvim_set_keymap("n", "<Leader>cRN",
":NVUpdateRemoveSource<CR>",
{ noremap = true, silent = true, desc = "Remove Neovim Source Directory" })
EOF- Clone, build, and install Neovim from the source.
- Customizable source path, build type
(
Debug,Release,RelWithDebInfo), and branch. - Provides default keybindings for quick actions or define your own custom keymaps.
- Integrates with lualine and statusline plugins via a dedicated buffer filetype for customization and a status component.
Tip
The plugin can integrate with DiffView and Telescope plugins
to display new commits in the Neovim source.
The setup function accepts an optional table to configure the pluginβs behavior.
-
source_dir: Path to where the Neovim source is cloned.
Default isvim.fn.expand("~/.local/src/neovim").The source directory path can be any valid path Neovim can write to.
-
build_type: The build type to use.
Default is"RelWithDebInfo".Possible values are:
"Release"- No debugging symbols.
"Debug"- All debugging symbols.
"RelWithDebInfo"- Release with common debugging symbols. -
branch: The branch to track when cloning Neovim.
Default is"master"(nightly).The branch can be used to track the Neovim version.
Possible values are:
"master"- Neovim nightly
"release-0.10"- Neovim 0.10
"release-0.9"- Neovim 0.9
etc.. -
verbose: (boolean) Enable verbose output.
Default isfalse.When set to
false,INFOandDEBUGnotifications from the plugin are suppressed.Possible values are:
true- Enable verbose output.
false- Disable verbose output. -
check_for_updates: (boolean) Enable automatic update checks.
Default isfalse.When set to
false, the plugin will not check for updates automatically.Possible values are:
true- Enable automatic update checks.
false- Disable automatic update checks. -
update_interval: (number) Update interval in seconds.
Default is(60 * 60 * 6)(6 hours).The update interval is the time between checks for new commits in the neovim source repository.
Possible values are:
number- Update interval in seconds. -
notify_updates: (boolean) Produce update notifications
Default isfalse.Possible values are:
true- Produce update notifications at update_interval.false- Do not produce update notifications. -
build_fresh: (boolean) Remove the build directory before compiling.
Default istrue.Possible values are:
true- Always remove the build directory before compiling.
false- Do not remove the build directory before compiling. -
default_keymaps: (boolean) Enable default keymaps.
Default isfalse.When set to
true, the plugin provides a set of default keymaps.Possible values are:
true- Enable default keymaps.
false- Disable default keymaps.
Default configuration:
require("nvim_updater").setup({
source_dir = "~/.local/src/neovim", -- Default source directory
build_type = "RelWithDebInfo", -- Default build mode
branch = "master", -- Represents "nightly"
check_for_updates = false, -- Disable automatic update checks
update_interval = (60 * 60) * 6, -- 6 hours default update interval
notify_updates = false, -- Disable update notifications
verbose = false, -- Disable verbose output
build_fresh = true, -- Remove the build directory before compiling
default_keymaps = false, -- Disable default keymaps
})Note
If you do not wish to specify your own custom keymaps, the plugin provides default keymaps that you can use.
<Leader>uU: Update Neovim using the default configuration.<Leader>uD: Update Neovim using aDebugbuild.<Leader>uR: Update Neovim using aReleasebuild type.<Leader>uC: Remove Neovim source directory.<Leader>un: Show new updates available
You can override these keybindings by providing a table of custom key mappings in the pluginβs setup (as demonstrated in the installation example).
-
:NVUpdateNeovim: Updates Neovim from the source, using the default or custom options youβve set (e.g., source directory, build type, and branch). If the source does not exist at the specified path, the repository is cloned and built.:NVUpdateNeovim
This command pulls the latest changes from the source and builds Neovim based on your configuration.
-
:NVUpdateRemoveSource: Removes the source directory.:NVUpdateRemoveSource
This command is useful if you want to clean up your source directory after youβve built and installed Neovim.
-
:NVUpdateShowNewCommits: Shows new updates available.:NVUpdateShowNewCommits
This command allows you to check for new updates and show the changes in a floating terminal.
-
:NVUpdateShowNewCommitsInDiffView: Shows new updates available in the DiffView plugin.:NVUpdateShowNewCommitsInDiffView
This command allows you to check for new updates and show the changes in the DiffView plugin.
-
:NVUpdatePickNewCommits: Shows new updates available in the Telescope plugin.:NVUpdatePickNewCommits
This command allows you to check for new updates and show the changes in the Telescope plugin.
The plugin exposes several Lua functions.
The following functions are available in the nvim_updater namespace:
Note
The defaults shown below are for the default configuration.
If options aren't provided to the function, the values from
the plugin configuration will be used.
require("nvim_updater").update_neovim( [options] )Available [options]:
source_dir: Path to where the Neovim source is cloned. Default is~/.local/src/neovim.build_type: The build type to use, e.g.,Release,Debug, orRelWithDebInfo. Default isRelWithDebInfo.branch: The branch to track when cloning Neovim. Default ismaster.
require("nvim_updater").remove_source_dir( [options] )Available [options]:
source_dir: Path to where the Neovim source is cloned. Default is~/.local/src/neovim.
require("nvim_updater").generate_source_dir( [options] )Available [options]:
source_dir: Path to where the Neovim source is to be cloned. Default is~/.local/src/neovim.branch: The branch to track when cloning Neovim. Default ismaster.
require("nvim_updater").show_new_commits( [options] )This function opens a floating terminal with the new commits/changes on the remote repository vs the local src directory.
Available [options]:
isupdate: Whether to prompt for updating after showing the changes. Default isfalseshort: Whether to show short commit messages. Default istrue
Options may be specified in the following manners:
-
Specify parameters directly: (must follow the same order as shown above)
require("nvim_updater").show_new_commits(true, false)
-
Use a table: (may be specified in any order or combination)
require("nvim_updater").show_new_commits({ isupdate = true, short = false })
require("nvim_updater").show_new_commits_in_diffview()This function opens DiffView with the new commits/changes on the remote repository vs the local src directory.
require("nvim_updater").show_new_commits_in_telescope()This function opens Telescope with the new commits/changes on the remote repository vs the local src directory.
require("nvim_updater").notify_new_commits( [options] )This function triggers a notification with the new commits/changes on the remote repository vs the local src directory.
Available [options]:
-
show_none: Whether to show a notification when there are no new commits. Default isfalse -
level: The level of notification to use. Default isINFO.
Possible values are:INFO,WARN,ERROR,DEBUG.
require("nvim_updater.utils").open_floating_terminal( [TerminalOptions] )This is a helper function for opening a floating terminal that is used by the updater to display the terminal output.
Available [TerminalOptions]:
-
cmd: Command to run in the terminal. -
filetype: Filetype to assign to the terminal buffer. Default is"nvim_updater_term". -
ispreupdate: (Deprecated) Whether the terminal will be followed by an update build. Default isfalse. -
autoclose: Whether the terminal buffer will be closed when the process ends. Default isfalse. -
enter_insert: Whether the terminal should start in insert mode and maintain it when focused. Default isfalse. -
callback: A function to call when the terminal buffer is closed. Default isnil.[!NOTE]
Theispreupdateoption is now deprecated and will be removed in a future version.The callback function allows you to define a function to be triggered when the terminal buffer is closed.
The callback function is called with the following arguments:
ev: The event object received from the terminal close event.exit_code: The exit code of the process that was run in the terminal buffer.output: The output of the process that was run in the terminal buffer.
In most cases, this will occur after the process has completed.
However, if the window is closed before the process is complete, the exit code returned will be
-1. This allows us to identify those scenarios and handle them appropriately.Here is an example of how to use the callback function:
require("nvim_updater.utils").open_floating_terminal({ command = "my_test_script.sh", -- Command to run filetype = "my_test_script_term", -- Filetype to assign autoclose = true, -- Close the terminal buffer automatically callback = function(result) -- Callback function if result.result_code == -1 then vim.notify( "Terminal closed before process completed", vim.log.levels.ERROR ) elseif result.result_code == 0 then vim.notify( "Terminal process completed successfully", vim.log.levels.INFO ) else vim.notify( "Terminal process failed with exit code: " .. result.result_code, vim.log.levels.ERROR ) end end, })
require("nvim_updater").setup( [options] )See Configuration for setup [options].
There are several features that allow the plugin to better integrate with other plugins.
The plugin assigns a custom filetype to the terminal buffer used to run shell commands for updating Neovim.
You can easily integrate with statusline plugins like lualine by referencing this filetype and applying custom conditions. For example, you may want to hide certain lualine components when this filetype is active in your terminal buffers.
require("lualine").setup {
sections = {
lualine_a = { "mode" },
lualine_b = { "branch" },
lualine_c = {
{ -- Hide filename when using the updater
"filename",
cond = function()
return not string.find(vim.bo.filetype, "neovim_updater_term")
end,
},
{ -- Neovim Updater
function()
local ft = vim.bo.filetype
if ft == "neovim_updater_term.updating" then
return "Neovim Updating.."
elseif ft == "neovim_updater_term.cloning" then
return "Neovim Source Cloning.."
elseif ft == "neovim_updater_term.changes" then
return "Neovim Source Changelog"
end
end,
icon = "σ°
’ ",
color = "lualine_a_terminal",
separator = { left = "ξΆ", right = "ξ΄" },
padding = { left = 0, right = 0 },
cond = function()
return string.find(vim.bo.filetype, "neovim_updater_term") ~= nil
end,
},
},
-- Other lualine components
}This configuration hides the file name in lualine when
the neovim_updater_term root filetype is detected and
shows the nvim-updater component instead.
In this way we can avoid a messy "filename" being displayed when using the updater and instead display a customized "Neovim Updating" message.
The condition can also be applied to any other components you wish to hide when using the updater.
We can also take advantage of the "sub-filetype" to determine the mode of the updater plugin.
The plugin exposes the following sub-filetypes:
neovim_updater_term.updating- Neovim is updatingneovim_updater_term.changes- Showing Neovim source changesneovim_updater_term.cloning- Neovim source directory is cloning
The plugin exposes a function nvim_updater.get_statusline()
This function returns a table of values that can be used to populate your statusline component.
The table is not updated when the function is called. This prevents blocking or caching from negatively impacting your status component.
Instead, set the check_for_updates option to true and configure a
update_interval in the plugin setup options. The plugin will then
periodically check for updates and update the statusline component
automatically at that interval.
Alternatively, set check_for_updates to false and manually
call nvim_updater.utils.get_commit_count() when you'd like to
refresh the updates.
Here is an example adding a component to the lualine statusline:
require("lualine").setup {
sections = {
lualine_x = {
{ -- Neovim Updater Status
function()
return require("nvim_updater").get_statusline().icon_text
end,
color = function()
return require("nvim_updater").get_statusline().color
end,
on_click = function()
require("nvim_updater").show_new_commits({
isupdate = true, -- Update after showing changes
short = true, -- Use short commit messages
})
end,
},
},
},
}This will produce statusline components like this:
Clicking on the component will open the changelog in a floating terminal.
The get_statusline() function provides the following values:
- count: The number of new commits
- text: The text of the status
- icon: An icon representing the update status
- icon_text: The icon and text of the status
- icon_count: The icon and count of the status
- color: A highlight group representing the update status
The plugin exposes a couple additional functions that provide better integration with other plugins.
The plugin exposes a function nvim_updater.show_new_commits_in_diffview()
This function opens the changelog in the DiffView plugin.
If the plugin is not installed/available, the function will produce an error notification and then fallback to opening the changelog in a floating terminal.
The plugin exposes a function nvim_updater.show_new_commits_in_telescope()
This function opens the changelog in the Telescope plugin.
If the plugin is not installed/available, the function will produce an error notification and then fallback to opening the changelog in a floating terminal.
You can also use this plugin to update Neovim directly from the command line or from the desktop.
This is achieved by the use of an environment variable.
The NVIMUPDATER_HEADLESS environment variable can be set
to enable headless mode. In this mode, Neovim will be exited
immediately after the update completes.
Warning
Lazy-loading the plugin may prevent headless operation from functioning properly.
If you receive an error with external calls:
E492: Not an editor command: NVUpdateNeovimThis generally indicates the plugin was not loaded at startup.
After installing the plugin, you can run the following command:
NVIMUPDATER_HEADLESS=1 nvim "+NVUpdateNeovim"This command will open Neovim directly to the updater.
- If the update completes successfully, Neovim will be closed.
- If the update fails, the window will be kept open.
You can also alias this command to a shortcut like nvimup:
bash/zsh:
alias nvimup='NVIMUPDATER_HEADLESS=1 nvim "+NVUpdateNeovim"'fish:
alias --save nvimup='NVIMUPDATER_HEADLESS=1 nvim "+NVUpdateNeovim"'This will allow you to simply run nvimup from anywhere in your terminal.
You can also create a desktop shortcut for this command like so:
nvimup.desktop:
[Desktop Entry]
Name=Neovim Updater
Exec=env NVIMUPDATER_HEADLESS=1 nvim "+NVUpdateNeovim"
Terminal=true
Type=Application
Icon=nvimPlace this file in your ~/.local/share/applications directory.
You will then have a shortcut available in your system's application menu
for updating Neovim called
Neovim Updater. This shortcut will open the updater in your
default terminal emulator.
To use a specific terminal emulator instead of the default, you can modify the desktop file like so:
kitty-nvimup.desktop:
[Desktop Entry]
Name=Neovim Updater (kitty)
Exec=env NVIMUPDATER_HEADLESS=1 kitty nvim "+NVUpdateNeovim"
Terminal=false
Type=Application
Icon=nvimThis example uses the kitty terminal emulator.
You can substitute kitty with any terminal emulator of your choice.
- Platform: The plugin is primarily developed for Linux environments.
Although it may work on macOS or other platforms,
sudo make installis hard-coded and assumes a Linux-based setup. - Neovim Version: This plugin requires Neovim 0.9+ to operate correctly, as it depends on specific Lua API features.
If you find any issues or have suggestions for improvement, feel free to open a GitHub issue or send a pull request. We welcome contributions!
Be sure to include the following information when reporting bugs:
- The output of
nvim --version. - Error messages from Neovim (if any).
- Steps to reproduce the issue.
- Fork the repository.
- Create a new branch for your feature or fix.
- Make your changes, add or update tests, and confirm everything works.
- Submit a pull request with a clear description of the changes made.
This repository is licensed under the MIT License.
You are free to use, modify, and distribute this project in your own work.

