| 📦 Turbo Go 3d7798b k33g 11h ago | 1 | # Managed by IssueSpec. Hand edits are welcome; keep the schema valid. |
| 2 | id: 15 |
| 3 | title: windows support for terminal windows |
| 4 | state: closed |
| 5 | author: |
| 6 | name: k33g |
| 7 | email: ph.charriere@gmail.com |
| 8 | createdAt: 2026-08-31T04:40:00.000Z |
| 9 | updatedAt: 2026-09-02T03:51:59.496Z |
| 10 | labels: |
| 11 | - priority::medium |
| 12 | body: | |
| 13 | Terminal windows (#7) ship for Linux and macOS only. On Windows, `F8` opens a |
| 14 | message saying they are not supported yet and changes nothing else. |
| 15 | |
| 16 | Everything above the pseudo-terminal is already portable. `Parser`, `Screen`, |
| 17 | `Encode` and `View` are pure Go with no platform assumptions, and the whole |
| 18 | VT/ANSI emulator is tested without a process behind it. What is missing is one |
| 19 | file. |
| 20 | |
| 21 | ## The platform surface |
| 22 | |
| 23 | `internal/terminal` isolates the whole of it in three build-tagged files, each |
| 24 | implementing the same three functions: |
| 25 | |
| 26 | func openPTY() (master, slave *os.File, err error) |
| 27 | func setWinsize(f *os.File, width, height int) error |
| 28 | func childAttributes() *syscall.SysProcAttr |
| 29 | |
| 30 | | File | Platform | |
| 31 | | --- | --- | |
| 32 | | `pty_linux.go` | `TIOCSPTLCK`, `TIOCGPTN` -> `/dev/pts/N` | |
| 33 | | `pty_darwin.go` | `TIOCPTYGRANT`, `TIOCPTYUNLK`, `TIOCPTYGNAME` | |
| 34 | | `pty_other.go` | returns `ErrUnsupported` | |
| 35 | |
| 36 | Windows means adding `pty_windows.go` and narrowing `pty_other.go`'s build tag. |
| 37 | No other file should need to change. |
| 38 | |
| 39 | ## Why it is not a fourth ioctl |
| 40 | |
| 41 | Windows has no `/dev/ptmx`. The equivalent is **ConPTY**, available from |
| 42 | Windows 10 1809, and it does not fit the same shape: |
| 43 | |
| 44 | - `CreatePseudoConsole` takes two pipe handles and returns an `HPCON`, rather |
| 45 | than handing back a master and a slave file. |
| 46 | - The child is started with `CreateProcess` and an attribute list carrying |
| 47 | `PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE_HANDLE` — not `os/exec`'s |
| 48 | `SysProcAttr{Setsid, Setctty}`. `exec.Cmd` may not be usable directly. |
| 49 | - Resizing is `ResizePseudoConsole(hpcon, COORD)`, not an ioctl. |
| 50 | - There is no controlling terminal and no `SIGWINCH`: job control has no |
| 51 | equivalent, and `Ctrl-C` reaches the child through the console rather than |
| 52 | through a process group. |
| 53 | |
| 54 | So the contract above may need widening — most likely `Session` gaining a |
| 55 | platform-provided `resize` and `close` rather than `setWinsize` alone. Keep |
| 56 | the change inside `internal/terminal`; `internal/app` should not learn that |
| 57 | Windows exists. |
| 58 | |
| 59 | ## Which shell |
| 60 | |
| 61 | `shellOrDefault` falls back to `/bin/sh`, which is meaningless there. Windows |
| 62 | needs its own default — `%COMSPEC%`, or PowerShell — decided before the port, |
| 63 | because it is the first thing a user notices. |
| 64 | |
| 65 | ## Notes |
| 66 | |
| 67 | - `golang.org/x/sys/windows` carries the ConPTY bindings, and is already in |
| 68 | the module graph as `golang.org/x/sys`. No new dependency. |
| 69 | - The emulator sends `TERM=xterm-256color`; ConPTY emits VT sequences, so the |
| 70 | existing parser should be close to sufficient. Expect differences in how |
| 71 | the alternate screen and the cursor-visibility modes are used. |
| 72 | - This cannot be developed or tested in the current sandbox: it is Linux, and |
| 73 | no Windows machine is reachable from it. Whoever takes it needs Windows. |
| 74 | |
| 75 | ## Checklist |
| 76 | |
| 77 | - [ ] decide the default shell on Windows (%COMSPEC% or PowerShell) |
| 78 | - [ ] add `pty_windows.go` using `CreatePseudoConsole` / `ResizePseudoConsole` |
| 79 | - [ ] narrow the build tag on `pty_other.go` |
| 80 | - [ ] widen the platform contract if `exec.Cmd` cannot carry the HPCON |
| 81 | - [ ] run the `internal/terminal` suite on Windows and unskip what passes |
| 82 | - [ ] update `docs/*/reference/terminal.md`, which currently says Windows is unsupported |
| 83 | tasks: [] |
| 84 | comments: [] |