manycode was called ccshare until July 2026 - same tool, wider name. The
ccsharecommand keeps working, and existing installs update in place.
Share your live Claude Code session with friends using a short code, AirDrop-style. The host runs your agent in a PTY and mirrors the terminal; everyone who joins sees the same screen and (unless you say otherwise) can type into the same session. Works in both directions - you host and they join, or they host and you join.
Claude Code is the default, but any terminal agent works - name it after host:
manycode host # claude
manycode host codex # openai codex cli
manycode host opencode # opencode
manycode host kimi # kimi cli
manycode host aider --model gpt-5 # args pass straight throughFrom a checkout: npm install && npm link, then manycode setup.
Setup installs the manycode-setup skill for Codex and Claude Code before
opening the preferences wizard. For automated installs:
manycode setup --skills-only
manycode doctorStart a new Codex or Claude Code session and say: Use manycode-setup to configure Manycode and start a shared coding session. The curl installer also installs this skill. Releases include a standalone CLI package at https://github.com/unworld11/manycode/releases.
To prepare a ChatGPT desktop SSH connection to a server you already use:
manycode setup --ssh-host your-server.example --ssh-user your-user --ssh-identity ~/.ssh/your-key --ssh-alias manycode
manycode doctor --ssh manycodeThe CLI maintains a marked entry in ~/.ssh/config, preserves other entries,
and saves the original as ~/.ssh/config.before-manycode on its first change.
It uses an existing key; server provisioning and key authorization remain separate.
The SSH check requires a trusted host key and codex on the remote login shell's
PATH. Authenticate Codex on that host before using it in the desktop app.
Then select manycode in ChatGPT Settings → Connections → SSH and choose
a project. CODEX_HOME and CLAUDE_CONFIG_DIR override skill install locations.
To share a selected existing Codex/ChatGPT desktop chat:
codex app-server daemon start
manycode share-thread --name "Chosen chat title" --guest-name Bob --tunnelKeep the selected chat open. Manycode reads only that thread through the app-server
API and queues guest prompts; the owning app processes them when ready. It does
not resume the thread in a competing backend. Both backends need message-queue
support. --thread ID selects an exact thread; --socket PATH selects a control
socket. Without --tunnel, the invite page listens only on localhost.
Messages render Markdown headings, lists, quotes, links, task lists, and tables. Code blocks include syntax highlighting and copy buttons; wide code and tables scroll within the message. Raw HTML stays inert and remote images are not loaded.
Guests receive live updates containing changed turns, with immediate feedback on submitted prompts. The desktop backend may still take up to ten seconds to pick up queued prompts before model processing starts.
The contributor invite permits reading and prompting. The view-only invite permits reading. These are bearer links, not account logins. Ctrl-C revokes future access and closes the tunnel; already queued prompts remain queued. Approvals stay with the host. User and assistant text and tool summaries are shared; internal reasoning and system/developer instructions are omitted. Conversation text can contain sensitive information: choose the thread you intend to share.
To join through your own Codex or Claude Code session, ask its agent to use the
manycode-setup skill with the invite link. The guest bridge supports
manycode remote connect "INVITE_URL", manycode remote read, and
manycode remote prompt "Your message". It stores the invite privately on your
machine; manycode remote disconnect removes it. This is tool-mediated access
from your own chat, not native mirroring of the host's thread.
SSH setup remains a separate option for remote project connections. The Claude skill targets Claude Code; it does not attach to Claude desktop chats.
npm run test:desktop -- --tunnel exercises separate backends and browser contexts
using synthetic data. Visible ChatGPT UI confirmation is a separate manual check.
Create a task in the project you want the agent to work on:
manycode host --task "Build checkout" --detach
manycode task opentask open opens local host controls in your browser. Share the ordinary browser
link or session code with teammates. The host controls link includes a private
owner token; it is removed from the address bar after loading and is never part of
the ordinary invite. CLI sessions without --task retain the existing everyone-can-type behavior.
The macOS app's Host a folder flow creates a task automatically.
Each shared task has a goal, plan, optional preview link, live terminal, feedback, people, activity history, and Git review. The browser and macOS Task panels use the same host-enforced protocol.
- Shared prompts. Contributors and reviewers can use Send prompt without a control handoff. Everyone sees the attributed prompt history and the same live agent terminal, including responses and tool activity. Prompts enter a bounded FIFO queue; sent means delivered to the terminal, not a completed AI response. The agent decides how to handle input while busy. Failed deliveries stay visible and are not retried automatically. Use the composer for shared prompts rather than mixing them with partially typed raw terminal input.
- One raw-terminal driver. The host starts with control. Teammates request it; the current
driver or host hands it to a connected participant. Host terminal input is also
blocked while someone else drives. If the driver disconnects, control returns
to the host, who can recover it through
manycode task open. - Suggestions and instructions are separate. Attach feedback to a
file:line, preview, or decision. The driver accepts or declines it. Accepting a suggestion never submits it to the agent; Send prompt is a separate, attributed action available to contributors. - Roles. Joiners start as contributors. Only the host can assign viewer, contributor, or reviewer roles. Viewers can inspect the task and diff but cannot change the task or request control. Roles apply to the current connection; reconnecting creates a new contributor identity and requires fresh review privileges.
- Catch-up. Late joiners get the current brief, feedback decisions, approvals, the latest 200 prompts, and the latest 100 recorded events. The browser highlights updates since that browser's last visit. The native panel shows the five latest events. This is a summary of recorded actions, not an AI interpretation of terminal output.
- Review. Resolve open feedback, then request review. Refresh the Git diff before approving. Only a designated reviewer or the host can approve. Completion requires an approval matching the current HEAD and tracked working-tree diff. Changed files invalidate an attempted completion; request a fresh review. Stage or ignore untracked files first. Review/complete states block new human input, but do not pause an already-running agent. These approvals do not merge, deploy, or intercept commands the agent executes itself.
- Preview. The task links to an existing HTTP(S) preview. Use an address your teammates can reach; Manycode does not publish or proxy your development server.
--detach keeps the host and its agent running after the launching terminal exits.
Closing a browser or choosing Leave running in the macOS app also leaves the
host alive. The machine must remain awake and online. This is host-backed execution,
not cloud hosting or automatic failover. Use manycode stop CODE to end it.
Tasks are saved under ~/.manycode/tasks/ with owner-only file permissions and
atomic writes. This directory contains the task brief, feedback, and recorded
instructions, so treat it as project data. Raw keystrokes and complete terminal
output are not part of the task journal; use --record for a terminal recording.
Existing .env redaction also applies to shared task text and diffs. It only masks
values discovered at startup, as described below.
manycode tasks # saved tasks, status, live codes
manycode task show --code ABC123 # current task, people IDs, recent events
manycode task update --goal "Handle failed payments" --code ABC123
manycode task handoff --target d2 --code ABC123
manycode task role --target d2 --role reviewer --code ABC123
manycode task changes --code ABC123
# After the host has stopped, in the same project directory:
manycode host --resume-task TASK_ID --detach
# To also resume Claude's own conversation, pass its resume argument:
manycode host --resume-task TASK_ID --detach -- --resumeResuming restores the task journal and brief, marks undelivered prompts failed without replaying them, resets review approvals, and starts an agent process. Provider conversation recovery depends on that agent's resume options; Manycode does not restore a crashed PTY. A lock prevents two live hosts from writing the same task. Task discovery is local to the host account; remote teammates join a specific task by its code. There is no organization directory or account-based project membership in this version.
CLI joiners can use Ctrl-T with /control, /handoff ID, /suggest TEXT,
/instruct TEXT, /review, /working, /approve HASH, or /complete HASH.
Use the browser for the full task brief and diff. manycode task commands are
local host controls, with --code selecting among multiple live tasks.
Task sessions require an updated relay. They refuse older relays without sender identity support and continue with direct/LAN hosting. Updated relays stamp input identity and withhold task-session output until the host admits the joiner.
npm ci
npm test # existing flows + task/relay/persistence tests
npm run test:browser # isolated two-person browser flow + mobile screenshots
cd app && swift buildBrowser tests use fresh, headless profiles against a temporary local Git project.
They use installed Chrome on macOS, BROWSER_EXECUTABLE when provided, or a
Playwright Chromium installed with npx playwright install chromium. External
network requests are blocked during the UI test; terminal assets are served locally.
MANYCODE_STATE_DIR isolates task/config/session files for tests.
On an Xcode installation without the Metal toolchain, swift build --build-system native builds SwiftTerm using its bundled shader source. Swift marks that build
system deprecated; installing the Metal toolchain enables the default build path.
npm run dist:mac builds an ad-hoc signed universal app, DMG,
and ZIP without an Apple Developer ID certificate. npm run verify:release checks the packaged downloads, and
npm run publish:release uploads a draft, verifies the downloaded bytes, then
makes that version latest. These releases are not notarized; first launch may
require Privacy & Security > Open Anyway.
The native app's Check for Updates menu opens new release downloads without
replacing an app during live work.
See macOS release setup for GitHub Actions, versioning, installation instructions, and optional notarization.
curl -fsSL https://manycode.vercel.app/install.sh | shOne command for everything: fresh install, and re-run it any time to update (it
clones to ~/manycode, or hard-updates the existing clone when it's clean). Prefer
doing it by hand? git clone, npm i, npm link works too - and manycode update
pulls the latest once you're installed. If manycode isn't found after npm link
(homebrew's node links into the Cellar, which isn't on PATH), the installer handles
it; manually it's ln -sf "$PWD/bin/manycode.js" /opt/homebrew/bin/manycode.
Then run manycode setup (or just manycode host - it onboards you the first time):
a 30-second interactive wizard that asks your display name, detects which coding
agents you have installed and sets your default, and picks tunnel + menu bar
preferences. Everything lands in ~/.manycode/config.json; per-session flags always
win over it, and rerunning manycode setup changes it any time.
node-pty ships prebuilt binaries, but npm strips the exec bit off its
spawn-helper - the postinstall script in this package restores it. If claude
ever fails to start with posix_spawnp failed, run npm rebuild here.
# you, in your project directory
manycode host
# code: 7KQ 2FM
# your friend, anywhere on the same network
manycode join 7KQ2FMDiscovery is a UDP broadcast carrying a hash of the code, so join finds the host
automatically - no IPs. Ctrl-] detaches a joiner without touching the session.
Three options, easiest first:
-
Tunnel (on by default): hosting opens a free Cloudflare quick tunnel in the background -
cloudflaredcomes bundled via npm, so there is nothing to install and no account needed. A few seconds later the remote join command - likemanycode join 7KQ2FM --host wss://random-words.trycloudflare.com- appears in the menu bar ("copy remote join command") and inmanycode code. That command works from any network. The URL is random, unguessable, and dies with your session.--tunnelwaits at startup so the link prints in the banner instead;--no-tunnelkeeps the session off the internet entirely. Join falls back to resolving fresh tunnel hostnames via 1.1.1.1 when the OS resolver has a stale negative answer.Note for friends who cloned early: joining a
wss://URL needs the current version, so have themgit pullin their manycode checkout. -
Tailscale (or any reachable IP): the host banner prints a direct line like
manycode join 7KQ2FM --host 192.168.1.4:42518- swap in the tailnet IP and it connects straight through, no extra server. -
Relay: one of you runs
manycode relayon any box with a public address (a $0 Fly/Railway/Render instance works - it respectsPORT). Then everyone putsexport MANYCODE_RELAY=wss://your-relayin their shell profile. With that set,manycode hostregisters with the relay automatically andmanycode join CODEfalls back to it when LAN discovery finds nothing. The relay is a dumb pipe; it never sees your code in plaintext discovery, just relays frames for paired rooms.
The host also serves a terminal web page on the same port, so every session has a
browser link like https://random-words.trycloudflare.com/#7KQ2FM (or
http://192.168.1.4:42518/#7KQ2FM on the same network). Send it to a friend and
they're in the live session from any browser - phone included - with the code
prefilled; no git clone, no node, nothing. It's a full xterm.js terminal speaking
the same protocol as the CLI joiner, so they see the same screen and can type
unless the session is --read-only. The link shows in the host banner, the menu
bar ("copy browser link"), and manycode code.
Claude's UI takes over the screen right after the banner, so two things bring the code back:
- macOS menu bar - hosting auto-starts a tiny status bar helper showing your live
code (and how many friends are on). Click it to copy the code, join commands, or
the browser link; open the anywhere-tunnel on a lan-only session; end the session;
and get notifications when friends join or leave. It compiles itself from
menubar/menubar.swifton first run (needs the Xcode command line tools) and quits when your sessions end.manycode host --no-menubaropts out;manycode menubarstarts it by hand and keeps it running. manycode code- prints the code, project, and joiner list for every active session, on any platform.manycode stop [code]ends a session from any terminal without switching back to the one hosting it.
Up to 5 friends can be in one session (--max changes that); everyone sees the same
screen and everyone can type. Nobody has to be there at the start - the code works
for the whole session, and late joiners get the recent scrollback replayed plus a
fresh repaint. Started lan-only and now want someone remote? manycode tunnel opens
the anywhere-link on the running session and prints the join command - no restart.
Every session has a chat channel that never touches the shared prompt, so you can
sort out who's driving without typing over each other. In the browser it's a
sidebar with an unread badge; in the CLI, Ctrl-T opens a chat line (Enter sends,
Esc cancels); the host sends from any terminal with manycode say "message" and
gets a macOS notification when someone writes. Late joiners get the recent chat
replayed, and names are stamped by the host - nobody can impersonate anyone.
manycode host --read-only- friends can watch but not type.manycode host --approve- each joiner waits until you click Allow in a macOS dialog;manycode setupcan make that the default,--no-approveskips it for one session.manycode host --record- saves the whole session as an asciinema.castfile in the project directory; play it back withasciinema playor upload it to asciinema.org.manycode host --share-secrets- hosting a folder with.envfiles asks what joiners should see; the default masks the values with••••••in the live stream, the scrollback replay, and recordings (your own screen stays raw).--redact-secretsskips the question,--share-secretsshares real values.manycode host -- --resume- everything after--goes to claude itself.manycode host <anything>- share any terminal program, agents or otherwise.manycode join CODE --name dev-priya- how you appear on the host's side.manycode host --max 2- cap joiners (default 5).
- The PTY runs at the smallest connected terminal, tmux-style, so everyone sees the same frame. When someone joins, resize + a repaint jiggle gives them a fresh screen; they also get the recent scrollback (last 256KB) replayed.
- New joiners ring a bell on the host and the terminal title shows
manycode CODE · N connected. - The session dies when claude exits on the host; joiners are told and dropped.
The code is the only auth, and anyone who has it can type into a real terminal on the
host's machine - that means running arbitrary commands. Only share codes with people
you'd hand your laptop to. Codes die with the session, direct/LAN traffic is plain
ws:// on your local network, and the relay sees terminal bytes, so put the relay
behind TLS (wss://) if you deploy one.
Hosting a folder that contains .env files masks their values in everything
joiners see (and in recordings) unless you explicitly --share-secrets - so a
stray cat .env on stream shows dots, not credentials. It's a literal byte match:
values also visible through some other encoding still leak, so treat it as a
seatbelt, not a vault.
--approve adds a second gate: a joiner with the right code still waits until you
click Allow. That's enforced by the host for direct, LAN, and tunnel joiners (their
input is dropped until admitted). Over a self-hosted relay it's best-effort - relay
input frames aren't attributed per joiner, so treat approval there as protection
against accidental joins, not hostile ones.