A Figma-style multiplayer review canvas for AI-generated code.
Comment, compare, and ship the changes Claude Code (and other agents) just wrote — without leaving the canvas.
Quick start · Demo · Architecture · Deep wiki · Roadmap
The bottleneck in software development has shifted. With Claude Code and similar agents, writing variants is cheap and fast — but reviewing them, comparing them, commenting on them, deciding which to ship, and getting changes made is still stuck in text-first tools designed for an era when humans wrote every line.
Today, AI codegen output leaks out of the developer's terminal into Slack, Loom, screenshots dropped into Notion, and Figma comments about implementations the designer can't actually run. Foldo closes that loop.
It is the missing review surface for a world where most code is written by agents and the human's job is to direct, compare, and approve.
The name comes from fold — the point where two things meet (branches folding together at merge), the act of revealing hidden state (a foldout), and a familiar software metaphor (code folding). The product folds parallel AI-generated work back into a single spatial surface where humans can see it all at once.
- Developers running Claude Code (or any AI coding agent) who currently triage variants in their terminal — opening preview URLs one by one, switching branches, losing context.
- Everyone who reviews what agents built but doesn't run code locally: PMs, designers, founders reviewing contractor work, engineers reviewing teammates' AI-assisted branches. Today these people are locked out of the review loop.
Foldo turns the linear shuffle into a spatial canvas with live, interactive frames — so any reviewer can pin a comment, request a change in natural language, and watch the agent ship a new commit.
And every reviewer on the canvas is still a proxy for the real user — so Foldo now also gathers evidence from real users, not just internal eyes. With User Tests, real people record screen+voice sessions against your build and the results land as frames you can comment on: the build → real users → evidence → fix loop, closed without leaving the canvas.
- 🎬 User Tests — publish a short
foldo.dev/t/:tokenlink, real users record screen+voice sessions completing your tasks, and the results — recording, per-task outcomes, questionnaire answers, transcript, AI synthesis — stream back onto the board as frames. Three auto-detected delivery modes (iframe,handoff,dom_snapshot) cover everything from an embedded app to a localhost-only build. - 🎙️ Evidence, not proxies — each session lands as a scrubbable
test_sessionframe clustered under atest_summarywith per-task completion stats; Claude synthesizes a summary + extracted issues, and every issue carries a "Make this an edit" button straight into the dispatch pipeline. - 🖼️ Live app frames — every frame is an iframe of the actual running app at a specific commit, navigated to a specific reproducible state (modal open, form half-filled, recipe-replayed).
- 📄 Markdown frames — PRDs, ADRs, READMEs render side-by-side with the code that implements them.
- 💬 Pinned comments with replies, resolve, and "Make this an edit" → turn any thread into a structured Claude Code prompt.
- ⚡ Streaming edit dispatches — your comment flows back to local Claude Code via an MCP server; new frames appear on the canvas with connector lines to their parent as the agent works.
- 👥 Multiplayer: live cursors, presence avatars, selection ghosts, follow-me viewports — Figma-grade real-time over plain WebSockets.
- 🔗 Deep-linkable URLs — every board, frame, and comment is shareable. Paste in Slack → open at the exact state.
- 📸 Chrome extension — capture any deployed URL (Vercel preview, staging, localhost) into a Foldo frame without running the MCP.
- 🎛️ GitHub-aware — webhook receiver auto-creates frames for every push; agent-authored branches carry a bot badge.
git clone https://github.com/lukataylo/foldo.git
cd foldo
npm install
npm run devThis boots three services concurrently:
| Service | URL | Description |
|---|---|---|
| Web canvas | http://localhost:5173 | The Foldo canvas you actually use |
| Cloud server | http://localhost:4000 | REST + WebSocket + SQLite |
| Sample app | http://localhost:5174 | The "user's running app" rendered inside frames |
Open the canvas at http://localhost:5173 and you'll land on board-acme-landing — a seeded board with three branches (one baseline, two AI-generated) and four pre-pinned comments.
To plug in the in-directory MCP server (so dispatches go through real tool execution rather than the in-process simulator):
npm run dev:mcpTo build the Chrome extension for unpacked install:
npm run build:extension
# then chrome://extensions → Developer mode → Load unpacked → apps/extension/distThe headline 30-second tour that proves the value:
- Open http://localhost:5173 — the canvas loads with three rows (
main,feat/cta-revamp,feat/pro-tier-highlight). - Scroll down to the
feat/cta-revamprow and click the orange pin on the CTA button — Anna left a comment: "Button still doesn't name the trial duration — spec says it has to." - Click "Make this an edit" — the right-side edit panel opens with a structured prompt pre-filled (branch, commit, file, line, element, the recipe to reach this state, current source, and Anna's text as intent).
- Click "Send to Claude Code" — a streaming run log shows
sending → running → doneas the agent replays the recipe, applies the edit, and pushes a new commit. - A new frame appears to the right with a curved connector line back to the parent. The CTA now reads "Start your 14-day free trial" and a no-credit-card line sits beneath it.
- Open a second browser and pick a different demo user (top-right user switcher → "Mateo Rivas"). The two windows now see each other's cursors and selections live.
[More demo paths — Pro tier flow, Capture from URL, follow-me — in docs/DEMO.md].
Foldo is a TypeScript monorepo with five workspaces and a shared protocol package:
+----------------------+ +----------------------+
| Browser canvas | REST + WS | Cloud server |
| apps/web :5173 | <--------------> | apps/server :4000 |
+----------+-----------+ +----------+-----------+
| |
| iframe | WS /ws/mcp
v v
+----------+-----------+ +----------+-----------+
| Sample app | | In-dir MCP server |
| apps/sample-app:5174 | | apps/mcp |
+----------------------+ +----------+-----------+
^ stdio
|
+--------+---------+
| Claude Code |
+------------------+
Chrome extension (apps/extension)
|
v POST /api/captures
| Workspace | Tech | Role |
|---|---|---|
apps/web |
Vite · React 18 · Tailwind | The user-facing canvas. Multiplayer cursors, presence, URL routing, comment threads, dispatch panel, live iframes. |
apps/server |
Fastify · @fastify/websocket · better-sqlite3 |
REST + two WS endpoints (/ws for browsers, /ws/mcp for agents). Brokers dispatches; simulates in-process when no MCP is attached. |
apps/sample-app |
Vite · React 18 | Standalone pricing app rendered inside every app frame's iframe. Three variants. postMessage protocol for element selection + recipe replay. |
apps/mcp |
@modelcontextprotocol/sdk · ws |
Local Node process exposing foldo_freeze_current_state, foldo_replay_recipe, foldo_apply_edit_prompt, foldo_list_branches to Claude Code over stdio, bridging to cloud over /ws/mcp. |
apps/extension |
Vite · @crxjs/vite-plugin · Manifest V3 |
Chrome extension for capturing any deployed URL into a Foldo frame. Service worker, content scripts, popup. |
packages/protocol |
TypeScript types only | Single source of truth: domain model, WS message protocol, REST schemas, MCP tool schemas. Imported by every workspace. |
The shared protocol is what keeps the five components honest: every wire message and every REST shape is declared once in packages/protocol/src/ and imported by everyone.
For a deeper dive: docs/ARCHITECTURE.md.
Live multiplayer is built on a single WebSocket per browser tab:
- Cursors — throttled to ~33 Hz per sender, smoothly interpolated on receivers, counter-scaled to stay constant size at any zoom level.
- Presence avatars — top bar shows everyone currently on the board. Hover to follow, click to lock follow-me.
- Selection ghosts — when another user selects an element, you see a dashed outline in their color with a name tag.
- Follow-me viewports — viewport updates broadcast over WS so a presenter can drag everyone along.
- Comments + replies sync live across browsers; resolve toggles propagate instantly.
The cloud's WS hub is an in-memory pub/sub abstracted to be Redis-swappable for multi-instance scale.
When a reviewer hits Send to Claude Code, the cloud creates a Dispatch record and:
- If a local MCP server is connected for that board → routes the dispatch over
/ws/mcp. The MCP runs the heuristic-driven edit (in prototype) or shells out to the realclaudeCLI (in production), replays the recipe to verify state, commits, pushes, and reports a new frame. - If no MCP is online → simulates the same lifecycle in-process so the demo works solo.
Either way, the browser sees the same dispatch.status stream and the same frame.added event with a connector line drawn back to the parent.
Hook your own MCP server in by adding to your Claude Code settings.json:
{
"mcpServers": {
"foldo": {
"command": "node",
"args": ["/absolute/path/to/foldo/apps/mcp/bin/foldo-mcp.mjs"]
}
}
}Details: docs/MCP.md.
You don't need the MCP or the Chrome extension to evaluate Foldo:
npm install && npm run dev- Open http://localhost:5173 in two browser windows
- Pick different demo users via the user switcher (top-right)
- Drop comment pins, send dispatches, watch the canvas converge in real time
If the server isn't running, the canvas falls back to a fully-functional offline demo using local mock data.
foldo/
├── apps/
│ ├── web/ # The canvas (Vite, React, Tailwind)
│ ├── server/ # Fastify + better-sqlite3 + WS
│ ├── sample-app/ # The user's "running app" — iframed
│ ├── mcp/ # @modelcontextprotocol/sdk in-dir agent
│ └── extension/ # Chrome MV3 capture-from-URL extension
├── packages/
│ └── protocol/ # Shared types: domain, WS, REST, MCP
├── docs/ # Deep wiki
└── scripts/ # WS multiplayer + dispatch smoke tests
| Doc | What it covers |
|---|---|
| ARCHITECTURE.md | Component boundaries, data flow, ports, scaling notes |
| PROTOCOL.md | REST endpoints, WS messages, MCP tool schemas, postMessage bridge |
| MCP.md | Running the MCP server, wiring it to Claude Code, env vars, tool semantics |
| EXTENSION.md | Building, loading, and configuring the Chrome extension |
| DEMO.md | Full walkthroughs of every demo path with screenshots |
| DEPLOYMENT.md | Putting Foldo on a real server: Postgres, Redis, GitHub App, auth |
- Language: TypeScript 5.6 (strict)
- Frontend: React 18, Vite 5, Tailwind CSS 3
- Backend: Node 20, Fastify 5,
@fastify/websocket, better-sqlite3,nanoid - Realtime: plain
wsover a single WebSocket per board; throttled cursor broadcasts; debounced viewport updates; ping/pong heartbeat with reconnect-backoff - Agent integration:
@modelcontextprotocol/sdkfor Claude Code interop,simple-gitfor repo ops - Browser extension:
@crxjs/vite-pluginfor Manifest V3 - No state library (a 200-line Map-based store +
useSyncExternalStore) - No router library (the History API + a tiny
parseRoute/buildPathpair)
- User Tests (Phases 1–4) — shipped 2026-05-14. Unmoderated UX testing folded into the canvas: public
foldo.dev/t/:tokenlinks, three delivery modes, screen+voice recording, results-as-frames, pluggable transcription + Claude synthesis, S3/R2 storage, range playback, rate-limited public endpoints. Design doc: docs/UX_TESTS.md - Real transcription provider — swap the honest stub for a real speech-to-text provider behind the existing env-var hook
- Production object-storage wiring — promote the S3/R2 recording path from config-ready to deployed (buckets, lifecycle rules, signed URLs)
- Real Claude Code dispatch — shell out to the
claudeCLI fromapps/mcp/src/runner/editSim.tsinstead of inferring overrides - Headless Playwright frame capture — real screenshots + DOM at a commit via
apps/mcp/src/runner/playwright.ts - Postgres + Redis for multi-instance —
apps/server/src/db.ts(Postgres) +apps/server/src/ws/hub.ts(Redis pub/sub) - GitHub App — production webhook with signature verification, OAuth login
- Frame dragging — the API exists (
POST /api/frames/:id/move); UI affordance pending - Comment edit-in-place & delete — REST endpoints exist; CommentPopover affordance pending
- Real recipe verification — Playwright replay to confirm an edit landed at the correct state before reporting
done - Bigger boards — virtualize the frame list; lazy-mount iframes are in; viewport culling pending
Issues and PRs welcome. Each workspace owns its dev, build, and typecheck scripts; npm run typecheck at the root runs the whole suite. Smoke tests in scripts/ exercise the multiplayer round-trip and the dispatch lifecycle.
MIT — see the LICENSE file.
ai code review · claude code · multiplayer canvas · figma for code · agent code review · mcp server · model context protocol · pr review tool · pull request review · visual git diff · branch comparison · llm code review · developer collaboration · code review platform · live preview review · chrome extension capture · figma-style review · real-time review · pair programming with ai · unmoderated ux testing · user testing · usability testing · session recording · screen recording · user research
Built as a demo of what review tools look like when most code is written by agents.
Branding inspired by the dachshund — small, focused, low to the ground.
