You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Two things still block a clean python bootstrap.py: (1) api/terminal.py hard-imports fcntl/termios/select at module level, crashing the import on Windows even when the terminal is never used; (2) bootstrap.py:94 raises RuntimeError before anything else runs.
The terminal has no Windows equivalent (fcntl/termios/pty are POSIX-only), but it's optional, just a slash command, not part of core chat. Guarding the imports and raising NotImplementedError at the function boundary follows the existing pattern from api/turn_journal.py:18 and api/providers.py:28.
The bootstrap block can safely become a warning: discover_agent_dir(), ensure_python_has_webui_deps(), and api/paths.py all handle Windows already. Two sub-features need their own guards: install_hermes_agent() (calls /bin/bash) and the foreground os.execv path (on Windows, Python's execv uses CreateProcess instead of replacing the process image, orphaning the child from supervisors).
What Changed
api/terminal.py: Moved fcntl, select, termios imports behind a _TERMINAL_SUPPORTED = sys.platform != "win32" guard. Added NotImplementedError early returns to start_terminal, write_terminal, resize_terminal. close_terminal returns False (no-op), get_terminal returns None. Guarded the module-level _ensure_spawn_supervisor() call. Pattern matches api/turn_journal.py:18 and api/providers.py:28.
bootstrap.py: Replaced RuntimeError in ensure_supported_platform() with a warning via info(). Added RuntimeError guard in install_hermes_agent() (calls /bin/bash, which does not exist on native Windows). Added sys.platform == "win32" branch in the foreground path to use subprocess.Popen + sys.exit(0) instead of os.execv (which on Windows spawns a child process rather than replacing the image, orphaning it from supervisors).
tests/test_windows_native_support.py: 14 tests covering both changes. Terminal tests verify _TERMINAL_SUPPORTED flag, NotImplementedError on Windows, and graceful no-ops for close_terminal/get_terminal. Bootstrap tests verify ensure_supported_platform does not raise, install_hermes_agent raises on Windows, and the foreground path routes to Popen on Windows vs execv on POSIX.
Why It Matters
Windows users can run python bootstrap.py (or python server.py) natively without WSL. The chat, model picker, workspace, and all non-terminal features work. The terminal gracefully reports "not supported" instead of crashing the server import.
Verification
# Unit tests (--noconftest because upstream conftest.py test_server has a pre-existing# Windows symlink privilege issue unrelated to this PR)
python -m pytest tests/test_windows_native_support.py -v --timeout=60 --noconftest
# Manual: start the server on Windows
python bootstrap.py --foreground
# Manual: verify terminal endpoint returns clean error
curl -X POST http://127.0.0.1:8787/api/terminal/start -H "Content-Type: application/json" -d '{"session_id":"test","workspace":"C:\\Users"}'# Expected: 500 with "Embedded terminal is not supported on Windows"
Risks / Follow-ups
No PTY on Windows: The embedded terminal relies on os.openpty() and POSIX signals (SIGHUP, SIGWINCH, SIGKILL). A Windows equivalent would need ConPTY or similar, which is a separate feature.
os.killpg in close_terminal/_reap_abandoned_spawn: These POSIX-only calls are unreachable on Windows because start_terminal guards early, but a future refactor should consider them.
conftest.py symlink issue: The upstream tests/conftest.py:537 calls symlink_to() which fails on Windows without developer mode. This is pre-existing and unrelated to this PR; tests must run with --noconftest on Windows.
scripts/windows/setup_webui_autostart.ps1: Existing script targets WSL. A native Windows autostart script (Task Scheduler) could be a follow-up.
Shipped in v0.51.236 (Release HD) via release PR #3491 — thank you @rodboev! 🙏
Native Windows support for bootstrap.py + the embedded terminal is now on master and tagged. This was the first Phase-3 (deep-review) pick this session, selected for high impact + well-mitigated risk + your strong recent contributor track record (this is your third merged fix today, after #3446 and #3486).
Absorbed a few things on the way in (reviewed fresh after each):
subprocess.CREATE_NEW_PROCESS_GROUP → getattr(subprocess, "CREATE_NEW_PROCESS_GROUP", 0) — the constant is Windows-only, so the win32-simulating test AttributeError'd when run on the Linux CI box. Mirrors your own SO_EXCLUSIVEADDRUSE getattr guard from fix(server): disable SO_REUSEADDR to prevent silent port sharing (#3289) #3446.
Two tests in test_windows_native_support.py: test_install_hermes_agent_allowed_in_wsl was launching a real installer subprocess (unstubbed subprocess.run) — now stubbed and deterministic; removed two unused imports.
test_onboarding_static.py asserted the OLD "Native Windows is not supported" hard-block string your PR intentionally replaces — updated it to assert the new experimental-warning + the auto-install native-Windows guard.
--foreground help text now mentions the Windows Popen path (was "via os.execv" only).
Both pre-release reviewers (Codex regression + Opus correctness) confirmed the POSIX path is provably unchanged and the Windows guards are complete. The Windows runtime couldn't be exercised on the Linux box — it was reviewed statically + via your 209-line monkeypatched test. Authorship preserved via Co-authored-by and credited in the CHANGELOG. Closes #1952.
Closing as merged-via-release-stage (the change is in master, recommitted on the stage branch).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
fix(terminal): guard POSIX-only imports for Windows compatibilityfeat(bootstrap): unblock native Windows bootstrapThinking Path
python server.pydirectly.O_DIRECTORY), Windows: /api/media 500s on cross-drive files (commonpath ValueError: Paths don't have the same drive) #3171 (commonpath), Windows: HERMES_HOME mismatch between Agent installer and WebUI causes SOUL.md / config.yaml not found #2840 (HERMES_HOME), Windows: .env file reading encoding issue prevents API key detection #741 (GBK encoding). The codebase is more Windows-ready than the bootstrap guard gives it credit for.python bootstrap.py: (1)api/terminal.pyhard-importsfcntl/termios/selectat module level, crashing the import on Windows even when the terminal is never used; (2)bootstrap.py:94raisesRuntimeErrorbefore anything else runs.fcntl/termios/ptyare POSIX-only), but it's optional, just a slash command, not part of core chat. Guarding the imports and raisingNotImplementedErrorat the function boundary follows the existing pattern fromapi/turn_journal.py:18andapi/providers.py:28.discover_agent_dir(),ensure_python_has_webui_deps(), andapi/paths.pyall handle Windows already. Two sub-features need their own guards:install_hermes_agent()(calls/bin/bash) and the foregroundos.execvpath (on Windows, Python'sexecvusesCreateProcessinstead of replacing the process image, orphaning the child from supervisors).What Changed
api/terminal.py: Movedfcntl,select,termiosimports behind a_TERMINAL_SUPPORTED = sys.platform != "win32"guard. AddedNotImplementedErrorearly returns tostart_terminal,write_terminal,resize_terminal.close_terminalreturnsFalse(no-op),get_terminalreturnsNone. Guarded the module-level_ensure_spawn_supervisor()call. Pattern matchesapi/turn_journal.py:18andapi/providers.py:28.bootstrap.py: ReplacedRuntimeErrorinensure_supported_platform()with a warning viainfo(). AddedRuntimeErrorguard ininstall_hermes_agent()(calls/bin/bash, which does not exist on native Windows). Addedsys.platform == "win32"branch in the foreground path to usesubprocess.Popen+sys.exit(0)instead ofos.execv(which on Windows spawns a child process rather than replacing the image, orphaning it from supervisors).tests/test_windows_native_support.py: 14 tests covering both changes. Terminal tests verify_TERMINAL_SUPPORTEDflag,NotImplementedErroron Windows, and graceful no-ops forclose_terminal/get_terminal. Bootstrap tests verifyensure_supported_platformdoes not raise,install_hermes_agentraises on Windows, and the foreground path routes to Popen on Windows vs execv on POSIX.Why It Matters
Windows users can run
python bootstrap.py(orpython server.py) natively without WSL. The chat, model picker, workspace, and all non-terminal features work. The terminal gracefully reports "not supported" instead of crashing the server import.Verification
Risks / Follow-ups
os.openpty()and POSIX signals (SIGHUP,SIGWINCH,SIGKILL). A Windows equivalent would need ConPTY or similar, which is a separate feature.os.killpginclose_terminal/_reap_abandoned_spawn: These POSIX-only calls are unreachable on Windows becausestart_terminalguards early, but a future refactor should consider them.tests/conftest.py:537callssymlink_to()which fails on Windows without developer mode. This is pre-existing and unrelated to this PR; tests must run with--noconfteston Windows.scripts/windows/setup_webui_autostart.ps1: Existing script targets WSL. A native Windows autostart script (Task Scheduler) could be a follow-up.Model Used
Claude Opus 4.6 via Claude Code CLI