{
  "markdown": "# vibeshare\n\nShare your live agent coding session by URL — traces.com-style, open source, CLI-first. Spectators watch read-only; invite links let viewers request to join as collaborators (host approves, live).\n\nPart of the **Vibe Suite** — companion tools for agentic coding CLIs (Claude Code, Codex, Gemini, Grok/pi, Kimi). Ships as **CLI + npm package + MCP server**, built on [`@pooriaarab/vibe-core`](https://www.npmjs.com/package/@pooriaarab/vibe-core) (consent ledger, hooks bus, badges).\n\n**Local-first: the share runs on your machine.** The consent ledger gates every share (`share:session` scope), the stream is served straight from your host, and nothing is stored on a server.\n\n## Works with any harness\n\nvibeshare shares a LIVE TERMINAL SESSION. It wraps a PTY, so the program inside is irrelevant — any agent CLI, shell, or TUI renders faithfully (colors, cursor, full-screen) via xterm.js in the browser.\n\n**Two ways to share a session:**\n- **Wrap at launch (no tmux):** `vibeshare --public -- <harness>` — vibeshare is the parent, PTY-captures. Examples: `vibeshare --public -- claude`, `-- codex`, `-- gemini`, `-- aider`, `-- opencode`, `-- kimi`, `-- amp`, or any shell/command.\n- **Attach to an already-running session (needs tmux):** run the harness inside tmux, then `vibeshare attach <pane>` taps it live. Harness-agnostic — it captures the terminal, not the app.\n\n**Verified harnesses** (all render the real TUI live): Claude Code (`claude`), OpenAI Codex (`codex`), Gemini CLI (`gemini`), aider (requires `pip install aider-chat`), opencode, Moonshot Kimi (`kimi`), pi (grok/glm), Sourcegraph amp (requires its own PATH setup). Others (Continue, Goose, Crush, Qwen, Cursor Agent, Warp, Zed, …) wrap identically — they're just terminal programs.\n\n| Need | Command |\n| :--- | :--- |\n| Share a new claude session | `vibeshare --public -- claude` |\n| Share a running session | Run it in tmux + `vibeshare attach <pane>` |\n| Local-only sharing | `vibeshare -- <cmd>` |\n\n*Modes:* `--public` (WebRTC P2P + e2e via getvibe.dev), `--tunnel <provider>` (12 providers, e2e), or local loopback/LAN. Presence + attributed chat included.\n\n## Demo\n\n[▶ Watch the launch video](branding/launch-video.mp4) — claude is multiplayer now.\n\nhttps://github.com/pooriaarab/vibeshare/raw/main/branding/launch-video.mp4\n\n## Install & build\n\n```sh\nnpm install\nnpm run build      # tsup → dist/ (cli.js, index.js, mcp.js + types)\nnpm run typecheck  # tsc --noEmit\nnpm test           # vitest\n```\n\n## CLI\n\n```sh\nvibeshare                        # share your shell, spectate read-only\nvibeshare --invite --expire 1h   # viewers may request to join; auto-expires\nvibeshare --pass hunter2         # passphrase second factor\nvibeshare -- npm test            # share a specific command\nvibeshare --host 0.0.0.0         # share on your LAN (default: loopback only)\n\nvibeshare viewers                # who's watching, pending join requests\nvibeshare viewers --approve <id> # promote a viewer to collaborator\nvibeshare viewers --kick <id>    # remove a viewer, live\nvibeshare stop                   # end the share (works from another terminal)\n```\n\nRunning `vibeshare` prints the link:\n\n```\n● local · no data out\n  sharing:  npm test\n  url:      http://127.0.0.1:50613/s/KKxzdjLpr_km\n  access:   spectate (read-only)\n  expires:  until you stop\n  manage:   vibeshare viewers · vibeshare stop\n```\n\nOpening the URL shows a self-contained spectator page (no install for viewers) streaming the session live over SSE, with a \"Request to join\" button on invite links. First run asks for consent (`--yes` to skip); the grant is recorded locally in `~/.vibeshare/consent.json` and can be revoked any time.\n\nRead-only is real: there is no route that lets a viewer write — the host is the server of record, and promotion to collaborator goes only through a host-approved request (`ViewerRegistry.canWrite()` is the single gate).\n\n## Reliable connectivity (TURN)\n\n`--public` shares are peer-to-peer with **STUN only** by default (free, no infra) — that works across most NATs. If viewers sit behind symmetric NATs or isolated networks and get stuck on \"waiting for host\", add a **TURN relay**: ICE config is set on the host and automatically propagated to viewers over signaling, so both ends use it.\n\nPrecedence, highest first:\n\n1. `--ice-servers '<json>'` CLI flag — a JSON array of RTCIceServer objects\n2. `VIBESHARE_ICE_SERVERS` env var (same JSON)\n3. `~/.vibeshare/config.json` → `\"iceServers\"` key\n4. default: `[{ \"urls\": \"stun:stun.l.google.com:19302\" }]` (STUN only)\n\n```jsonc\n// ~/.vibeshare/config.json — self-hosted coturn, or a provider\n// (metered.ca, Twilio, Cloudflare Calls TURN, …)\n{\n  \"iceServers\": [\n    { \"urls\": \"stun:stun.l.google.com:19302\" },\n    {\n      \"urls\": \"turn:turn.example.com:3478\",\n      \"username\": \"vibeshare\",\n      \"credential\": \"long-lived-or-temporary-secret\"\n    }\n  ]\n}\n```\n\nThe credentials are the host's own (short-lived tokens by convention); they travel over the signaling channel to viewers so the browser can reach the relay. Malformed flag/env JSON is reported and skipped — resolution falls through to the next source, never breaking the share.\n\n## npm library\n\n```ts\nimport { createShare, grantConsent } from 'vibeshare';\n\ngrantConsent('share from my tool');              // once; local ledger\nconst { url, feed, viewers, revoke } = await createShare({\n  session: 'npm test',\n  access: 'spectate',                            // or 'invite'\n  expiry: '1h',                                  // or 'stop'\n});\n\nfeed.publish('tests starting…');\nviewers.on('request', (v) => viewers.approve(v.id));\nawait revoke();\n```\n\n`createShare` throws `ConsentRequiredError` without a `share:session` grant. Bring your own plumbing with `ShareManager`, `LocalHttpTransport`, and `FileConsentStore`.\n\n## MCP server\n\n```json\n{\n  \"mcpServers\": {\n    \"vibeshare\": { \"command\": \"vibeshare-mcp\" }\n  }\n}\n```\n\nTools: `vibeshare_create`, `vibeshare_viewers`, `vibeshare_stop` — so an agent can offer \"share this session?\". Your MCP client's tool-approval prompt is the consent act (recorded with that note). Approving *join requests* stays human-only, via the CLI.\n\n## Architecture & the vibelive seam\n\nvibeshare owns the **link + gate**; session content is an ordered feed served to spectators. The one deliberate seam is transport (`src/transport.ts`):\n\n- **`LocalHttpTransport`** (implemented, default): spectator page + SSE stream + loopback host-control API, served from your machine. Nothing stored on a server.\n- **`RelayTransport`** (lands with vibelive): a dumb e2e relay / p2p mesh handing out public `vibeshare.io` URLs — same `ShareTransport` interface, swap-in only. Collaborator input routing is part of that seam and must pass `ViewerRegistry.canWrite()`.\n\nEverything else — consent, access policy, passphrase gate, expiry teardown, viewer registry, revocation — is fully implemented and tested.\n\n## Prototype\n\nThe original UX prototype (no build, no network): open [`docs/prototype.html`](docs/prototype.html). Spec: [`docs/spec.md`](docs/spec.md).\n",
  "bytes": 7066,
  "sha": "e43f88347aa447f240885a835a49edce831d3ea7e814c4fdcb03258b275a5814",
  "repo_slug": "pooriaarab/vibeshare",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_pooriaarab_vibeshare_live_7d2a0211/readme"
}