From bde754b25f2303d0fe9339fe06aae38c4e2b39b5 Mon Sep 17 00:00:00 2001 From: dan-myles <79137382+dan-myles@users.noreply.github.com> Date: Wed, 20 Aug 2025 13:36:45 -0500 Subject: [PATCH] Add Unix domain socket support for server binding - Add --unix option to serve and tui commands - Update Server.listen() to accept unix socket path - Unix socket overrides port/hostname when specified - Enables parallel testing with isolated instances Fixes issue where multiple opencode instances needed unique socket addresses for parallel testing. Unix sockets provide deterministic addresses without port conflicts. --- packages/opencode/src/cli/cmd/serve.ts | 11 ++++++++++- packages/opencode/src/cli/cmd/tui.ts | 5 +++++ packages/opencode/src/server/server.ts | 17 ++++++++++++----- 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/packages/opencode/src/cli/cmd/serve.ts b/packages/opencode/src/cli/cmd/serve.ts index 0e13ddbd3e2..edebe8b3e82 100644 --- a/packages/opencode/src/cli/cmd/serve.ts +++ b/packages/opencode/src/cli/cmd/serve.ts @@ -18,6 +18,10 @@ export const ServeCommand = cmd({ type: "string", describe: "hostname to listen on", default: "127.0.0.1", + }) + .option("unix", { + type: "string", + describe: "unix socket path to bind to (overrides port/hostname)", }), describe: "starts a headless opencode server", handler: async (args) => { @@ -34,9 +38,14 @@ export const ServeCommand = cmd({ const server = Server.listen({ port, hostname, + unix: args.unix, }) - console.log(`opencode server listening on http://${server.hostname}:${server.port}`) + if (args.unix) { + console.log(`opencode server listening on unix socket: ${args.unix}`) + } else { + console.log(`opencode server listening on http://${server.hostname}:${server.port}`) + } await new Promise(() => {}) diff --git a/packages/opencode/src/cli/cmd/tui.ts b/packages/opencode/src/cli/cmd/tui.ts index 25d0fbcb343..1499626c7a7 100644 --- a/packages/opencode/src/cli/cmd/tui.ts +++ b/packages/opencode/src/cli/cmd/tui.ts @@ -69,6 +69,10 @@ export const TuiCommand = cmd({ type: "string", describe: "hostname to listen on", default: "127.0.0.1", + }) + .option("unix", { + type: "string", + describe: "unix socket path to bind to (overrides port/hostname)", }), handler: async (args) => { while (true) { @@ -108,6 +112,7 @@ export const TuiCommand = cmd({ const server = Server.listen({ port: args.port, hostname: args.hostname, + unix: args.unix, }) let cmd = ["go", "run", "./main.go"] diff --git a/packages/opencode/src/server/server.ts b/packages/opencode/src/server/server.ts index e661471ae02..44d3fae819a 100644 --- a/packages/opencode/src/server/server.ts +++ b/packages/opencode/src/server/server.ts @@ -1235,13 +1235,20 @@ export namespace Server { return result } - export function listen(opts: { port: number; hostname: string }) { - const server = Bun.serve({ - port: opts.port, - hostname: opts.hostname, + export function listen(opts: { port?: number; hostname?: string; unix?: string }) { + const serverOpts: any = { idleTimeout: 0, fetch: app().fetch, - }) + } + + if (opts.unix) { + serverOpts.unix = opts.unix + } else { + serverOpts.port = opts.port || 0 + serverOpts.hostname = opts.hostname || "127.0.0.1" + } + + const server = Bun.serve(serverOpts) return server } }