diff --git a/src/config/schema/tmux.ts b/src/config/schema/tmux.ts index a10edc7f9b..d3104c99f4 100644 --- a/src/config/schema/tmux.ts +++ b/src/config/schema/tmux.ts @@ -20,6 +20,17 @@ export const TmuxConfigSchema = z.object({ main_pane_size: z.number().min(20).max(80).default(60), main_pane_min_width: z.number().min(40).default(120), agent_pane_min_width: z.number().min(20).default(40), + /** + * Override the server URL used for health checks and pane spawning. + * Use this when opencode auto-detects the wrong IP (e.g., Tailscale). + * Example: "http://localhost:4096" + */ + server_url_override: z + .preprocess( + (val) => (val === "" || val === null ? undefined : val), + z.string().url().optional() + ) + .optional(), isolation: TmuxIsolationSchema.default("inline"), }) diff --git a/src/features/tmux-subagent/manager.ts b/src/features/tmux-subagent/manager.ts index 7bab2d215f..6e39a638d7 100644 --- a/src/features/tmux-subagent/manager.ts +++ b/src/features/tmux-subagent/manager.ts @@ -69,22 +69,24 @@ export class TmuxSessionManager { this.deps = deps const defaultPort = process.env.OPENCODE_PORT ?? "4096" const fallbackUrl = `http://localhost:${defaultPort}` - const rawServerUrl = ctx.serverUrl?.toString() - try { - if (rawServerUrl) { - const parsed = new URL(rawServerUrl) - const port = parsed.port || (parsed.protocol === 'https:' ? '443' : '80') - this.serverUrl = port === '0' ? fallbackUrl : rawServerUrl - } else { - this.serverUrl = fallbackUrl - } - } catch (error) { - log("[tmux-session-manager] failed to parse server URL, using fallback", { - serverUrl: rawServerUrl, - error: String(error), - }) - this.serverUrl = fallbackUrl - } + try { + const rawServerUrl = tmuxConfig.server_url_override || ctx.serverUrl?.toString() + try { + if (rawServerUrl) {uest? I'm adding react query to my project and wondering if I have to have server/client-specific query functions or if I can get away with sharing a single server query function between the two use cases? + + const parsed = new URL(rawServerUrl) + const port = parsed.port || (parsed.protocol === 'https:' ? '443' : '80') + this.serverUrl = port === '0' ? fallbackUrl : rawServerUrl + } else { + this.serverUrl = fallbackUrl + } + } catch (error) { + log("[tmux-session-manager] failed to parse server URL, using fallback", { + serverUrl: rawServerUrl, + error: String(error), + }) + this.serverUrl = fallbackUrl + } this.sourcePaneId = deps.getCurrentPaneId() this.pollingManager = new TmuxPollingManager( this.client, diff --git a/src/plugin/types.ts b/src/plugin/types.ts index b713781bd3..30359cbe5e 100644 --- a/src/plugin/types.ts +++ b/src/plugin/types.ts @@ -23,4 +23,5 @@ export type TmuxConfig = { main_pane_min_width: number agent_pane_min_width: number isolation: "inline" | "window" | "session" + server_url_override?: string }