Skip to content

Commit cdba6c6

Browse files
committed
fix: detect opencode process when command name is 'bun' instead of 'opencode'
Fixes #83 When opencode is installed via Nix or launched with Bun, the process name in lsof appears as 'bun' instead of 'opencode', causing the plugin to fail to auto-detect the running server. This changes the detection logic to: 1. Use pgrep to find PIDs by command line pattern 'opencode run' 2. Use lsof on the specific PIDs to get their listening ports This approach is more robust and works regardless of how opencode was installed or launched (node, bun, binary, etc.).
1 parent 0457708 commit cdba6c6

File tree

1 file changed

+42
-31
lines changed

1 file changed

+42
-31
lines changed

lua/opencode/cli/server.lua

Lines changed: 42 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -29,44 +29,55 @@ local function find_servers()
2929
0
3030
)
3131
end
32-
-- Going straight to `lsof` relieves us of parsing `ps` and all the non-portable 'opencode'-containing processes it might return.
33-
-- With these flags, we'll only get processes that are listening on TCP ports and have 'opencode' in their command name.
34-
-- i.e. pretty much guaranteed to be just opencode server processes.
35-
-- `-w` flag suppresses warnings about inaccessible filesystems (e.g. Docker FUSE).
36-
local output = exec("lsof -w -iTCP -sTCP:LISTEN -P -n | grep opencode")
37-
if output == "" then
32+
33+
-- Find PIDs by command line pattern (handles process names like 'bun', 'node', etc.)
34+
local pgrep_output = exec("pgrep -f 'opencode run' 2>/dev/null || true")
35+
if pgrep_output == "" then
3836
error("No `opencode` processes", 0)
3937
end
4038

4139
local servers = {}
42-
for line in output:gmatch("[^\r\n]+") do
43-
-- lsof output: COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
44-
local parts = vim.split(line, "%s+")
45-
46-
local pid = tonumber(parts[2])
47-
local port = tonumber(parts[9]:match(":(%d+)$")) -- Extract port from NAME field (which is e.g. "127.0.0.1:12345")
48-
if not pid or not port then
49-
error("Couldn't parse `opencode` PID and port from `lsof` entry: " .. line, 0)
50-
end
51-
52-
local cwd = exec("lsof -w -a -p " .. pid .. " -d cwd"):match("%s+(/.*)$")
53-
if not cwd then
54-
error("Couldn't determine CWD for PID: " .. pid, 0)
40+
for pid_str in pgrep_output:gmatch("[^\r\n]+") do
41+
local pid = tonumber(pid_str)
42+
if pid then
43+
-- `-w` suppresses warnings about inaccessible filesystems (e.g. Docker FUSE)
44+
local lsof_output = exec("lsof -w -iTCP -sTCP:LISTEN -P -n -a -p " .. pid .. " 2>/dev/null || true")
45+
46+
if lsof_output ~= "" then
47+
for line in lsof_output:gmatch("[^\r\n]+") do
48+
local parts = vim.split(line, "%s+")
49+
50+
if parts[1] ~= "COMMAND" then -- Skip header
51+
local port = parts[9] and parts[9]:match(":(%d+)$") -- Extract port from "127.0.0.1:12345"
52+
if port then
53+
port = tonumber(port)
54+
55+
local cwd = exec("lsof -w -a -p " .. pid .. " -d cwd 2>/dev/null || true"):match("%s+(/.*)$")
56+
if cwd then
57+
table.insert(
58+
servers,
59+
---@class Server
60+
---@field pid number
61+
---@field port number
62+
---@field cwd string
63+
{
64+
pid = pid,
65+
port = port,
66+
cwd = cwd,
67+
}
68+
)
69+
end
70+
end
71+
end
72+
end
73+
end
5574
end
75+
end
5676

57-
table.insert(
58-
servers,
59-
---@class Server
60-
---@field pid number
61-
---@field port number
62-
---@field cwd string
63-
{
64-
pid = pid,
65-
port = port,
66-
cwd = cwd,
67-
}
68-
)
77+
if #servers == 0 then
78+
error("No `opencode` processes with listening ports found", 0)
6979
end
80+
7081
return servers
7182
end
7283

0 commit comments

Comments
 (0)