* Executes a tmux command, routing through WSL on Windows. * On Windows, tmux only exists inside WSL — WSL interop lets the tmux session * launch .exe files as native Win32 processes while stdin/stdout flow through * the WSL pty.
(
args: string[],
opts?: { useCwd?: boolean },
)
| 42 | * the WSL pty. |
| 43 | */ |
| 44 | async function execTmux( |
| 45 | args: string[], |
| 46 | opts?: { useCwd?: boolean }, |
| 47 | ): Promise<{ stdout: string; stderr: string; code: number }> { |
| 48 | if (getPlatform() === 'windows') { |
| 49 | // -e execs tmux directly without the login shell. Without it, wsl hands the |
| 50 | // command line to bash which eats `#` as a comment: `display-message -p |
| 51 | // #{socket_path},#{pid}` below becomes `display-message -p ` → exit 1 → |
| 52 | // we silently fall back to the guessed path and never learn the real |
| 53 | // server PID. Same root cause as TungstenTool/utils.ts:execTmuxCommand. |
| 54 | const result = await execFileNoThrow('wsl', ['-e', TMUX_COMMAND, ...args], { |
| 55 | env: { ...process.env, WSL_UTF8: '1' }, |
| 56 | ...opts, |
| 57 | }) |
| 58 | return { |
| 59 | stdout: result.stdout || '', |
| 60 | stderr: result.stderr || '', |
| 61 | code: result.code || 0, |
| 62 | } |
| 63 | } |
| 64 | const result = await execFileNoThrow(TMUX_COMMAND, args, opts) |
| 65 | return { |
| 66 | stdout: result.stdout || '', |
| 67 | stderr: result.stderr || '', |
| 68 | code: result.code || 0, |
| 69 | } |
| 70 | } |
| 71 | |
| 72 | // Socket state - initialized lazily when Tmux tool is first used or a tmux command is run |
| 73 | let socketName: string | null = null |
no test coverage detected