Skip to content

feat(#153): compile-level Windows support + CI guard#161

Open
justrach wants to merge 4 commits into
mainfrom
feat/windows-prep
Open

feat(#153): compile-level Windows support + CI guard#161
justrach wants to merge 4 commits into
mainfrom
feat/windows-prep

Conversation

@justrach

Copy link
Copy Markdown
Owner

Closes #153.

Summary

Adds compile-level Windows support: zig build -Dtarget=x86_64-windows-gnu -Doptimize=ReleaseSafe produces all four user-facing PE32+ binaries (kuri.exe, kuri-agent.exe, kuri-browse.exe, kuri-fetch.exe) plus merjs-e2e.exe. A new windows-cross-compile CI job pins this baseline so a future refactor can't quietly re-introduce an ungated POSIX call (fork, std.c.open, raw setsockopt/read on a socket) without breaking CI.

macOS and Linux builds are unchanged; this is additive.

Commits

  1. docs(install): mark Windows unsupported and link tracking issue #153 — Original "punt" commit: a Platform-support table in readme.md, plus MINGW*/MSYS*/CYGWIN* detection in install.sh and a win32 branch in npm/bin/install.js so users get a tailored error pointing at this issue instead of a generic Unsupported OS. (The npm self-test still passes — the existing /unsupported platform: win32/ assertion still matches the new message.)
  2. refactor(compat): cross-platform realtime clock + isatty (towards #153) — Routes the three time wrappers in src/compat.zig through a single realtimeNanos() that picks GetSystemTimeAsFileTime on Windows and clock_gettime on POSIX. Adds compat.isTtyStderr() (GetConsoleMode on Windows, isatty(2) on POSIX). Switches the three call sites to it.
  3. feat(compat): compile-level Windows support — The big one. Adds enough cross-platform / stub code to make every Zig-side POSIX assumption Windows-compatible.
  4. ci(windows): cross-compile guard + docs update — The CI job + a more accurate readme entry ("Experimental — cross-compile only").

What works on Windows

  • Realtime clock, monotonic sleep, TTY detection (compat.zig).
  • Mutex / RwLock via Win32 SRWLOCK instead of pthread.
  • Stdout/stderr writes via WriteFile(GetStdHandle(...)).
  • --version / --help paths through main for each binary.
  • Pure in-memory operations.

What's stubbed with error.UnsupportedOnWindows

These return an error at runtime, they do not silently no-op:

  • compat.cwd* file ops, compat.runCommand, compat.tcp* / TcpStream / TcpServer (raw BSD-socket code).
  • chrome/launcher.zig Chrome spawn + reaper (fork + SIG.KILL).
  • cdp/websocket.zig connect + raw socket read; cdp/client.zig drainWsEvents.
  • server/router.zig discoverTabs (raw setsockopt/read on the CDP socket) — gets an explicit DiscoverTabsError so the handler's switch stays exhaustive on both platforms.
  • storage/auth_profiles.zig deleteProfile / listProfiles (POSIX opendir/readdir).
  • server/api_token.zig writeMode0600 (POSIX open + fchmod).
  • agent_main.zig cmdOpen (fork+exec Chrome) and fetchChromeTabs (raw socket).
  • browse_main.zig repl (POSIX stdin fd) and readLine (std.posix.read).
  • lifecycle.zig install (POSIX sigaction).

Out of scope for this PR (follow-up Windows work)

  • Real Chrome launching on Windows (CreateProcess + JobObject for cleanup).
  • Daemonization (CreateProcess with DETACHED_PROCESS).
  • Real Win32 socket implementations for the CDP path so Chrome automation works.
  • Signal-equivalent shutdown handling (SetConsoleCtrlHandler).
  • Windows release pipeline + manifest entry + npm installer asset.
  • A Windows runtime smoke test in CI (would need a windows-latest job, not just cross-compile).

Test plan

  • zig build clean on macOS (Apple Silicon, Zig 0.16.0).
  • zig build -Dtarget=x86_64-windows-gnu clean on macOS — produces 5 PE32+ x86_64 binaries.
  • node -e "require('./npm/bin/install.js').runSelfTest()" passes.
  • sh -n install.sh clean.
  • CI: existing Linux build + tests pass.
  • CI: new windows-cross-compile job passes.
  • Runtime: kuri.exe --version on a real Windows box (or under Wine) — out of scope for me to verify here.

🤖 Generated with Claude Code

@justrach justrach mentioned this pull request May 20, 2026
@justrach justrach force-pushed the feat/windows-prep branch from 92f583e to 95bd858 Compare May 20, 2026 17:15
justrach and others added 4 commits May 21, 2026 02:01
Windows users were hitting a generic "Unsupported OS" error with no
context. Add a Platform-support table to readme.md (macOS + Linux only,
WSL2 as fallback), and route win32 / MINGW / MSYS / CYGWIN through
explicit messages in both install.sh and npm/bin/install.js that link
issue #153. The npm self-test still passes — the existing
`/unsupported platform: win32/` assertion still matches the new message.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
`std.c.clock_gettime` and `std.c.isatty` are POSIX-only — they're the
easiest sites blocking a `-Dtarget=x86_64-windows` build. Route the
three time wrappers in src/compat.zig through a single `realtimeNanos()`
that picks `GetSystemTimeAsFileTime` on Windows and `clock_gettime` on
POSIX. Add `compat.isTtyStderr()` using `GetConsoleMode` on Windows and
`isatty(2)` on POSIX, and switch the three call sites in browse_main,
fetch_main, and server/api_token to it. macOS build + tests unchanged
(the Windows branch is comptime-unreachable on non-Windows targets).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…s-gnu` is green (#153)

Adds enough cross-platform and stub code to make all five binaries
(`kuri`, `kuri-agent`, `kuri-browse`, `kuri-fetch`, `merjs-e2e`) build
clean for `x86_64-windows-gnu`. macOS + Linux builds are unchanged.

What works on Windows:
- Realtime clock, monotonic sleep, TTY detection (compat.zig).
- Mutex / RwLock via Win32 SRWLOCK instead of pthread.
- Stdout/stderr writes via `WriteFile(GetStdHandle(...))`.
- `--version` / `--help` paths through `main` for each binary.

What is stubbed with `error.UnsupportedOnWindows` on Windows (returns
the error at runtime; does not silently no-op):
- `compat.cwd*` file ops, `compat.runCommand`, `compat.tcp*` /
  `TcpStream` / `TcpServer` (raw BSD-socket code).
- `chrome/launcher.zig` Chrome spawn + reaper (uses `fork`+`SIG.KILL`).
- `cdp/websocket.zig` connect + raw socket read; `cdp/client.zig`
  `drainWsEvents`.
- `server/router.zig` `discoverTabs` (uses `std.posix.setsockopt` and
  `std.posix.read` on the raw CDP socket); gets an explicit
  `DiscoverTabsError` so the handler's switch stays exhaustive on both
  platforms.
- `storage/auth_profiles.zig` `deleteProfile` / `listProfiles` (uses
  POSIX `opendir`/`readdir`).
- `server/api_token.zig` `writeMode0600` (uses POSIX `open` + `fchmod`).
- `agent_main.zig` `cmdOpen` (fork+exec Chrome) and `fetchChromeTabs`
  (raw socket).
- `browse_main.zig` `repl` (POSIX stdin fd) and `readLine`
  (`std.posix.read`).
- `lifecycle.zig` `install` (POSIX `sigaction`).

Real Chrome automation, signal-based shutdown, daemonization, the
agent's HAR recorder, and the file-backed auth store are all
follow-up work — none of them are wired up on Windows yet, but the
build succeeds and a Windows binary will load and respond to
`--version`/`--help` / static commands.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add a `windows-cross-compile` CI job that runs `zig build
-Dtarget=x86_64-windows-gnu -Doptimize=ReleaseSafe` and asserts that
all four user-facing binaries land as PE32+ executables. This pins the
compile-level Windows baseline introduced in the previous commit so a
future patch can't quietly re-introduce an ungated POSIX call (`fork`,
`std.c.open`, raw `setsockopt`/`read` on a socket) without breaking
CI.

Also widen the readme Platform-support table: Windows is no longer
"Not supported yet" but "Experimental — cross-compile only", with the
runtime caveats (Chrome / daemonize / sockets stubbed) spelled out.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@justrach justrach force-pushed the feat/windows-prep branch from 95bd858 to 5ae45a0 Compare May 20, 2026 18:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add Windows support

1 participant