Skip to content

Agent Install

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

Agent-Install

This page is written for an agent. Every step is non-interactive and copy-pasteable, and every step says what to check before moving on. If you are a human, Install is shorter.

If you were sent here to change the claude-jam source, this is the wrong page — read AGENTS.md in the repo instead.


0. Never do these

Not as a cleanup, not as a recovery, not "just this once". Each one destroys work that is not yours, and no later step can undo it.

never why
tmux kill-server ends every tmux session on the machine, including the human's
pkill, killall, kill $(pgrep …), any name- or pattern-matched kill you cannot tell your process from someone else's by its name
tmux kill-session with a bare or pattern target tmux prefix-matches, so -t jam also matches jamboree. Always -t =exact-name
ending a jam you did not start claude-jam sessions may list somebody's live work. Read it; do not end it
brew upgrade with no argument, or any global config edit you were asked to install one thing

A jam may already be running on this machine — commonly on port 7777, tmux session jam, on the default tmux socket. Treat it as read-only.


1. Check the prerequisites

node --version && tmux -V && claude --version

Verify: node is v22 or higher, tmux prints a version, claude prints a version. If claude is missing, stop — claude-jam hosts the real Claude Code CLI and cannot substitute for it. This step needs a human if Claude Code is not installed or not logged in.

Optional tools, each unlocking exactly one feature. Missing ones are not an error:

command -v ttyd cloudflared tailscale git pngpaste

2. Install

brew install roypadina/tap/claude-jam

Verify:

command -v claude-jam

Expected: a path (typically /opt/homebrew/bin/claude-jam or /usr/local/bin/claude-jam).

If Homebrew is not available, install from source instead:

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

Verify: node --check ~/claude-jam/host.mjs exits 0, and run everything below as ~/claude-jam/claude-jam … rather than claude-jam ….


3. Confirm the command

claude-jam --help

Expected: a usage block beginning

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

listing host, join, invite, invites, sessions, ls, end, kill, clean, remote.

jam is installed as a deprecated alias of the same executable. Never use it in anything you write down.

Do not run claude-jam with no arguments. With no arguments it opens an interactive launcher menu and waits for a keypress you cannot give it. Always pass a subcommand, or --no-menu for the usage text.


4. Look before you touch

claude-jam sessions

Expected, on a machine with no jam:

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

If it lists rows, read them and change nothing. A live row is somebody's running session. A row marked ! orphan (a dead session's leftover directory) or ! incomplete (a directory from a start that never claimed a session) is still not yours to clean unless you were asked to. claude-jam sessions --json is the same facts for a script.


5. Start a jam (host side)

claude-jam host --name <YourHumanName> --cwd "$PWD" --no-attach --no-prompt

Flags that matter for a non-interactive run:

flag why you want it here
--no-attach do not open a client of its own. Without it the launcher takes over the terminal
--no-prompt never ask "keep it running or end it?" — a prompt you cannot answer is a hang
--cwd <dir> the directory claude runs in. Use an already-trusted one (see below)
--port N pick a free port if 7777 is taken. The state dir and tmux socket follow the port
--tmux <name> name the tmux session. Default claude-jam; a second one auto-names claude-jam-2
--token <value> 8–64 chars of [A-Za-z0-9_-]. Without it the jam is knock-only and every join waits for a human
-- <claude args> everything after -- goes to claude verbatim, e.g. -- --model haiku

Verify: the command prints claude-jam up., a session UUID, the tmux session name and its socket, then a Send this to a friend: block. Then:

claude-jam sessions --json

Expected: one object whose "name" is your tmux session and whose "state" is "live".

This step can need a human: in a directory Claude Code has never run in, claude shows a "do you trust the files in this folder?" dialog. The daemon answers it automatically before its first injection, but if you see nothing happening, attach and look: tmux -L claude-jam-<port> attach -t <name>:claude.


6. Let somebody in

Pick one. An invite link is the recommended one — it is per person, revocable and expiring.

claude-jam invite Dana                          # multi-use, 24 h
claude-jam invite Dana --uses 1 --expires 30m   # one shot
claude-jam invites                              # list them (never reprints a link)
claude-jam invite revoke Dana                   # take one back

Verify: claude-jam invite Dana prints a line beginning claude-jam join cjam1_…. That whole line is the guest's entire command.

An invite link is a credential. Give it to the human to send over a private channel. Do not put it in a commit, an issue, a log, a pull request, or anything else that persists.


7. Join a jam (guest side)

claude-jam join cjam1_…                                    # an invite link: nothing else needed
claude-jam join ws://<host>:7777 --name Dana --token <tok> # a shared token
claude-jam join ws://<host>:7777 --name Dana               # no token: a knock, a human accepts you

Verify: the client opens on the host's live TUI. With a knock it prints waiting for host approval… and stays there until a human answers — that is a human step, and it times out after 2 minutes.

The client is a full-screen terminal app. Under an agent with no real terminal, add --basic (it is also chosen automatically when stdin is not a tty): transcript only, no live view, no F2/F3, no command list.


8. End it

claude-jam end <name>

Expected:

ending jam "<name>" (port <port>, session <first-8-of-uuid>)
  daemon told everyone the jam is ending
  tmux session <name> is gone

Exit code 0. Every connected client prints <Host> ended the jam and exits 0 as well.

claude-jam end refuses anything it did not create: a session is endable only when it carries claude-jam's ownership marker and that marker points at a state directory whose session.json names that exact session back. If it refuses, the message says what did not line up. Do not work around it with tmux kill-session — that is the human's call.


Self-test

Runs end to end, spends no tokens (no message is ever sent), touches nothing that already exists. It uses port 7788 and the session name agentcheck so it cannot collide with a default jam on 7777.

set -e
claude-jam --help | head -1
claude-jam host --tmux agentcheck --port 7788 --view-port 7789 \
  --name Check --token agentchecktoken0 --cwd "$PWD" --no-attach --no-prompt -- --model haiku
claude-jam sessions --json
claude-jam end agentcheck

Expected output, in order:

usage: claude-jam                  (no arguments) the launcher menu: host, join,
claude binary: /…/claude
shared-session contract → /…/claude-jam-7788/system-prompt.txt (--append-system-prompt-file, survives /compact)

claude-jam up. session <uuid>
  tmux: agentcheck on socket claude-jam-7788 (windows: daemon, claude) — detached;
        `tmux -L claude-jam-7788 attach -t agentcheck:claude` for the raw TUI

Send this to a friend:
  invite: … ws://<your-ip>:7788 --name <You> --token agentchecktoken0

then a JSON array containing an object with

{ "name": "agentcheck", "state": "live", "port": 7788, "socket": "claude-jam-7788" }

(other rows may be present — they are other jams, and the test says nothing about them) and finally

ending jam "agentcheck" (port 7788, session <first 8>)
  daemon told everyone the jam is ending
  tmux session agentcheck is gone

with exit code 0. Verified 2026-08-30 on node 24.15 / tmux 3.7c / claude 2.1.251, macOS.

One more line appears only if CLAUDE_CONFIG_DIR is set, naming the profile the jam will run under — claude profile: /…/.claude-work2. Its absence is normal; its presence is not a failure.

If step 2 hangs, claude is probably showing the trust dialog for --cwd: attach with tmux -L claude-jam-7788 attach -t agentcheck:claude, answer it, Ctrl-b d to detach, and finish with claude-jam end agentcheck.

If anything fails, clean up only what this test made, by exact name:

claude-jam end agentcheck || tmux -L claude-jam-7788 kill-session -t =agentcheck
rm -rf "${TMPDIR:-/tmp}/claude-jam-7788"

Never tmux kill-server, and never a pattern.


Where to go next

Hosting a Jam · Joining a Jam · Remote Access · Security Model · Troubleshooting

Clone this wiki locally