Skip to content

feat(neovim): add opencode.nvim for AI assistant integration - #575

Merged
shunkakinoki merged 1 commit into
mainfrom
add-opencode-nvim
Jan 15, 2026
Merged

feat(neovim): add opencode.nvim for AI assistant integration#575
shunkakinoki merged 1 commit into
mainfrom
add-opencode-nvim

Conversation

@shunkakinoki

@shunkakinoki shunkakinoki commented Jan 15, 2026

Copy link
Copy Markdown
Owner

Add opencode.nvim plugin from https://github.com/NickvanDyke/opencode.nvim for integrating the opencode AI assistant with Neovim.

Features

  • Auto-connect to `opencode` running inside Neovim's CWD
  • Input prompts with completions, highlights, and normal-mode support
  • Select prompts from a library and define your own
  • Share editor context (buffer, cursor, selection, diagnostics, etc.)
  • Execute commands and respond to permission requests
  • Reload edited buffers in real-time
  • Monitor state via statusline component

Keymaps

Keymap Description
`` Ask opencode about current context
`` Execute opencode action from selection menu
`<C-.>` Toggle opencode terminal
`go` Operator: add range to opencode prompt
`goo` Operator: add line to opencode prompt
`` Scroll opencode session up
`` Scroll opencode session down
`+` Increment (remapped from ``)
`-` Decrement (remapped from ``)

Context Placeholders

opencode.nvim replaces these placeholders in prompts with editor context:

  • `@this` - Operator range or visual selection
  • `@buffer` - Current buffer
  • `@buffers` - Open buffers
  • `@visible` - Visible text
  • `@diagnostics` - Buffer diagnostics
  • `@quickfix` - Quickfix list
  • `@diff` - Git diff
  • `@marks` - Global marks

Dependencies

  • Added `folke/snacks.nvim` (required for opencode.nvim input/picker/terminal)

Tests

All tests pass:
```
✓ opencode.nvim API patterns
✓ Context placeholders
✓ Prompt library
✓ All keymap patterns
✓ Command patterns
```

Ref: https://x.com/theprimeagen/status/2011538844836143406


Summary by cubic

Add opencode.nvim to Neovim to enable context-aware prompts, actions, and a terminal for coding assistance. Includes keymaps, context sharing, and tests, and adds the required snacks.nvim dependency.

  • New Features

    • Integrated opencode.nvim with default opts and enabled autoread for buffer reloads.
    • Keymaps: ask, select action, <C-.> toggle terminal, go/goo operators, / scroll session, +/- remap for increment/decrement.
    • Operator mode for ranges/lines and half-page session scrolling.
    • Supports context placeholders (@this, @buffer, @Buffers, @visible, @diagnostics, @quickfix, @diff, @marks) and prompt library; added tests for API, keymaps, and placeholders.
  • Dependencies

    • Added folke/snacks.nvim (required by opencode.nvim).
    • Added NickvanDyke/opencode.nvim to the plugin list.

Written for commit 27d7ed9. Summary will update on new commits.

Copilot AI review requested due to automatic review settings January 15, 2026 12:49
@coderabbitai

coderabbitai Bot commented Jan 15, 2026

Copy link
Copy Markdown
📝 Walkthrough

Summary by CodeRabbit

Release Notes

New Features

  • Added comprehensive AI assistant integration with opencode plugin featuring keybindings for code prompts, execution, and terminal access
  • Integrated snacks plugin to enhance AI workflow capabilities
  • New operator-mode and context-aware AI commands available through custom keybindings

Tests

  • Added extensive test coverage for new AI integrations and keybindings

✏️ Tip: You can customize this high-level summary in your review settings.

Walkthrough

This change adds AI integration to Neovim by configuring three plugins—sidekick.nvim, snacks.nvim, and opencode.nvim—with extensive keybindings for prompting, execution, terminal toggling, and operator modes. Comprehensive tests validate the configuration structure and keymap patterns.

Changes

Cohort / File(s) Summary
AI Configuration & Plugins
home-manager/programs/neovim/lua/ai.lua, home-manager/programs/neovim/lua/plugins.lua
Added setup for sidekick.nvim, snacks.nvim, and opencode.nvim with opencode configuration including vim.g.opencode_opts and autoread. Established 8+ keybindings (e.g., <C-a> for prompt, <C-x> for select, <C-.> for terminal toggle, go for operator, +/- for increment/decrement remaps).
AI Test Coverage
home-manager/programs/neovim/tests/ai_spec.lua
Added 132+ lines of test suites for snacks API structure (input, picker, terminal), opencode API validation (config table, autoread, context placeholders like @this, @buffer, prompt library), keymaps across normal/visual/operator modes, and session scroll commands.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly related PRs

Poem

🐰 Bounces with glee With Neovim now talking AI so bright,
Opencode whispers through the fuzzy night,
Keybindings dance, tests shine with care,
The editor knows magic—beyond compare! ✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately and concisely describes the main change: adding opencode.nvim for AI assistant integration to Neovim.
Description check ✅ Passed The description is comprehensive and directly related to the changeset, detailing features, keymaps, context placeholders, dependencies, and test results.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch add-opencode-nvim

🧹 Recent nitpick comments
home-manager/programs/neovim/tests/ai_spec.lua (2)

13-21: Test validates static data rather than actual snacks integration.

This test only asserts that hardcoded string literals are strings. It doesn't verify that snacks.nvim is loaded or that the components are functional. Consider testing the actual module:

it("should have expected snacks components structure", function()
    local snacks = require("snacks")
    assert.is_table(snacks)
    -- Verify components exist after setup
end)

37-71: Context placeholder and prompt tests validate static data only.

These tests assert that hardcoded strings are strings and start with @. They don't verify that opencode.nvim actually recognizes or processes these placeholders. The tests will always pass regardless of opencode.nvim's actual behavior.

Consider documenting this as pattern/contract validation in test names, or testing actual functionality when the plugin is loaded.


📜 Recent review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between b699cf0 and 27d7ed9.

📒 Files selected for processing (3)
  • home-manager/programs/neovim/lua/ai.lua
  • home-manager/programs/neovim/lua/plugins.lua
  • home-manager/programs/neovim/tests/ai_spec.lua
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (15)
  • GitHub Check: Upload results
  • GitHub Check: cubic · AI code reviewer
  • GitHub Check: Mesa Review
  • GitHub Check: docker-build-push (linux/amd64, amd64, ubuntu-latest)
  • GitHub Check: e2e-run (MacOS, macos-latest)
  • GitHub Check: e2e-run (NixOS, ubuntu-latest)
  • GitHub Check: e2e-run (Ubuntu, ubuntu-latest)
  • GitHub Check: lua-neovim
  • GitHub Check: docker-build-push (linux/arm64, arm64, ubuntu-24.04-arm)
  • GitHub Check: lua-neovim-test
  • GitHub Check: nix-nixos
  • GitHub Check: nix-linux
  • GitHub Check: nix-darwin
  • GitHub Check: shell-test
  • GitHub Check: shell-lint
🔇 Additional comments (7)
home-manager/programs/neovim/lua/plugins.lua (1)

87-89: LGTM!

The plugin declarations follow the existing pattern and the dependency comment for snacks.nvim is helpful for maintainability.

home-manager/programs/neovim/lua/ai.lua (4)

1-18: LGTM!

The sidekick and snacks setup with default configurations is appropriate for initial integration. The empty tables enable the required snacks components (input, picker, terminal) that opencode.nvim depends on.


31-32: Global autoread affects all buffers.

Setting vim.o.autoread = true globally enables automatic buffer reload for the entire editor, not just opencode-related buffers. This is generally desirable for keeping files in sync, but worth noting that it changes behavior for all editing scenarios.


51-57: The go mapping overrides Vim's default go-to-byte command.

The go keymap shadows Vim's built-in go command (:h go - goto byte offset). While rarely used, if you need byte navigation, you'll need to use :go {byte} instead.

The goo mapping cleverly uses .. "_" to apply the operator to the current line (the _ motion).


68-70: Good approach to preserve increment/decrement.

Using noremap = true correctly ensures + and - map to the original Vim <C-a> and <C-x> commands rather than the newly defined opencode mappings.

home-manager/programs/neovim/tests/ai_spec.lua (2)

74-138: Keymap API pattern tests are well-structured.

Good practice to create, verify, and clean up keymaps in each test. These validate that the keymap patterns used in ai.lua are syntactically valid and work with Neovim's API.


140-152: LGTM!

The command pattern validation follows the same structure as other tests. The regex pattern check (^session%.) is useful for documenting the expected command namespace.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello @shunkakinoki, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request integrates the opencode.nvim plugin into the Neovim configuration, providing a powerful AI assistant directly within the editor. This enhancement allows users to leverage AI for tasks such as context-aware prompting, executing AI actions, and managing AI sessions, streamlining the development workflow by bringing intelligent assistance closer to the code. The integration also includes necessary dependencies and comprehensive test coverage to ensure stability and functionality.

Highlights

  • AI Assistant Integration: The opencode.nvim plugin has been integrated to provide an AI assistant directly within Neovim, enabling context-aware interactions and streamlining development workflows.
  • New Dependency Added: The folke/snacks.nvim plugin, a required dependency for opencode.nvim providing input, picker, and terminal components, has been added to the configuration.
  • Comprehensive Keymaps: A wide range of keymaps have been configured for opencode.nvim, including <C-a> for asking the AI, <C-x> for executing actions, <C-.> for toggling the terminal, and operator modes (go, goo) for adding context to prompts.
  • Keymap Remapping: The default increment (+) and decrement (-) keymaps have been reassigned to C-a and C-x respectively, to free up these common control key combinations for opencode.nvim functionality.
  • Enhanced Test Coverage: The ai_spec.lua test file has been significantly expanded with new test suites for snacks.nvim and opencode.nvim's API, keymaps, and command patterns, ensuring robust integration and functionality.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Add opencode.nvim plugin from https://github.com/NickvanDyke/opencode.nvim
for integrating the opencode AI assistant with Neovim.

Features:
- Auto-connect to opencode running in Neovim's CWD
- Input prompts with completions and highlights
- Share editor context (buffer, cursor, selection, diagnostics)
- Execute commands and respond to permission requests
- Reload edited buffers in real-time

Keymaps:
- <C-a> - Ask opencode about current context
- <C-x> - Execute opencode action from selection menu
- <C-.> - Toggle opencode terminal
- go/goo - Operator mode for adding ranges
- <S-C-u>/<S-C-d> - Scroll opencode session
- +/- - Remapped increment/decrement

Dependencies:
- Added folke/snacks.nvim (required for opencode.nvim)

Tests:
- Added comprehensive tests for opencode API patterns
- Tests for keymap configurations
- Tests for context placeholders and prompts

Ref: https://x.com/theprimeagen/status/2011538844836143406
@mesa-dot-dev

mesa-dot-dev Bot commented Jan 15, 2026

Copy link
Copy Markdown

Mesa Description

TL;DR

Added the opencode.nvim plugin to Neovim for AI assistant integration, enabling features like AI interaction, context sharing, and command execution directly within the editor.

What changed?

  • Integrated opencode.nvim for AI assistant capabilities within Neovim.
  • Introduced features such as auto-connection to opencode, prompt input with completions, a prompt library, editor context sharing, command execution, real-time buffer reloading, and statusline monitoring.
  • Defined new keymaps for interacting with opencode, including asking about context, executing actions, toggling the terminal, and scrolling sessions.
  • Implemented support for context placeholders (@this, @buffer, @buffers, @visible, @diagnostics, @quickfix, @diff, @marks) in prompts.
  • Added folke/snacks.nvim as a new dependency, required by opencode.nvim.

Description generated by Mesa. Update settings

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR integrates the opencode.nvim plugin for AI assistant functionality in Neovim. The plugin provides AI-powered code assistance with context-aware prompting, command execution, and real-time buffer synchronization.

Changes:

  • Added opencode.nvim and snacks.nvim (dependency) to the plugin list
  • Configured opencode.nvim with keymaps for asking, selecting, toggling, and operator modes
  • Added comprehensive test coverage for opencode.nvim API patterns, keymaps, and commands

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

File Description
home-manager/programs/neovim/lua/plugins.lua Added snacks.nvim and opencode.nvim to the plugin dependencies in the AI section
home-manager/programs/neovim/lua/ai.lua Configured snacks.nvim and opencode.nvim with keymaps (<C-a>, <C-x>, <C-.>, go, goo) and scroll commands; remapped +/- for increment/decrement
home-manager/programs/neovim/tests/ai_spec.lua Added tests for snacks API structure, opencode API patterns, context placeholders, prompt library, keymaps, and command patterns

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +51 to +57
vim.keymap.set({ "n", "x" }, "go", function()
return require("opencode").operator("@this ")
end, { expr = true, desc = "Add range to opencode" })

vim.keymap.set("n", "goo", function()
return require("opencode").operator("@this ") .. "_"
end, { expr = true, desc = "Add line to opencode" })

Copilot AI Jan 15, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The go keymap conflicts with the existing buffer-local go keymap defined in autocmds.lua (line 217) for fugitive buffers. This creates a keybinding collision where the opencode keymap will be shadowed by the fugitive buffer-local mapping. Consider using a different key combination like gO or <leader>go to avoid conflicts.

Suggested change
vim.keymap.set({ "n", "x" }, "go", function()
return require("opencode").operator("@this ")
end, { expr = true, desc = "Add range to opencode" })
vim.keymap.set("n", "goo", function()
return require("opencode").operator("@this ") .. "_"
end, { expr = true, desc = "Add line to opencode" })
vim.keymap.set({ "n", "x" }, "gO", function()
return require("opencode").operator("@this ")
end, { expr = true, desc = "Add range to opencode (gO)" })
vim.keymap.set("n", "gOO", function()
return require("opencode").operator("@this ") .. "_"
end, { expr = true, desc = "Add line to opencode (gOO)" })

Copilot uses AI. Check for mistakes.
Comment on lines +60 to +64
vim.keymap.set("n", "<S-C-u>", function()
require("opencode").command("session.half.page.up")
end, { desc = "opencode half page up" })

vim.keymap.set("n", "<S-C-d>", function()

Copilot AI Jan 15, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The <S-C-u> and <S-C-d> keymaps may not work reliably in all terminal emulators. Shift+Ctrl combinations with letter keys are often not distinguishable from their non-shifted counterparts in terminal Neovim. Consider using alternative keymaps that work consistently across terminals, such as <leader>u and <leader>d or using the standard <C-u> and <C-d> with a prefix key.

Suggested change
vim.keymap.set("n", "<S-C-u>", function()
require("opencode").command("session.half.page.up")
end, { desc = "opencode half page up" })
vim.keymap.set("n", "<S-C-d>", function()
vim.keymap.set("n", "<leader>u", function()
require("opencode").command("session.half.page.up")
end, { desc = "opencode half page up" })
vim.keymap.set("n", "<leader>d", function()

Copilot uses AI. Check for mistakes.
Comment on lines +31 to +33
-- Required for opts.events.reload
vim.o.autoread = true

Copilot AI Jan 15, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Setting autoread globally affects all buffers in Neovim, not just opencode buffers. This can cause unexpected behavior where files are automatically reloaded without user confirmation when they change on disk. Consider whether this global setting is necessary, or if opencode.nvim should handle buffer reloading through its own mechanisms without requiring a global option change.

Suggested change
-- Required for opts.events.reload
vim.o.autoread = true

Copilot uses AI. Check for mistakes.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request integrates the opencode.nvim plugin for AI assistant functionality. The changes look good overall, adding the necessary plugin dependencies, configuration, and keymaps. However, I've identified a few issues that should be addressed. There's a keymap conflict for <C-.> between opencode.nvim and the existing sidekick.nvim configuration. I also recommend moving the new keymaps to the central keymaps.lua file for consistency. Additionally, the remapping of + and - overrides fundamental Vim motions, which could be disruptive. Finally, several of the new tests are tautological and don't actually test the integration, which could be misleading about test coverage. My detailed comments provide suggestions for resolving these points.

Comment on lines +46 to +48
vim.keymap.set({ "n", "t" }, "<C-.>", function()
require("opencode").toggle()
end, { desc = "Toggle opencode" })

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

This introduces a keymap <C-.> that conflicts with an existing keymap for sidekick defined in keymaps.lua:257. The sidekick mapping is for modes n, t, i, x, while this new mapping is for n, t. Since ai.lua is loaded after keymaps.lua, this mapping will override the sidekick one in normal and terminal modes, but not in insert or visual mode. This leads to inconsistent behavior where <C-.> does different things depending on the mode. This conflict should be resolved by choosing a different keymap for one of the actions or by removing the conflicting one if it's no longer needed.

Comment on lines +34 to +70
-- Keymaps for opencode
-- <C-a> - Ask opencode about current context
vim.keymap.set({ "n", "x" }, "<C-a>", function()
require("opencode").ask("@this: ", { submit = true })
end, { desc = "Ask opencode" })

-- <C-x> - Execute opencode action from selection menu
vim.keymap.set({ "n", "x" }, "<C-x>", function()
require("opencode").select()
end, { desc = "Execute opencode action…" })

-- <C-.> - Toggle opencode terminal
vim.keymap.set({ "n", "t" }, "<C-.>", function()
require("opencode").toggle()
end, { desc = "Toggle opencode" })

-- Operator mode: add range to opencode prompt
vim.keymap.set({ "n", "x" }, "go", function()
return require("opencode").operator("@this ")
end, { expr = true, desc = "Add range to opencode" })

vim.keymap.set("n", "goo", function()
return require("opencode").operator("@this ") .. "_"
end, { expr = true, desc = "Add line to opencode" })

-- Scroll keymaps for opencode session
vim.keymap.set("n", "<S-C-u>", function()
require("opencode").command("session.half.page.up")
end, { desc = "opencode half page up" })

vim.keymap.set("n", "<S-C-d>", function()
require("opencode").command("session.half.page.down")
end, { desc = "opencode half page down" })

-- Remap increment/decrement since we use <C-a> and <C-x> for opencode
vim.keymap.set("n", "+", "<C-a>", { desc = "Increment", noremap = true })
vim.keymap.set("n", "-", "<C-x>", { desc = "Decrement", noremap = true })

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The keymaps for opencode.nvim are defined here in ai.lua. However, there is a central keymaps.lua file where other keymaps, including those for sidekick, are defined. To maintain consistency and have a single source of truth for keybindings, it would be better to move these opencode.nvim keymaps to keymaps.lua, under a new OPENCODE section. This would also make the <C-.> conflict with sidekick more apparent and easier to manage.

Comment on lines +69 to +70
vim.keymap.set("n", "+", "<C-a>", { desc = "Increment", noremap = true })
vim.keymap.set("n", "-", "<C-x>", { desc = "Decrement", noremap = true })

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

These keymaps override the default behavior of + and - in normal mode, which are standard Vim motions for moving to the next and previous line respectively. While this is documented in the pull request description, it's a significant departure from default Vim behavior that could be disruptive and surprising. Have you considered using different keys for increment/decrement to avoid overriding these built-in motions? For example, <leader>+ and <leader>- could be alternatives that don't clash with default functionality.

Comment on lines +14 to +20
it("should have expected snacks components structure", function()
-- snacks.nvim provides input, picker, and terminal
local expected_components = { "input", "picker", "terminal" }
for _, component in ipairs(expected_components) do
assert.is_string(component)
end
end)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The test should have expected snacks components structure is tautological. It defines a local table and then asserts properties of that same table. It doesn't test any interaction with the snacks.nvim plugin or its configuration. This provides no value and can be misleading about test coverage. Please consider removing this test or changing it to assert something meaningful about the integration, if possible within your testing framework.

Comment on lines +37 to +53
it("should support context placeholders pattern", function()
-- opencode.nvim uses context placeholders like @this, @buffer, etc.
local placeholders = {
"@this",
"@buffer",
"@buffers",
"@visible",
"@diagnostics",
"@quickfix",
"@diff",
"@marks",
}
for _, placeholder in ipairs(placeholders) do
assert.is_string(placeholder)
assert.is_true(placeholder:sub(1, 1) == "@")
end
end)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This test for context placeholders is tautological. It defines a local table placeholders and asserts its contents. It doesn't test anything about opencode.nvim itself. This test provides a false sense of coverage as it will pass regardless of the plugin's actual implementation. If the goal is to document the placeholders, a comment in the configuration file would be more appropriate. As a test, this provides little value and should be refactored or removed.

Comment on lines +55 to +71
it("should support prompt library pattern", function()
-- opencode.nvim includes built-in prompts
local prompts = {
"diagnostics",
"diff",
"document",
"explain",
"fix",
"implement",
"optimize",
"review",
"test",
}
for _, prompt in ipairs(prompts) do
assert.is_string(prompt)
end
end)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Similar to other new tests in this file, this test for the prompt library is tautological. It verifies a hardcoded list of strings. This doesn't ensure that opencode.nvim actually provides these prompts or that they are correctly configured. This test is misleading about the actual test coverage and should be removed or refactored to be a meaningful test of the plugin's integration.

@mesa-dot-dev mesa-dot-dev Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Performed full review of b699cf0...27d7ed9

Analysis

  1. Error Handling Vulnerability - The code directly calls require() without protection (e.g., pcall), which will cause a hard failure on Neovim startup if dependencies like snacks.nvim or opencode.nvim are not installed.

  2. Dependency Chain Fragility - There's an implicit dependency chain (opencode.nvim → snacks.nvim) that could lead to undefined behavior if snacks.nvim fails or is removed.

  3. Global State Mutation - Setting vim.o.autoread = true affects all buffers system-wide and may have unexpected side effects with other file watchers or external modifications.

  4. External Binary Dependency - The integration assumes the opencode binary exists in PATH without graceful degradation if it's missing.

  5. Keymap Override Risk - Common Vim keybindings (<C-a>, <C-x>) are overridden without runtime checks, potentially causing user friction despite the alternative mappings.

Tip

Help

Slash Commands:

  • /review - Request a full code review
  • /review latest - Review only changes since the last review
  • /describe - Generate PR description. This will update the PR body or issue comment depending on your configuration
  • /help - Get help with Mesa commands and configuration options

0 files reviewed | 3 comments | Edit Agent SettingsRead Docs


-- Keymaps for opencode
-- <C-a> - Ask opencode about current context
vim.keymap.set({ "n", "x" }, "<C-a>", function()

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Medium

The keymaps for opencode should also be wrapped in error handling. If opencode.nvim fails to load, these keymaps will cause runtime errors when triggered. Consider:

local opencode_ok, opencode = pcall(require, "opencode")
if opencode_ok then
  vim.keymap.set({ "n", "x" }, "<C-a>", function()
    opencode.ask("@this: ", { submit = true })
  end, { desc = "Ask opencode" })
  -- ... other keymaps
end

This ensures graceful degradation if the plugin is unavailable.

Agent: 🏛 Architecture • Fix in Cursor • Fix in Claude

Prompt for Agent
Task: Address review feedback left on GitHub.
Repository: shunkakinoki/dotfiles#575
File: home-manager/programs/neovim/lua/ai.lua#L36
Action: Open this file location in your editor, inspect the highlighted code, and resolve the issue described below.

Feedback:
The keymaps for opencode should also be wrapped in error handling. If opencode.nvim fails to load, these keymaps will cause runtime errors when triggered. Consider:

```lua
local opencode_ok, opencode = pcall(require, "opencode")
if opencode_ok then
  vim.keymap.set({ "n", "x" }, "<C-a>", function()
    opencode.ask("@this: ", { submit = true })
  end, { desc = "Ask opencode" })
  -- ... other keymaps
end

This ensures graceful degradation if the plugin is unavailable.


</details>

}

-- Required for opts.events.reload
vim.o.autoread = true

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Medium

Setting vim.o.autoread = true globally affects all buffers in Neovim, not just opencode-related buffers. This means any file modified externally will be automatically reloaded without warning.

While necessary for opencode's reload functionality, this could cause unexpected behavior if users are working with files that are also being modified by external processes. Consider documenting this side effect more prominently, perhaps with a comment explaining the global impact.

Agent: 🏛 Architecture • Fix in Cursor • Fix in Claude

Prompt for Agent
Task: Address review feedback left on GitHub.
Repository: shunkakinoki/dotfiles#575
File: home-manager/programs/neovim/lua/ai.lua#L32
Action: Open this file location in your editor, inspect the highlighted code, and resolve the issue described below.

Feedback:
Setting `vim.o.autoread = true` globally affects all buffers in Neovim, not just opencode-related buffers. This means any file modified externally will be automatically reloaded without warning.

While necessary for opencode's reload functionality, this could cause unexpected behavior if users are working with files that are also being modified by external processes. Consider documenting this side effect more prominently, perhaps with a comment explaining the global impact.

-- SNACKS (Required for opencode.nvim)
-- From: https://github.com/folke/snacks.nvim
-- ====================================================================================
require("snacks").setup({

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Medium

Missing error handling for snacks.nvim setup. If the plugin isn't installed, this will cause Neovim to fail on startup. Consider wrapping in pcall() for graceful degradation:

local ok, snacks = pcall(require, "snacks")
if ok then
  snacks.setup({
    input = {},
    picker = {},
    terminal = {},
  })
else
  vim.notify("snacks.nvim not available - opencode.nvim will not function", vim.log.levels.WARN)
end

This pattern is already used elsewhere in the codebase (e.g., utils.lua line 64 for nvim-web-devicons).

Agent: 🏛 Architecture • Fix in Cursor • Fix in Claude

Prompt for Agent
Task: Address review feedback left on GitHub.
Repository: shunkakinoki/dotfiles#575
File: home-manager/programs/neovim/lua/ai.lua#L14
Action: Open this file location in your editor, inspect the highlighted code, and resolve the issue described below.

Feedback:
Missing error handling for snacks.nvim setup. If the plugin isn't installed, this will cause Neovim to fail on startup. Consider wrapping in pcall() for graceful degradation:

```lua
local ok, snacks = pcall(require, "snacks")
if ok then
  snacks.setup({
    input = {},
    picker = {},
    terminal = {},
  })
else
  vim.notify("snacks.nvim not available - opencode.nvim will not function", vim.log.levels.WARN)
end

This pattern is already used elsewhere in the codebase (e.g., utils.lua line 64 for nvim-web-devicons).


</details>

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

5 issues found across 3 files

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="home-manager/programs/neovim/lua/plugins.lua">

<violation number="1" location="home-manager/programs/neovim/lua/plugins.lua:87">
P2: New plugins added without corresponding lock entries—snacks.nvim and opencode.nvim are unpinned, undermining reproducibility.</violation>
</file>

<file name="home-manager/programs/neovim/tests/ai_spec.lua">

<violation number="1" location="home-manager/programs/neovim/tests/ai_spec.lua:18">
P2: AI integration test is tautological: only asserts hardcoded strings are strings, so it cannot fail even if snacks/opencode integrations are broken.</violation>

<violation number="2" location="home-manager/programs/neovim/tests/ai_spec.lua:33">
P2: Test sets vim.o.autoread globally without restoring the prior value, causing state leakage between tests.</violation>

<violation number="3" location="home-manager/programs/neovim/tests/ai_spec.lua:88">
P2: Keymap existence check is unreliable: maparg() returns empty string for Lua callback mappings, so these assertions can fail even when the mapping exists.</violation>
</file>

<file name="home-manager/programs/neovim/lua/ai.lua">

<violation number="1" location="home-manager/programs/neovim/lua/ai.lua:60">
P2: Ctrl+Shift-U/D mappings likely collapse to Ctrl-U/D and override default half-page scroll keys globally, breaking normal navigation.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

{ src = "https://github.com/yioneko/nvim-vtsls" },

-- AI
{ src = "https://github.com/folke/snacks.nvim" }, -- Required for opencode.nvim

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: New plugins added without corresponding lock entries—snacks.nvim and opencode.nvim are unpinned, undermining reproducibility.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At home-manager/programs/neovim/lua/plugins.lua, line 87:

<comment>New plugins added without corresponding lock entries—snacks.nvim and opencode.nvim are unpinned, undermining reproducibility.</comment>

<file context>
@@ -84,7 +84,9 @@ vim.pack.add({
 	{ src = "https://github.com/yioneko/nvim-vtsls" },
 
 	-- AI
+	{ src = "https://github.com/folke/snacks.nvim" }, -- Required for opencode.nvim
 	{ src = "https://github.com/folke/sidekick.nvim" },
+	{ src = "https://github.com/NickvanDyke/opencode.nvim" },
</file context>


it("should support autoread option for reload events", function()
-- Required for opencode reload functionality
vim.o.autoread = true

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Test sets vim.o.autoread globally without restoring the prior value, causing state leakage between tests.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At home-manager/programs/neovim/tests/ai_spec.lua, line 33:

<comment>Test sets vim.o.autoread globally without restoring the prior value, causing state leakage between tests.</comment>

<file context>
@@ -10,6 +10,67 @@ describe("ai", function()
+
+		it("should support autoread option for reload events", function()
+			-- Required for opencode reload functionality
+			vim.o.autoread = true
+			assert.equals(true, vim.o.autoread)
+		end)
</file context>

-- snacks.nvim provides input, picker, and terminal
local expected_components = { "input", "picker", "terminal" }
for _, component in ipairs(expected_components) do
assert.is_string(component)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: AI integration test is tautological: only asserts hardcoded strings are strings, so it cannot fail even if snacks/opencode integrations are broken.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At home-manager/programs/neovim/tests/ai_spec.lua, line 18:

<comment>AI integration test is tautological: only asserts hardcoded strings are strings, so it cannot fail even if snacks/opencode integrations are broken.</comment>

<file context>
@@ -10,6 +10,67 @@ describe("ai", function()
+			-- snacks.nvim provides input, picker, and terminal
+			local expected_components = { "input", "picker", "terminal" }
+			for _, component in ipairs(expected_components) do
+				assert.is_string(component)
+			end
+		end)
</file context>

vim.keymap.set({ "n", "x" }, "<C-a>", function() end, { desc = "Ask opencode" })
local keymap_n = vim.fn.maparg("<C-a>", "n")
local keymap_x = vim.fn.maparg("<C-a>", "x")
assert.is_true(keymap_n ~= "")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Keymap existence check is unreliable: maparg() returns empty string for Lua callback mappings, so these assertions can fail even when the mapping exists.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At home-manager/programs/neovim/tests/ai_spec.lua, line 88:

<comment>Keymap existence check is unreliable: maparg() returns empty string for Lua callback mappings, so these assertions can fail even when the mapping exists.</comment>

<file context>
@@ -18,5 +79,75 @@ describe("ai", function()
+			vim.keymap.set({ "n", "x" }, "<C-a>", function() end, { desc = "Ask opencode" })
+			local keymap_n = vim.fn.maparg("<C-a>", "n")
+			local keymap_x = vim.fn.maparg("<C-a>", "x")
+			assert.is_true(keymap_n ~= "")
+			assert.is_true(keymap_x ~= "")
+			vim.keymap.del("n", "<C-a>")
</file context>

end, { expr = true, desc = "Add line to opencode" })

-- Scroll keymaps for opencode session
vim.keymap.set("n", "<S-C-u>", function()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Ctrl+Shift-U/D mappings likely collapse to Ctrl-U/D and override default half-page scroll keys globally, breaking normal navigation.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At home-manager/programs/neovim/lua/ai.lua, line 60:

<comment>Ctrl+Shift-U/D mappings likely collapse to Ctrl-U/D and override default half-page scroll keys globally, breaking normal navigation.</comment>

<file context>
@@ -1,3 +1,70 @@
+end, { expr = true, desc = "Add line to opencode" })
+
+-- Scroll keymaps for opencode session
+vim.keymap.set("n", "<S-C-u>", function()
+	require("opencode").command("session.half.page.up")
+end, { desc = "opencode half page up" })
</file context>

@shunkakinoki
shunkakinoki merged commit 1226634 into main Jan 15, 2026
39 checks passed
@shunkakinoki
shunkakinoki deleted the add-opencode-nvim branch January 15, 2026 19:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants