Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Seamlessly integrate the opencode AI assistant with Neovim.

License

Notifications You must be signed in to change notification settings

cds-io/opencode.nvim

Folders and files

NameName
Last commit message
Last commit date

Latest commit

History

275 Commits

Repository files navigation

opencode.nvim

Seamlessly integrate the opencode AI assistant with Neovim.

demo.mp4

Note

Uses opencode's currently undocumented, likely unstable API.

Latest tested opencode version: v0.4.1

✨ Features

  • Auto-find any opencode process running inside Neovim's CWD or open in an embedded terminal
  • Select and input customizable prompts
  • Inject customizable editor context
  • Auto-reload edited buffers
  • Write and refine prompts quickly with completion, highlight, and normal-mode support

πŸ•΅οΈ Context

When your prompt contains placeholders, opencode.nvim will replace them with context before sending:

Placeholder Context
@buffer Current buffer
@buffers Open buffers
@cursor Cursor position
@selection Selected text
@visible Visible text
@diagnostic Current line diagnostics
@diagnostics Current buffer diagnostics
@quickfix Quickfix list
@diff Git diff

πŸ“¦ Setup

lazy.nvim
{
 'NickvanDyke/opencode.nvim',
 dependencies = { 'folke/snacks.nvim', },
 ---@type opencode.Config
 opts = {
 -- Your configuration, if any
 },
 -- stylua: ignore
 keys = {
 { '<leader>ot', function() require('opencode').toggle() end, desc = 'Toggle embedded opencode', },
 { '<leader>oa', function() require('opencode').ask() end, desc = 'Ask opencode', mode = 'n', },
 { '<leader>oa', function() require('opencode').ask('@selection: ') end, desc = 'Ask opencode about selection', mode = 'v', },
 { '<leader>op', function() require('opencode').select_prompt() end, desc = 'Select prompt', mode = { 'n', 'v', }, },
 { '<leader>on', function() require('opencode').command('session_new') end, desc = 'New session', },
 { '<leader>oy', function() require('opencode').command('messages_copy') end, desc = 'Copy last message', },
 { '<S-C-u>', function() require('opencode').command('messages_half_page_up') end, desc = 'Scroll messages up', },
 { '<S-C-d>', function() require('opencode').command('messages_half_page_down') end, desc = 'Scroll messages down', },
 },
}
nixvim
programs.nixvim = {
 extraPlugins = [
 pkgs.vimPlugins.opencode-nvim
 ];
 keymaps = [
 { key = "<leader>ot"; action = "<cmd>lua require('opencode').toggle()<CR>"; }
 { key = "<leader>oa"; action = "<cmd>lua require('opencode').ask()<CR>"; mode = "n"; }
 { key = "<leader>oa"; action = "<cmd>lua require('opencode').ask('@selection: ')<CR>"; mode = "v"; }
 { key = "<leader>oe"; action = "<cmd>lua require('opencode').select_prompt()<CR>"; mode = ["n" "v"]; }
 { key = "<leader>on"; action = "<cmd>lua require('opencode').command('session_new')<CR>"; }
 ];
};

βš™οΈ Configuration

See all the available options and their defaults here.

Tip

opencode.nvim offers a flexible API β€” customize prompts, contexts, and keymaps to fit your workflow!

Prompts

Add custom selectable prompts to opts.prompts:

{
 prompts = {
 joke = {
 description = 'Tell me a cat joke',
 prompt = 'Tell me a joke about cats. Make it funny, but not too funny.',
 },
 },
}

Add keymaps for your favorite built-in or custom prompts:

local prompts = require('opencode.config').options.prompts or {}
vim.keymap.set('n', '<leader>oj', function() require('opencode').prompt(prompts.joke.prompt) end, { desc = prompts.joke.description })
vim.keymap.set('v', '<leader>os', function() require('opencode').prompt("Tell me a story about cats and @selection") end, { desc = "Tell me a story" })

Contexts

Add custom contexts to opts.contexts. The below replaces @grapple with files tagged by grapple.nvim:

{
 contexts = {
 ---@type opencode.Context
 ['@grapple'] = {
 description = 'Files tagged by grapple',
 value = 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,
 },
 }
}

✍️ Completion

opencode.nvim offers context placeholder completions in the ask input.

blink.cmp

opencode.nvim automatically registers opts.auto_register_cmp_sources (default: { "opencode", "buffer" }) with blink.cmp (if loaded) at runtime.

Built-in

Press <Tab> to trigger Neovim's built-in completion.

πŸ‘€ Events

opencode.nvim forwards opencode's Server-Sent-Events as an autocmd:

-- Listen for opencode events
vim.api.nvim_create_autocmd("User", {
 pattern = "OpencodeEvent",
 callback = function(args)
 -- See the available event types and their properties
 vim.notify(vim.inspect(args.data), vim.log.levels.DEBUG)
 -- Do something interesting, like show a notification when opencode finishes responding
 if args.data.type == "session.idle" then
 vim.notify("opencode finished responding", vim.log.levels.INFO)
 end
 end,
})

🌈 Highlights

Name Description
OpencodePlaceholder Placeholders in ask input

πŸ™ Acknowledgments

About

Seamlessly integrate the opencode AI assistant with Neovim.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Lua 100.0%

AltStyle γ«γ‚ˆγ£γ¦ε€‰ζ›γ•γ‚ŒγŸγƒšγƒΌγ‚Έ (->γ‚ͺγƒͺγ‚ΈγƒŠγƒ«) /