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
Fixed AttributeError: module 'jupyter_kernel_client' has no attribute 'KernelClient' in ColabRuntime.kernel_client by updating the fallback class name to jupyter_kernel_client.JupyterKernelClient.
Testing Verification
Verified end-to-end on Windows 11 with PowerShell:
Created sessions using colab new --gpu T4 -s demo-session
Handled OAuth flow & Drive automation
Executed Python code & GPU workloads (nvidia-smi on Tesla T4 runtime)
While testing this branch on Windows 11 with colab ssh --proxy-mode (e.g. for VS Code Remote - SSH and OpenSSH), we identified an issue where the proxy bridge terminates immediately after the server's SSH identification banner, causing OpenSSH to fail:
debug1: SSH2_MSG_KEXINIT sent
Connection closed by UNKNOWN port 65535
SSH server closed unexpectedly. Error code: 255
Root Cause in src/colab_cli/commands/ssh.py
select.select() fails on non-socket file descriptors on Windows:
In _bridge_proxy_mode(), stdin_to_ws() calls:
On Windows, Python's select.select() only supports Winsock network sockets (not anonymous pipes, console handles, or file descriptors). Calling it on stdin_fd raises: OSError: [WinError 10038] An operation was attempted on something that is not a socket.
The try...except (OSError, ...) catches this error and immediately runs _close_quietly(ws) in finally, killing the WebSocket connection right after the initial banner. Fix: Since stdin_to_ws runs in a dedicated daemon thread, we can bypass select.select on Windows and let os.read(stdin_fd, 8192) block natively.
Windows stdio mode & binary packet corruption:
On Windows, sys.stdin and sys.stdout open in text mode by default. Binary SSH traffic is corrupted by automatic CRLF translation (\n <-> \r\n), and byte 0x1A (Ctrl+Z) is treated as EOF by the C runtime. Fix: Call msvcrt.setmode(sys.stdin.fileno(), os.O_BINARY) and msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY) when sys.platform == "win32".
Missing signal.SIGHUP on Windows: signal.SIGHUP does not exist in Python on Windows. Accessing it in _install_rm_signal_handlers() raises AttributeError whenever --rm is used. Fix: Guard signal.SIGHUP with hasattr(signal, "SIGHUP").
Suggested Patch
diff --git a/src/colab_cli/commands/ssh.py b/src/colab_cli/commands/ssh.py
index 1d5c4b6..e58b334 100644
--- a/src/colab_cli/commands/ssh.py+++ b/src/colab_cli/commands/ssh.py@@ -352,14 +352,20 @@ def _bridge_proxy_mode(ws: websocket.WebSocket) -> int:
Returns:
0 when either side closes.
"""
+ if sys.platform == 'win32':+ import msvcrt+ msvcrt.setmode(sys.stdin.fileno(), os.O_BINARY)+ msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)+
stdin_fd = sys.stdin.buffer.fileno()
def stdin_to_ws():
try:
while True:
- ready, _, _ = select.select([stdin_fd], [], [], None)- if not ready:- continue+ if sys.platform != 'win32':+ ready, _, _ = select.select([stdin_fd], [], [], None)+ if not ready:+ continue
data = os.read(stdin_fd, 8192)
if not data:
break
@@ -528,7 +534,10 @@ def _install_rm_signal_handlers(do_rm: Callable[[], None]) -> None:
do_rm()
os._exit(0)
- for sig in (signal.SIGHUP, signal.SIGTERM, signal.SIGINT):+ signals = [signal.SIGTERM, signal.SIGINT]+ if hasattr(signal, 'SIGHUP'):+ signals.append(signal.SIGHUP)+ for sig in signals:
try:
signal.signal(sig, _on_signal)
except (ValueError, OSError):
All 50 unit tests in tests/test_ssh.py pass with this change.
How to Connect on Windows (VS Code / OpenSSH)
With this fix applied, connecting from Windows works smoothly:
(Note: Passing -s <session_name> like -s colab is recommended because colab ssh will automatically provision a new runtime session if none exists, routing output to stderr so the SSH byte stream remains clean).
Connect:
Terminal:
ssh colab
VS Code / Cursor Remote - SSH:
Press Ctrl+Shift+P -> Remote-SSH: Connect to Host... -> Select colab.
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.
Fixes #100
Summary of Fixes
This PR adds native cross-platform support for Windows and resolves a runtime
AttributeError:Windows Console Compatibility (
colab_cli/console.py):termiosandttyimports in atry/except ImportErrorblock.termios,tty,fileno(), andsignal.SIGWINCHcalls to preventModuleNotFoundError: No module named 'termios'on Windows.Google Drive Auth
/dev/ttyFallback (colab_cli/commands/automation.py):open("/dev/tty")on non-POSIX systems to usesys.stdin.readline().JupyterKernelClientFallback (colab_cli/runtime.py):AttributeError: module 'jupyter_kernel_client' has no attribute 'KernelClient'inColabRuntime.kernel_clientby updating the fallback class name tojupyter_kernel_client.JupyterKernelClient.Testing Verification
Verified end-to-end on Windows 11 with PowerShell:
colab new --gpu T4 -s demo-sessionnvidia-smion Tesla T4 runtime)