opencode.nvim

by nickjvandykeβœ“ Verified

Neovim 🀝 OpenCode in the flow that you already know.

3,780
Stars
150
Forks
Lua
Language
8/23/2026
Added
View on GitHubDownload ZIP

⚠️ Third-Party Software Notice

This skill is third-party open-source software developed and hosted independently on GitHub. SkillTip is an informational directory and does not control or maintain the underlying repository. Any security checks displayed are automated and limited in scope. Review the source code before installing.

Read the Terms of Service

Installation

Add to your Claude Code skills directory:

# Add to your Claude Code skills
git clone https://github.com/nickjvandyke/opencode.nvim

Getting Started

Guides for using skills like opencode.nvim.

Security Report

Verified

Last scanned: β€”

{
  "status": "PASSED",
  "issues": []
}

README.md

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:

PlaceholderContext
@thisRange or selection if any, else cursor position
@bufferCurrent buffer
@buffersOpen buffers
@diagnosticsDiagnostics within the range or selection if any, else in the current buffer
@marksGlobal marks
@quickfixQuickfix list
@visibleVisible text

[!TIP] OpenCode reads referenced files from disk β€” save your changes!

Prompts

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

NamePrompt
diagnosticsExplain @diagnostics
documentAdd comments documenting @this
explainExplain @this and its context
fixFix @diagnostics
implementImplement @this
optimizeOptimize @this for performance and readability
reviewReview @this for correctness and readability
testAdd 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 <leader> here, remove 't' β€” otherwise Neovim will add input delay to your <leader> when typing in the terminal to watch for the mapping.
vim.keymap.set({ 'n', 't' }, '<C-.>', function()
  require('snacks.terminal').toggle(opencode_cmd, snacks_terminal_opts)
end, { desc = 'Toggle OpenCode' })

-- Optionally show upon submitting prompt
vim.api.nvim_create_autocmd('User', {
  pattern = { 'OpencodeEvent:tui.command.execute' },
  callback = function(args)
    ---@type opencode.server.Event
    local event = args.data.event
    if event.properties.command == 'prompt.submit' then
      local win = require('snacks.terminal').get(opencode_cmd, { create = false })
      if win then
        win:show()
      end
    end
  end,
})

opencode.nvim prioritizes focused pairing with a single OpenCode instance. As such, it connects to an OpenCode server before interacting with it, listening for events and targeting it for future interactions. Consider disabling vim.g.opencode_opts.server.connect if you frequently jump between servers or don't care for disruptive synchronous events like permission requests.

πŸš€ Usage

Ask β€” require("opencode").ask()

Input a prompt for OpenCode.

  • Passes the text to Prompt.
  • Press <Up> to browse recent asks.
  • Highlights and completes contexts and OpenCode subagents.
    • Press <Tab> to trigger built-in completion.
    • Provided by in-process LSP when using snacks.input.

Select β€” require("opencode").select()

Select from all opencode.nvim functionality.

  • Prompts
  • Commands
  • Servers

Highlights and previews items when using snacks.picker.

Prompt β€” require("opencode").prompt()

Prompt OpenCode.

  • Injects configured contexts.
  • Trailing space appends; trailing "..." opens in Ask.
  • OpenCode will interpret references to files or subagents.

Operator β€” require("opencode").operator()

Wraps Prompt as an operator, supporting ranges and dot-repeat.

Command β€” require("opencode").command()

Command OpenCode:

CommandDescription
agent.cycleCycle selected agent
prompt.clearClear current prompt
prompt.submitSubmit current prompt
session.compactCompact current session
session.firstJump to first message in session
session.half.page.upScroll messages up half a page
session.half.page.downScroll messages down half a page
session.interruptInterrupt current session
session.lastJump to last message in current session
session.newStart new session
session.page.upScroll messages up one page
session.page.downScroll messages down one page
session.selectSelect session
session.shareShare current session
session.redoRedo last undone action in current session
session.undoUndo last action in current session

πŸ‘€ Events

opencode.nvim forwards the connected OpenCode's Server-Sent-Events as an OpencodeEvent autocmd:

-- Handle OpenCode events
vim.api.nvim_create_autocmd("User", {
  pattern = "OpencodeEvent:*", -- Optionally filter event types
  callback = function(args)
    ---@type opencode.server.Event
    local event = args.data.event
    ---@type string
    local url = args.data.url

    -- See the available event types and their properties
    vim.notify(vim.inspect(event))
    -- Do something useful
    if event.type == "session.status" then
      vim.notify("OpenCode status updated: " .. event.properties.status.type)
    end
  end,
})

[!NOTE] Event payloads are passed through from the OpenCode as-is and follow its schema. They may change with OpenCode releases, so treat them as best-effort rather than a stable API contract.

Edits

When the connected OpenCode edits a file, opencode.nvim reloads the corresponding buffer in real-time. vim.o.autoread = true is set automatically to enable this unless you've explicitly configured it.

Permissions

When the connected OpenCode requests a permission, opencode.nvim asks you to approve or deny it.

Edits

When the connected Opencode requests an edit, opencode.nvim opens the target file in a new tab and uses Neovim's :diffpatch to display the proposed changes side-by-side. See :h 'diffopt' for customization.

KeymapFunction
daAccept the entire edit request
drReject the entire edit request
]c/[cNext/prev change
dpNatively accept only the hunk under the cursor, and reject the edit request
doNatively reject only the hunk under the cursor, and reject the edit request
qClose the diff

Frequently Asked Questions

What is opencode.nvim?βŒ„

opencode.nvim is an open-source ai agents skill for AI coding assistants such as Claude Code, Codex CLI, and ChatGPT, built by nickjvandyke. Neovim 🀝 OpenCode in the flow that you already know. It has 3,780 GitHub stars.

Is opencode.nvim safe to use?βŒ„

Yes. opencode.nvim passed SkillsLLM's automated security scan β€” a dependency vulnerability audit plus prompt-injection heuristics β€” with no high-severity issues. You can read the full report in the Security Report section on this page.

How do I install opencode.nvim?βŒ„

Clone the repository with "git clone https://github.com/nickjvandyke/opencode.nvim" and add it to your Claude Code skills directory (see the Installation section above).

What programming language is opencode.nvim written in?βŒ„

opencode.nvim is primarily written in Lua. It is open-source under nickjvandyke on GitHub, so you can review or fork the full source.

Are there alternatives to opencode.nvim?βŒ„

Yes. SkillsLLM lists many other AI Agents skills you can browse and compare side by side. Open the AI Agents category from the badge at the top of this page, or use the Related Skills and comparison links further down to weigh opencode.nvim against similar tools.

Comments (0)

No comments yet. Be the first to share your thoughts!

ECC

by affaan-m

10

The agent harness performance optimization system. Skills, instincts, memory, security, and research-first development for Claude Code, Codex, Opencode, Cursor and beyond.

⭐ 242,219β‘‚ 36,702JavaScript
AI Agentsai-agentsanthropicclaude-code
View details β†’
15

An agentic skills framework & software development methodology that works.

⭐ 234,966β‘‚ 20,863Shell
AI Agentsai-agentsbrainstorming
View details β†’

The agent harness performance optimization system. Skills, instincts, memory, security, and research-first development for Claude Code, Codex, Opencode, Cursor and beyond.

⭐ 185,940β‘‚ 28,768JavaScript
AI Agentsai-agentsanthropicclaude-code
View details β†’

cc-switch

by farion1231

3

A cross-platform desktop All-in-One assistant for Claude Code, Codex, OpenCode, OpenClaw, Grok Build & Hermes Agent. Only official website: ccswitch.io

⭐ 128,868β‘‚ 8,826Rust
AI Agentsclaude-codeai-tools
View details β†’

claude-code

by anthropics

Claude Code is an agentic coding tool that lives in your terminal, understands your codebase, and helps you code faster by executing routine tasks, explaining complex code, and handling git workflows - all through natural language commands.

⭐ 120,031β‘‚ 19,897Shell
AI Agents
View details β†’

Developers Also Liked

Based on votes and bookmarks from developers who liked this skill

ECC

by affaan-m

10

The agent harness performance optimization system. Skills, instincts, memory, security, and research-first development for Claude Code, Codex, Opencode, Cursor and beyond.

⭐ 242,219β‘‚ 36,702JavaScript
AI Agentsai-agentsanthropicclaude-code
View details β†’
15

An agentic skills framework & software development methodology that works.

⭐ 234,966β‘‚ 20,863Shell
AI Agentsai-agentsbrainstorming
View details β†’

n8n

by n8n-io

12

Fair-code workflow automation platform with native AI capabilities. Combine visual building with custom code, self-host or cloud, 400+ integrations.

⭐ 201,881β‘‚ 60,308TypeScript
MCP Serversapisai-tools
View details β†’

The agent harness performance optimization system. Skills, instincts, memory, security, and research-first development for Claude Code, Codex, Opencode, Cursor and beyond.

⭐ 185,940β‘‚ 28,768JavaScript
AI Agentsai-agentsanthropicclaude-code
View details β†’

cc-switch

by farion1231

3

A cross-platform desktop All-in-One assistant for Claude Code, Codex, OpenCode, OpenClaw, Grok Build & Hermes Agent. Only official website: ccswitch.io

⭐ 128,868β‘‚ 8,826Rust
AI Agentsclaude-codeai-tools
View details β†’