Use the AI CLI Integration
mainaider, claude, or copilot) directly within Neovim. Each tool runs in its own scratch terminal window and can access buffer context, cursor position, and diagnostics via helper prompts.repository·main·Indexed 25 days ago
https://github.com/folke/sidekick.nvimA Neovim plugin that integrates Copilot LSP's 'Next Edit Suggestions' (NES) and provides an integrated terminal wrapper for AI CLI tools such as Claude, Gemini, and Codex. It features support for terminal multiplexers like tmux and zellij, predefined prompts and context variables for AI queries, and a Lua API for programmatic control of NES and CLI sessions.
aider, claude, or copilot) directly within Neovim. Each tool runs in its own scratch terminal window and can access buffer context, cursor position, and diagnostics via helper prompts.Install sidekick.nvim using your preferred package manager. Below is a recommended configuration for lazy.nvim that includes essential keybindings for Next Edit Suggestions (NES) and the AI CLI terminal.
{
"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",
},
},
}The module is configured using require("sidekick").setup({ ... }). It provides safe defaults for Next Edit Suggestions (NES), CLI tool integration, Copilot status tracking, and UI icons.
Key configuration sections include:
nes: Settings for Next Edit Suggestions (triggers, diff styles, signs, etc.).cli: Settings for interacting with AI CLI tools, including window layouts (float or split), terminal keymaps, and multiplexer (tmux/zellij) settings.copilot: Status tracking configuration.ui: Customization of icons used by the plugin.debug: Boolean to enable debug logging.Follow these steps to get started with sidekick.nvim:
vim.lsp.enable.:checkhealth sidekick to verify installation.:LspCopilotSignIn if prompted.<Tab> to navigate or apply them.<leader>aa to open AI CLI tools.If you use blink.cmp, you can integrate Next Edit Suggestions (NES) into your <Tab> keymap to allow seamless switching between snippets, NES, and native inline completions.
{
"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",
},
},
},
}To use sidekick.nvim, ensure you meet the following requirements:
>= 0.11.2 or newer.copilot-language-server must be enabled with vim.lsp.enable. You can install it via npm, mason-lspconfig.nvim, or use copilot.lua/copilot.vim which bundle it.lsp/copilot.lua configuration (included in nvim-lspconfig).snacks.nvim: For improved prompt/tool selection.nvim-treesitter-textobjects (main branch): For {function} and {class} context variables.lsof and ps: Recommended on Unix-like systems for detecting running AI CLI sessions.If you only want to use the AI CLI integration and do not require the Next Edit Suggestions feature, you can disable NES in your configuration.
opts = {
nes = { enabled = false },
}The cli.mux section allows you to persist CLI sessions using a multiplexer.
backend: Set to "tmux" or "zellij". Defaults to "zellij" if the ZELLIJ environment variable is detected, otherwise "tmux".enabled: Boolean to enable multiplexer support.create: Determines how new sessions are created: "terminal" (new terminal), "window" (new multiplexer tab), or "split" (new multiplexer split). Note that Zellij only supports "terminal".split: Configuration for vertical/horizontal orientation and size (0-1 percentage).require("sidekick").setup({
cli = {
mux = {
enabled = true,
backend = "tmux",
create = "split",
split = {
vertical = true,
size = 0.5,
},
},
},
})You can extend sidekick.nvim by adding your own AI tools to the cli.tools configuration. Each tool requires a cmd (a table containing the command and flags) and can optionally include custom keys for submitting input.
opts = {
cli = {
tools = {
my_tool = {
cmd = { "my-ai-cli", "--flag" },
-- Optional: custom keymaps for this tool
keys = {
submit = { "<c-s>", function(t) t:send("\n") end },
},
},
},
},
}Define custom prompts in the cli.prompts configuration. Prompts can be static strings using placeholders like {this} or {file}, or dynamic functions that receive a context object (ctx) containing ctx.buf and ctx.row.
Once configured, use them via <leader>ap or the :Sidekick cli prompt command.
opts = {
cli = {
prompts = {
refactor = "Please refactor {this} to be more maintainable",
security = "Review {file} for security vulnerabilities",
custom = function(ctx)
return "Current file: " .. ctx.buf .. " at line " .. ctx.row
end,
},
},
}Within the cli.win configuration, you can define how the terminal window appears and how it behaves.
layout: Choose between "float", "left", "bottom", "top", or "right".float: Configuration for floating windows (width/height).split: Configuration for split windows (width/height).keys: A table of keymaps for the CLI tool. The default mode is "t" (terminal mode).nav: A function to handle window navigation (defaults to vim.cmd.wincmd).require("sidekick").setup({
cli = {
win = {
layout = "right",
split = {
width = 80,
height = 20,
},
keys = {
-- Example: custom keymap
prompt = { "<c-p>", "prompt", mode = "t", desc = "insert prompt" },
},
},
},
})Customize the keybindings used within the Sidekick CLI terminal window using the cli.win.keys option.
Default Keymaps:
q (normal mode): Hide the terminal window.<c-q> (terminal mode): Hide the terminal window.<c-z>: Leave the CLI window.<c-p>: Insert prompt or context.Example Override:
{
"folke/sidekick.nvim",
opts = {
cli = {
win = {
keys = {
-- override the default hide keymap
hide_n = { "<leader>q", "hide", mode = "n" },
-- add a new keymap to say hi
say_hi = {
"<c-h>",
function(t)
t:send("hi!")
end,
},
},
},
},
},
}