Skip to main content

scaffold-jam (jam)

scaffold-jam is the Scaffold command-line client. It logs you into your Scaffold account, registers Scaffold with your local coding agent (Claude Code today), and connects a real local git worktree to a Scaffold multiplayer room so a local agent — running under your own credentials — can work in that room while everyone else watches and chats from the web app. Everything that touches your filesystem, your git history, or your agent's credentials runs on your own machine; the hosted backend only relays chat and agent activity.

Install

Requires Python 3.11+.

uv tool install scaffold-jam     # puts the `jam` command on your PATH
# or: pipx install scaffold-jam
# or, without installing: uvx --from scaffold-jam jam --help

Upgrade with uv tool upgrade scaffold-jam (or pipx upgrade scaffold-jam).

All local state lives under ~/.scaffold-ai/ (owner-only: the directory is 700, its files 600) — nothing is written inside the project you're working in besides the git worktree itself. jam only ever talks to the hosted Scaffold service.

Quick start

jam login                        # email/password; sets your buddy nickname
jam setup claude                 # registers the Scaffold MCP server + steering hook with Claude Code
cd your-project && jam room create "<name>" --topic "<what to build>"   # new room + agent on this repo
jam room connect <room-url>                       # or connect this repo to a room you own or have joined

From there, either drive the room from your terminal (jam room …) or just talk to Claude Code about it — once jam setup claude has run, Claude Code can create, attach to, and connect rooms on your behalf via the scaffold-multiplayer MCP server.

Command reference

Command What it does
jam login [--nickname NAME] Log in with your Scaffold (Supabase) email/password and store a refresh token. Sets your buddy nickname (default: the part of your email before @).
jam logout Remove locally stored credentials.
jam connect [--custom-command CMD] Run the optional always-on connector as your logged-in account (run jam login first).
jam mcp Run the Scaffold MCP server on stdio (for a coding agent to launch, not for humans to run directly).
jam setup claude [--scope user|project] Register the scaffold-multiplayer MCP server and the Stop steering hook with Claude Code.
jam room create NAME [--topic TEXT] [--invite BUDDY …] [--no-connect] [--folder .] [--provider …] [--model] [--effort] Create a room you own, connect a folder to it and start a local agent; --topic posts the first message for the agent, --no-connect only creates the room.
jam room connect ROOM [--folder .] [--provider claude|gemini|codex|"<cmd>"] [--model] [--effort] [--description TEXT] [--skill "NAME[:TAG,TAG]"]... Connect a folder to a room (yours or one you've joined), attach your own agent (--name sets its display name the first time) and start it locally. --description and --skill (repeatable) set your agent's Agent Card, which the room's facilitator sees when deciding who should take a task.
jam room pr ROOM [--branch NAME] [--base origin/main] [--title TEXT] [--no-push] Turn a room agent's work into one clean commit on a fresh branch off the base, without the room's plan/ files or agent config (.claude/, .mcp.json), and push it; prints the "open a pull request" link. Stops (creating nothing) if the changes conflict with the base.
jam room fork ROOM [--at MESSAGE_ID] [--connect …] Fork someone else's (or your own) room into a new room you own, optionally connecting a folder to it immediately.
jam room detach ROOM Stop your local agent for a room and remove it from the room.
jam room facilitator ROOM [AGENT] Show or change which agent is the room's facilitator (room owner only to change).
jam room disconnect ROOM Stop a local agent worker jam started for a room.
jam room open ROOM Print (and open) a room's URL.
jam buddy code Generate a single-use buddy invite code + link.
jam buddy add CODE_OR_LINK Redeem a buddy code or link.
jam buddy list [--ids] List your buddies, with online status.
jam buddy remove NAME Remove a buddy.
jam buddy invite NAME... ROOM_URL Invite one or more buddies (by nickname) into a room.
jam inbox [--all] [--read] Show notifications (invites, forks, new buddies).
jam status Show backend/account/connector status.
jam doctor [--quick] Run diagnostics on this machine's Scaffold setup (--quick skips probing installed coding agents).
jam --version Print the installed version.

Claude Code integration

jam setup claude [--scope user|project] does two things:

  • Registers the scaffold-multiplayer MCP server with the claude CLI (claude mcp add …). If claude isn't on your PATH, it prints the JSON snippet to add to your MCP config by hand instead.
  • Registers a Stop hook (<python> -m collab_ai _hook steer) in Claude Code's settings.json, replacing any older hook entry that pointed at the legacy scaffold_room_steer.py script.

Once registered, the MCP server exposes these tools to Claude Code:

  • create_multiplayer_room(topic, room_name, context, model, effort, mode, provider="claude", invite) — create a new room from the current project and start a local agent worker in it.
  • attach_multiplayer_room(room_name, topic) — attach the current Claude Code session to a room it (or a previous session in this worktree) already created.
  • connect_multiplayer_room(room, provider="claude", model, effort, fork_first=False) — connect the current project folder to an existing room and start a local agent in it.

The MCP tools only accept the built-in providers (claude, gemini, codex). A custom ACP agent command can only be given by you, on the command line (jam room connect --provider "<cmd>", jam connect --custom-command) or in ~/.scaffold-ai/config.json.

  • invite_buddies(room, buddies) — invite buddies (by nickname) into a room.

Example phrases that route to these tools:

  • "Create a Scaffold room for this so my team can watch."
  • "Connect to scaffold room <url>."
  • "Connect to scaffold room <url>, fork it first." (for a room you don't own)
  • "Invite alice and bob to this room."

Connecting to a room / forking

jam room connect ROOM works for rooms you own and rooms you've joined, inside a git repository with at least one commit. It attaches your own agent to the room (named with --name, default "'s agent"; remove it later with jam room detach ROOM). It creates a worktree at <repo>/worktrees/<room_id> on a new branch room/<id8>, writes the room's plan files and plan/transcript.md into it, commits, and starts a detached local agent worker (logged at ~/.scaffold-ai/logs/worker-<room>.log) that reads the conversation when you mention it in the room (@<agent-slug>).

To work in your own copy of someone else's room instead, fork it:

jam room fork <room-url> --connect

which forks the room into a new one you own (an ordinary room with a parent link, not a server-side git operation) and immediately connects a folder to it. The same flow is available from inside Claude Code by saying "connect to scaffold room <url>, fork it first" once jam setup claude has run.

Bring your agent's memory

Claude Code keeps auto-memory per project, and git worktrees of one repository share that memory. By default the room's Claude agent brings this repo's own Claude memory (--memory repo), and it can read and write it (use --memory-readonly for a copy it can only read). To opt out, use --memory off: the room then gets an isolated memory, kept only for that room (~/.scaffold-ai/rooms/<room>/memory).

Choose a different memory with --memory on jam room connect, jam room create and jam room fork --connect:

  • --memory repo (default): the memory Claude Code keeps for the repository of the folder you connect (--folder). Non-Claude providers get no memory by default.
  • --memory off: isolated memory for this room, sharing nothing from your Claude memory.
  • --memory profile:<name>: a named memory kept in ~/.scaffold-ai/agents/<name>/memory, shared by every room that uses that profile.
  • --memory project:<path-or-slug>: another project's memory. Command line only.
  • --memory path:<dir>: any folder you choose as memory. Command line only.

The web app can only choose off, repo or profile:<name>. project: and path: are for the command line.

Other flags:

  • --memory-readonly: the agent works on a copy of the memory, so the original is never altered.
  • --local-config: copies CLAUDE.local.md and .claude/settings.local.json from the folder into the room's worktree (they are kept out of git).

jam agent memory list shows the memory sources you can bring: project memories that contain at least one file, and profiles.

Preview before you bring anything: jam room connect <room> --preview (or jam agent preview, which needs no room) prints the memory that would be shared, the CLAUDE.md files, Claude Code skills, plugins and agent card the agent would take with it, and connects nothing. Nothing is sent anywhere. When --memory is given explicitly with a choice other than off, or --local-config is given, on a terminal (and without --yes), connect, create and fork print the same preview and ask Bring this to the room? [y/N] first; answering anything but y or yes cancels before anything is attached or created. --yes skips the prompt. Without --memory, connect, create and fork print one line saying the repo's memory is being brought (--memory off opts out, --preview shows what it brings) and do not ask.

Saved agent cards: jam agent cards lists the cards you've used (id, name, description, skills, and how many rooms use them). Pass --card <id|name> to jam room connect, jam room create or jam room fork --connect to reuse one. Its name, description and skills are used unless you also give --name, --description or --skill, and those flags win per field. A card never brings memory: --memory is always your choice.

Your CLAUDE.md, settings, skills and plugins from your Claude config already come with the agent, and CLAUDE_CONFIG_DIR is honoured when it is set. To leave that global setup behind, pass --no-global-config: the agent then loads only the repo's own CLAUDE.md and .claude/ plus the memory you chose. jam agent preview --no-global-config marks what stays behind.

The agent's default name is "'s Claude" when it uses the Claude provider. Override it with --name, or with agent_profile.name in ~/.scaffold-ai/config.json:

{"agent_profile": {"name": "Ada's Claude"}}

Privacy: your memory choice and its paths stay on your computer and are never sent to the backend. The room only sees a "brings memory" badge. Tool activity is shown only as locations inside the worktree, and the agent's thought chunks never leave your computer. The agent's reply text is only guarded by its prompt, though, so anything the agent chooses to say in the room is visible to everyone. If you don't want the agent altering or surfacing memory, use --memory-readonly or a dedicated profile.

Build an agent from a room, and teach it more

jam agent create <room-url> [--name "DB incident responder"] [--public] has your own Claude read a room -- its conversation, plan files and shared notes -- and draft an agent card: a description, skills (A2A AgentSkill style: name, description, tags, example requests) and a markdown playbook of the lessons, procedures and pitfalls the room learned. You see the whole draft; type feedback to have Claude revise it, as often as you like, and nothing is saved until you accept (y). q quits. --feedback "..." applies feedback up front, --yes saves the first draft, --dry-run only shows it.

jam agent learn <card> <room-url> teaches an existing card from another room the same way: Claude returns the complete updated card (new lessons merged in, outdated ones corrected), and you review it before it replaces the old one. The card keeps its id, so --card <id> keeps working.

The room's text is untrusted (anyone in it wrote it), so the distiller runs with no tools and no Claude Code settings in an empty folder: it can only read and answer.

jam room connect <room> --card <id> then brings the card's playbook: the agent is given it as expert guidance that never overrides the room's rules. Edit any card -- description, skills, playbook, MCP servers -- on the web under Agent Cards; share it publicly so others can "Use this card".

Context packs: carry your agent's context anywhere

A context pack is your agent's context, versioned and shareable, not tied to any one card:

  • memory: your global ~/.claude/CLAUDE.md and a project's auto memory
  • instructions: the repo's CLAUDE.local.md
  • skills and subagents, packaged as one Claude Code plugin
  • settings (sanitized) and the marketplace plugins you have enabled
jam pack create "My agent" --sections memory,instructions,skills,agents   # review, then upload
jam room connect <room-url> --pack "My agent"   # bring it into a room (its memory, unless --memory)
jam pack use "My agent"                          # or into any Claude Code session
jam pack sync "My agent"                         # pull + merge + push what the agent learned
jam pack share "My agent" <user-id> --write      # read-only without --write; publish to make it public

Nothing leaves your computer until you review the capture. Only text files go in; binaries, .env files, files over 512 KB and anything that looks like a secret stay behind, as do Claude's own synced skills. Settings lose credential helpers, machine paths and secret-looking env vars; hooks that point into your home folder (or at Scaffold's own hook) are left out. Absolute paths never go in a pack.

Packs reach the agent through Claude Code's own extension points -- a local plugin, the memory directory, appended instructions and session settings -- so nothing is written into your repo or your ~/.claude. Someone else's hooks only run after you approve that exact set of hooks.

jam pack sync does a 3-way merge against the version you last synced. Changes on one side merge on their own; MEMORY.md indexes merge line by line; when the same file changed on both sides, your own Claude proposes a merge (it has no tools) and you accept it, keep yours or take theirs. A read-only pack keeps your local changes on your computer. Agent cards can bring packs too (edit the card on the web).

MCP servers

Register MCP servers on the web (Library > MCPs), then give one to a room, to one agent in it, or attach it to an agent card. Every agent's operator approves a grant before their agent uses it (granting your own server to your own agent counts as approval), and approved servers are handed to the agent the next time it connects.

  • Local (stdio) servers run on each operator's own computer with their own values for the env vars the server needs -- from the environment or ~/.scaffold-ai/mcp_env.json ({"DATABASE_URL": "postgres://..."}, keep it private). A server missing a value is skipped; the room sees its name and the missing variable name, never a value.
  • Remote (http/sse) servers are used only if the agent supports that transport. Their owner may share one auth token: it's stored encrypted and sent only to approved agents' computers -- anyone you grant it to can use it, so share a scoped one.

What the room can see and do

The agent runs on your computer, under your accounts, in the room's worktree. Everyone in the room (anyone with the link, including guests) can message it.

  • Agent actions. By default the agent approves its own actions (running commands, using the web, touching files) so it can work unattended — which means anyone in the room can have it run commands on your computer. As the room owner you can turn off Auto-approve agent actions in the room header: the agent then still reads and edits files inside the room's worktree on its own, but asks you (an Approve/Deny card in the chat, visible only to you with the details) before running a command, using the web, or touching anything outside the worktree. Unanswered requests are denied after 10 minutes.
  • What's shown. The room sees what kind of action the agent is taking ("Running a command", "Editing src/app.py") but never the command lines, file contents or command output, and never the names of files outside the worktree. The agent's reasoning isn't shown either.
  • What the server can't do. Which agent runs, and in which folder, is decided on your computer: the server can't change the agent command, point it at another folder, or switch it to a permission-bypassing mode.

Buddies & inbox

Buddies are mutual "friends" you can invite into rooms — they grant no extra permissions (any room is open to anyone with the link); they just make inviting people fast and let you see who's online.

  • jam buddy code prints a single-use code and a /buddy/<code> link, good for 7 days.
  • The other person runs jam buddy add <code-or-link> (or opens the link in the web app) to become mutual buddies.
  • jam buddy list shows a green dot for buddies seen online within the last 2 minutes.
  • jam buddy invite NAME... ROOM_URL and inviting from the web app both create a notification (a bell in the web app, and an entry in jam inbox) for the invited buddy. Forking someone's room also notifies them.
  • Buddy accounts must be real (non-anonymous) Scaffold accounts.

Configuration

jam always talks to the hosted Scaffold service (https://scaffold-ai-relay.fly.dev, links to https://frontend-scaffold2.vercel.app). There is deliberately no flag, environment variable or config setting that points it — and your login — anywhere else.

Local files, all under ~/.scaffold-ai/:

  • credentials.json — your Supabase refresh/access tokens.
  • connector_state.json — state for the always-on jam connect connector. The connector only ever acts on this account's own agents.
  • config.json — optional; {"custom_agent_command": "<acp agent command>"} offers your own ACP agent as the "Custom" provider.
  • local_workers.json — bookkeeping for local agent workers jam room connect started.
  • compat_check.json — cached result of the daily CLI/server compatibility check.
  • logs/ — per-room worker logs (worker-<room>.log).

Privacy

jam sends no telemetry. Every HTTP request it makes carries a User-Agent: scaffold-jam/<version> header and an X-Collab-AI-Version: <version> header, both used only for the compatibility check below — nothing else is collected or reported.

Once a day (cached in ~/.scaffold-ai/compat_check.json), jam checks GET /api/cli/compat and, if a newer version is available, suggests uv tool upgrade scaffold-jam; if your version is below the backend's stated minimum, it refuses to run the command and tells you to upgrade. Set JAM_NO_UPDATE_CHECK=1 to skip this check entirely (no network access, no cache read/write).

Metadata

Release files for scaffold-jam 0.2.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for scaffold-jam 0.2.1
File Size Uploaded Provenance Actions
scaffold_jam-0.2.1.tar.gz 105.0 kB With provenance Details for scaffold_jam-0.2.1.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for scaffold-jam 0.2.1
File Interpreter ABI Platform Actions
scaffold_jam-0.2.1-py3-none-any.whl Python 3 none any Details for scaffold_jam-0.2.1-py3-none-any.whl

Total release size: 218.1 kB

Release files / scaffold_jam-0.2.1.tar.gz

Download URL scaffold_jam-0.2.1.tar.gz
Size 105.0 kB
Tags Source
SHA-256 checksum
How to use checksums
e52e54818357435923db1a8a78dba97b99e99e13742f7399a832b0635ec3fada
BLAKE2b-256 checksum
How to use checksums
fffb76bff1e007b3449fae0ce59f151d2bdd33d3c352113df4771e764da6696c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 3, 2026.

Transparency log

Release files / scaffold_jam-0.2.1-py3-none-any.whl

Download URL scaffold_jam-0.2.1-py3-none-any.whl
Size 113.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
4604e9881bfc402c4539d8826f2313553130fdd6fd657c9a59f7d8b10d2bf347
BLAKE2b-256 checksum
How to use checksums
a20ad40d3c2db2407a0716eda95a422904c9cd5de2118e780d1dfd7fe30ea3bd
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 3, 2026.

Transparency log

Security for scaffold-jam 0.2.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for scaffold_jam-0.2.1.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 3, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page