Skip to content

Conversation

@epheien
Copy link
Contributor

@epheien epheien commented Jan 15, 2026

Summary

  • Add a new confirmation dialog for edit permission requests that displays the diff with syntax highlighting
  • Support configurable key bindings via opts.events.permissions.confirm.window.mappings
  • Support for multiple keys per action (e.g., "a" and "" both map to "once")
  • Footer display that dynamically shows configured keys in sorted order
  • Window configuration and options customization
  • Type-safe implementation with full LuaLS type annotations
  • Fast key response with nowait option

Configuration

Add the following to vim.g.opencode_opts to enable:

events = {
  permissions = {
    confirm = {
      enabled = true,
      window = {
        config = {},      -- vim.api.nvim_open_win config
        options = {},     -- window-local options
        mappings = {      -- key bindings
          ["a"] = "Once",
          ["<CR>"] = "Once",
          ["A"] = "Always",
          ["r"] = "Reject",
          ["q"] = "Close",
        },
      },
    },
  },
}

Changes

  • Add lua/opencode/ui/confirm.lua for confirmation dialog UI
  • Add lua/opencode/ui/formatter.lua for diff syntax highlighting
  • Add lua/opencode/ui/output.lua and output_window.lua for text rendering
  • Add lua/opencode/util.lua with create_scratch_floatwin helper
  • Update plugin/events/permissions.lua to use confirmation dialog
  • Add confirm configuration to lua/opencode/config.lua
  • Add type definitions for opencode.events.permissions.confirm.Opts

Screenshot

Xnip2026-01-15_21-49-34

@epheien epheien force-pushed the pr/confirm-dialog-upstream branch 2 times, most recently from 2e0e08e to ddacece Compare January 15, 2026 18:02
…bindings

Add a new confirmation dialog for edit permission requests that displays
the diff with syntax highlighting and supports configurable key bindings.

Features:
- Diff preview with syntax highlighting using a custom formatter
- Dynamic key bindings configurable via opts.events.permissions.confirm.window.mappings
- Support for multiple keys per action (e.g., "a" and "<CR>" both map to "once")
- Footer display that dynamically shows configured keys in sorted order
- Window configuration and options customization
- Type-safe implementation with full LuaLS type annotations
- Fast key response with nowait option

Configuration:
Add the following to vim.g.opencode_opts to enable:
  events = {
    permissions = {
      confirm = {
        enabled = true,
        window = {
          config = {},      -- vim.api.nvim_open_win config
          options = {},     -- window-local options
          mappings = {      -- key bindings
            ["a"] = "Once",
            ["<CR>"] = "Once",
            ["A"] = "Always",
            ["r"] = "Reject",
            ["q"] = "Close",
          },
        },
      },
    },
  }

Changes:
- Add lua/opencode/ui/confirm.lua for confirmation dialog UI
- Add lua/opencode/ui/formatter.lua for diff syntax highlighting
- Add lua/opencode/ui/output.lua and output_window.lua for text rendering
- Add lua/opencode/util.lua with create_scratch_floatwin helper
- Update plugin/events/permissions.lua to use confirmation dialog
- Add confirm configuration to lua/opencode/config.lua
- Add type definitions for opencode.events.permissions.confirm.Opts
@epheien epheien force-pushed the pr/confirm-dialog-upstream branch from ddacece to 4ac0577 Compare January 15, 2026 18:05
@NickvanDyke
Copy link
Owner

NickvanDyke commented Jan 15, 2026

Ooo that is sweet!!

I'll try to take a look at this soon. How do you think it compares inline diffs, i.e. in the already-open buffer? I'm curious which you think is better to use and how much work it'd be to convert this PR to that.

(I do worry that the "inline diff preview" has more sharp edges though - like what if opencode edits a file that's not open in the current buffer? Whereas this PR doesn't have to worry about that)

@epheien
Copy link
Contributor Author

epheien commented Jan 16, 2026

Xnip2026-01-15_15-08-50 Xnip2026-01-16_13-03-38

The above is the dialog box of avante.nvim and codecompanion.nvim. Do you expect it to be in the same form as avante.nvim? The issue with avante.nvim's form is that it still requires a confirmation dialog, which affects the display of content; if a dialog is not used and other facilities are used to display key hints, it can easily interfere with the functions of other plugins.

I plan to complete this feature later, referring to the implementation of avante.nvim.

In the form of codecompanion.nvim, the implementation would be easier.

@NickvanDyke
Copy link
Owner

Thanks for those comparison screenshots, very helpful!

I guess in avante.nvim style, I envisioned keybinds to accept/reject the diff while the cursor is within its range. That seems the most vim-y? And would allow vim.keymap.set for those keymaps, which I'd prefer to stick to.

However I could be overlooking shortcomings of that style. 🤔 The main question with inline diffing seems to be what to do when the diff is off-screen or even in a different file. Whereas the dialog doesn't need to care about the current editor view.

@epheien
Copy link
Contributor Author

epheien commented Jan 16, 2026

However I could be overlooking shortcomings of that style. 🤔 The main question with inline diffing seems to be what to do when the diff is off-screen or even in a different file. Whereas the dialog doesn't need to care about the current editor view.

I have analyzed the opencode code using the large model (glm-4.7), and its edit tool processes only a single file at a time.

@NickvanDyke
Copy link
Owner

Ah that's helpful! But it might edit files other than the open one right? So we'd have to open that file on the user's behalf to display the inline diff. Or scroll to an inline diff that appears off-screen in the open buffer.

@epheien
Copy link
Contributor Author

epheien commented Jan 16, 2026

Ah that's helpful! But it might edit files other than the open one right? So we'd have to open that file on the user's behalf to display the inline diff. Or scroll to an inline diff that appears off-screen in the open buffer.

That's right, avante.nvim does it like that.

@NickvanDyke
Copy link
Owner

Ah cool, so it's somewhat tried and proven already!

What do you think then? I'm most curious about inline diffs with keymaps to accept/reject the diff under the cursor. But you clearly have more knowledge of typical patterns here. And I also want to respect that you're implementing it haha.

@epheien
Copy link
Contributor Author

epheien commented Jan 16, 2026

What do you think then? I'm most curious about inline diffs with keymaps to accept/reject the diff under the cursor. But you clearly have more knowledge of typical patterns here. And I also want to respect that you're implementing it haha.

If you mean to say that it partially accepts modifications, I haven't seen any tool that has implemented this feature. Because agents are designed to only accept/reject all changes.

@NickvanDyke
Copy link
Owner

Yeah I agree, I meant it'd accept the entire diff when the cursor is on any line within the diff's range.

@epheien
Copy link
Contributor Author

epheien commented Jan 16, 2026

Yeah I agree, I meant it'd accept the entire diff when the cursor is on any line within the diff's range.

In the diff view of vim/nvim, this situation is handled by do/dp, but the original meaning is to only accept modifications at the cursor position. If this behavior becomes accept all changes, users may feel confused.

If according to your idea, then it would be to export the API for these 3 keys so that users can bind them themselves.

But this way, it's difficult to display the relevant key help information on the interface; and users must read the entire configuration document to use this feature, making it hard to achieve out-of-the-box use.

Additionally, many of the best practices guidelines above are not suitable for explicit use, for example, when a dialog box is needed, some default keys are required and help information must be displayed, even Vim does it this way, for example confirm().

@NickvanDyke
Copy link
Owner

That's fair @epheien - thanks for the discussion. Let me think on this a bit! Right now I think the avante.nvim experience seems smoother to me, but I also haven't actually used either. If that's a lot more effort, I'm also happy to start with the dialog solution and go from there. 🙂

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