⥠A Chat interface for Ai agents in Neovim that supports Claude, Gemini, Codex, OpenCode, Cursor Agent, and Auggie through the Agent Client Protocol (ACP).
Agentic.nvim brings your AI assistant to Neovim through the implementation of the Agent Client Protocol (ACP).
Without reinventing the wheel, Agentic.nvim is the interface, your agent is the Brain. This plugin will use all the same configurations and authentication methods you already have set up on your terminal.
You can start your work in Neovim, close it, and resume from the terminal, if your agent supports session restoration. (Session restoration inside Neovim is not supported yet, ACP limitation)
You'll get the same results and performance as you would when using the ACP provider's official CLI directly from the terminal.
There're no hidden prompts or magic happening behind the scenes. Just a Chat interface, your colors, and your keymaps.
claude /login, or gemini auth login
once and, if they're working on your Terminal, they will work automatically
on Agentic./ in the prompt as the first character@ to trigger autocomplete for workspace files@file1.lua @file2.luaDefault, Auto Accept, Plan mode, etc... (depends on the provider)https://github.com/user-attachments/assets/4b33bb18-95f7-4fea-bc12-9a9208823911
https://github.com/user-attachments/assets/6ae57136-9c08-4d71-bc8a-59babc49be4d
https://github.com/user-attachments/assets/96a11aae-3095-46e7-86f1-ccc02d21c04f
https://github.com/user-attachments/assets/b6b43544-a91e-407f-834e-4b4de41259f8
@ to fuzzy find any file:https://github.com/user-attachments/assets/c6653a8b-20ef-49c8-b644-db0df1b342f0
We recommend using pnpmpnpm uses a constant, static global path, that's resilient to updates.
While npm loses global packages every time you change Node versions using
tools like nvm, fnm, etc...
You are free to chose any installation method you prefer!
| Provider | Install |
|---|---|
| claude-code-acp | pnpm add -g @zed-industries/claude-code-acp OR npm i -g @zed-industries/claude-code-acp OR Download binary |
| gemini-cli | pnpm add -g @google/gemini-cli OR npm i -g @google/gemini-cli OR brew install --cask gemini |
| codex-acp | pnpm add -g @zed-industries/codex-acp OR npm i -g @zed-industries/codex-acp OR Download binary |
| opencode | pnpm add -g opencode-ai OR npm i -g opencode-ai OR brew install opencode OR curl -fsSL https://opencode.ai/install | bash |
| cursor-agent | pnpm add -g @blowmage/cursor-agent-acp OR npm i -g @blowmage/cursor-agent-acp |
| auggie | pnpm add -g @augmentcode/auggie OR npm i -g @augmentcode/auggie OR See Auggie docs |
[!WARNING]
These install commands are here for convenience, please always refer to the official installation instructions from the respective ACP provider.
[!NOTE]
Why install ACP provider CLIs globally? shai-hulud should be reason enough. đ Pin your versions!
But frontend projects with strict package management policies will fail to start when usingnpx ...
{
"carlos-algms/agentic.nvim",
opts = {
-- Available by default: "claude-acp" | "gemini-acp" | "codex-acp" | "opencode-acp" | "cursor-acp" | "auggie-acp"
provider = "claude-acp", -- setting the name here is all you need to get started
},
-- these are just suggested keymaps; customize as desired
keys = {
{
"<C-\\>",
function() require("agentic").toggle() end,
mode = { "n", "v", "i" },
desc = "Toggle Agentic Chat"
},
{
"<C-'>",
function() require("agentic").add_selection_or_file_to_context() end,
mode = { "n", "v" },
desc = "Add file or selection to Agentic to Context"
},
{
"<C-,>",
function() require("agentic").new_session() end,
mode = { "n", "v", "i" },
desc = "New Agentic Session"
},
},
}
You don't have to copy and paste anything from the default config, linking it
here for ease access and reference:
lua/agentic/config_default.lua.
You can customize the supported ACP providers by configuring the acp_providers
property:
[!NOTE]
You don't have to override anything or include these in your setup!
These are just examples of how you can customize the commands, env, etc.
{
"carlos-algms/agentic.nvim",
opts = {
acp_providers = {
-- Override existing provider (e.g., add API key)
-- Agentic.nvim doesn't require API keys
-- Only add it if that's how you prefer to authenticate
["claude-acp"] = {
env = {
ANTHROPIC_API_KEY = os.getenv("ANTHROPIC_API_KEY"),
},
},
-- Example of how override the ACP command to suit your installation, if needed
["codex-acp"] = {
command = "~/.local/bin/codex-acp",
},
},
},
}
Provider Configuration Fields:
command (string) - The CLI command to execute (must be in PATH or absolute
path)args (table, optional) - Array of command-line argumentsenv (table, optional) - Environment variables to set for the processdefault_mode (string, optional) - Default mode ID to set on session creation
(e.g., "bypassPermissions", "plan")[!NOTE]
Customizing a provider only requires specifying the fields you want to override, not the entire configuration.
If you prefer a specific agent mode other than the provider's default, you can configure it per provider:
{
"carlos-algms/agentic.nvim",
opts = {
acp_providers = {
["claude-acp"] = {
-- Automatically switch to this mode when a new session starts
default_mode = "bypassPermissions",
},
},
},
}
The mode will only be set if it's available from the provider. Use <S-Tab> to
see available modes for your provider.
You can customize the behavior of individual chat widget windows by configuring
the win_opts property for each window. These options override the default
window settings.
You can customize the header text for each panel in the chat widget using either a table configuration or a custom render function.
{
"carlos-algms/agentic.nvim",
opts = {
headers = {
chat = {
title = "ķ°ģ My Custom Chat Title",
suffix = "<S-Tab>: change mode",
},
-- ...
},
},
}
For complete control over header rendering, provide a function that receives the header parts:
{
"carlos-algms/agentic.nvim",
opts = {
headers = {
chat = function(parts)
local header = parts.title
if parts.context then
header = header .. " [" .. parts.context .. "]"
end
if parts.suffix then
header = header .. " âĸ " .. parts.suffix
end
return header
end,
},
},
}
| Function | Description |
|---|---|
:lua require("agentic").toggle() |
Toggle chat sidebar |
:lua require("agentic").open() |
Open chat sidebar (keep open if already visible) |
:lua require("agentic").close() |
Close chat sidebar |
:lua require("agentic").add_selection() |
Add visual selection to context |
:lua require("agentic").add_file() |
Add current file to context |
:lua require("agentic").add_selection_or_file_to_context() |
Add selection (if any) or file to the context |
:lua require("agentic").new_session() |
Start new chat session, destroying and cleaning the current one |
:lua require("agentic").stop_generation() |
Stop current generation or tool execution (session stays active) |
Open and Toggle supports optional parameter:
true) - Whether to automatically
add the current visual selection or file to context when opening the Chat-- Open the chat without adding anything to context
require("agentic").open({ auto_add_to_context = false })
When adding files or selections to context, you can also specify whether to focus the prompt input after opening the chat:
true) - Whether to move cursor to prompt
input after opening the chatAvailable on: add_selection(opts), add_file(opts),
add_selection_or_file_to_context(opts)
-- Add selection without focusing the prompt
require("agentic").add_selection({ focus_prompt = false })
These keybindings are automatically set in Agentic buffers:
| Keybinding | Mode | Description |
|---|---|---|
<S-Tab> |
n/v/i | Switch agent mode (only available if provider supports modes) |
<CR> |
n | Submit prompt |
<C-s> |
n/v/i | Submit prompt |
<localLeader>p |
n | Paste image from clipboard in the Prompt buffer |
<C-v> |
i | Paste image from clipboard (same as Claude-code) |
q |
n | Close chat widget |
d |
n | Remove file or code selection at cursor |
d |
v | Remove multiple selected files or code selections |
]c |
n | Navigate to next diff hunk (when diff preview is active) |
[c |
n | Navigate to previous diff hunk (when diff preview is active) |
You can customize the default keybindings by configuring the keymaps option in
your setup:
{
"carlos-algms/agentic.nvim",
opts = {
keymaps = {
-- Keybindings for ALL buffers in the widget (chat, prompt, code, files)
widget = {
close = "q", -- String for a single keybinding
change_mode = {
{
"<S-Tab>",
mode = { "i", "n", "v" }, -- Specify modes for this keybinding
},
},
},
-- Keybindings for the prompt buffer only
prompt = {
submit = {
"<CR>", -- Normal mode, just Enter
{
"<C-s>",
mode = { "n", "v", "i" },
},
},
paste_image = {
{
"<localLeader>p",
mode = { "n" },
},
{
"<C-v>", -- Same as Claude-code in insert mode
mode = { "i" },
}
},
},
-- Keybindings for diff preview navigation
diff_preview = {
next_hunk = "]c",
prev_hunk = "[c",
},
},
},
}
Keymap Configuration Format:
close = "q" - Simple keybinding (normal mode by default)submit = { "<CR>", "<C-s>" } - Multiple keybindings (normal mode
only){ "<C-s>", mode = { "i", "v" } } - Keybinding with
specific modesThe header text in the chat and prompt buffers will automatically update to show the appropriate keybinding for the current mode.
When the agent makes file edits, agentic.nvim can show a preview of the changes before you accept or reject them. You can configure the diff preview layout:
{
"carlos-algms/agentic.nvim",
opts = {
diff_preview = {
enabled = true,
layout = "split", -- "split" or "inline"
center_on_navigate_hunks = true,
},
},
}
Layout Options:
"split" (default) - Side-by-side diff view"inline" - Unified diff view in a single bufferNavigation:
Use ]c and [c to navigate between diff hunks (configurable).
Note: Changing the layout requires restarting Neovim.
Type / in the Prompt buffer to see available slash commands with
auto-completion.
The /new command is always available to start a new session, other commands
are provided by your ACP provider.
You can reference and add files to the context by typing @ in the Prompt.
It will trigger the native Neovim completion menu with a list of all files in
the current workspace.
rg, fd, git ls-files, or lua globs as
fallback@file1.lua @file2.luaYou can drag-and-drop images into the Prompt buffer or paste images and screenshots directly from your clipboard.
The support still depends on the ACP provider capabilities, but most of them support images in the conversation.
Drag-and-drop should work out of the box if your terminal supports it, no need for extra configuration or plugins.
But, if you want to paste screenshots directly from your clipboard, you'll need
to install the img-clip.nvim dependency:
{
"carlos-algms/agentic.nvim",
dependencies = {
{ "hakonharnes/img-clip.nvim", opts = {} }
}
-- ... rest of your config
}
Please note img-clip.nvim, on Linux depends on xclip (x11) or wl-clipboard
(wayland), or pngpaste on macOS, Windows requires no extra dependencies.
Then just press <localleader>p in the Prompt buffer to paste the image from
your clipboard.
NOTE: Due to Terminal and Neovim limitations, when pasting an image from the Clipboard, there's no way of intercepting it, as it's considered binary and not text, so either your Terminal or Neovim will just ignore and do nothing with it, that's why we need the help of the external plugin. It's totally out of our control.
Agentic automatically includes environment and project information in the first message of each session:
This helps the AI Agent understand the context of the current project without having to run additional commands or grep through files, the goals is to reduce time for the first response.
Agentic.nvim provides hooks that let you respond to specific events during the chat lifecycle. These are useful for logging, notifications, analytics, or integrating with other plugins.
{
"carlos-algms/agentic.nvim",
opts = {
hooks = {
-- Called when the user submits a prompt
on_prompt_submit = function(data)
-- data.prompt: string - The user's prompt text
-- data.session_id: string - The ACP session ID
-- data.tab_page_id: number - The Neovim tabpage ID
vim.notify("Prompt submitted: " .. data.prompt:sub(1, 50))
end,
-- Called when the agent finishes responding
on_response_complete = function(data)
-- data.session_id: string - The ACP session ID
-- data.tab_page_id: number - The Neovim tabpage ID
-- data.success: boolean - Whether response completed without error
-- data.error: table|nil - Error details if failed
if data.success then
vim.notify("Agent finished!", vim.log.levels.INFO)
else
vim.notify("Agent error: " .. vim.inspect(data.error), vim.log.levels.ERROR)
end
end,
}
}
}
Agentic.nvim uses custom highlight groups that you can override to match your colorscheme.
| Highlight Group | Purpose | Default |
|---|---|---|
AgenticDiffDelete |
Deleted lines in diff view | Links to DiffDelete |
AgenticDiffAdd |
Added lines in diff view | Links to DiffAdd |
AgenticDiffDeleteWord |
Word-level deletions in diff | bg=#9a3c3c, bold=true |
AgenticDiffAddWord |
Word-level additions in diff | bg=#155729, bold=true |
AgenticStatusPending |
Pending tool call status indicator | bg=#5f4d8f |
AgenticStatusCompleted |
Completed tool call status indicator | bg=#2d5a3d |
AgenticStatusFailed |
Failed tool call status indicator | bg=#7a2d2d |
AgenticCodeBlockFence |
The left border decoration on tool calls | Links to Directory |
AgenticTitle |
Window titles in sidebar | bg=#2787b0, fg=#000000, bold=true |
If any of these highlight exists, Agentic will use it instead of creating new ones.
To get Copilot suggestions while you are typing your prompt, you need to tell
Copilot to attach to the AgenticInput filetype.
{
"github/copilot.vim",
-- ....
init = function()
vim.g.copilot_filetypes = {
AgenticInput = true,
}
end,
}
{
"zbirenbaum/copilot.lua",
-- ....
opts = {
-- Override should_attach to allow copilot in AgenticInput buffers
-- AgenticInput uses buftype = "nofile" which copilot.lua rejects by default
should_attach = function(bufnr, bufname)
local filetype = vim.bo[bufnr].filetype
if filetype == "AgenticInput" then
return true
end
-- Delegate to default behavior for all other buffers
local default_should_attach =
require("copilot.config.should_attach").default
return default_should_attach(bufnr, bufname)
end,
},
}
If you're using lualine.nvim or similar statusline plugins, configure it to ignore Agentic windows to prevent conflicts with custom window decorations:
require('lualine').setup({
options = {
disabled_filetypes = {
statusline = { 'AgenticChat', 'AgenticInput', 'AgenticCode', 'AgenticFiles' },
winbar = { 'AgenticChat', 'AgenticInput', 'AgenticCode', 'AgenticFiles' },
}
}
})
This ensures that Agentic's custom window titles and statuslines render correctly without interference from your statusline plugin.
Only the AgenticChat buffer is properly set as markdown and starts
Treesitter parser, you only need to mention it in your markdown render plugin
setup.
{
"MeanderingProgrammer/render-markdown.nvim",
-- ...
opts = {
file_types = { "markdown", "md", "AgenticChat" },
}
}
You can disable blink.cmp from attaching to Agentic prompt buffers by adding
the following to your blink.cmp setup:
require('blink.cmp').setup({
enabled = function()
return not vim.tbl_contains({"AgenticInput"}, vim.bo.filetype)
end,
})
You can disable nvim-cmp from attaching to Agentic prompt buffers by using
filetype-specific setup or the enabled option:
-- Option 1: Filetype-specific setup (disable all sources)
require('cmp').setup.filetype('AgenticInput', {
sources = {}
})
-- Option 2: Global enabled function
require('cmp').setup({
enabled = function()
return not vim.tbl_contains({"AgenticInput"}, vim.bo.filetype)
end,
})
Verify your installation and dependencies:
:checkhealth agentic
This will check:
Enable debug logging to troubleshoot issues:
{
"carlos-algms/agentic.nvim",
opts = {
debug = true,
-- ... rest of your options
}
}
View debug logs with :messages (lost after restarting Neovim)
View messages exchanged with the ACP provider in the log file at:
(persistent until you delete it)
~/.cache/nvim/agentic_debug.logMIT License
Feel free to copy, modify, and distribute, just be a good samaritan and include
the the acknowledgments đ.