fix(tmux): pick per-instance ports and restore pane cleanup

This commit is contained in:
alex
2026-03-11 12:36:45 +00:00
parent 00335c86ae
commit 5aae551edd
3 changed files with 16 additions and 25 deletions

View File

@@ -1,7 +1,9 @@
function c --wraps=opencode --description 'opencode (auto-starts tmux for visual subagent panes)'
set -l port (python -c 'import socket; s=socket.socket(); s.bind(("127.0.0.1", 0)); print(s.getsockname()[1]); s.close()')
if not set -q TMUX
tmux new-session opencode $argv
tmux new-session opencode --port $port $argv
else
opencode $argv
opencode --port $port $argv
end
end

View File

@@ -1,7 +1,9 @@
function cc --wraps='opencode --continue' --description 'opencode --continue (auto-starts tmux for visual subagent panes)'
set -l port (python -c 'import socket; s=socket.socket(); s.bind(("127.0.0.1", 0)); print(s.getsockname()[1]); s.close()')
if not set -q TMUX
tmux new-session opencode --continue $argv
tmux new-session opencode --port $port --continue $argv
else
opencode --continue $argv
opencode --port $port --continue $argv
end
end

View File

@@ -1,6 +1,5 @@
import type { Plugin } from "@opencode-ai/plugin"
import { spawn } from "bun"
import { appendFileSync } from "fs"
/**
* tmux-panes plugin
@@ -14,14 +13,8 @@ import { appendFileSync } from "fs"
* - Panes close automatically when subagent sessions end
*
* Only activates when running inside a tmux session (TMUX env var is set).
*
* Debug log: /tmp/opencode-tmux-debug.log
*/
const DEBUG_LOG = "/tmp/opencode-tmux-debug.log"
const log = (msg: string) =>
appendFileSync(DEBUG_LOG, `[${new Date().toISOString()}] ${msg}\n`)
const isInsideTmux = () => Boolean(process.env.TMUX)
const getCurrentPaneId = () => process.env.TMUX_PANE
@@ -31,7 +24,6 @@ const plugin: Plugin = async (ctx) => {
const sessions = new Map<string, string>() // sessionId → tmux paneId
const sourcePaneId = getCurrentPaneId()
const serverUrl = (ctx.serverUrl?.toString() ?? "").replace(/\/$/, "")
log(`plugin init — serverUrl=${serverUrl} sourcePaneId=${sourcePaneId}`)
// Ordered list of pane IDs in the right column.
// Empty = no right column yet; length > 0 = right column exists.
@@ -44,14 +36,10 @@ const plugin: Plugin = async (ctx) => {
const info = (event as any).properties?.info
// parentID presence distinguishes subagents from the root session
if (!info?.id || !info?.parentID) return
const sessionId: string = info.id
if (sessions.has(sessionId)) return
const sessionId: string = info.id
if (sessions.has(sessionId)) return
// Wrap the attach command: on failure, show the error and keep the
// pane open for 30 s so we can read it before it disappears.
const attachCmd = `opencode attach ${serverUrl} --session ${sessionId}`
const cmd = `bash -c '${attachCmd}; echo "--- exit: $? ---" >> ${DEBUG_LOG}; sleep 30'`
log(`spawning pane — cmd: ${attachCmd}`)
const cmd = `opencode attach ${serverUrl} --session ${sessionId}`
let args: string[]
if (rightColumnPanes.length === 0) {
@@ -88,12 +76,11 @@ const plugin: Plugin = async (ctx) => {
const proc = spawn(args, { stdout: "pipe", stderr: "pipe" })
const paneId = (await new Response(proc.stdout).text()).trim()
const exitCode = await proc.exited
log(`split-window exit=${exitCode} paneId=${paneId}`)
if (exitCode === 0 && paneId) {
sessions.set(sessionId, paneId)
rightColumnPanes.push(paneId)
}
const exitCode = await proc.exited
if (exitCode === 0 && paneId) {
sessions.set(sessionId, paneId)
rightColumnPanes.push(paneId)
}
}
// Kill the pane when the subagent session ends