Skip to content

Support native Windows SSH machines in cmux-tui - #9682

Closed
lawrencecchen wants to merge 108 commits into
mainfrom
feat-tui-native-windows
Closed

lawrencecchen wants to merge 108 commits into
mainfrom
feat-tui-native-windows

Conversation

@lawrencecchen

@lawrencecchen lawrencecchen commented Aug 6, 2026 •

Copy link
Copy Markdown
Contributor

Stacked on #9447.

Adds native x86_64 Windows OpenSSH machines without requiring WSL. The client detects cmd.exe, installs a matching Windows companion over SCP, protects remote state with a current-user DACL, bridges the mux control socket on Windows, and launches terminal surfaces through ConPTY.

Packaged npm and PyPI distributions carry the matching Windows companion. Development builds discover the matching sibling executable or accept CMUX_TUI_WINDOWS_REMOTE_BINARY.

Windows sessions use a detached resident mux owner. Carrier loss no longer owns or closes the mux or its ConPTY children. The per-machine connection hub keeps connected carriers warm while cmux-tui runs, selection is immediate, and each connection attempt has a finite deadline with visible loading and copyable errors.

The stale-owner recovery is deliberately narrow. SSH bootstrap accepts a failed legacy stop only for an explicit Windows cmd.exe target whose bounded stderr contains both mux.sock and exact (os error 10050). The native Windows helper treats raw WSAENETDOWN 10050 as an absent orphaned AF_UNIX socket. An unrelated-error negative test prevents generic 10050 transport failures from being hidden.

The Windows stdio carrier now flushes every opaque AF_UNIX read chunk to stdout. Rust's line-buffered StdoutLock previously retained the owner's first 100-byte Noise reply until EOF, so the client waited, timed out, and closed stdin before the next handshake frame. The relay still forwards the existing length-delimited Noise bytes unchanged.

Verification:

The exact pre-fix full run https://github.com/manaflow-ai/cmux/actions/runs/31108875010 has an unrelated bindings job setup failure. The unchanged job omits npm ci, so global TypeScript lacks @types/node, and Zig 0.16 rejects the unchanged adapter's older std.fs.File API. PR 9682 changes neither binding source nor that job. PR 9387 separately restores the public resource API to cmux.protocol/2.


Note

High Risk
Changes authentication boundaries (owner-only local evidence), remote daemon lifecycle on Windows, SSH bootstrap/install, and DACL enforcement—security-critical remote access paths with large cross-platform surface area.

Overview
Enables native Windows OpenSSH machines without WSL: SSH bootstrap detects cmd.exe, installs a matching Windows companion via SCP, and runs remote-link through one cmd-safe remote command with resolved shell/binary targets.

On Windows remotes, the daemon can listen on a DACL-protected AF_UNIX socket with owner-only local carrier auth, an async socket bridge for blocking uds_windows I/O, secure LOCALAPPDATA state directories, and mux control over the same socket path. Carrier-scoped session policy (resume_lease = 0) closes logical sessions when the stdio carrier drops so a detached resident mux owner keeps ConPTY children alive across SSH reconnects.

SSH provider changes add Windows cmd remotes, stderr diagnostics on carrier close, and a registry of resolved targets; legacy Windows remote-stop failures are ignored only for narrow upgrade cases (explicit unsupported message or stale mux.sock + os error 10050).

CI and packaging require include_windows=true for npm/PyPI, download the Windows artifact into package verification, and expand hosted Windows smoke (native tests, remote-probe/link, OpenSSH script, ConPTY). Machine connections gain cancellation checks and timeout messaging; non-Unix mux recovery discards unrecoverable restored terminals instead of empty tabs.

Smaller fixes: iOS push registration tests wait on AsyncStream snapshots instead of clock polling; relay e2e disables heartbeat during forced disconnect; PATH resolution skips zero-byte Windows app execution aliases.

Reviewed by Cursor Bugbot for commit e9b03ae. Bugbot is set up for automated code reviews on this repo. Configure here.

Summary by CodeRabbit

  • New Features
    • Added native Windows OpenSSH support with ConPTY sessions, secure local connectivity, companion installation, and session ownership.
    • Added connection cancellation, bounded startup, timeout guidance, and improved connection status displays.
  • Bug Fixes
    • Improved remote session recovery, authentication, diagnostics, and stale-resource cleanup.
    • Prevented invalid executable stubs from being treated as runnable files.
  • Documentation
    • Updated Windows SSH setup, configuration, session behavior, and connection requirements.
  • Tests
    • Expanded Windows integration, smoke, connectivity, packaging, and lifecycle coverage.

@coderabbitai

coderabbitai Bot commented Aug 6, 2026 •

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Native Windows SSH support adds shell-aware bootstrapping, companion installation, authenticated local sockets, persistent mux ownership, ConPTY validation, and package checks. Machine connections gain cancellation and deadlines. Asynchronous tests use deterministic stream and signal synchronization.

Changes

Native Windows remote runtime

Layer / File(s) Summary
Windows transport and local authentication
cmux-tui/crates/cmux-remote/..., cmux-tui/crates/cmux-tui/Cargo.toml
Adds secure Windows state directories, owner-only authentication, carrier-scoped sessions, daemon sockets, mux-control bridging, and Tokio-compatible socket transport.
Resolved SSH targets and Windows bootstrap
cmux-tui/crates/cmux-remote/src/provider/*, cmux-tui/crates/cmux-remote/src/ssh_bootstrap.rs
Adds shell-aware SSH targets, Windows command construction, companion installation, target registration, diagnostics, and Windows stop recovery.
Windows remote commands and owner lifecycle
cmux-tui/crates/cmux-tui/src/remote_cli_windows.rs, cmux-tui/crates/cmux-tui/tests/windows_remote_owner.rs
Adds native Windows remote commands, SSH bridging, persistent mux owners, carrier relays, shutdown handling, and lifecycle tests.
Windows validation and packaging
.github/workflows/*, cmux-tui/scripts/*, cmux-tui/docs/*
Adds Windows SSH and ConPTY smoke checks, companion package checks, macOS artifact upload, and updated connection documentation.

Connection lifecycle and recovery

Layer / File(s) Summary
Cancelable machine connection attempts
cmux-tui/crates/cmux-tui/src/machine_runtime.rs, cmux-tui/crates/cmux-tui/src/machine_provider_runtime.rs
Adds per-attempt cancellation, deadlines, stale-result protection, cleanup on hub changes, and provider cancellation propagation.
Cancelable client startup and SSH registration
cmux-tui/crates/cmux-tui/src/remote_cli.rs, cmux-tui/crates/cmux-tui/src/remote_runtime.rs
Adds cancelable runtime startup, bounded readiness polling, asynchronous SSH lease cancellation, and resolved-target registration.
Connection UI and terminal recovery
cmux-tui/crates/cmux-tui-core/src/*, cmux-tui/crates/cmux-tui/src/ui/*, cmux-tui/crates/cmux-tui/src/localization.rs
Adds non-Unix terminal cleanup, rejects empty executable stubs, and displays localized connection timeout status and hints.

Deterministic asynchronous tests

Layer / File(s) Summary
Stream-driven test synchronization
Packages/Shared/CmuxAuthRuntime/Tests/CmuxAuthRuntimeTests/*, cmuxTests/PhonePushPresenceGateTests.swift
Replaces polling and clock delays with async streams, timeout races, and explicit injected-clock observation.
Signal-driven APNs fixtures
web/tests/apns.test.ts
Replaces timer-based APNs timeout fixtures with explicit timeout signals and microtask completion.

Estimated code review effort: 5 (Critical) | ~120 minutes

Possibly related PRs

  • manaflow-ai/cmux#9390: Shares cmux-remote daemon transport, authentication, socket, and secure-directory code.
  • manaflow-ai/cmux#9837: Modifies the same workflows with expanded build, packaging, and hosted verification behavior.
  • manaflow-ai/cmux#9890: Shares terminal and workspace closure behavior in cmux-tui-core/src/mux.rs.

Important

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

❌ Failed checks (3 errors, 1 warning)

Check name Status Explanation Resolution
Cmux Algorithmic Complexity ❌ Error On non-Unix startup, mux.rs:2389-2399 commits TabClose once per restored tab; each close clones the full mux state at resource_topology.rs:2696, creating O(T×S) work for scalable records. Build one recovery mutation or batch close plan for all affected tab IDs, then update projections once; keep indexed lookups and measure startup at about 1000 records.
Cmux User-Facing Error Privacy ❌ Error Production errors expose raw SSH stderr and owner-log tails, and the Windows binary error names CMUX_TUI_WINDOWS_REMOTE_BINARY; these violate the privacy rule. Show sanitized, generic connection and startup errors. Keep SSH stderr and owner logs in protected diagnostics, and move the environment-variable guidance to advanced help text.
Cmux Full Internationalization ❌ Error User-facing Markdown changed in cmux-tui/docs/{configuration,getting-started,machines}.md, but no locale source or web/messages entries were added; the web TUI page links these docs publicly. Route these docs through a locale-specific source and add matching entries for all 20 locales in web/i18n/routing.ts, or document that they are not an end-user surface.
Docstring Coverage ⚠️ Warning Docstring coverage is 39.45% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (21 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Cmux Swift Actor Isolation ✅ Passed The PR-range diff changes only three Swift test files; no production Swift changes introduce or worsen actor-isolation issues.
Cmux Swift Blocking Runtime ✅ Passed The PR changes only three Swift files, all under test targets. Added Task.sleep is test timeout scaffolding, and the changes replace polling; no production Swift blocking runtime was introduced.
Cmux Browser Automation Off-Main ✅ Passed The PR changes no browser automation or rule-target files; the complete merge-base diff has no browser/WebKit wait, worker-router, or policy-routing changes.
Cmux Expensive Synchronous Load ✅ Passed The PR changes only three Swift test files; no production Swift paths or expensive agent-history loaders were added or moved.
Cmux Cache Substitution Correctness ✅ Passed The PR changes only Swift/TypeScript test files and a JavaScript launcher; the launcher adds environment/path setup, with no cached substitution for persistence, history, undo, or snapshots.
Cmux No Hacky Sleeps ✅ Passed The only fixed sleep is test-only CI smoke scaffolding; PowerShell uses bounded process waits, and production JS/package changes add no timers, polling, or wall-clock synchronization.
Cmux Swift Concurrency ✅ Passed The Swift diff changes only three test files. It replaces polling with AsyncStream/task groups; the added test Task is awaited, with no new production Dispatch, Combine, or completion-handler pattern.
Cmux Swift @Concurrent ✅ Passed Changed Swift code only adds test-side AsyncStream/task timeout coordination and an injected-clock test; no @MainActor or heavy async helper requires an explicit @concurrent hop.
Cmux Swift Package Boundaries ✅ Passed The PR changes only three Swift test files; no production Swift source changes introduce or expand app-target domain logic.
Cmux Swiftpm Lockfiles ✅ Passed The aggregate diff has no Package.swift, Package.resolved, Xcode project/workspace, or .gitignore changes; Cargo-only dependency changes add no SwiftPM resolution, and cmux package ignores preserve...
Cmux Swift Logging ✅ Passed The PR changes only three Swift test files; their diff replaces timing sleeps with AsyncStream/task coordination and adds no logging or ad hoc output.
Cmux Swiftui State Layout ✅ Passed The PR changes no SwiftUI views. Its only three Swift files are test utilities importing Foundation/Testing, with no SwiftUI state, layout, list-row stores, or render-time state writes.
Cmux Architecture Rethink ✅ Passed All three changed Swift files are test targets; AsyncStream, task-group timeouts, and injected sleeps replace polling only in tests, with no production lifecycle or ownership changes.
Cmux Swift Auxiliary Window Close Shortcuts ✅ Passed The aggregate PR diff changes only three Swift test-support files; it adds no NSWindow, NSPanel, NSWindowController, SwiftUI Window, or WindowGroup code.
Cmux Source Artifacts ✅ Passed All 41 changed paths are source, tests, docs, workflows, or tracked release-packaging templates; no binaries, logs, screenshots, caches, scratch directories, or build outputs were added.
Cmux No Test Or Debug Seam In Production Source ✅ Passed The full PR diff changes no Swift file under a production Sources path; all three changed Swift files are under Tests or cmuxTests.
Cmux No Ambient Global State ✅ Passed The PR diff contains only three Swift files, all under test paths; it contains no production Swift changes, so this check is not applicable.
Title check ✅ Passed The title clearly summarizes the primary change: adding native Windows SSH machine support to cmux-tui.
Description check ✅ Passed The description explains the change, rationale, testing, verification results, risks, and follow-up scope, but omits the template checklist and demo-video section.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat-tui-native-windows

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@lawrencecchen
lawrencecchen force-pushed the feat-tui-native-windows branch from 9c9a859 to c3896be Compare August 6, 2026 02:36
@lawrencecchen
lawrencecchen force-pushed the feat-tui-native-windows branch from c3896be to 2b115c3 Compare August 6, 2026 02:43
@lawrencecchen
lawrencecchen marked this pull request as ready for review August 6, 2026 03:13
@cursor

cursor Bot commented Aug 6, 2026

Copy link
Copy Markdown

Bugbot is paused — on-demand spend limit reached

Bugbot uses usage-based billing for this team and has hit its on-demand spend limit.

A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue.

@greptile-apps

greptile-apps Bot commented Aug 6, 2026 •

Copy link
Copy Markdown
Contributor

Too many files changed for review (820 files, 100 file limit).

@cursor

cursor Bot commented Aug 6, 2026

Copy link
Copy Markdown

Bugbot is paused — on-demand spend limit reached

Bugbot uses usage-based billing for this team and has hit its on-demand spend limit.

A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue.

@cursor

cursor Bot commented Aug 11, 2026

Copy link
Copy Markdown

Bugbot is paused — on-demand spend limit reached

Bugbot uses usage-based billing for this team and has hit its on-demand spend limit.

A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue.

@cursor

cursor Bot commented Aug 11, 2026

Copy link
Copy Markdown

Bugbot is paused — on-demand spend limit reached

Bugbot uses usage-based billing for this team and has hit its on-demand spend limit.

A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue.

@cursor

cursor Bot commented Aug 11, 2026

Copy link
Copy Markdown

Bugbot is paused — on-demand spend limit reached

Bugbot uses usage-based billing for this team and has hit its on-demand spend limit.

A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue.

@cursor

cursor Bot commented Aug 11, 2026

Copy link
Copy Markdown

Bugbot is paused — on-demand spend limit reached

Bugbot uses usage-based billing for this team and has hit its on-demand spend limit.

A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue.

* test: remove APNs wall-clock waits

* test: prove APNs owner event synchronization

* ci: retain exact-head cmux-tui verification

* test(auth): bound push registration waits

* test(auth): release request observers

* test(auth): consume buffered request count

* test(auth): remove racy stream cancellation check
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

stale-revisit Closed after 30+ days without activity; preserved for possible revisit or reopening.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants