Skip to content

Windows Support#766

Merged
gtrrz-victor merged 24 commits intomainfrom
dvydra/WINDOWS
Mar 30, 2026
Merged

Windows Support#766
gtrrz-victor merged 24 commits intomainfrom
dvydra/WINDOWS

Conversation

@dvydra
Copy link
Copy Markdown
Contributor

@dvydra dvydra commented Mar 25, 2026

Summary

Adds Windows support across the CLI and test harness.

  • Cross-compile Windows binaries via goreleaser (build, zip archive, Scoop bucket) and mise tasks
  • Normalize git output/path handling for Windows (CRLF-safe parsing, more as default pager)
  • Switch signal handling to os.Interrupt for cross-platform compatibility
  • OS-specific process-group/cancellation helpers (procattr_unix.go, procattr_windows.go)
  • Windows-compatible detached telemetry spawning with proper DETACHED_PROCESS flag
  • Skip interactive E2E tests on Windows (tmux not available) — StartSession returns nil, tests auto-skip
  • Add Windows E2E as parallel job in the main E2E workflow with Slack failure notifications
  • WINDOWS.md guide for build, test, and architecture docs

Test plan

  • mise run fmt && mise run lint passes
  • mise run test:ci passes (unit + integration + canary)
  • Windows E2E runs non-interactive (RunPrompt) tests via CI
  • Interactive tests auto-skip on Windows (session == nil)
  • Verify Slack notifications fire on Windows E2E failure

🤖 Generated with Claude Code

@dvydra dvydra requested a review from a team as a code owner March 25, 2026 02:09
Copilot AI review requested due to automatic review settings March 25, 2026 02:09
Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 3 potential issues.

Fix All in Cursor

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Comment @cursor review or bugbot run to trigger another review on this PR

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds Windows support to the Entire CLI and its test harness by removing the tmux dependency, introducing native PTY session handling (ConPTY on Windows / PTY on Unix), and normalizing a few cross-platform path/line-ending behaviors.

Changes:

  • Add mise tasks and documentation for Windows cross-compilation and usage.
  • Replace E2E interactive sessions from tmux to native PTY/ConPTY and refactor agent session startup accordingly.
  • Improve cross-platform behavior (CRLF handling, Windows path normalization, pager default, Windows telemetry detachment implementation).

Reviewed changes

Copilot reviewed 27 out of 28 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
mise.toml Adds Windows cross-compile tasks (build:windows, build:windows-arm64).
go.mod Adds github.com/UserExistsError/conpty for Windows ConPTY support.
go.sum Updates sums for new ConPTY dependency and its indirect deps.
e2e/tests/main_test.go Removes tmux preflight dependency; uses os.DevNull for Git config isolation.
e2e/agents/tmux.go Removes tmux-backed session implementation.
e2e/agents/pty_session.go Introduces cross-platform PTY session abstraction (capture/wait/send/close).
e2e/agents/pty_session_unix.go Unix PTY implementation via creack/pty.
e2e/agents/pty_session_windows.go Windows PTY implementation via ConPTY (conpty).
e2e/agents/procattr_unix.go Adds Unix process-group setup helper for agent subprocess cleanup.
e2e/agents/procattr_windows.go Adds Windows process-group setup helper for agent subprocess cleanup.
e2e/agents/opencode.go Switches OpenCode sessions to PTY sessions.
e2e/agents/gemini.go Uses shared setupProcessGroup; switches interactive session to PTY.
e2e/agents/droid.go Uses shared setupProcessGroup; switches interactive session to PTY.
e2e/agents/cursor_cli.go Switches Cursor CLI interactive session + helper signatures to PTY.
e2e/agents/claude.go Uses shared setupProcessGroup; switches interactive session to PTY and simplifies env injection.
cmd/entire/main.go Adjusts signal handling for cross-platform compilation (now interrupt-only).
cmd/entire/cli/telemetry/detached_windows.go Adds Windows implementation for detached telemetry subprocess spawning.
cmd/entire/cli/telemetry/detached_other.go Refines build tags to exclude Windows from the “other” implementation.
cmd/entire/cli/strategy/manual_commit_hooks.go Normalizes CRLF in git output parsing for staged files.
cmd/entire/cli/strategy/common.go Normalizes CRLF in line-splitting used for diff stats.
cmd/entire/cli/paths/paths.go Normalizes git path output on Windows via filepath.FromSlash.
cmd/entire/cli/integration_test/resume_test.go Uses detachFromTerminal helper; moves interactive tests behind unix build tags.
cmd/entire/cli/integration_test/resume_interactive_test.go Adds unix-only interactive integration tests for resume prompts.
cmd/entire/cli/integration_test/procattr_unix.go Adds unix-only detachFromTerminal helper.
cmd/entire/cli/integration_test/procattr_windows.go Adds windows-only detachFromTerminal helper.
cmd/entire/cli/integration_test/interactive.go Restricts interactive PTY test helpers to integration && unix.
cmd/entire/cli/explain.go Defaults pager to more on Windows, less elsewhere.
WINDOWS.md Adds Windows build/install/testing guidance and platform-specific notes.

@pjbgf
Copy link
Copy Markdown
Member

pjbgf commented Mar 25, 2026

Perhaps we could also expand on the goreleaser settings to add windows as well.

@Soph Soph changed the title Dvydra/windows Windows Support Mar 30, 2026
dvydra and others added 10 commits March 30, 2026 10:40
Cross-platform fixes informed by Buildkite agent patterns:
- Remove syscall.SIGTERM (Unix-only) from main.go, use os.Interrupt only
- Extract platform-specific process group setup (Setpgid/CREATE_NEW_PROCESS_GROUP)
  into build-tagged files for e2e agents and integration tests
- Add CRLF-safe git output parsing (normalize \r\n before splitting)
- Normalize git rev-parse paths with filepath.FromSlash for Windows
- Default pager to 'more' on Windows instead of 'less'
- Add Windows telemetry subprocess support (CREATE_NEW_PROCESS_GROUP)
- Guard PTY-dependent integration tests with unix build tag
- Add mise build:windows and build:windows-arm64 tasks

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Entire-Checkpoint: 12558d9fcbfc
Replace TmuxSession with PTYSession backed by creack/pty (Unix) and
UserExistsError/conpty (Windows). This removes the tmux dependency so
E2E tests can run on Windows and Linux without tmux installed.

- Add pty_session.go with shared Send/WaitFor/Capture/Close/SendKeys
- Add pty_session_unix.go using creack/pty
- Add pty_session_windows.go using conpty (pure Go, no CGO)
- Update all 5 agents to use NewPTYSession
- Delete tmux.go
- Fix main_test.go: remove tmux binary check, use os.DevNull

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Entire-Checkpoint: 509a1d12a58f
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Entire-Checkpoint: 178811f44dd2
Adds windows to the build matrix, overrides the archive format to zip
for Windows, and configures a Scoop bucket for Windows package management.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Runs on windows-latest with schedule (6am UTC) and manual dispatch.
Supports any agent via input, defaults to claude-code.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Replace os.DevNull / hardcoded /dev/null with empty temp files for
  GIT_CONFIG_GLOBAL/SYSTEM (git on Windows cannot open NUL as config)
- Replace /dev/null in core.hooksPath with empty temp directory
- Drop "..." wildcard from E2E test package path to avoid Go toolchain
  panic on Windows ARM64

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace os.Symlink with OS-specific linkRepo helper for E2E_KEEP_REPOS.
On Unix, symlinks as before. On Windows, writes a repo.txt file with
the path since symlinks require elevated privileges.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- cleanConfigDir: Unix uses symlink, Windows copies the file (symlinks
  require elevated privileges). Windows also injects primaryApiKey from
  ANTHROPIC_API_KEY env to prevent the API key confirmation dialog.

- StartSession: Unix delegates to startSessionCommon with no-op callback.
  Windows returns nil to skip interactive PTY tests since ConPTY cannot
  reliably deliver key escape sequences to huh/bubbletea TUI forms.

- NewPTYSession (Windows): resolve bare command names via exec.LookPath
  before passing to ConPTY, which unlike exec.Command does not search PATH.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
filepath.Rel() returns OS-native separators (backslashes on Windows),
but git and the session state expect forward slashes. This caused
duplicate entries in files_touched (docs/a.md and docs\a.md) which
led to duplicate git tree entries on shadow branches, preventing
shadow branch cleanup after commit.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
gtrrz-victor and others added 11 commits March 30, 2026 11:59
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…on.go

These symbols are already defined in tmux.go and shared by both session types.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…tion

Remove pty_session.go, pty_session_unix.go, pty_session_windows.go and
the conpty dependency. Restore all agents to use NewTmuxSession. Keep
cleanConfigDir as OS-specific (symlink on Unix, copy on Windows).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Undo filepath.FromSlash and filepath.ToSlash changes from b831086 —
not needed now that interactive E2E tests are disabled on Windows.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ications

Reuse e2e-windows.yml via workflow_call so both Linux matrix and Windows
run in parallel. Slack notification triggers on failure from either.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…mpat

Replace direct syscall.Setpgid/syscall.Kill usage with the existing
platform-aware setupProcessGroup() in codex, copilot-cli, roger-roger,
and vogon agents.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
tmux is only needed for interactive session tests which are skipped on
Windows. Use NUL instead of /dev/null for GIT_CONFIG_GLOBAL on Windows.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Claude's StartSession returns nil on Windows to skip tmux-dependent
interactive tests. Use an empty temp file for GIT_CONFIG_GLOBAL instead
of NUL which git on Windows cannot open as a config file.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Symlink works on both platforms in CI. The OS-specific copy workaround
for Windows is unnecessary since Bootstrap() already writes the config.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Use both CREATE_NEW_PROCESS_GROUP and DETACHED_PROCESS from
golang.org/x/sys/windows so the analytics subprocess truly detaches
from the parent console and survives parent exit.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Member

@pjbgf pjbgf left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small nit on the sigterm, apart from that LGTM.

Without SIGTERM handling, the CLI can't cancel its context and run
cleanup when terminated by systemd, Docker, or plain `kill`. Add
build-tagged helpers so Unix gets both SIGINT and SIGTERM while
Windows stays on SIGINT only.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@gtrrz-victor
Copy link
Copy Markdown
Contributor

Small nit on the sigterm, apart from that LGTM.

Fixed

gtrrz-victor and others added 2 commits March 30, 2026 15:39
Symlinks require elevated privileges on Windows. Add link_unix.go
(real symlink) and link_windows.go (file copy) so E2E config setup
works without Developer Mode or admin rights.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Switch from syscall.CREATE_NEW_PROCESS_GROUP to the windows package
constants and add DETACHED_PROCESS to fully detach from the parent
console in integration tests.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@gtrrz-victor gtrrz-victor requested a review from pjbgf March 30, 2026 13:42
@gtrrz-victor gtrrz-victor merged commit 93d7d46 into main Mar 30, 2026
3 checks passed
@gtrrz-victor gtrrz-victor deleted the dvydra/WINDOWS branch March 30, 2026 13:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

5 participants