Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save arikon/6320e04deed123d4a1042a4752c072b7 to your computer and use it in GitHub Desktop.

Select an option

Save arikon/6320e04deed123d4a1042a4752c072b7 to your computer and use it in GitHub Desktop.
oh-my-codex #3328: portable BSD/GNU script(1) PTY test fixture
From 63cc1aa664b3c08e4ddd798fcf27c71acc4a5839 Mon Sep 17 00:00:00 2001
From: Sergey Belov <peimei@ya.ru>
Date: Tue, 28 Jul 2026 01:50:38 +0200
Subject: [PATCH] test: support BSD script PTY fixtures
---
src/cli/__tests__/launch-fallback.test.ts | 5 +++--
src/team/__tests__/tmux-test-fixture.test.ts | 18 +++++++++++++++++-
src/team/__tests__/tmux-test-fixture.ts | 8 +++++++-
3 files changed, 27 insertions(+), 4 deletions(-)
diff --git a/src/cli/__tests__/launch-fallback.test.ts b/src/cli/__tests__/launch-fallback.test.ts
index 051a93ed..6b5d7ce1 100644
--- a/src/cli/__tests__/launch-fallback.test.ts
+++ b/src/cli/__tests__/launch-fallback.test.ts
@@ -15,7 +15,7 @@ import {
writeSessionStart,
type LaunchSessionBinding,
} from '../../hooks/session.js';
-import { isRealTmuxAvailable, withTempTmuxSession } from '../../team/__tests__/tmux-test-fixture.js';
+import { buildPtyScriptArgs, isRealTmuxAvailable, withTempTmuxSession } from '../../team/__tests__/tmux-test-fixture.js';
const CLI_SPAWN_TIMEOUT_MS = 60_000;
function buildRunOmxEnv(envOverrides: Record<string, string>): NodeJS.ProcessEnv {
@@ -2714,9 +2714,10 @@ exit 0
].map((kv) => `export ${kv}`).join('; ');
const result = spawnSync(
'script',
- ['-q', '-e', '-c', `${envPrefix}; cd ${JSON.stringify(wd)} && exec ${JSON.stringify(process.execPath)} ${JSON.stringify(omxBin)} --tmux ${JSON.stringify('e2e prompt')}`, '/dev/null'],
+ buildPtyScriptArgs(`${envPrefix}; cd ${JSON.stringify(wd)} && exec ${JSON.stringify(process.execPath)} ${JSON.stringify(omxBin)} --tmux ${JSON.stringify('e2e prompt')}`),
{
encoding: 'utf-8',
+ stdio: ['ignore', 'pipe', 'pipe'],
timeout: 120_000,
killSignal: 'SIGKILL',
env: buildRunOmxEnv({ TMUX: '', TMUX_PANE: '' }),
diff --git a/src/team/__tests__/tmux-test-fixture.test.ts b/src/team/__tests__/tmux-test-fixture.test.ts
index e5d2f1c5..8c545102 100644
--- a/src/team/__tests__/tmux-test-fixture.test.ts
+++ b/src/team/__tests__/tmux-test-fixture.test.ts
@@ -1,7 +1,23 @@
import { execFileSync } from 'node:child_process';
import assert from 'node:assert/strict';
import { describe, it, type TestContext } from 'node:test';
-import { isRealTmuxAvailable, tmuxSessionExists, withTempTmuxSession } from './tmux-test-fixture.js';
+import { buildPtyScriptArgs, isRealTmuxAvailable, tmuxSessionExists, withTempTmuxSession } from './tmux-test-fixture.js';
+
+describe('buildPtyScriptArgs', () => {
+ it('uses the BSD command-after-file form on macOS', () => {
+ assert.deepEqual(
+ buildPtyScriptArgs('exit 7', 'darwin'),
+ ['-q', '/dev/null', '/bin/sh', '-c', 'exit 7'],
+ );
+ });
+
+ it('uses the util-linux command option and exit-status propagation on Linux', () => {
+ assert.deepEqual(
+ buildPtyScriptArgs('exit 7', 'linux'),
+ ['-q', '-e', '-c', 'exit 7', '/dev/null'],
+ );
+ });
+});
function skipUnlessTmux(t: TestContext): void {
if (!isRealTmuxAvailable()) {
diff --git a/src/team/__tests__/tmux-test-fixture.ts b/src/team/__tests__/tmux-test-fixture.ts
index 0fda8500..26f196ca 100644
--- a/src/team/__tests__/tmux-test-fixture.ts
+++ b/src/team/__tests__/tmux-test-fixture.ts
@@ -153,6 +153,12 @@ function uniqueTmuxIdentifier(prefix: string): string {
return `${prefix}-${process.pid}-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
}
+export function buildPtyScriptArgs(command: string, platform: NodeJS.Platform = process.platform): string[] {
+ return platform === 'darwin'
+ ? ['-q', '/dev/null', '/bin/sh', '-c', command]
+ : ['-q', '-e', '-c', command, '/dev/null'];
+}
+
export async function withTempTmuxSession<T>(
optionsOrFn: TempTmuxSessionOptions | ((fixture: TempTmuxSessionFixture) => Promise<T> | T),
maybeFn?: (fixture: TempTmuxSessionFixture) => Promise<T> | T,
@@ -207,7 +213,7 @@ export async function withTempTmuxSession<T>(
throw new Error(`invalid trigger cols: ${cols}`);
}
const script = `(sleep 0.1; stty rows ${rows} cols ${cols}) & exec env TERM=xterm timeout 1 tmux -f ${JSON.stringify(NULL_TMUX_CONFIG)} -L ${JSON.stringify(serverName)} attach-session -t ${JSON.stringify(targetSession)}`;
- const result = spawnSync('script', ['-q', '-e', '-c', script, '/dev/null'], {
+ const result = spawnSync('script', buildPtyScriptArgs(script), {
encoding: 'utf-8',
env: { ...process.env, TMUX: undefined, TMUX_PANE: undefined },
stdio: ['ignore', 'pipe', 'pipe'],
--
2.50.1 (Apple Git-155)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment