Bring the powerful opencode AI to Neovim — editor-aware research, reviews, and refactors, all in one place.
demo.mp4
- Toggle an
opencodeterminal window within Neovim - Send prompts and commands
- Insert editor context
- Auto-reload edited buffers
Important
Set your opencode theme to system — other themes currently have visual bugs in embedded terminals.
Using lazy.nvim:
{
'NickvanDyke/opencode.nvim',
dependencies = {
'folke/snacks.nvim',
},
---@type opencode.Config
opts = {
-- Your configuration, if any
},
-- stylua: ignore
keys = {
-- opencode.nvim exposes a general, flexible API — customize it to your workflow!
-- But here are some examples to get you started :)
{ '<leader>ot', function() require('opencode').toggle() end, desc = 'Toggle opencode', },
{ '<leader>oa', function() require('opencode').ask() end, desc = 'Ask opencode', mode = { 'n', 'v' }, },
{ '<leader>oA', function() require('opencode').ask('@file ') end, desc = 'Ask opencode about current file', mode = { 'n', 'v' }, },
{ '<leader>on', function() require('opencode').command('/new') end, desc = 'New session', },
{ '<leader>oe', function() require('opencode').prompt('Explain @cursor and its context') end, desc = 'Explain code near cursor' },
{ '<leader>or', function() require('opencode').prompt('Review @file for correctness and readability') end, desc = 'Review file', },
{ '<leader>of', function() require('opencode').prompt('Fix these @diagnostics') end, desc = 'Fix errors', },
{ '<leader>oo', function() require('opencode').prompt('Optimize @selection for performance and readability') end, desc = 'Optimize selection', mode = 'v', },
{ '<leader>od', function() require('opencode').prompt('Add documentation comments for @selection') end, desc = 'Document selection', mode = 'v', },
{ '<leader>ot', function() require('opencode').prompt('Add tests for @selection') end, desc = 'Test selection', mode = 'v', },
},
}Default settings:
---@type opencode.Config { auto_reload = false, -- Automatically reload buffers edited by opencode auto_focus = false, -- Focus the opencode window after prompting command = "opencode", -- Command to launch opencode context = { -- Context to inject in prompts ["@file"] = require("opencode.context").file, ["@files"] = require("opencode.context").files, ["@cursor"] = require("opencode.context").cursor_position, ["@selection"] = require("opencode.context").visual_selection, ["@diagnostics"] = require("opencode.context").diagnostics, ["@quickfix"] = require("opencode.context").quickfix, ["@diff"] = require("opencode.context").git_diff, }, win = { position = "right", -- See https://github.com/folke/snacks.nvim/blob/main/docs/win.md for more window options }, -- See https://github.com/folke/snacks.nvim/blob/main/docs/terminal.md for more terminal options }
When your prompt contains placeholders, the plugin will replace it with context before sending:
| Placeholder | Context |
|---|---|
@file |
Current file |
@files |
Open files |
@cursor |
Cursor position |
@selection |
Selected text |
@diagnostics |
Current buffer diagnostics |
@quickfix |
Quickfix list |
@diff |
Git diff |
You can add custom contexts via opts.context. This example replaces @grapple with files tracked by grapple.nvim:
---@type opencode.Config { context = { ---@return string|nil ['@grapple'] = function() local tags = require('grapple').tags() if not tags or #tags == 0 then return nil end local paths = {} for _, tag in ipairs(tags) do table.insert(paths, tag.path) end return table.concat(paths, ', ') end, } }
- Inspired by (and partially based on) nvim-aider.
- This plugin uses opencode's familiar interface to reduce cognitive load. See sudo-tee/opencode.nvim for a Neovim frontend.
- mcp-neovim-server may better suit your workflow, although it lacks custom contexts and tool calls are slow and unreliable.