Yeachan-Heo/oh-my-codex · error

tmux is unavailable; omx question requires tmux for OMX-owne

Error message

tmux is unavailable; omx question requires tmux for OMX-owned question UI rendering.

What it means

defaultExecTmux resolves the tmux binary per platform (resolveTmuxBinaryForPlatform) before every tmux invocation; when no binary can be found (tmux absent on PATH, or the Windows psmux shim missing), it throws immediately. OMX-owned question UI rendering is tmux-based, so tmux is a hard requirement, not optional.

Source

Thrown at src/question/renderer.ts:503

  }
  sleepImpl(QUESTION_TEXT_SETTLE_MS);
  execTmux(['send-keys', '-t', paneId, 'C-m']);

  return {
    renderer: 'tmux-pane',
    target: paneId,
    launched_at: options.launchedAt,
    ...(options.returnTarget ? { return_target: options.returnTarget, return_transport: 'tmux-send-keys' as const } : {}),
  };
}

function defaultSpawnDetachedRenderer(command: string, args: string[], options: SpawnOptions): Pick<ChildProcess, 'pid' | 'unref'> {
  return spawn(command, args, options);
}

function defaultExecTmux(args: string[]): string {
  const tmux = resolveTmuxBinaryForPlatform();
  if (!tmux) throw new Error('tmux is unavailable; omx question requires tmux for OMX-owned question UI rendering.');
  return execFileSync(tmux, args, {
    encoding: 'utf-8',
    ...(process.platform === 'win32' ? { windowsHide: true } : {}),
  });
}

function readJsonFileIfExists(path: string): Record<string, unknown> | null {
  if (!existsSync(path)) return null;
  try {
    const parsed = JSON.parse(readFileSync(path, 'utf-8')) as unknown;
    return parsed && typeof parsed === 'object' && !Array.isArray(parsed)
      ? parsed as Record<string, unknown>
      : null;
  } catch {
    return null;
  }
}

View on GitHub (pinned to 3ad79a8a6f)

Solutions

  1. Install tmux (`apt-get install tmux`, `brew install tmux`) or on Windows install the psmux/wintmux shim.
  2. Ensure tmux is on PATH for the process environment (echo process.env.PATH from your host).
  3. Pre-check availability with resolveTmuxBinaryForPlatform or `tmux -V` before launching the question UI.
Defensive patterns

Strategy: validation

Validate before calling

import { execFileSync } from 'node:child_process';
function tmuxAvailable(): boolean {
  try { execFileSync(process.platform === 'win32' ? 'psmux' : 'tmux', ['-V']); return true; } catch { return false; }
}

Try / catch

try { launchQuestionRenderer(opts); } catch (e) { if (e instanceof Error && /tmux is unavailable/.test(e.message)) { /* degrade to non-interactive question mode */ } else throw e; }

Prevention

When it happens

Trigger: Calling launchQuestionRenderer (or any code path that shells out to tmux, e.g. supersedeLiveQuestionsForSession) on a machine without tmux installed; PATH stripped in the execution environment; Windows without the psmux/wintmux shim.

Common situations: Docker containers/CI images without tmux; SSH sessions where PATH differs; macOS/Linux minimal installs; Windows hosts missing the bundled shim.

Related errors


AI-assisted analysis of Yeachan-Heo/oh-my-codex@3ad79a8a6f (2026-08-27). Data as JSON: /api/errors/23add392549b15bd. Report an issue: GitHub.