From f2d2d0cb095bf4c734bb81f6ef845e56a51f208f Mon Sep 17 00:00:00 2001 From: Ethan Callanan Date: Wed, 28 Jan 2026 13:24:55 -0500 Subject: [PATCH 1/3] feature(server): add provider specific fallback discovery + tmux implementation --- lua/opencode/cli/server.lua | 9 +++++++++ lua/opencode/provider/init.lua | 4 ++++ lua/opencode/provider/tmux.lua | 36 ++++++++++++++++++++++++++++++++++ 3 files changed, 49 insertions(+) diff --git a/lua/opencode/cli/server.lua b/lua/opencode/cli/server.lua index d4dc654c..3f8a22e3 100644 --- a/lua/opencode/cli/server.lua +++ b/lua/opencode/cli/server.lua @@ -158,6 +158,15 @@ local function find_server_inside_nvim_cwd() end end end + + -- Fallback: try provider-specific discovery + if not found_server then + local provider = require("opencode.config").provider + if provider and provider.find_server then + found_server = provider:find_server() + end + end + if not found_server then error("No `opencode` servers inside Neovim's CWD", 0) end diff --git a/lua/opencode/provider/init.lua b/lua/opencode/provider/init.lua index 74359a7f..da45951f 100644 --- a/lua/opencode/provider/init.lua +++ b/lua/opencode/provider/init.lua @@ -33,6 +33,10 @@ ---Should return `true` if the provider is available, ---else a reason string and optional advice (for `vim.health.warn`). ---@field health? fun(): boolean|string, ...string|string[] +--- +---Find an existing `opencode` server via provider-specific discovery. +---Called as a fallback when CWD-based discovery fails. +---@field find_server? fun(self: opencode.Provider): opencode.cli.server.Server|nil ---Configure and enable built-in providers. ---@class opencode.provider.Opts diff --git a/lua/opencode/provider/tmux.lua b/lua/opencode/provider/tmux.lua index 2f364fe9..b34e68b6 100644 --- a/lua/opencode/provider/tmux.lua +++ b/lua/opencode/provider/tmux.lua @@ -113,4 +113,40 @@ function Tmux:stop() end end +---Find an `opencode` server running in a sibling pane of the current tmux window. +---@return opencode.cli.server.Server|nil +function Tmux:find_server() + if self.health() ~= true then + return nil + end + + local session_window = vim.fn.system("tmux display-message -p '#{session_name}:#{window_index}'"):gsub("\n", "") + local panes_output = vim.fn.system(string.format("tmux list-panes -t '%s' -F '#{pane_tty}'", session_window)) + + for tty in panes_output:gmatch("[^\r\n]+") do + local tty_short = tty:gsub("^/dev/", "") + local ps_output = vim.fn.system(string.format("ps -t %s -o pid,command", tty_short)) + + for line in ps_output:gmatch("[^\r\n]+") do + local pid = line:match("^%s*(%d+).*opencode") + if pid then + local lsof = vim.fn.system(string.format("lsof -w -iTCP -sTCP:LISTEN -P -n -a -p %s", pid)) + local port = lsof:match(":(%d+) %(LISTEN%)") + if port then + local ok, path = pcall(require("opencode.cli.client").get_path, tonumber(port)) + if ok then + return { + pid = tonumber(pid), + port = tonumber(port), + cwd = path.directory or path.worktree, + } + end + end + end + end + end + + return nil +end + return Tmux From 41782910ae5aadce61461ec1c8147802d8b194be Mon Sep 17 00:00:00 2001 From: Ethan Callanan Date: Wed, 28 Jan 2026 13:35:51 -0500 Subject: [PATCH 2/3] Update provider documentation regarding find_server --- lua/opencode/provider/init.lua | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lua/opencode/provider/init.lua b/lua/opencode/provider/init.lua index da45951f..2118e072 100644 --- a/lua/opencode/provider/init.lua +++ b/lua/opencode/provider/init.lua @@ -1,8 +1,8 @@ ---@module 'snacks.terminal' ---Provide an integrated `opencode`. ----Providers should ignore manually-started `opencode` instances, ----operating only on those they start themselves. +---`start`/`stop`/`toggle` should only operate on provider-managed instances. +---`find_server` may attach to any existing instance for connection purposes. ---@class opencode.Provider --- ---The name of the provider. @@ -35,6 +35,7 @@ ---@field health? fun(): boolean|string, ...string|string[] --- ---Find an existing `opencode` server via provider-specific discovery. +---Unlike other methods, may return servers not started by the provider. ---Called as a fallback when CWD-based discovery fails. ---@field find_server? fun(self: opencode.Provider): opencode.cli.server.Server|nil From 87e967c5be79fa1585fd4d7149a3bc9cde2cfd4b Mon Sep 17 00:00:00 2001 From: Ethan Callanan Date: Wed, 28 Jan 2026 13:38:00 -0500 Subject: [PATCH 3/3] Update find_server_inside_nvim_cwd docstring --- lua/opencode/cli/server.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lua/opencode/cli/server.lua b/lua/opencode/cli/server.lua index 3f8a22e3..1c9e42f8 100644 --- a/lua/opencode/cli/server.lua +++ b/lua/opencode/cli/server.lua @@ -209,7 +209,8 @@ end ---Attempt to get the `opencode` server's port. Tries, in order: ---1. A process responding on `opts.port`. ---2. Any `opencode` process running inside Neovim's CWD. Prioritizes embedded. ----3. Calling `opts.provider.start` and polling for the port. +---3. Provider-specific discovery (e.g., tmux sibling panes). +---4. Calling `opts.provider.start` and polling for the port. --- ---@param launch boolean? Whether to launch a new server if none found. Defaults to true. function M.get_port(launch)