Skip to content

Windows WSL2 Host

Roy Padina edited this page Aug 30, 2026 · 1 revision

Hosting from Windows, through WSL2

Windows can host a jam. Not natively — a native Windows host was investigated and dropped, because nothing reattaches to a running ConPTY, so the person running the jam would be the one person stuck on a slow proxied screen. The route is WSL2: tmux, claude, claude-jam and the daemon all run inside the Linux distribution, and you sit in Windows Terminal looking at it.

From claude-jam's point of view that is a Linux host. Everything on Hosting a Jam applies unchanged. This page is only the four places where Windows is still visible.

Read this first. Nobody working on claude-jam has a Windows machine. Every decision on this page is unit-tested on macOS, Linux and Windows CI, and the WSL-specific behaviour — wslpath, DrvFs, interop, localhost forwarding — has never been run on a real install. docs/COMPATIBILITY.md in the repo says which is which, row by row, and there is a command that answers most of it on your machine:

git clone --depth 1 https://github.com/roypadina/claude-jam ~/claude-jam-src
node ~/claude-jam-src/scripts/check-wsl.mjs

It needs no npm install — it imports only claude-jam's own pure modules — and it prints PASS / FAIL / NOT EXERCISED, one line per fact. It is not in the npm package on purpose (the published tarball carries no test scripts).

If something here is wrong, that output is the bug report.


1. Setup, once

In Windows Terminal, on the Ubuntu (or other) profile — not PowerShell:

wsl --version                     # (run this one in PowerShell) WSL 2 and a recent kernel

Inside the distribution:

sudo apt update && sudo apt install -y tmux curl procps
node --version                    # >= 22. Install node INSIDE WSL, not the Windows one
claude --version                  # the Claude Code CLI, installed inside WSL
npm i -g claude-jam               # or clone the repo
claude-jam --help

Two things people get wrong here, both of which look like claude-jam being broken:

  • Install node and claude inside the distribution. A Windows node on PATH through interop will start, and then nothing that needs a pty will work properly.
  • Run claude-jam from a Linux directory (~/code/...), not from /mnt/c/.... See §2.

2. Where your files live, and the one hard rule

WSL gives you two filesystems, and they are not equivalent:

what it is use it for
/home/you/... the distribution's own ext4 the jam, and ideally your project
/mnt/c/... your Windows drive, mounted as DrvFs files that have to be on Windows

claude-jam refuses to put its state directory on a Windows drive, and it will tell you so:

refusing to use this jam's state dir /mnt/c/tmp/claude-jam-7777: its mode is 777, which grants
the group access — jam's state dir holds host.key and token.json, so it must be 0700.
  /mnt/c/tmp/claude-jam-7777 is on Windows drive C:, mounted into WSL as DrvFs. Windows drives
  cannot hold a private directory here: without the `metadata` mount option every file reports
  mode 0777 and one owner, and `chmod` on such a mount reports success and changes nothing — so
  neither chmod nor another --port can fix this.

That is not conservatism. The state directory holds host.key, which is host authority — a process that can read it can type into your real Claude session — and a directory that reports 0777 cannot be told apart from one another user could reach. chmod will not help: on a DrvFs mount without the metadata option it reports success and changes nothing.

The state directory is $TMPDIR/claude-jam-<port>, and $TMPDIR inside WSL is /tmp, which is on the Linux side. So this only bites you if you have set TMPDIR yourself. If you have:

unset TMPDIR                              # or
claude-jam host --state ~/.claude-jam-state

Your project can stay on /mnt/c. Only the state directory must not. Working from /mnt/c is slower and file-watching is less reliable — that is WSL, not claude-jam — but it works, and jam-uploads/ lands there fine.


3. Paths, across the \\wsl$ boundary

Windows and Linux name the same file differently, and you will paste both kinds. claude-jam translates the Windows spellings for /send:

you type it opens
/send C:\Users\you\shot.png /mnt/c/Users/you/shot.png
/send \\wsl$\Ubuntu\home\you\notes.md /home/you/notes.md
/send ~/notes.md, /send ./x.png unchanged
/send \\wsl$\Debian\home\you\x refused — that is another distribution, not mounted here
/send \\fileserver\team\x.docx refused — a Windows network share is not mounted in WSL

Going the other way, to open something from Windows: a file at /home/you/proj/jam-uploads/a.png is \\wsl$\Ubuntu\home\you\proj\jam-uploads\a.png in Explorer, and explorer.exe . from inside the distribution opens the current directory in Windows.

/paste reads the Windows clipboard through interop, so Win+Shift+S then /paste in your client works the way it does on a Mac. If interop is off you get a line saying so, and /send still works. (Unverified: see the warning at the top.)


4. Who can reach the jam

This is the part where WSL2 being a virtual machine behind NAT shows. When you start a jam the join block says so:

Send this to a friend:
  invite: claude-jam join ws://172.28.144.3:7777 --name <You> --token …
  from Windows on this PC: claude-jam join ws://localhost:7777 --name <You> --token …
  this jam runs in WSL2 (Ubuntu), so the addresses above are the VM's. Windows on this PC
  reaches it on localhost; another machine needs mirrored networking, a portproxy, or --tunnel.
who how notes
you, from Windows Terminal the localhost line WSL2 forwards localhost into the VM by default (localhostForwarding in %USERPROFILE%\.wslconfig)
you, inside WSL either line it is all one machine
anyone else, over the internet claude-jam host --tunnel a relay dials out, so NAT is irrelevant. This is the reliable answer
anyone else, on your LAN mirrored networking, or a portproxy see below

For a LAN guest you need one of:

# .wslconfig, Windows 11 22H2+ — the clean way. Restart WSL after (wsl --shutdown).
[wsl2]
networkingMode=mirrored
# or forward one port, as Administrator. The WSL IP changes on every boot, so this needs redoing.
netsh interface portproxy add v4tov4 listenport=7777 listenaddress=0.0.0.0 `
  connectport=7777 connectaddress=(wsl hostname -I).Trim()
New-NetFirewallRule -DisplayName "claude-jam 7777" -Direction Inbound -LocalPort 7777 -Protocol TCP -Action Allow

If you use --view, its port needs the same treatment; the join block prints its localhost URL for you.

--funnel needs Tailscale installed inside the distribution — the Windows Tailscale cannot serve a port that lives in the VM. --funnel is unverified on every platform (see Remote Access).

LAN discovery (claude-jam find) does not work here, and says so: it needs Apple's dns-sd, which Linux does not have. Use an invite link.


5. Checking it, on your machine

Run these in order. Each is a command and an expected observation, and the first one does most of the work.

# where command expected
1 WSL node ~/claude-jam-src/scripts/check-wsl.mjs (see the clone line above) all checks passed. Every FAIL line names what it measured — that is the bug report
2 WSL claude-jam host --name You --cwd ~/somewhere the jam starts; the join block carries the from Windows on this PC: line
3 Windows Terminal (PowerShell) curl.exe -s -m 3 http://localhost:7777/health {"ok":true,...} — this is localhost forwarding, and it is a claim until you run it
4 Windows claude-jam join ws://localhost:7777 --name You2 --token <token> a second client joins; you see the same screen twice
5 WSL /send C:\Windows\System32\drivers\etc\hosts in the host client it is offered — the path was translated
6 WSL copy an image (Win+Shift+S), then /paste the image is offered. A refusal naming interop is also a result — write down which
7 another machine curl -s -m 3 http://<windows-ip>:7777/health refused/timeout is expected unless you did §4. Says which
8 WSL claude-jam host --tunnel …, then join from a phone this is the path that should not need any of §4
9 WSL claude-jam end <name>, then claude-jam sessions gone, and no state directory left

If step 1 prints NOT EXERCISED for wslpath, you are not in WSL — check you are on the Ubuntu profile and not PowerShell.


Known limits, in one place

  • LAN discovery is unsupported (no dns-sd on Linux). Invite links work.
  • The state directory cannot be on a Windows drive. §2.
  • A LAN guest needs mirrored networking or a portproxy. --tunnel needs neither.
  • /mnt/c is slow and its file-watching is unreliable. That is WSL.
  • None of this has been run on a real Windows machine. The repo's docs/COMPATIBILITY.md says so row by row, and scripts/check-wsl.mjs is how that changes.

Clone this wiki locally