From b7ffc74a057b2f30dc38b584848e95d75a129d64 Mon Sep 17 00:00:00 2001 From: MrBanh Date: Wed, 7 Jan 2026 04:12:52 -0800 Subject: [PATCH 1/3] fix: add option to specify picker layout for snacks picker The default snacks picker layout is used for various sources that is not always ideal for this plugin's use case. E.g., many layouts have preview = 'file', which is useless for the session_picker. There's no way to disable preview just for Opencode's snacks picker without affecting other uses of snacks picker for other sources. --- lua/opencode/types.lua | 15 +++++---------- lua/opencode/ui/base_picker.lua | 5 +++++ lua/opencode/ui/session_picker.lua | 1 + 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/lua/opencode/types.lua b/lua/opencode/types.lua index 1248eb27..310770dd 100644 --- a/lua/opencode/types.lua +++ b/lua/opencode/types.lua @@ -134,6 +134,7 @@ ---@field input { text: { wrap: boolean } } ---@field completion OpencodeCompletionConfig ---@field highlights? OpencodeHighlightConfig +---@field picker OpencodeUIPickerConfig ---@class OpencodeHighlightConfig ---@field vertical_borders? { tool?: { fg?: string, bg?: string }, user?: { fg?: string, bg?: string }, assistant?: { fg?: string, bg?: string } } @@ -149,6 +150,10 @@ ---@field rendering OpencodeUIOutputRenderingConfig ---@field always_scroll_to_bottom boolean +---@class OpencodeUIPickerConfig +---@field snacks_layout? snacks.picker.layout.Config +--- TODO: add more picker-specific presets + ---@class OpencodeContextConfig ---@field enabled boolean ---@field cursor_data { enabled: boolean, context_lines?: number } @@ -506,13 +511,3 @@ ---@field messages number Number of messages reverted ---@field tool_calls number Number of tool calls reverted ---@field files table Summary of file changes reverted - ----@class CodeReference ----@field file_path string Relative or absolute file path ----@field line number|nil Line number (1-indexed) ----@field column number|nil Column number (optional) ----@field message_id string ID of the message containing this reference ----@field match_start number Start position of match in original text ----@field match_end number End position of match in original text ----@field file string Absolute file path (for Snacks picker preview) ----@field pos number[]|nil Position as {line, col} for Snacks picker preview diff --git a/lua/opencode/ui/base_picker.lua b/lua/opencode/ui/base_picker.lua index 1a05dcb4..3a19952c 100644 --- a/lua/opencode/ui/base_picker.lua +++ b/lua/opencode/ui/base_picker.lua @@ -18,6 +18,7 @@ local Promise = require('opencode.promise') ---@field width? number Optional width for the picker (defaults to config or current window width) ---@field multi_selection? table Actions that support multi-selection ---@field preview? "file"|"none"|false Preview mode: "file" for file preview, "none" or false to disable +---@field layout_opts? OpencodeUIPickerConfig ---@class TelescopeEntry ---@field value any @@ -395,11 +396,15 @@ local function snacks_picker_ui(opts) local title = type(opts.title) == 'function' and opts.title() or opts.title ---@cast title string + local layout_opts = opts.layout_opts and opts.layout_opts.snacks_layout or {} + ---@type snacks.picker.Config local snack_opts = { title = title, layout = { + preset = layout_opts.preset, config = function(layout) + vim.tbl_deep_extend('force', layout.layout, layout_opts.layout or {}) local width = opts.width and (opts.width + 3) or nil -- extra space for snacks UI if not has_preview then layout.layout.width = width diff --git a/lua/opencode/ui/session_picker.lua b/lua/opencode/ui/session_picker.lua index bfdfe97c..817cbc6f 100644 --- a/lua/opencode/ui/session_picker.lua +++ b/lua/opencode/ui/session_picker.lua @@ -112,6 +112,7 @@ function M.pick(sessions, callback) callback = callback, title = 'Select A Session', width = config.ui.picker_width or 100, + layout_opts = config.ui.picker, }) end From e9d906792e29cabe851b27cdada460f27b3ab868 Mon Sep 17 00:00:00 2001 From: MrBanh Date: Wed, 7 Jan 2026 05:03:36 -0800 Subject: [PATCH 2/3] better handling of layout_opts in snacks_picker_ui --- lua/opencode/ui/base_picker.lua | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/lua/opencode/ui/base_picker.lua b/lua/opencode/ui/base_picker.lua index 3a19952c..754d5329 100644 --- a/lua/opencode/ui/base_picker.lua +++ b/lua/opencode/ui/base_picker.lua @@ -396,15 +396,13 @@ local function snacks_picker_ui(opts) local title = type(opts.title) == 'function' and opts.title() or opts.title ---@cast title string - local layout_opts = opts.layout_opts and opts.layout_opts.snacks_layout or {} + local layout_opts = opts.layout_opts and opts.layout_opts.snacks_layout or nil ---@type snacks.picker.Config local snack_opts = { title = title, - layout = { - preset = layout_opts.preset, + layout = layout_opts or { config = function(layout) - vim.tbl_deep_extend('force', layout.layout, layout_opts.layout or {}) local width = opts.width and (opts.width + 3) or nil -- extra space for snacks UI if not has_preview then layout.layout.width = width From 759fa0b5fa4a4aa1323f7f4875868954d5d2020c Mon Sep 17 00:00:00 2001 From: MrBanh Date: Wed, 7 Jan 2026 05:20:41 -0800 Subject: [PATCH 3/3] add documentation --- README.md | 62 +++++++++++++++++++++++++++++++++++++++-- lua/opencode/config.lua | 3 ++ 2 files changed, 63 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index b967537f..b258ccbd 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ Opencode logo -### Quick buffer chat (o/) EXPERIMENTAL: +### Quick buffer chat (o/) EXPERIMENTAL This is an experimental feature that allows you to chat with the AI using the current buffer context. In visual mode, it captures the selected text as context, while in normal mode, it uses the current line. The AI will respond with quick edits to the files that are applied by the plugin. @@ -219,6 +219,9 @@ require('opencode').setup({ wrap = false, -- Wraps text inside input window }, }, + picker = { + snacks_layout = nil -- `layout` opts to pass to Snacks.picker.pick({ layout = ... }) + }, completion = { file_sources = { enabled = true, @@ -371,6 +374,61 @@ Available icon keys (see implementation at lua/opencode/ui/icons.lua lines 7-29) - status_on, status_off - border, bullet +### Picker Layout + +You can customize the layout of the picker used for history, session, references, and timeline + +#### Snacks Picker Layout + +There's 3 main ways on how to change the snacks picker layout + +1. Don't specify the new options -> it'll just default to the user's snack picker layout preset from their snacks config +2. Specify the new options for opencode, e.g. + + ```lua + require("opencode").setup({ + ui = { + picker = { + ---@module "snacks" + ---@type snacks.picker.layout.Config | nil + snacks_layout = { + layout = { border = "none", box = "vertical", ... } + }, + }, + }, + }) + ``` + +3. Specify a [builtin layout preset](https://github.com/folke/snacks.nvim/blob/main/docs/picker.md#%EF%B8%8F-layouts) for snacks picker OR a custom layout defined in your snacks config's `opts.picker.layouts` + + ```lua + -- opencode.lua + require("opencode").setup({ + ui = { + picker = { + ---@module "snacks" + ---@type snacks.picker.layout.Config | nil + snacks_layout = { + preset = "custom_layout" -- or builtin snacks, like "select", "default", etc + }, + }, + }, + }) + ``` + + ```lua + -- snacks.lua + { + "folke/snacks.nvim", + opts = { + picker = { + layouts = { + custom_layout = { + layout = { border = "none", box = "vertical", ... } + -- ... + } + ``` + ## 🧰 Usage ### Available Actions @@ -458,7 +516,7 @@ Run a prompt in a new session using the Plan agent and disabling current file co :Opencode run "Fix the bug in the current file" model=github-copilot/claude-sonned-4 ``` -##👮 Permissions +## 👮 Permissions Opencode can issue permission requests for potentially destructive operations (file edits, reverting files, running shell commands, or enabling persistent tool access). Permission requests appear inline in the output and must be responded to before the agent performs the action. Visit [Opencode Permissions Documentation](https://opencode.ai/docs/permissions/) for more details. diff --git a/lua/opencode/config.lua b/lua/opencode/config.lua index 7a897862..060e72ef 100644 --- a/lua/opencode/config.lua +++ b/lua/opencode/config.lua @@ -135,6 +135,9 @@ M.defaults = { wrap = false, }, }, + picker = { + snacks_layout = nil, + }, completion = { file_sources = { enabled = true,