by folke
Your Neovim AI sidekick
# Add to your Claude Code skills
git clone https://github.com/folke/sidekick.nvimsidekick.nvimsidekick.nvim is your Neovim AI sidekick that integrates Copilot LSP's "Next Edit Suggestions" with a built-in terminal for any AI CLI. Review and apply diffs, chat with AI assistants, and streamline your coding, without leaving your editor.
π€ Next Edit Suggestions (NES) powered by Copilot LSP
π¬ Integrated AI CLI Terminal
tmux and zellij integration.No comments yet. Be the first to share your thoughts!
π Extensible and Customizable
>= 0.11.2 or newervim.lsp.enable. Can be installed in multiple ways:
npm or your OS's package managerlsp/copilot.lua configuration.
main branch) for {function} and {class} context variables (optional)vim.lsp.enable:checkhealth sidekick:LspCopilotSignIn<Tab> to navigate through or apply suggestions<leader>aa to open AI CLI tools[!NOTE] New to Next Edit Suggestions? Unlike inline completions, NES suggests entire refactorings or multi-line changes anywhere in your file - think of it as Copilot's "big picture" suggestions.
Install with your favorite manager. With lazy.nvim:
{
"folke/sidekick.nvim",
opts = {
-- add any options here
cli = {
mux = {
backend = "zellij",
enabled = true,
},
},
},
keys = {
{
"<tab>",
function()
-- if there is a next edit, jump to it, otherwise apply it if any
if not require("sidekick").nes_jump_or_apply() then
return "<Tab>" -- fallback to normal tab
end
end,
expr = true,
desc = "Goto/Apply Next Edit Suggestion",
},
{
"<c-.>",
function() require("sidekick.cli").focus() end,
desc = "Sidekick Focus",
mode = { "n", "t", "i", "x" },
},
{
"<leader>aa",
function() require("sidekick.cli").toggle() end,
desc = "Sidekick Toggle CLI",
},
{
"<leader>as",
function() require("sidekick.cli").select() end,
-- Or to select only installed tools:
-- require("sidekick.cli").select({ filter = { installed = true } })
desc = "Select CLI",
},
{
"<leader>ad",
function() require("sidekick.cli").close() end,
desc = "Detach a CLI Session",
},
{
"<leader>at",
function() require("sidekick.cli").send({ msg = "{this}" }) end,
mode = { "x", "n" },
desc = "Send This",
},
{
"<leader>af",
function() require("sidekick.cli").send({ msg = "{file}" }) end,
desc = "Send File",
},
{
"<leader>av",
function() require("sidekick.cli").send({ msg = "{selection}" }) end,
mode = { "x" },
desc = "Send Visual Selection",
},
{
"<leader>ap",
function() require("sidekick.cli").prompt() end,
mode = { "n", "x" },
desc = "Sidekick Select Prompt",
},
-- Example of a keybinding to open Claude directly
{
"<leader>ac",
function() require("sidekick.cli").toggle({ name = "claude", focus = true }) end,
desc = "Sidekick Toggle Claude",
},
},
}
[!TIP] It's a good idea to run
:checkhealth sidekickafter install.
{
"saghen/blink.cmp",
---@module 'blink.cmp'
---@type blink.cmp.Config
opts = {
keymap = {
["<Tab>"] = {
"snippet_forward",
function() -- sidekick next edit suggestion
return require("sidekick").nes_jump_or_apply()
end,
function() -- if you are using Neovim's native inline completions
return vim.lsp.inline_completion.get()
end,
"fallback",
},
},
},
}
{
"folke/sidekick.nvim",
opts = {
-- add any options here
},
keys = {
{
"<tab>",
function()
-- if there is a next edit, jump to it, otherwise apply it if any
if require("sidekick").nes_jump_or_apply() then
return -- jumped or applied
end
-- if you are using Neovim's native inline completions
if vim.lsp.inline_completion.get() then
return
end
-- any other things (like snippets) you want to do on <tab> go here.
-- fall back to normal tab
return "<tab>"
end,
mode = { "i", "n" },
expr = true,
desc = "Goto/Apply Next Edit Suggestion",
},
},
}
After installation sign in with :LspCopilotSignIn if prompted.
The module ships with safe defaults and exposes everything through
require("sidekick").setup({ ... }).
---@class sidekick.Config
local defaults = {
nes = {
---@type boolean|fun(buf:integer):boolean?
enabled = function(buf)
return vim.g.sidekick_nes ~= false and vim.b.sidekick_nes ~= false
end,
debounce = 100,
trigger = {
-- events that trigger sidekick next edit suggestions
events = { "ModeChanged i:n", "TextChanged", "User SidekickNesDone" },
},
clear = {
-- events that clear the current next edit suggestion
events = { "TextChangedI", "InsertEnter" },
esc = true, -- clear next edit suggestions when pressing <Esc>
},
---@class sidekick.diff.Opts
---@field inline? "words"|"chars"|false Enable inline diffs
---@field show? "always"|"cursor" `cursor` will only show the diff when the cursor is at the edit position.
diff = {
inline = "words",
show = "always",
},
signs = true, -- show signs for next edit suggestions
jumplist = true, -- add an entry to the jumplist
},
-- Work with AI cli tools directly from within Neovim
cli = {
watch = true, -- notify Neovim of file changes done by AI CLI tools
---@class sidekick.win.Opts
win = {
--- This is run when a new terminal is created, before starting it.
--- Here you can change window options `terminal.opts`.
---@param terminal sidekick.cli.Terminal
config = function(terminal) end,
wo = {}, ---@type vim.wo
bo = {}, ---@type vim.bo
layout = "right", ---@type "float"|"left"|"bottom"|"top"|"right"
--- Options used when layout is "float"
---@type vim.api.keyset.win_config
float = {
width = 0.9,
height = 0.9,
},
-- Options used when layout is "left"|"bottom"|"top"|"right"
---@type vim.api.keyset.win_config
split = {
width = 80, -- set to 0 for default split width
height = 20, -- set to 0 for default split height
},
--- CLI Tool Keyma