Skip to content

fix(ipc): give a tmux-compatible -S file path a private server on Windows - #247

Open
xanth wants to merge 1 commit into
Helvesec:mainfrom
xanth:fix/windows-socket-path
Open

xanth wants to merge 1 commit into
Helvesec:mainfrom
xanth:fix/windows-socket-path

Conversation

@xanth

@xanth xanth commented Oct 26, 2026

Copy link
Copy Markdown

Closes #237

Summary

tmux names a private server by a socket path, and tools written for tmux pass -S <path> when RMUX runs as their tmux (a tmux shim or copy). On Windows every such call failed: -S accepts only an explicit \\.\pipe\rmux-... name, and the error points rmux users at -L.

That rule stays for the rmux CLI and the SDK. The tmux-compatible resolver, which already adapts tmux callers (it reads $TMUX and redirects Claude Code's swarm socket), now maps a filesystem path to the managed endpoint of the label path-<sha256 of the resolved, lowercased path>. That is the same RMUX-derived, per-user and per-integrity pipe that an -L label gets, with the same peer checks. So RMUX still never binds or connects to a pipe name it did not derive, and a foreign \\.\pipe\... name is still refused. The directory part is canonicalized, so the 8.3 and long spellings of one path name one server. No file is created at the path: access stays with the per-user pipe, never with the directory's ACL.

Changed files: crates/rmux-ipc/src/endpoint.rs, crates/rmux-ipc/src/windows_endpoint_naming.rs.

Testing

Tested on: Windows 11 Pro 10.0.26300 (build 26300), with this branch on RMUX 0.10.0.

  • rmux-ipc unit tests: the new test tmux_compatible_socket_path_names_one_private_server_per_file resolves one path, the same path with . and other letter case (same endpoint), another path (different endpoint), and resolve_endpoint with the path (still InvalidInput). It fails at the fork point and passes with the fix. The existing refusal test for the rmux CLI still passes.
  • As tmux.exe: tmux -S %TEMP%\a.sock new-session -d -s x, then tmux -S %TEMP%\A.SOCK has-session -t x returns 0, and tmux -S %TEMP%\b.sock has-session -t x returns 1. rmux -S %TEMP%\a.sock ls still fails with the existing message.
  • A tmux conformance suite run with -S paths gives the same results as with -L labels.

Linux and macOS are not affected (the change is in the Windows arm) and are covered by this PR's CI.

Cargo gates on the workspace:

  • cargo fmt --all -- --check: pass.
  • cargo clippy --workspace --all-targets -- -D warnings: pass with the pinned toolchain (1.96.1).
  • cargo build --workspace: pass.
  • cargo test --workspace --all-targets: run once on Windows with all of these fixes merged, with the same settings as the Windows CI job. 7,018 passed. 45 tests in the release and bench specs fail on this machine because Python is not on PATH (43) or the temp path is too long (2); they fail the same way without these fixes. Not run here, because they open console windows: windows_attach_exit, windows_attach_fuzz, windows_nested_mouse_issue96, windows_prompt_overlay_chain, windows_mouse_border_resize, rmux-pty's windows_conpty, and rmux-client's managed_attach_stdout_has_single_console_mode_owner.

🤖 Generated with Claude Code

…dows

tmux names a private server by a socket path, and tools written for tmux
pass `-S <path>` when RMUX runs as their tmux (a `tmux` shim or copy). On
Windows every such call failed: -S accepts only an explicit
`\\.\pipe\rmux-...` name, and the error points rmux users at -L.

That rule stays for the rmux CLI and the SDK. The tmux-compatible
resolver, which already adapts tmux callers (it reads $TMUX and redirects
Claude Code's swarm socket), now maps a filesystem path to the managed
endpoint of the label `path-<sha256 of the resolved, lowercased path>`.
That is the same RMUX-derived, per-user and per-integrity pipe an -L label
gets, with the same peer checks, so RMUX still never binds or connects to
a pipe name it did not derive, and a foreign `\\.\pipe\...` name is still
refused. The directory part is canonicalized, so the 8.3 and long
spellings of one path name one server. No file is created at the path:
access stays with the per-user pipe, never with the directory's ACL.

Tested on Windows 11 (build 26300): rmux-ipc unit tests (the new test,
and the existing refusal test for the rmux CLI), and the tmux
conformance suite with -S paths matches its -L results.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: rhys <5460583+xanth@users.noreply.github.com>

This branch has not been deployed

No deployments
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.

[Windows] tmux -S <file path> fails when RMUX runs as tmux

1 participant