Skip to content

Windows: daemon cannot start — unguarded fcntl/termios import in agents/tmux/pty_bridge.py #26

Description

@fvegiard

Summary

gobby/agents/tmux/pty_bridge.py imports fcntl and termios at module scope. Both are POSIX-only, so the daemon cannot start on Windows — the import chain runs during gobby start and dies before the runner comes up.

Still present on main @ 45b0ea0: pty_bridge.py#L11-L18.

Traceback

File "...\gobby\runner.py", line 219, in __init__
  from gobby.runner_init import (
File "...\gobby\runner_init\__init__.py", line 6, in <module>
  from gobby.runner_init.orchestration import init_orchestration
File "...\gobby\runner_init\orchestration.py", line 9, in <module>
  from gobby.agents.lifecycle_monitor import AgentLifecycleMonitor
File "...\gobby\agents\lifecycle_monitor.py", line 28, in <module>
  from gobby.agents.tmux.session_manager import TmuxSessionManager
File "...\gobby\agents\tmux\__init__.py", line 23, in <module>
  from gobby.agents.tmux.pty_bridge import TmuxPTYBridge
File "...\gobby\agents\tmux\pty_bridge.py", line 14, in <module>
  import fcntl
ModuleNotFoundError: No module named 'fcntl'

gobby start reports Health check failed and the daemon exits; the traceback lands in ~/.gobby/logs/gobby-error.log.

Reproduce

On Windows: uv tool install gobby then gobby start.

Root cause

gobby/agents/tmux/__init__.py unconditionally imports TmuxPTYBridge, and that module imports fcntl/termios at the top. Since lifecycle_monitor pulls in the tmux package during daemon init, there is no way to reach the runner on a platform without those modules.

Both are only used inside methods — fcntl.ioctl(..., termios.TIOCSWINSZ, ...) at lines 82 and 177 — so nothing at import time needs them.

Suggested fix

Guard the import; PTY bridging is inherently POSIX-only and can fail at call time instead of import time:

 import asyncio
-import fcntl
 import logging
 import os
 import struct
-import termios
 from dataclasses import dataclass, field
 from datetime import UTC, datetime
 
+try:  # POSIX-only: tmux PTY bridging is unavailable on Windows
+    import fcntl
+    import termios
+except ImportError:  # pragma: no cover - Windows
+    fcntl = None  # type: ignore[assignment]
+    termios = None  # type: ignore[assignment]
+
 from gobby.config.tmux import TmuxConfig

Ideally the two ioctl call sites would also raise a clear error when fcntl is None, rather than an AttributeError.

Note

Fixing this alone is not sufficient to start the daemon on Windows — the next blocker is loop.add_signal_handler raising NotImplementedError, filed separately.

Windows isn't listed as a supported platform in the README, but gobby/agents/tmux/wsl_compat.py (needs_wsl, convert_windows_path_to_wsl) suggests it's at least partly intended. Happy to open a PR if a Windows daemon is in scope.

Environment

  • gobby 0.4.6 (installed via uv tool install)
  • Python 3.13 (CPython, windows-x86_64)
  • Windows 11 Pro 10.0.26220

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions