Create GitHub releases from inside Neovim, driven by the gh CLI.
Instead of gh's terminal prompts, nvim-ghrelease lists your existing releases,
suggests the next semantic version, and asks each question gh release create asks.
Free-text answers (tag, title, release notes) open in a dedicated buffer per step —
edit, then :wq to move to the next question. When every answer is collected it runs
gh release create and reports the new release URL.
https://github.com/user-attachments/assets/47dda2ee-c6a8-4229-8cee-7135bb7712a5
major / minor / patch / prerelease / custom).:wq saves the answer and advances.Publish / Save as draft / Cancel step, plus a prerelease question.vim.system), no blocking of the editor.vim.system; the plugin refuses to load and warns on older versions). Tested in CI on 0.10, 0.11, stable, and nightly.gh, installed and authenticated: gh auth login{
"mesirendon/nvim-ghrelease",
-- Load at startup so the default keymap (<leader>gr) is registered.
event = "VeryLazy",
opts = {}, -- optional; see Configuration
}
setup()(viaopts) is what installs the default keymaps, so the plugin must be loaded for them to exist. If you prefer to lazy-load only on the keypress, disable the built-in maps and let lazy own the key:{ "mesirendon/nvim-ghrelease", opts = { keymaps = false }, keys = { { "<leader>gr", "<cmd>GhRelease<cr>", desc = "GitHub Release: create" } }, }
use({
"mesirendon/nvim-ghrelease",
config = function()
require("ghrelease").setup()
end,
})
Plug 'mesirendon/nvim-ghrelease'
" then, in your Lua config:
lua require('ghrelease').setup()
add({ source = "mesirendon/nvim-ghrelease" })
Calling setup() is optional — the :GhRelease command is available as soon as the
plugin is on the runtimepath.
Run inside a GitHub repository:
:GhRelease
or from Lua:
require("ghrelease").create()
Then follow the steps:
<CR>, q, or <Esc> to continue.custom.:wq.In any editing buffer, :wq accepts and continues; :q keeps whatever is shown.
setup() installs one default keymap, sitting in the <leader>g (git) family:
| Keys | Mode | Action | Command |
|---|---|---|---|
<leader>gr |
n |
GitHub Release: create | :GhRelease |
The description shows up in which-key automatically under your git group.
Pass a keymaps table to setup() (or opts in lazy.nvim). Each key is an action
name; the value is the normal-mode lhs, or false to skip that action:
require("ghrelease").setup({
keymaps = {
create = "<leader>oR", -- remap "create" to <leader>oR
},
})
Disable a single action:
require("ghrelease").setup({
keymaps = { create = false },
})
Disable all default keymaps and map it yourself:
require("ghrelease").setup({ keymaps = false })
vim.keymap.set("n", "<leader>R", "<cmd>GhRelease<cr>",
{ desc = "GitHub Release: create", silent = true })
Defaults, with overrides passed to setup():
require("ghrelease").setup({
list_limit = 30, -- releases shown in the context view
default_bump = "patch", -- highlighted first in the version menu
tag_prefix = "v", -- prefix for the suggested first tag
first_tag = "v0.1.0", -- seed tag when the repo has no releases
win = "float", -- editing window style: "float" | "split" | "vsplit"
height = 12, -- editing buffer height / float rows
keymaps = { -- default keymaps; false disables all (see Keymaps)
create = "<leader>gr",
},
})
The choice menus use vim.ui.select, so they integrate automatically with
dressing.nvim, telescope-ui-select, etc.
Run the pure version-logic tests headlessly:
nvim --headless -l tests/version_spec.lua
MIT