Symptom
switchyard launch codex from the published v0.2.0 Windows wheel crashes before the native proxy or Codex starts. The launcher imports the POSIX-only ShellTUI unconditionally, which imports fcntl on native Windows.
While validating the full startup path, three follow-on Windows blockers were also reproducible: the npm extensionless shim is selected instead of codex.cmd, Codex's UTF-8 model catalog is decoded with the active Windows code page, and a configured system proxy can intercept the loopback proxy URL inherited by Codex.
Reproduction
In a clean PowerShell session:
py -3.12 -m venv .venv
.\.venv\Scripts\python.exe -m pip install "nemo-switchyard[cli,server]==0.2.0"
npm install -g @openai/codex
.\.venv\Scripts\switchyard.exe launch codex --model switchyard
No provider request is made and no API key is required to reach the failure; it happens while dispatching the Codex launcher.
Published-wheel traceback, with the local environment path redacted:
Traceback (most recent call last):
File "<venv>\Scripts\switchyard.exe\__main__.py", line 7, in <module>
File "<venv>\Lib\site-packages\switchyard\cli\switchyard_cli.py", line 157, in main
args.func(args)
File "<venv>\Lib\site-packages\switchyard\cli\launch_command.py", line 37, in cmd_launch_codex
from switchyard.cli.launchers.codex_cli_launcher import launch_codex_config
File "<venv>\Lib\site-packages\switchyard\cli\launchers\codex_cli_launcher.py", line 33, in <module>
from switchyard.server.shell_tui import ShellTUI
File "<venv>\Lib\site-packages\switchyard\server\shell_tui.py", line 21, in <module>
import fcntl
ModuleNotFoundError: No module named 'fcntl'
Forcing UTF-8 does not change this first failure:
PYTHONUTF8=1
preferred_encoding=utf-8
ModuleNotFoundError: No module named 'fcntl'
After locally bypassing the POSIX TUI import to continue the same startup path:
shutil.which("codex") -> <npm-prefix>\codex
OSError: [WinError 193] %1 is not a valid Win32 application
The sibling Windows shim works:
shutil.which("codex.cmd") -> <npm-prefix>\codex.cmd
codex-cli 0.147.0
The next catalog read fails under the default cp936 locale because subprocess.check_output(..., text=True) uses the active code page for Codex's UTF-8 JSON:
UnicodeDecodeError: 'gbk' codec can't decode byte 0x9d
Expected vs. actual
- Expected: The Codex launcher should start on native Windows, inherit the current console instead of using the POSIX PTY footer, resolve the launchable npm shim, and connect Codex to the loopback Switchyard proxy.
- Actual: The published Windows wheel crashes at import time on
fcntl; bypassing that reveals the npm shim and model-catalog decoding failures above.
Environment
- Switchyard version (or commit SHA):
nemo-switchyard==0.2.0, official cp312-abi3-win_amd64 wheel from the v0.2.0 release
- Python version (
python --version): Python 3.12.0
- OS / arch: Windows 11 Pro
10.0.26200, x86-64
- Install path (
uv sync, pip install nemo-switchyard, source build, etc.): clean virtual environment, pip install "nemo-switchyard[cli,server]==0.2.0"
- Inbound format (Chat Completions / Anthropic Messages / Responses): Responses (Codex CLI)
- Backend (OpenAI / Anthropic / NVIDIA Inference Hub / other): not reached by the initial reproduction; end-to-end validation used an OpenAI-compatible endpoint
- Codex version:
codex-cli 0.147.0, installed with npm
Additional context
The release publishes Windows wheels and the package installs successfully; the failure is specific to the coding-agent launcher path. switchyard launch codex --help also succeeds because argparse exits before dispatch imports the launcher, so it does not exercise this failure.
A focused fix can keep the existing ShellTUI behavior on POSIX, use the inherited console on Windows, select the sibling codex.cmd created by npm, decode the bundled catalog explicitly as UTF-8, and preserve loopback hosts in the child process's NO_PROXY environment.
Symptom
switchyard launch codexfrom the published v0.2.0 Windows wheel crashes before the native proxy or Codex starts. The launcher imports the POSIX-onlyShellTUIunconditionally, which importsfcntlon native Windows.While validating the full startup path, three follow-on Windows blockers were also reproducible: the npm extensionless shim is selected instead of
codex.cmd, Codex's UTF-8 model catalog is decoded with the active Windows code page, and a configured system proxy can intercept the loopback proxy URL inherited by Codex.Reproduction
In a clean PowerShell session:
No provider request is made and no API key is required to reach the failure; it happens while dispatching the Codex launcher.
Published-wheel traceback, with the local environment path redacted:
Forcing UTF-8 does not change this first failure:
After locally bypassing the POSIX TUI import to continue the same startup path:
The sibling Windows shim works:
The next catalog read fails under the default cp936 locale because
subprocess.check_output(..., text=True)uses the active code page for Codex's UTF-8 JSON:Expected vs. actual
fcntl; bypassing that reveals the npm shim and model-catalog decoding failures above.Environment
nemo-switchyard==0.2.0, officialcp312-abi3-win_amd64wheel from the v0.2.0 releasepython --version):Python 3.12.010.0.26200, x86-64uv sync,pip install nemo-switchyard, source build, etc.): clean virtual environment,pip install "nemo-switchyard[cli,server]==0.2.0"codex-cli 0.147.0, installed with npmAdditional context
The release publishes Windows wheels and the package installs successfully; the failure is specific to the coding-agent launcher path.
switchyard launch codex --helpalso succeeds because argparse exits before dispatch imports the launcher, so it does not exercise this failure.A focused fix can keep the existing
ShellTUIbehavior on POSIX, use the inherited console on Windows, select the siblingcodex.cmdcreated by npm, decode the bundled catalog explicitly as UTF-8, and preserve loopback hosts in the child process'sNO_PROXYenvironment.