thinkpool-pair
v0.6.12
Published
Share a local coding-agent CLI (Claude Code, Codex, Gemini, Aider, …) into a ThinkPool Code room, live.
Readme
thinkpool-pair — the ThinkPool Code bridge
Share your local Claude Code (or any terminal CLI) into a ThinkPool Code room, live. Both people see the real terminal stream and can both drive it — no copy/paste.
A web page can't read your terminal directly (browser security). This tiny helper is the bridge: it runs CLIs in PTYs and streams them to the room.
Run it (one command)
cd bridge && npm i # one-time (builds node-pty — needs Xcode CLT / build-essential)
node bridge.mjs <ROOM> # picks an installed agent, shared into room <ROOM><ROOM>is the 5-char room code from the ThinkPool Code web UI (/code).- Share a specific CLI:
node bridge.mjs <ROOM> -- aider/… -- bash. - Pure relay (no local terminal):
node bridge.mjs <ROOM> --headless.
Keep it stable (auto-restart)
The bridge self-heals at three levels — all cross-platform (macOS / Linux / Windows):
--supervise— wrap it so a crash respawns automatically (exponential backoff). Zero-dependency. Combined with session restore (below), a crash is invisible — the room reconnects and the Claude session resumes where it left off.npx thinkpool-pair <ROOM> --supervise -- claude- Boot-persistent service — survive reboot/logout too. Installs the right
native service for your OS (launchd on macOS, systemd
--useron Linux, a Startup-folder script on Windows):
The service runsnpx thinkpool-pair install-service <ROOM> -- claude # set and forget npx thinkpool-pair uninstall-service <ROOM> # remove itnpx thinkpool-pair@latest, so it auto-updates — new versions apply on the next restart, no re-install. (Linux: runloginctl enable-linger $USERonce to keep it running after logout.) - Watchdog — if the realtime channel wedges for >60s, the bridge exits so the supervisor/service restarts a clean process. Brief network blips reconnect on their own.
Structured Claude sessions persist their scrollback + session id to
~/.thinkpool-pair/<ROOM>/ and resume on restart (live context if recent),
so none of the above loses your place.
Your first agent runs attached — use it exactly like your normal terminal, every byte mirrors to the web. The web's "+ New terminal" spawns additional headless terminals here (same directory, same env), driven entirely from the room. One bridge, many terminals.
Run it in the cloud (remote host / VM / container)
The bridge connects outbound to Supabase — no inbound ports, no public IP, no tunnel. So a cloud VM, container, devcontainer, or remote dev box can stream its Claude Code into the room exactly like a laptop. Run the same command there:
export ANTHROPIC_API_KEY=sk-ant-... # headless auth (no Keychain login)
cd /path/to/your/repo
npx thinkpool-pair <ROOM> -- claude # structured Claude, no TTY needed- Auth: set
ANTHROPIC_API_KEY(orCLAUDE_CODE_OAUTH_TOKEN) in the box's env — the Agent SDK reads it automatically. The structured path runs the SDK's bundledclaude, so you don't need Claude Code separately installed. - No TTY required: the agent picker auto-selects and raw-mode is skipped when
there's no terminal, so it runs fine under CI / a service /
nohup. - Always-on:
npx thinkpool-pair install-service <ROOM> -- claudeinstalls a systemd--userunit (auto-restart + boot-persistent + auto-update). On a server, also runloginctl enable-linger $USERso it survives logout. - Security: anyone with the room code can drive the agent (shell-trust by design) — on a server that's a real shell, so treat the room code like a secret.
How it works
bridge.mjs ⇄ Supabase realtime (tpcode:<ROOM>) ⇄ web xterm:
bridge— announce: installed agents + live terminals.pty-out— terminal bytes (base64, per-terminal) → web clients render them.pty-in— keystrokes/prompts from the web → written to that terminal's PTY.term-open/term-close/term-exit— web-driven terminal lifecycle.replay-request/pty-replay— each terminal keeps a rolling ~120 KB scrollback buffer; joining/reloading clients get it replayed, so the room never opens blank while the bridge is up. Nothing is stored server-side — history lives exactly as long as the bridge runs.resize— web viewport size → headless PTYs only (the attached terminal follows your own TTY).
Public anon creds are embedded (the same ones the web app ships). Override with
TP_SUPABASE_URL / TP_SUPABASE_ANON if needed. Set TP_NAME to label yourself.
