Skip to content

NickvanDyke/opencode.nvim

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

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.45

✨ 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.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 5

Languages