Skip to content

Commit c5653ca

Browse files
Danilo Verde RibeiroDanilo Verde Ribeiro
authored andcommitted
Squashed commit of the following:
commit 7653234 Author: Guillaume BOEHM <github@mail.gboehm.com> Date: Wed Oct 29 10:27:47 2025 +0000 feat: add prompt_guard callback mechanism (sudo-tee#78) This PR adds a plugin option to run a callback before sending promts to the LLM or before opening the opencode window. In my use case I want to be able to exclude some directories of my computer with sensitive information in order to not mistakenly send them to the LLM. I've mostly vibe-coded this and then went back on the code to check what it did, I'm not super well versed in lua so I might have missed things. Implementation details: Add prompt_guard configuration option (function that returns boolean) Check guard before sending prompts (ERROR notification if denied) Check guard before opening buffer first time (WARN notification if denied) Add util.check_prompt_allowed() helper functions Guard has no parameters, users can access vim state directly Proper error handling for guard callback failures Co-authored-by: Guillaume BOEHM <git@mail.gboehm.com> commit 0dc254b Author: Francis Belanger <francis.belanger@gmail.com> Date: Tue Oct 28 12:01:42 2025 -0400 fix(run): context args not passed in run new session commit 6eb7354 Author: Francis Belanger <francis.belanger@gmail.com> Date: Tue Oct 28 11:18:48 2025 -0400 chore(icons): deprecate emoji icons in favor of nerdfonts commit 3dea370 Author: Francis Belanger <francis.belanger@gmail.com> Date: Tue Oct 28 08:49:27 2025 -0400 chore(emmyrc): fix broken .emmyrc.json commit c07f293 Author: Cameron Ring <cameron@cs.stanford.edu> Date: Mon Oct 27 17:32:50 2025 -0700 fix(renderer): render errors after last part commit bebe01c Author: Francis Belanger <francis.belanger@gmail.com> Date: Mon Oct 27 15:56:57 2025 -0400 feat(rendering): incremental rendering (sudo-tee#62) Introduces an incremental rendering that updates only the changed portion(s) of the buffer instead of re-rendering everything on every change. This reduces CPU usages for large sessions. This PR also incorporate a functional test suite in `tests/manual` where you can record a run snapshot tests. This is a major revision of the rendering system. Co-authored-by: Cameron Ring <cameron@cs.stanford.edu> commit 0f2d1e5 Author: Francis Belanger <francis.belanger@gmail.com> Date: Thu Oct 23 07:32:58 2025 -0400 feat(blink): enable other completion sources for blink This should fix sudo-tee#65 commit e06f651 Author: Francis Belanger <francis.belanger@gmail.com> Date: Thu Oct 23 07:31:11 2025 -0400 fix(cmp): fix file mention closing when typing for nvim_cmp commit 84d9ae0 Author: Francis Belanger <francis.belanger@gmail.com> Date: Thu Oct 23 06:32:17 2025 -0400 fix(mentions): letter `a` appended when triggering mentions commit 44d22ba Author: Francis Belanger <francis.belanger@gmail.com> Date: Thu Oct 23 06:23:49 2025 -0400 test(toggle): fix tests for api.open commit 826341d Author: Francis Belanger <francis.belanger@gmail.com> Date: Thu Oct 23 06:18:09 2025 -0400 fix(toggle): toggle keymap was always triggering insert mode This should fix sudo-tee#77 commit 803eb3e Author: Francis Belanger <francis.belanger@gmail.com> Date: Wed Oct 22 15:53:52 2025 -0400 docs(session_picker): add config for delete session in README commit edba833 Author: Francis Belanger <francis.belanger@gmail.com> Date: Wed Oct 22 15:50:21 2025 -0400 feat(session_picker): add keybind in title commit 357ef3c Author: Cameron Ring <cameron@cs.stanford.edu> Date: Fri Oct 17 18:37:41 2025 -0700 feat(session_picker): Fixes sudo-tee#68 commit fed6941 Author: Francis Belanger <francis.belanger@gmail.com> Date: Mon Oct 20 15:19:21 2025 -0400 fix(completion): completion were broken after last change commit c505554 Author: Francis Belanger <francis.belanger@gmail.com> Date: Mon Oct 20 14:53:50 2025 -0400 fix(focus_input): fix focusing input on window opening commit 4824151 Author: Francis Belanger <francis.belanger@gmail.com> Date: Mon Oct 20 14:37:36 2025 -0400 fix(input_window): properly restore input text when reopening the window commit ca62c0c Author: Francis Belanger <francis.belanger@gmail.com> Date: Mon Oct 20 14:24:17 2025 -0400 fix(bash-tool): properly shown bash command on permission prompt This should fix sudo-tee#74 commit 28d6379 Author: Francis Belanger <francis.belanger@gmail.com> Date: Mon Oct 20 14:08:45 2025 -0400 fix: focusing input window in insert mode The shortcut <C-i> is interpreted as <tab> by terminals I moved it to i. sudo-tee#72 focusing the input_window should restore to the previous position not the char before sudo-tee#64 commit 946af3a Author: Francis Belanger <francis.belanger@gmail.com> Date: Sat Oct 18 15:11:17 2025 -0400 fix(slash_commands): allow slash_commands to be entered in input window This should fix sudo-tee#71 commit abc1e2a Author: Francis Belanger <francis.belanger@gmail.com> Date: Sat Oct 18 11:25:55 2025 -0400 feat(completion): add folder icon kind commit 031bf0a Author: Francis Belanger <francis.belanger@gmail.com> Date: Sat Oct 18 11:12:19 2025 -0400 feat: support for folder mentions commit e99a463 Author: Francis Belanger <francis.belanger@gmail.com> Date: Thu Oct 16 16:34:41 2025 -0400 feat(completion): add file search from server api commit 601cc82 Author: Cameron Ring <cameron@cs.stanford.edu> Date: Thu Oct 9 15:52:47 2025 -0700 fix(config): add config metatable (sudo-tee#59) Fixes sudo-tee#58 Makes config access less error prone and more ergonomic commit ca0ff90 Author: Francis Belanger <francis.belanger@gmail.com> Date: Thu Oct 9 09:50:28 2025 -0400 chore: update .luarc.json for better support of emmylua_ls commit a82b08c Author: Francis Belanger <francis.belanger@gmail.com> Date: Thu Oct 9 09:49:28 2025 -0400 fix: prefix replacement not working properly commit 9d949e7 Author: Francis Belanger <francis.belanger@gmail.com> Date: Thu Oct 9 08:43:57 2025 -0400 feat: add a keymap_prefix to configure the default `<leader>o` commit 8c65d9b Author: Cameron Ring <cameron@cs.stanford.edu> Date: Thu Oct 9 03:29:02 2025 -0700 feat(config)!: modern keymap format + mode support (sudo-tee#52) This is a complete overhaul of the keymaps, The old config should still work but with a warning for migration The new format shoud now be: ```lua keymap = { editor = { ['<leader>og'] = { 'toggle' }, -- I don't think we really need to support just string, it makes things more complex for nothing ['<leader>oi'] = { 'open_input' }, ['<leader>oI'] = { 'open_input_new_session' }, ['<leader>oo'] = { 'open_output' }, ['<leader>ot'] = { 'toggle_focus' }, ['<leader>oq'] = { 'close' }, ['<leader>os'] = { 'select_session' }, ['<leader>op'] = { 'configure_provider' }, ['<leader>od'] = { 'diff_open' }, ['<leader>o]'] = { 'diff_next' }, ['<leader>o['] = { 'diff_prev' }, ['<leader>oc'] = { 'diff_close' }, ['<leader>ora'] = { 'diff_revert_all_last_prompt' }, ['<leader>ort'] = { 'diff_revert_this_last_prompt' }, ['<leader>orA'] = { 'diff_revert_all' }, ['<leader>orT'] = { 'diff_revert_this' }, ['<leader>orr'] = { 'diff_restore_snapshot_file' }, ['<leader>orR'] = { 'diff_restore_snapshot_all' }, ['<leader>oC'] = { 'open_configuration_file' }, ['<leader>ox'] = { 'swap_position' }, ['<leader>opa'] = { 'permission_accept' }, ['<leader>opA'] = { 'permission_accept_all' }, ['<leader>opd'] = { 'permission_deny' }, }, output_window = { ['<leader>something'] = {function () -- custom code end}, ['<esc>'] = { 'close' }, ['<C-c>'] = { 'stop' }, [']]'] = { 'next_message' }, ['[['] = { 'prev_message' }, ['<tab>'] = { 'toggle_pane', mode = { 'n', 'i' } }, ['<C-i>'] = { 'focus_input' }, ['<leader>oS'] = { 'select_child_session' }, ['<leader>oD'] = { 'debug_message' }, ['<leader>oO'] = { 'debug_output' }, ['<leader>ods'] = { 'debug_session' }, }, input_window = { ['<cr>'] = { 'submit_input_prompt', mode = { 'n', 'i' } }, ['<esc>'] = { 'close' }, ['<C-c>'] = { 'stop' }, ['~'] = { 'mention_file', mode = 'i' }, ['@'] = { 'mention', mode = 'i' }, ['/'] = { 'slash_commands', mode = 'i' }, ['<tab>'] = { 'toggle_pane', mode = { 'n', 'i' } }, ['<up>'] = { 'prev_prompt_history', mode = { 'n', 'i' } }, ['<down>'] = { 'next_prompt_history', mode = { 'n', 'i' } }, ['<M-m>'] = { 'switch_mode' }, ['<leader>oS'] = { 'select_child_session' }, ['<leader>oD'] = { 'debug_message' }, ['<leader>oO'] = { 'debug_output' }, ['<leader>ods'] = { 'debug_session' }, }, permission = { accept = 'a', accept_all = 'A', deny = 'd', }, ``` commit fb33ce6 Author: Francis Belanger <francis.belanger@gmail.com> Date: Tue Oct 7 10:22:36 2025 -0400 refactor: simplify keymaps by having a corresponding api function commit fa31457 Author: Francis Belanger <francis.belanger@gmail.com> Date: Tue Oct 7 13:23:32 2025 -0400 feat: restore mentions when navigating history
1 parent 25c099d commit c5653ca

File tree

111 files changed

+64422
-1365
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

111 files changed

+64422
-1365
lines changed

.emmyrc.json

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"$schema": "https://raw.githubusercontent.com/EmmyLuaLs/emmylua-analyzer-rust/refs/heads/main/crates/emmylua_code_analysis/resources/schema.json",
3+
"runtime": {
4+
"version": "LuaJIT"
5+
},
6+
"workspace": {
7+
"library": [
8+
"$VIMRUNTIME",
9+
"$HOME/.local/share/nvim/lazy/luvit-meta/library/uv.lua"
10+
],
11+
"ignoreGlobs": [
12+
"**/*_spec.lua"
13+
]
14+
}
15+
}

.github/workflows/tests.yml

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# From
2+
# https://github.com/shortcuts/neovim-plugin-boilerplate/blob/main/.github/workflows/main.yml
3+
4+
name: tests
5+
6+
on:
7+
push:
8+
pull_request:
9+
types: [opened, synchronize]
10+
11+
jobs:
12+
lint:
13+
runs-on: ubuntu-latest
14+
name: lint
15+
steps:
16+
- uses: actions/checkout@v4
17+
18+
- uses: JohnnyMorganz/stylua-action@v4
19+
with:
20+
token: ${{ secrets.GITHUB_TOKEN }}
21+
version: latest
22+
args: --check . -g '*.lua' -g '!deps/'
23+
24+
test:
25+
timeout-minutes: 4
26+
strategy:
27+
matrix:
28+
os: [ubuntu-latest]
29+
neovim_version: ["v0.10.3", "v0.11.4", "nightly"]
30+
include:
31+
- os: macos-latest
32+
neovim_version: v0.11.4
33+
runs-on: ${{ matrix.os }}
34+
35+
steps:
36+
- uses: actions/checkout@v4
37+
38+
- name: setup neovim
39+
uses: rhysd/action-setup-vim@v1
40+
with:
41+
neovim: true
42+
version: ${{ matrix.neovim_version }}
43+
44+
# only needed if testing in ssh but doesn't hurt
45+
- name: Add nvim to PATH
46+
run: echo "${{ steps.setup_nvim.outputs.executable }}" >> $GITHUB_PATH
47+
48+
- name: Install plenary
49+
run: |
50+
git clone --depth 1 https://github.com/nvim-lua/plenary.nvim ~/.local/share/nvim/site/pack/vendor/start/plenary.nvim
51+
52+
- name: Run tests
53+
run: ./run_tests.sh
54+
55+
# # For sshing in to debug GH actions
56+
# - name: Setup tmate session
57+
# uses: mxschmitt/action-tmate@v3
58+
# with:
59+
# detached: true

.luarc.json

Lines changed: 0 additions & 5 deletions
This file was deleted.

AGENTS.md

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,24 @@
11
# AGENTS.md
22

33
## Build, Lint, and Test
4+
45
- **Run all tests:** `./run_tests.sh`
56
- **Minimal tests:**
67
`nvim --headless -u tests/minimal/init.lua -c "lua require('plenary.test_harness').test_directory('./tests/minimal', {minimal_init = './tests/minimal/init.lua', sequential = true})"`
78
- **Unit tests:**
89
`nvim --headless -u tests/minimal/init.lua -c "lua require('plenary.test_harness').test_directory('./tests/unit', {minimal_init = './tests/minimal/init.lua'})"`
910
- **Run a single test:** Replace the directory in the above command with the test file path, e.g.:
10-
`nvim --headless -u tests/minimal/init.lua -c "lua require('plenary.test_harness').test_directory('./tests/unit/job_spec.lua', {minimal_init = './tests/minimal/init.lua'})"`
11+
`nvim --headless -u tests/manual/init.lua -c "lua require('plenary.test_harness').test_directory('./tests/unit/job_spec.lua', {minimal_init = './tests/minimal/init.lua'})"`
12+
- **Manual/Visual tests:** `./tests/manual/run_replay.sh` - Replay captured event data for visual testing
13+
- **Debug rendering in headless mode:**
14+
`nvim --headless -u tests/manual/init_replay.lua "+ReplayHeadless" "+ReplayLoad tests/data/FILE.json" "+ReplayAll 0" "+qa"`
15+
This will replay events and dump the output buffer to stdout, useful for debugging rendering issues without a UI.
16+
You can also run to just a specific message # with (e.g. message # 12):
17+
`nvim --headless -u tests/manual/init_replay.lua "+ReplayHeadless" "+ReplayLoad tests/data/message-removal.json" "+ReplayNext 12" "+qa"`
1118
- **Lint:** No explicit lint command; follow Lua best practices.
1219

1320
## Code Style Guidelines
21+
1422
- **Imports:** `local mod = require('mod')` at the top. Group standard, then project imports.
1523
- **Formatting:** 2 spaces per indent. No trailing whitespace. Lines ≤ 100 chars.
1624
- **Types:** Use Lua annotations (`---@class`, `---@field`, etc.) for public APIs/config.
@@ -19,6 +27,6 @@
1927
- **Comments:** Only when necessary for clarity. Prefer self-explanatory code.
2028
- **Functions:** Prefer local functions. Use `M.func` for module exports.
2129
- **Config:** Centralize in `config.lua`. Use deep merge for user overrides.
22-
- **Tests:** Place in `tests/minimal/` or `tests/unit/`.
30+
- **Tests:** Place in `tests/minimal/` or `tests/unit/`. Manual/visual tests in `tests/manual/`.
2331

2432
_Agentic coding agents must follow these conventions strictly for consistency and reliability._

README.md

Lines changed: 110 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -90,61 +90,72 @@ Install the plugin with your favorite package manager. See the [Configuration](#
9090

9191
## ⚙️ Configuration
9292

93+
> **Note**: The keymap configuration structure has been updated. Old keymaps (`keymap.global` and `keymap.window`) will be mapped to the new format (`keymap.editor`, `keymap.input_window`, `keymap.output_window`) but you should update your config to the new format. See [Keymap Configuration](#keymap-configuration) below for details.
94+
9395
```lua
9496
-- Default configuration with all available options
9597
require('opencode').setup({
9698
preferred_picker = nil, -- 'telescope', 'fzf', 'mini.pick', 'snacks', if nil, it will use the best available picker. Note mini.pick does not support multiple selections
9799
preferred_completion = nil, -- 'blink', 'nvim-cmp','vim_complete' if nil, it will use the best available completion
98100
default_global_keymaps = true, -- If false, disables all default global keymaps
99101
default_mode = 'build', -- 'build' or 'plan' or any custom configured. @see [OpenCode Agents](https://opencode.ai/docs/modes/)
102+
keymap_prefix = '<leader>o', -- Default keymap prefix for global keymaps change to your preferred prefix and it will be applied to all keymaps starting with <leader>o
100103
keymap = {
101-
global = {
102-
toggle = '<leader>og', -- Open opencode. Close if opened
103-
open_input = '<leader>oi', -- Opens and focuses on input window on insert mode
104-
open_input_new_session = '<leader>oI', -- Opens and focuses on input window on insert mode. Creates a new session
105-
open_output = '<leader>oo', -- Opens and focuses on output window
106-
toggle_focus = '<leader>ot', -- Toggle focus between opencode and last window
107-
close = '<leader>oq', -- Close UI windows
108-
select_session = '<leader>os', -- Select and load a opencode session
109-
configure_provider = '<leader>op', -- Quick provider and model switch from predefined list
110-
diff_open = '<leader>od', -- Opens a diff tab of a modified file since the last opencode prompt
111-
diff_next = '<leader>o]', -- Navigate to next file diff
112-
diff_prev = '<leader>o[', -- Navigate to previous file diff
113-
diff_close = '<leader>oc', -- Close diff view tab and return to normal editing
114-
diff_revert_all_last_prompt = '<leader>ora', -- Revert all file changes since the last opencode prompt
115-
diff_revert_this_last_prompt = '<leader>ort', -- Revert current file changes since the last opencode prompt
116-
diff_revert_all = '<leader>orA', -- Revert all file changes since the last opencode session
117-
diff_revert_this = '<leader>orT', -- Revert current file changes since the last opencode session
118-
diff_restore_snapshot_file = '<leader>orr', -- Restore file to snapshot
119-
diff_restore_snapshot_all = '<leader>orR', -- Restore all files to snapshot
120-
open_configuration_file = '<leader>oC', -- Open opencode configuration file
121-
swap_position = '<leader>ox', -- Swap Opencode pane left/right
122-
permission_accept = '<leader>opa', -- Accept permission request once
123-
permission_accept_all = '<leader>opA', -- Accept all (for current tool)
124-
permission_deny = '<leader>opd',-- Accept permission request once
125-
},
126-
window = {
127-
submit = '<cr>', -- Submit prompt (normal mode)
128-
submit_insert = '<cr>', -- Submit prompt (insert mode)
129-
close = '<esc>', -- Close UI windows
130-
stop = '<C-c>', -- Stop opencode while it is running
131-
next_message = ']]', -- Navigate to next message in the conversation
132-
prev_message = '[[', -- Navigate to previous message in the conversation
133-
mention = '@', -- Insert mention (file/agent)
134-
mention_file = '~', -- Pick a file and add to context. See File Mentions section
135-
slash_commands = '/', -- Pick a command to run in the input window
136-
toggle_pane = '<tab>', -- Toggle between input and output panes
137-
prev_prompt_history = '<up>', -- Navigate to previous prompt in history
138-
next_prompt_history = '<down>', -- Navigate to next prompt in history
139-
switch_mode = '<M-m>', -- Switch between modes (build/plan)
140-
focus_input = '<C-i>', -- Focus on input window and enter insert mode at the end of the input from the output window
141-
select_child_session = '<leader>oS', -- Select and load a child session
142-
debug_message = '<leader>oD', -- Open raw message in new buffer for debugging
143-
debug_output = '<leader>oO', -- Open raw output in new buffer for debugging
144-
permission_accept = 'a', -- Accept permission request once (only available when there is a pending permission request)
145-
permission_accept_all = 'A', -- Accept all (for current tool) permission request once (only available when there is a pending permission request)
146-
permission_deny = 'd',-- Accept permission request once (only available when there is a pending permission request)
147-
debug_session = '<leader>ods', -- Debug session info
104+
editor = {
105+
['<leader>og'] = { 'toggle' }, -- Open opencode. Close if opened
106+
['<leader>oi'] = { 'open_input' }, -- Opens and focuses on input window on insert mode
107+
['<leader>oI'] = { 'open_input_new_session' }, -- Opens and focuses on input window on insert mode. Creates a new session
108+
['<leader>oo'] = { 'open_output' }, -- Opens and focuses on output window
109+
['<leader>ot'] = { 'toggle_focus' }, -- Toggle focus between opencode and last window
110+
['<leader>oq'] = { 'close' }, -- Close UI windows
111+
['<leader>os'] = { 'select_session' }, -- Select and load a opencode session
112+
['<leader>op'] = { 'configure_provider' }, -- Quick provider and model switch from predefined list
113+
['<leader>od'] = { 'diff_open' }, -- Opens a diff tab of a modified file since the last opencode prompt
114+
['<leader>o]'] = { 'diff_next' }, -- Navigate to next file diff
115+
['<leader>o['] = { 'diff_prev' }, -- Navigate to previous file diff
116+
['<leader>oc'] = { 'diff_close' }, -- Close diff view tab and return to normal editing
117+
['<leader>ora'] = { 'diff_revert_all_last_prompt' }, -- Revert all file changes since the last opencode prompt
118+
['<leader>ort'] = { 'diff_revert_this_last_prompt' }, -- Revert current file changes since the last opencode prompt
119+
['<leader>orA'] = { 'diff_revert_all' }, -- Revert all file changes since the last opencode session
120+
['<leader>orT'] = { 'diff_revert_this' }, -- Revert current file changes since the last opencode session
121+
['<leader>orr'] = { 'diff_restore_snapshot_file' }, -- Restore a file to a restore point
122+
['<leader>orR'] = { 'diff_restore_snapshot_all' }, -- Restore all files to a restore point
123+
['<leader>ox'] = { 'swap_position' }, -- Swap Opencode pane left/right
124+
['<leader>opa'] = { 'permission_accept' }, -- Accept permission request once
125+
['<leader>opA'] = { 'permission_accept_all' }, -- Accept all (for current tool)
126+
['<leader>opd'] = { 'permission_deny' }, -- Deny permission request once
127+
},
128+
input_window = {
129+
['<cr>'] = { 'submit_input_prompt', mode = { 'n', 'i' } }, -- Submit prompt (normal mode and insert mode)
130+
['<esc>'] = { 'close' }, -- Close UI windows
131+
['<C-c>'] = { 'stop' }, -- Stop opencode while it is running
132+
['~'] = { 'mention_file', mode = 'i' }, -- Pick a file and add to context. See File Mentions section
133+
['@'] = { 'mention', mode = 'i' }, -- Insert mention (file/agent)
134+
['/'] = { 'slash_commands', mode = 'i' }, -- Pick a command to run in the input window
135+
['<tab>'] = { 'toggle_pane', mode = { 'n', 'i' } }, -- Toggle between input and output panes
136+
['<up>'] = { 'prev_prompt_history', mode = { 'n', 'i' } }, -- Navigate to previous prompt in history
137+
['<down>'] = { 'next_prompt_history', mode = { 'n', 'i' } }, -- Navigate to next prompt in history
138+
['<M-m>'] = { 'switch_mode' }, -- Switch between modes (build/plan)
139+
},
140+
output_window = {
141+
['<esc>'] = { 'close' }, -- Close UI windows
142+
['<C-c>'] = { 'stop' }, -- Stop opencode while it is running
143+
[']]'] = { 'next_message' }, -- Navigate to next message in the conversation
144+
['[['] = { 'prev_message' }, -- Navigate to previous message in the conversation
145+
['<tab>'] = { 'toggle_pane', mode = { 'n', 'i' } }, -- Toggle between input and output panes
146+
['i'] = { 'focus_input', 'n' }, -- Focus on input window and enter insert mode at the end of the input from the output window
147+
['<leader>oS'] = { 'select_child_session' }, -- Select and load a child session
148+
['<leader>oD'] = { 'debug_message' }, -- Open raw message in new buffer for debugging
149+
['<leader>oO'] = { 'debug_output' }, -- Open raw output in new buffer for debugging
150+
['<leader>ods'] = { 'debug_session' }, -- Open raw session in new buffer for debugging
151+
},
152+
permission = {
153+
accept = 'a', -- Accept permission request once (only available when there is a pending permission request)
154+
accept_all = 'A', -- Accept all (for current tool) permission request once (only available when there is a pending permission request)
155+
deny = 'd', -- Deny permission request once (only available when there is a pending permission request)
156+
},
157+
session_picker = {
158+
delete_session = { '<C-d>' }, -- Delete selected session in the session picker
148159
},
149160
},
150161
ui = {
@@ -157,13 +168,17 @@ require('opencode').setup({
157168
display_cost = true, -- Display cost in the footer
158169
window_highlight = 'Normal:OpencodeBackground,FloatBorder:OpencodeBorder', -- Highlight group for the opencode window
159170
icons = {
160-
preset = 'nerdfonts', -- 'emoji' | 'nerdfonts' | 'text'. Choose UI icon style (default: 'nerdfonts')
161-
overrides = {}, -- Optional per-key overrides, see section below
171+
preset = 'nerdfonts', -- 'nerdfonts' | 'text'. Choose UI icon style (default: 'nerdfonts')
172+
overrides = {}, -- Optional per-key overrides, see section below
162173
},
163174
output = {
164175
tools = {
165176
show_output = true, -- Show tools output [diffs, cmd output, etc.] (default: true)
166177
},
178+
rendering = {
179+
markdown_debounce_ms = 250, -- Debounce time for markdown rendering on new data (default: 250ms)
180+
on_data_rendered = nil, -- Called when new data is rendered; set to false to disable default RenderMarkdown/Markview behavior
181+
},
167182
},
168183
input = {
169184
text = {
@@ -174,7 +189,7 @@ require('opencode').setup({
174189
file_sources = {
175190
cache_timeout = 300, -- seconds
176191
enabled = true,
177-
preferred_cli_tool = 'fd', -- 'fd','fdfind','rg','git' if nil, it will use the best available tool
192+
preferred_cli_tool = 'server', -- 'fd','fdfind','rg','git','server' if nil, it will use the best available tool, 'server' uses opencode cli to get file list (works cross platform) and supports folders
178193
ignore_patterns = {
179194
'^%.git/',
180195
'^%.svn/',
@@ -309,10 +324,29 @@ require('opencode').setup({
309324
debug = {
310325
enabled = false, -- Enable debug messages in the output window
311326
},
327+
prompt_guard = nil, -- Optional function that returns boolean to control when prompts can be sent (see Prompt Guard section)
312328
})
313329

314330
```
315331

332+
### Keymap Configuration
333+
334+
The keymap configuration has been restructured for better organization and clarity:
335+
336+
- **`editor`**: Global keymaps that are available throughout Neovim
337+
- **`input_window`**: Keymaps specific to the input window
338+
- **`output_window`**: Keymaps specific to the output window
339+
- **`permission`**: Special keymaps for responding to permission requests (available in input/output windows when there's a pending permission)
340+
341+
**Backward Compatibility**: The plugin automatically maps configurations that use `keymap.global` and `keymap.window` to the new structure. A deprecation warning will be shown during migration. Update your configuration to use the new structure to remove the warning.
342+
343+
Each keymap entry is a table consising of:
344+
345+
- The string name of an api function = `{ 'toggle' }`
346+
- Or a custom function: `{ function() ... end }`
347+
- An optional mode: `{ 'toggle', mode = { 'n', 'i' } }`
348+
- An optional desc: `{'toggle', desc = 'Toggle Opencode' }`
349+
316350
### UI icons (disable emojis or customize)
317351

318352
By default, opencode.nvim uses emojis for icons in the UI. If you prefer a plain, emoji-free interface, you can switch to the `text` preset or override icons individually.
@@ -630,9 +664,34 @@ The plugin defines several highlight groups that can be customized to match your
630664
- `OpencodeAgentBuild`: Agent indicator in winbar for Build mode (default: #616161 background)
631665
- `OpencodeAgentCustom`: Agent indicator in winbar for custom modes (default: #3b4261 background)
632666
- `OpencodeContestualAction`: Highlight for contextual actions in the output window (default: #3b4261 background)
633-
- `OpencodeInpuutLegend`: Highlight for input window legend (default: #CCCCCC background)
667+
- `OpencodeInputLegend`: Highlight for input window legend (default: #CCCCCC background)
634668
- `OpencodeHint`: Highlight for hinting messages in input window and token info in output window footer (linked to `Comment`)
635669

670+
## 🛡️ Prompt Guard
671+
672+
The `prompt_guard` configuration option allows you to control when prompts can be sent to Opencode. This is useful for preventing accidental or unauthorized AI interactions in certain contexts.
673+
674+
### Configuration
675+
676+
Set `prompt_guard` to a function that returns a boolean:
677+
678+
```lua
679+
require('opencode').setup({
680+
prompt_guard = function()
681+
-- Your custom logic here
682+
-- Return true to allow, false to deny
683+
return true
684+
end,
685+
})
686+
```
687+
688+
### Behavior
689+
690+
- **Before sending prompts**: The guard is checked before any prompt is sent to the AI. If denied, an ERROR notification is shown and the prompt is not sent.
691+
- **Before opening UI**: The guard is checked when opening the Opencode buffer for the first time. If denied, a WARN notification is shown and the UI is not opened.
692+
- **No parameters**: The guard function receives no parameters. Access vim state directly (e.g., `vim.fn.getcwd()`, `vim.bo.filetype`).
693+
- **Error handling**: If the guard function throws an error or returns a non-boolean value, the prompt is denied with an appropriate error message.
694+
636695
## 🔧 Setting up Opencode
637696

638697
If you're new to opencode:

0 commit comments

Comments
 (0)