opencode.nvim is a free, open source ai interaction & interfaces project written in Lua and released under MIT. It has 3,834 GitHub stars, 159 forks and 6 open issues, and was last pushed 3 days ago. On this registry it ranks #50 of 76 tracked projects in AI Interaction & Interfaces, with 5 head-to-head comparisons available. It gained 6 stars over the last 3 tracked days.

What is opencode.nvim?

What it is

opencode.nvim is Neovim plugin, Lua code, MIT license. It connects Neovim to OpenCode, AI coding assistant. It lives in Neovim plugin ecosystem, under AI and machine learning, AI interaction and interfaces. It targets users wanting AI help without leaving terminal text editor. It bridges Neovim buffers, selections, cursor position, and prompt selection to OpenCode. It keeps user in known Neovim flow. It does not replace OpenCode interface. It uses OpenCode existing terminal user interface and API through standard Neovim interfaces. Topic tags include ai, ai-agents, ai-assistant, lua, neovim, neovim-plugin, nvim, opencode, plugin, terminal. Repository facts: 3826 stars, 158 forks, 6 open issues, 1 year age, last push 2026-09-14T14:30:31Z.

Problem solved is context loss. AI works best at small, focused scopes, pair programmer with human driving. Without editor bridge, user copies code, pastes prompts, moves between windows. opencode.nvim injects editor context and sends it to OpenCode. It exposes Lua functions for ask, select, operator, command, prompt, format. It keeps environment, config, flow.

Key capabilities

  • Connects to any OpenCode server, or starts integrated OpenCode instance.
  • Injects editor context, including cursor, selection, buffer, and @this references.
  • Provides prompt input with completions and highlights, and lets user select built-in and custom prompts.
  • Executes OpenCode commands from Neovim, including session.half.page.up and session.half.page.down.
  • Accepts, rejects, reloads OpenCode edits.
  • Handles OpenCode events as Neovim autocmds.
  • Exposes Lua functions ask, select, operator, command, prompt, format.

Who uses it and how

  • Developers editing code in Neovim use ask keymap to send current range or line to OpenCode.
  • Users with multiple buffers use selection and buffer context for focused questions.
  • People using custom prompts use select interface to choose prompt.
  • Operators use command execution for session scrolling and other OpenCode commands.
  • Snacks.nvim users map picker selection to opencode.format and prompt; blink.cmp users configure completion integration.

Getting started

Install opencode.nvim with vim.pack, lazy.nvim, or nixvim, using nickjvandyke/opencode.nvim, version *, or pkgs.vimPlugins.opencode-nvim. Then set vim.g.opencode_opts and map require("opencode").ask, select, operator, command.

When to use it — and when not to

Use when user already works in Neovim and has OpenCode server or wants integrated instance, because it fits small, focused AI pairing, not another interaction model. Trade-off is narrow scope and dependence on OpenCode and Neovim; user must maintain server or local instance and configure keymaps. No database, SMTP, or storage duties are listed, and no paid product replacement is named.

project readme (upstream, from github) — read inline

opencode.nvim

Neovim plugin that integrates with OpenCode to keep you in the flow that you already know.

https://github.com/user-attachments/assets/e85e021c-fa8f-466e-830c-c667b28f611e

⭐ Motivation

AI works best at small, focused scopes — as a pair programmer with the human driving. You stay in control, craft the code that matters, and keep your skills sharp. opencode.nvim just provides the context and connection to make that pairing seamless.

Rather than introduce yet another interaction model, opencode.nvim leverages OpenCode's existing TUI and API via standard Neovim interfaces. You keep your environment, your config, your flow.

For me, the best tools are the ones that "just work." opencode.nvim is designed to be one of them.

✨ Features

  • Connect to any OpenCode server, or start an integrated instance
  • Inject editor context (cursor, selection, buffer, etc.)
  • Input prompts with completions and highlights
  • Select from built-in and custom prompts
  • Execute OpenCode commands
  • Accept/reject and reload OpenCode edits
  • Handle OpenCode events as autocmds
  • Simple, sensible, Vim-y defaults and interfaces

📦 Setup

vim.pack (recommended)

vim.pack.add({
  {
    src = "https://github.com/nickjvandyke/opencode.nvim",
    version = vim.version.range("*"), -- Latest stable release
  },
})

---@type opencode.Opts
vim.g.opencode_opts = {
  -- Your configuration, if any; goto definition on the type for details
}

-- Recommended/example keymaps
vim.keymap.set({ "n", "x" }, "<C-a>",   function() require("opencode").ask("@this: ") end,                    { desc = "Ask OpenCode…" })
vim.keymap.set({ "n", "x" }, "<C-x>",   function() require("opencode").select() end,                          { desc = "Select OpenCode…" })
vim.keymap.set({ "n", "x" }, "go",      function() return require("opencode").operator("@this ") end,         { desc = "Append range to OpenCode", expr = true })
vim.keymap.set({ "n" },      "goo",     function() return require("opencode").operator("@this ") .. "_" end,  { desc = "Append line to OpenCode", expr = true })
vim.keymap.set({ "n" },      "<S-C-u>", function() require("opencode").command("session.half.page.up") end,   { desc = "Scroll OpenCode up" })
vim.keymap.set({ "n" },      "<S-C-d>", function() require("opencode").command("session.half.page.down") end, { desc = "Scroll OpenCode down" })
lazy.nvim
{
  "nickjvandyke/opencode.nvim",
  version = "*", -- Latest stable release
  config = function()
    ---@type opencode.Opts
    vim.g.opencode_opts = {
      -- Your configuration, if any; goto definition on the type for details
    }

    -- Recommended/example keymaps
    vim.keymap.set({ "n", "x" }, "<C-a>",   function() require("opencode").ask("@this: ") end,                    { desc = "Ask OpenCode…" })
    vim.keymap.set({ "n", "x" }, "<C-x>",   function() require("opencode").select() end,                          { desc = "Select OpenCode…" })
    vim.keymap.set({ "n", "x" }, "go",      function() return require("opencode").operator("@this ") end,         { desc = "Append range to OpenCode", expr = true })
    vim.keymap.set({ "n" },      "goo",     function() return require("opencode").operator("@this ") .. "_" end,  { desc = "Append line to OpenCode", expr = true })
    vim.keymap.set({ "n" },      "<S-C-u>", function() require("opencode").command("session.half.page.up") end,   { desc = "Scroll OpenCode up" })
    vim.keymap.set({ "n" },      "<S-C-d>", function() require("opencode").command("session.half.page.down") end, { desc = "Scroll OpenCode down" })
  end,
}
nixvim
programs.nixvim = {
  extraPlugins = [
    pkgs.vimPlugins.opencode-nvim
  ];
};

Integrations

The below examples are specific, but generalize to other plugins.

snacks.nvim
require("snacks").setup({
  input = {
    enabled = true, -- Enhances Ask
  },
  picker = {
    enabled = true, -- Enhances Select
    win = {
      input = {
        keys = {
          ["<a-o>"] = { "opencode_send", mode = { "n", "i" } },
        },
      },
    },
    actions = {
      opencode_send = function(picker) ---@param picker snacks.Picker
        local items = vim.tbl_map(function(item) ---@param item snacks.picker.Item
          return item.file
            and require("opencode").format({ path = item.file, from = item.pos, to = item.end_pos })
            or item.text
        end, picker:selected({ fallback = true }))

        require("opencode").prompt(table.concat(items, ", ") .. " ")
      end,
    },
  },
})
blink.cmp
-- Configure blink.cmp to show completions in Ask from opencode.nvim's in-process LSP.
-- Only applicable when using snacks.input.
require("blink.cmp").setup({
  sources = {
    -- Either enable LSP (and optionally buffer) source globally
    default = { 'lsp', 'buffer' },
    -- Or only for Ask
    per_filetype = {
      opencode_ask = { 'lsp', 'buffer' },
    },
    -- Display buffer completions (if included above) when no LSP completions are available
    providers = { lsp = { fallbacks = {} } },
  },
})
lualine.nvim
require("lualine").setup({
  sections = {
    lualine_z = {
      {
        -- Show the currently connected server and its status
        require("opencode").statusline,
      },
    },
  },
})

[!TIP] Run :checkhealth opencode after setup.

⚙️ Configuration

opencode.nvim provides a rich and reliable default experience — see all available options and their defaults here.

Contexts

opencode.nvim replaces placeholders in prompts with the corresponding context:

Placeholder Context
@this Range or selection if any, else cursor position
@buffer Current buffer
@buffers Open buffers
@diagnostics Diagnostics within the range or selection if any, else in the current buffer
@marks Global marks
@quickfix Quickfix list
@visible Visible text

[!TIP] OpenCode reads referenced files from disk — save your changes!

Prompts

Select prompts to review, explain, and improve your code:

Name Prompt
diagnostics Explain @diagnostics
document Add comments documenting @this
explain Explain @this and its context
fix Fix @diagnostics
implement Implement @this
optimize Optimize @this for performance and readability
review Review @this for correctness and readability
test Add tests for @this

Server

Run opencode locally however you like and opencode.nvim will find them! Or point vim.g.opencode_opts.server.url to a specific server, including remotes.

[!IMPORTANT] You must run opencode with the --port flag to expose its server.

If opencode.nvim can't find a running opencode, it starts one via vim.g.opencode_opts.server.start, defaulting to term://opencode --port.

Start via snacks.terminal
local opencode_cmd = 'opencode --port'
---@type snacks.terminal.Opts
local snacks_terminal_opts = {
  win = {
    position = 'right',
    enter = false,
  },
}

---@type opencode.Opts
vim.g.opencode_opts = {
  server = {
    start = function()
      require('snacks.terminal').open(opencode_cmd, snacks_terminal_opts)
    end,
  },
}

-- Can also leverage toggle functionality.
-- If you use  here, remove 't' — otherwise Neovim will add input delay to your  when typing in the terminal to watch for the mapping.
vim.keymap.set({ 'n', 't' }, '', function()

readme truncated — read the full docs on github

Frequently asked questions

Is opencode.nvim free to use?

opencode.nvim is open source under the MIT licence. There is no licence fee and no seat count — you can self-host it or, where the project offers one, pay a vendor for a managed version instead.

What does opencode.nvim do?

Neovim 🤝 OpenCode in the flow that you already know.

What is opencode.nvim written in?

opencode.nvim is primarily written in Lua. Its source is publicly available at https://github.com/nickjvandyke/opencode.nvim, and it has 3,834 GitHub stars.