Octo.nvim
Edit and review GitHub issues and pull requests from the comfort of your favorite editor
Install / Use
/learn @pwntester/Octo.nvimREADME
:octopus: Octo.nvim
Edit and review GitHub issues, pull requests, and discussions from the comfort of your favorite editor.
Just edit the title, body, or comments as a regular buffer and use :w(rite) to sync with GitHub.
<img src="https://cdn.buymeacoffee.com/buttons/v2/default-blue.png" alt="BuyMeACoffee" width="140">
🌲 Table of Contents
<!--toc:start-->- :octopus: Octo.nvim <!--toc:end-->
💫 Features
- Edit GitHub issues, PRs, and discussions
- Add/Modify/Delete comments
- Add/Remove label, reactions, assignees, project cards, reviewers, etc.
- Add Review PRs
- Interact with
GitHub CLIfromluawithocto.ghmodule.
🔥 Examples
Octo https://github.com/pwntester/octo.nvim/issues/12
Octo issue create
Octo issue create pwntester/octo.nvim
Octo comment add
Octo reaction add hooray
Octo issue edit pwntester/octo.nvim 1
Octo issue edit 1
Octo issue list createdBy=pwntester
Octo issue list neovim/neovim labels=bug,help\ wanted states=OPEN
Octo search assignee:pwntester is:pr
Octo search is:discussion repo:pwntester/octo.nvim category:"Show and Tell"
You can pass GitHub URLs directly to the Octo command, including GitHub Enterprise URLs:
" GitHub.com URLs
Octo https://github.com/pwntester/octo.nvim/issues/12
Octo https://github.com/pwntester/octo.nvim/pull/123
" GitHub Enterprise URLs (hostname is automatically detected)
Octo https://ghe.example.com/owner/repo/issues/456
Octo https://ghe.example.com/owner/repo/pull/789
You can also use octo:// URLs to open issues and PRs directly:
" Open from the default GitHub instance (github.com or configured github_hostname)
:e octo://owner/repo/issue/123
:e octo://owner/repo/pull/456
" Open from a specific GitHub Enterprise instance
:e octo://ghe.example.com/owner/repo/issue/123
:e octo://ghe.example.com/owner/repo/pull/456
" Both singular and plural forms are supported
:e octo://owner/repo/issues/123
:e octo://owner/repo/pulls/456
The octo:// URL format is especially useful for:
- Opening issues/PRs from notes or wiki links without needing to be in the repository directory
- Working with multiple GitHub instances (e.g., GitHub.com and GitHub Enterprise) without setting
GH_HOSTglobally - Creating quick links in your workflow that work regardless of your current directory
From any octo buffer, press <CR> in normal mode to see common actions.
🎯 Requirements
- Neovim
>=0.10.0 - Install GitHub CLI
- If you'd like to use Projects v2
you will need to add the
read:projectscope to yourghtoken. You can do so by runninggh auth refresh -s read:project. - If you'd like to actually modify projects you can instead add the
projectscope to your token instead.
- If you'd like to use Projects v2
you will need to add the
- Install plenary.nvim
- Install one or none of:
- telescope.nvim
- fzf-lua
- snacks.nvim
- default picker uses
vim.ui.select
- Install nvim-web-devicons
After installation, run :checkhealth octo to verify your setup.
📦 Installation
For a basic installation using lazy.nvim, try:
{
"pwntester/octo.nvim",
cmd = "Octo",
opts = {
-- or "fzf-lua" or "snacks" or "default"
picker = "telescope",
-- bare Octo command opens picker of commands
enable_builtin = true,
},
keys = {
{
"<leader>oi",
"<CMD>Octo issue list<CR>",
desc = "List GitHub Issues",
},
{
"<leader>op",
"<CMD>Octo pr list<CR>",
desc = "List GitHub PullRequests",
},
{
"<leader>od",
"<CMD>Octo discussion list<CR>",
desc = "List GitHub Discussions",
},
{
"<leader>on",
"<CMD>Octo notification list<CR>",
desc = "List GitHub Notifications",
},
{
"<leader>os",
function()
require("octo.utils").create_base_search_command { include_current_repo = true }
end,
desc = "Search GitHub",
},
},
dependencies = {
"nvim-lua/plenary.nvim",
"nvim-telescope/telescope.nvim",
-- OR "ibhagwan/fzf-lua",
-- OR "folke/snacks.nvim",
"nvim-tree/nvim-web-devicons",
},
}
🔧 Configuration
Below is the full default configuration for octo.nvim.
require"octo".setup {
use_local_fs = false, -- use local files on right side of reviews
enable_builtin = false, -- shows a list of builtin actions when no action is provided
default_remote = {"upstream", "origin"}, -- order to try remotes
default_merge_method = "merge", -- default merge method which should be used for both `Octo pr merge` and merging from picker, could be `merge`, `rebase` or `squash`
default_delete_branch = false, -- whether to delete branch when merging pull request with either `Octo pr merge` or from picker (can be overridden with `delete`/`nodelete` argument to `Octo pr merge`)
ssh_aliases = {}, -- SSH aliases. e.g. `ssh_aliases = {["github.com-work"] = "github.com"}`. The key part will be interpreted as an anchored Lua pattern.
picker = "telescope", -- or "fzf-lua" or "snacks" or "default"
picker_config = {
use_emojis = false, -- only used by "fzf-lua" picker for now
search_static = true, -- Whether to use static search results (true) or dynamic search (false)
mappings = { -- mappings for the pickers
open_in_browser = { lhs = "<C-b>", desc = "open issue in browser" },
copy_url = { lhs = "<C-y>", desc = "copy url to system clipboard" },
copy_sha = { lhs = "<C-e>", desc = "copy commit SHA to system clipboard" },
checkout_pr = { lhs = "<C-o>", desc = "checkout pull request" },
merge_pr = { lhs = "<C-r>", desc = "merge pull request" },
},
snacks = { -- snacks specific config
actions = { -- custom actions for specific snacks pickers (array of tables)
issues = { -- actions for the issues picker
-- { name = "my_issue_action", fn = function(picker, item) print("Issue action:", vim.inspect(item)) end, lhs = "<leader>a", desc = "My custom issue action" },
},
pull_requests = { -- actions for the pull requests picker
-- { name = "my_pr_action", fn = function(picker, item) print("PR action:", vim.inspect(item)) end, lhs = "<leader>b", desc = "My custom PR action" },
},
notifications = {}, -- actions for the notifications picker
issue_templates = {}, -- actions for the issue templates picker
search = {}, -- actions for the search picker
-- ... add actions for other pickers as needed
},
},
},
comment_icon = "▎", -- comment marker
outdated_icon = " ", -- outdated indicator
resolved_icon = " ", -- resolved indicator
reaction_viewer_hint_icon = " ", -- marker for user reactions
commands = {}, -- additional subcommands made available to `Octo` command
users = "search", -- Users for assignees or reviewers. Values: "search" | "mentionable" | "assignable"
user_icon = " ", -- user icon
ghost_icon = " ", -- ghost icon
copilot_icon = " ", -- copilot icon
timeline_marker = " ", -- timeline marker
timeline_indent = 2, -- timeline indentation
use_timeline_icons = true, -- toggle timeline icons
timeline_icons = { -- the default icons based on timelineItems
auto_squash = " ",
commit_push = " ",
comment_deleted = " ",
force_push = " ",
draft = " ",
