WSL2/WSLg: cross-session messaging silently disabled — XDG_RUNTIME_DIR (/mnt/wslg/runtime-dir) is 0777 so the inbox socket dir vet refuses to bind
Summary
On WSL2, cross-session messaging (ListAgents / SendMessage between local sessions) silently fails for every session: ListAgents returns bare "No reachable agents." even with multiple healthy interactive sessions running on the same machine.
Root cause: WSLg sets XDG_RUNTIME_DIR=/mnt/wslg/runtime-dir, and WSLg creates that directory as mode 0777 (world-writable, no sticky bit). The messaging inbox refuses to bind its socket under $XDG_RUNTIME_DIR/cc-socks/ because a path component fails the private-or-sticky directory vet (directory_rule / socket_dir_refused), so no session ever registers a messagingSocketPath — and every peer is filtered out of the listing.
Since this is the stock WSLg configuration, cross-session messaging is effectively broken out-of-the-box for all WSL2 + WSLg users.
Environment
- Claude Code v2.1.245 (native binary install)
- WSL2 (kernel 6.6.87.2-microsoft-standard-WSL2), Ubuntu 24.04
XDG_RUNTIME_DIR=/mnt/wslg/runtime-dir(default set by WSLg)stat:/mnt/wslg/runtime-dir uid=1000 gid=1000 mode=777(tmpfs, recreated on every WSL boot)
Steps to reproduce
- On a default WSL2 install with WSLg (so
XDG_RUNTIME_DIRpoints at/mnt/wslg/runtime-dir), start two interactiveclaudesessions. - In one, run
ListAgents.
Expected: the other session is listed as a peer.
Actual: "No reachable agents." Neither session's ~/.claude/sessions/<pid>.json contains messagingSocketPath, and no cc-socks directory / cc-msg-*-style socket is created.
Verified root cause / workaround
chmod 700 /mnt/wslg/runtime-dir and restarting the sessions fully fixes it: sessions bind $XDG_RUNTIME_DIR/cc-socks/<pid>.sock, register messagingSocketPath, and ListAgents/SendMessage work. (The chmod has to be re-applied every WSL boot since WSLg recreates the dir as 777.)
Why this is hard to diagnose
- The refusal is only logged with
--debug([uds-messaging] Failed to set up sockets directory ... cross-session messaging is OFF for this session). A normal session shows no indication anywhere. ListAgentsreturns the bare "No reachable agents." — the same output as "no other sessions running" — so both sides of the conversation look healthy: sessions register in~/.claude/sessions/, heartbeats update, versions/peerProtocol match. Nothing points at the socket directory.
Suggestions
- On Linux, when
XDG_RUNTIME_DIRfails the directory vet, fall back to the tmpdir path (/tmp/cc-socks-<uid>/, 0700, which would pass —/tmpis sticky) instead of disabling messaging outright. A Termux-style fallback already exists for the path-length case. - Or special-case the known WSLg default:
/mnt/wslg/runtime-diris user-owned; achmod 700by the owning uid is safe and could be attempted (or at least suggested). - Surface the failure:
getUdsStartFailureCauseexists internally — showing it in/doctoroutput and/or appending the cause to the "No reachable agents." message ("peer messaging is off in this session: sockets directory refused ...") would have made this a 2-minute diagnosis instead of a deep dive.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗