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

Status Fixed / completed
Maintainer reply None cached
Activity 1 comment · opened Aug 25, 2026 · closed Aug 26, 2026

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

  1. On a default WSL2 install with WSLg (so XDG_RUNTIME_DIR points at /mnt/wslg/runtime-dir), start two interactive claude sessions.
  2. 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.
  • ListAgents returns 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

  1. On Linux, when XDG_RUNTIME_DIR fails the directory vet, fall back to the tmpdir path (/tmp/cc-socks-<uid>/, 0700, which would pass — /tmp is sticky) instead of disabling messaging outright. A Termux-style fallback already exists for the path-length case.
  2. Or special-case the known WSLg default: /mnt/wslg/runtime-dir is user-owned; a chmod 700 by the owning uid is safe and could be attempted (or at least suggested).
  3. Surface the failure: getUdsStartFailureCause exists internally — showing it in /doctor output 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.

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗