Skip to content

Feature: Un-intrusive floating popup for opencode permissions #304

Open
r0ckHopper wants to merge 4 commits into
nickjvandyke:mainfrom
r0ckHopper:main
Open

Feature: Un-intrusive floating popup for opencode permissions #304
r0ckHopper wants to merge 4 commits into
nickjvandyke:mainfrom
r0ckHopper:main

Conversation

@r0ckHopper

@r0ckHopper r0ckHopper commented Jun 24, 2026

Copy link
Copy Markdown

Tasks

  • I read CONTRIBUTING.md
  • I ensured my changes pass automated checks
  • I reviewed and understand the AI-generated code in my changes (if any)

Description

Issue 1 and Solution

The current 2 options (vim.ui.select and snacks) for permissions from opencode break the flow of coding, I found that while I was doing edits, opencode kept giving me popups and I wasn't ready to context switch yet. So I needed a non-intrusive solution to reviewing opencode requests.

This plugin addition is an optional floating window for Permissions that is not focused by default.
It keeps a queue of all concurrent requests that opencode made which can be navigated through and approved one at a time once user is ready to do so.

Issue 2 and Solution

if I hit cancel on the requests I couldn't go back to viewing them from within nvim which meant I had to use the tui to accept

This change allows user to toggle hide for permissions and go back to work, then toggle it back without losing state or needing to use tui.

Issue 3 and Solution

sometimes permissions can get out of sync if user replies in the tui. So nvim still shows the permission even though it is no longer up

Opencode server already sends events notifying us of this, so we can update when we receive this request.

Other niceties added

  • Allow All option when multiple requests stack
    • does it sequentially. I was careful to avoid race condition because I saw that if the requests were done out of order they would fail spectacularly
  • Auto update buttons
    • When multiple requests enter queue, popup re-renders to update buttons and number of permissions
    • Reject is updated to reject all (Opencode rejects all requests when you send reject, this was a gap in original vim.ui.select implementation of permissions, once you reject 1st request you cannot accept next one)
  • Multiple lines are formatted correctly so we can see better
  • Update highlight of border based on focus
  • Added some permission labels like $ for bash commands (just 4 for now)

Some design decisions

  • Closing the window hides it instead so u can still toggle back, only way to get rid of this is to reject
  • Diff ui is unaffected, you will not see this floating pop up when opencode requests an edit (I think current da and dr works well)

How to configure

This is an optional feature and requires user to add the following to opts

vim.g.opencode_opts = {
	events = {
		permissions = {
			floating = true,
		},
	},
}

Additionally they can keybind to most functions by doing the following

vim.keymap.set({ "n", "v", "i" }, "<C-h>", function() require("opencode.events.permissions.floating").move_left() end, { desc = "Permission: select left" })
vim.keymap.set({ "n", "v", "i" }, "<C-l>", function() require("opencode.events.permissions.floating").move_right() end, { desc = "Permission: select right" })
vim.keymap.set({ "n", "v", "i" }, "<C-n>", function() require("opencode.events.permissions.floating").next_permission() end, { desc = "Permission: next request" })
vim.keymap.set({ "n", "v", "i" }, "<C-p>", function() require("opencode.events.permissions.floating").prev_permission() end, { desc = "Permission: prev request" })
vim.keymap.set("n", "<leader><CR>", function() require("opencode.events.permissions.floating").confirm() end, { desc = "Permission: confirm" })
vim.keymap.set("n", "<leader>op", function() require("opencode.events.permissions.floating").toggle() end, { desc = "Toggle permission window" })

Testing

  1. Ask agent to make multiple concurrent requests -> check if popup shows up unfocused and dim
  2. Nav to popup -> should highlight + select 1st option
  3. h/l should navigate options
  4. n/p should navigate
  5. enter should accept option and changes should be reflected both in tui and nvim changes from tui should also be reflected in nvim
  6. Esc/q while window is focused should hide it, until you toggle it back on from toggle() command
  7. Allow all should accept all requests and not cause tool exception
  8. repeat 1 but ask for multi line request which should be formatted correctly
  9. repeat 1 but ask for edit, floating popup should not show up
  10. repeat 1 and accept from tui, changes should be reflected in nvim floating window
  11. All keybinds should work

Related Issue(s)

Not reported as an issue but there was a discussion regarding a non intrusive solution to permissions in #290 (reply in thread)
I had already been making this locally and wanted to share in case you were interested in this

Screenshots/Videos

recording_2026-06-23_19-28-41.mp4

@r0ckHopper r0ckHopper marked this pull request as draft June 24, 2026 06:20
@r0ckHopper r0ckHopper marked this pull request as ready for review June 24, 2026 06:46
@r0ckHopper r0ckHopper force-pushed the main branch 2 times, most recently from 2cf5baf to 30d2069 Compare June 26, 2026 19:51
- gives a custom buffer with extmarks, that doesn't steal focus
- allows navigation between permissions requests
- adds allow all capability and relabels reject as reject all when appropriate
- formats the requests with new lines
- adds some permissions label
- allows control either by nav to window or by keybinds
…ove unnecessary typecasts, correct calc_height (simpler human like)
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.

1 participant