Skip to content

Install

Roy Padina edited this page Aug 30, 2026 · 4 revisions

Install

Hosting a jam is macOS and Linux — the host is tmux. Windows hosts through WSL2: install claude-jam inside the distribution and run it there, where tmux and claude both live. A native Windows host was investigated and dropped (nothing reattaches to a running ConPTY, so the host's own operator would be the one person stuck on the slow proxied path).

Joining is macOS, Linux, and — since v0.32 W1 — Windows, natively: node ≥ 22 and Windows Terminal, no WSL and no tmux. Read The Windows client, honestly before you rely on it: it is implemented and unit-tested on real Windows in CI, and no human has run it yet.

Prerequisites

Required to HOST. A guest needs only the first row:

what why check
node ≥ 22 the daemon and both clients — the only thing a guest needs node --version
tmux the host's session is a tmux session tmux -V
claude on PATH the actual Claude Code CLI claude --version

Optional, each unlocking one thing:

what unlocks without it
ttyd --view, the read-only browser view the flag refuses at startup, with the reason
cloudflared --tunnel the flag refuses at startup, with the reason
tailscale --funnel (and the printed join line uses your tailnet IP) the flag refuses; LAN addresses are printed instead
git /diff /diff says the cwd is not a git repository; /files still works
pngpaste /paste is faster macOS falls back to osascript, which is built in

A guest needs node, tmux is not required for them, and the claude CLI is not required either — a guest only runs the client. On Windows a guest also needs Windows Terminal.

npm (any platform, and the only Windows path)

Not on the registry yet. As of 0.23.0 claude-jam has never been published to npm, so this command 404s:

npm i -g claude-jam            # NOT YET PUBLISHED — 404 until it is

Until it is, use a local tarball. It installs the identical package, from the same files list, through the same bin shim — which is what makes it a fair rehearsal of the published path:

git clone https://github.com/roypadina/claude-jam && cd claude-jam
npm install && npm pack        # → claude-jam-0.23.0.tgz
npm i -g ./claude-jam-0.23.0.tgz

The same package Homebrew ships, and it installs the same two commands. It needs node ≥ 22 and nothing else — no tmux and no claude are required to join a jam.

Once published: upgrading is npm i -g claude-jam@latest, uninstalling npm rm -g claude-jam.

The Windows client, honestly

Implemented, unit-tested on real Windows in CI, and never run by a human. Nobody working on claude-jam has a Windows machine. Every decision the Windows code makes is a pure function asserted on a windows-latest runner on every push — the PowerShell argv for a clipboard read, the %APPDATA% path, the ACL that replaces 0600, the sound table, the key sequences, the terminal check — and the client's entry point is spawned and checked there for real. What no runner can do is look or listen: no toast has been seen, no sound heard, no key pressed in Windows Terminal, no jam joined from Windows.

# NOT on npm yet — build the tarball, then install it globally.
git clone https://github.com/roypadina/claude-jam; cd claude-jam
npm install; npm pack
npm i -g .\claude-jam-0.23.0.tgz
claude-jam join <invite-link>
  • Windows Terminal is required. It ships with Windows 11 and is a free Microsoft Store install on Windows 10. The legacy cmd.exe console is refused by name, with the reason, rather than painting escape codes at you — it has no alternate screen buffer and no ANSI by default. Git Bash (mintty), ConEmu with ANSI on, and the VS Code terminal work too. JAM_ASSUME_ANSI=1 skips the check if you are certain.
  • Client only. claude-jam host, the launcher menu, sessions, invite, find, end and clean all refuse with the WSL2 route; claude-jam with no arguments prints that instead of a menu.
  • No F3. It attaches tmux on the machine running it, and that machine is the host's. F2 (the live view), /answer, /send, /paste, /export, /c, /ping all work.
  • Shift+Enter needs one line of config, because Windows Terminal sends a plain Enter for it. End a line with \, or add to the actions array in WT's settings.json:
    { "command": { "action": "sendInput", "input": "\\u001b[13;2u" }, "keys": "shift+enter" }
  • No 0600. Private files get an NTFS ACL granting only your account (icacls /inheritance:r /grant:r <you>:F) — the equivalent, not the same thing.

If you try it, please report what happened, including what looked wrong. That is the only way any of this becomes verified. The per-capability table lives in the repo at docs/COMPATIBILITY.md.

Homebrew

brew install roypadina/tap/claude-jam

That installs two commands: claude-jam (the real one) and jam (a deprecated alias of it, kept so anything you already typed still works). Nothing in the tool prints jam.

Upgrading:

brew update && brew upgrade claude-jam

From source

git clone https://github.com/roypadina/claude-jam
cd claude-jam
npm install
./claude-jam --help

There is no build step. npm install pulls five runtime dependencies (ws, ink, react, @inkjs/ui and ink-text-input) and nothing else. Run it as ./claude-jam … from the checkout, or npm link to put both commands on your PATH.

Verify

claude-jam --help

Expected: a usage block whose first line is

usage: claude-jam                  (no arguments) the launcher menu: host, join,

and which lists claude-jam host, join, invite, invites, sessions, ls, end, kill, clean and remote. It should never print a bare jam command — that is a lint in the test suite.

claude-jam sessions

Expected on a machine with no jam running:

no jams — `claude-jam host` starts one, and this list only ever shows claude-jam's own sessions

That command is read-only and safe to run at any time; it enumerates only claude-jam's own state directories ($TMPDIR/claude-jam-<port>), never tmux list-sessions.

The alias, if you want to confirm it:

jam --help      # same output — it execs claude-jam

What it writes on your machine

path what when it goes
$TMPDIR/claude-jam-<port>/ the state dir, mode 0700: session.json, token.json, roster.json, the generated settings.json, system-prompt.txt, the outbox when the jam ends, or claude-jam clean
~/.config/claude-jam/history your own last 50 submissions per client (mode 0600) never automatically — delete it yourself
<cwd>/jam-uploads/ files guests uploaded (host side) never automatically
./jam-downloads/ files you took with /get (guest side) never automatically
./jam-session-<id>.jsonl a transcript you took with /export never automatically

$XDG_CONFIG_HOME is honoured for the history file when it is set to an absolute path.

On Windows those paths are %TEMP%\claude-jam-<port>\ and %APPDATA%\claude-jam\history. There are no mode bits there: the same files get an NTFS ACL granting only the current user (icacls /inheritance:r /grant:r <you>:F, and (OI)(CI) on the directory so what is created inside it inherits the single entry). That is the equivalent of 0700/0600, not the same mechanism, and it is worth knowing which one you are relying on.

Nothing global is touched: the Claude Code hooks live in a generated settings.json passed with --settings, and the tmux key binding lives on claude-jam's own tmux server (socket claude-jam-<port>), not yours.

Next

Clone this wiki locally