Skip to content

Whiteboard

A desktop app that puts an agent and a person on the same canvas: the agent draws the review — sequence diagrams, entity relationships, code peeks pinned to specific commits — and every shape on that canvas links back to the code it was drawn from.

Screenshot of Whiteboard
Editor screenshot, 1 Oct 2026Whiteboard ↗

What it is

A desktop application where a coding agent and a person work on the same canvas. The agent connects over MCP — one shared whiteboard mcp launch serves Claude Code, Codex, Cursor, Pi and OpenCode — and draws what it did: sequence diagrams, an entity relationship diagram, a C4 software map, call-stack diffs, code peeks and quotes pulled from its own trace. The canvas is not free drawing. It is a document of typed blocks, fourteen kinds, each able to carry a source anchor written as head/path#L10-L24, and every anchor is validated against the commits the review is pinned to, so clicking a box in a sequence diagram opens the file it came from inside a vendored Code OSS editor with LSP and keybindings. A semantic, AST-aware diff viewer written in Rust collapses the noise — large added functions are summarised as pseudocode, test and documentation changes are hidden — and a review can be shared to another machine. The repository is six weeks old: created 2026-08-18, 575 commits, 2,400 stars, sixteen releases, MIT.

Who built itThe repository sits under the devdotfast organisation and the commit record is dominated by one account: thesiti92 wrote 292 of its 575 commits and is the author of almost every pull request in the sample, followed by ketan0 with 128 commits — 116 under the name Ketan Agrawal and 12 more under a second account listed separately — Sidharth Menon with 55 and Milan Bhandari with 35. Eleven accounts appear in the contributor list, two of them bots. The recon report carries no profile for the owner — no display name, join date or repository count — so nothing beyond the commit record is claimed here.

How it is put together

The parts · 6

Whiteboard is a desktop application wrapped around a document format, and most structural choices follow from that. The format is a list of typed blocks — a sequence diagram, an entity relationship diagram, a C4 software map, a code peek, a call-stack diff, a quote from the agent’s trace — and those blocks are what an agent writes over MCP while the app is what a person reads. Because a block carries a source anchor pinned to a specific commit, a review is not a snapshot of a diff but a set of claims about code, each one checkable when written and re-checkable when the pins move, which is why so much of the codebase is anchor validation, pin resolution and repin reporting. Underneath sits a vendored Code OSS fork: the editor, the language servers and the keybindings are inherited rather than rewritten, because the app is a reader of code first and an editor second. The two surfaces are then budgeted differently — the agent-facing tool catalog is a character budget that gets spent and reclaimed in public, and the canvas is a layout whose cost is measured in milliseconds per open.

packages/review/
693 files and 8.7 MB, the product itself: app/src is the React canvas and reader, src/review-api is the document, store and tool layer, src/server the headless and desktop hosts, src/sharing the review-sharing path, src/review-import the legacy import pipeline, and src/fixtures the block fixtures and four schema-4 legacy reviews kept as golden files.
packages/review/src/review-api/blocks/
Fourteen block kinds, one file each, from sequence and flow_diagram through database_lens, software_map, code, code_peek, call_stack_diff and trace_quote to markdown, callout, divider, image, section and tutorial, plus a shared definition.ts, an index.ts that registers them and an ids.ts for identity — the vocabulary an agent is allowed to draw with.
packages/review/app/src/software-map/
The largest single feature: SoftwareMap.tsx at 104 KB, c4-layout-geometry.ts at 83 KB, c4-projection.ts at 28 KB, edge-label and node measurement, keyboard navigation, snapshot and resolved-data modules, a hotkeys tab, and a separate absence state for reviews that have no map.
apps/review-desktop/
6,534 files and 88 MB, dominated by the vendored Code OSS fork with its UPSTREAM manifest, wrapped in packaging for macOS, Windows, Arch, RPM and DEB, plus an end-to-end suite of twenty-one recorded journeys and a 16 KB known-bugs document.
The side packages
local-vcs (git and jj plumbing, 60 KB of it), trace-core (agent trace capture, hooks, hosted and S3 storage), trace-protocol, review-protocol (a 42 KB contracts file), review-share-protocol, json, and agent-plugins, which carries connect metadata for Claude, Codex, Cursor and Pi. Each is separately versioned, which is how the diff viewer, diffr, can live in its own repository and still be pinned here.
Tooling and documents
tools/oxlint/anti-slop is a custom lint plugin with eighteen rules plus an Effect-specific one and a canvas-styles plugin, covering array chaining, chained type assertions, dictionary types, unknown parameters and returns, module mocking and mandatory safety comments for assertions. docs/telemetry.md is 49 KB and docs/privacy.md 9 KB; AGENTS.md is 373 bytes, CONTEXT.md 234 and CLAUDE.md 11. Seven workflow files drive CI and release, the largest at 38 KB.

Choices, and what they beat

  • Vendor Code OSS instead of maintaining a patch set over a fork that carries patches against upstream VS Code

    The README gives two reasons. Editing is no longer the job — with agent terminals and desktop apps doing the writing, a text editor is used mainly for reading diffs line by line — and patching would be the wrong shape for this project, because “coding agents have a hard time with patches”. Vendoring also drops what it calls about 45% of the stock codebase being Copilot, at the cost of merging upstream security and feature changes by hand.

  • Publish the edit schema as an open object, keep the host parser strict over spelling out every block kind in the schema agents see

    Pull request 820 measured the old published schema at 25,424 characters, over half of the whole tool catalog, and it still needed $ref for sections that nest blocks. The published version is now generated by the same function as the schema the host enforces, so the two operations cannot drift apart, nothing about what is accepted or stored changed, and because the client no longer checks shapes the type discriminator had to be added so an error names the offending block kind instead of a bare invalid-input message.

  • Stop advertising software-map uploads to agents over leaving the software-map model in the tool catalog

    That one upload kind carried about 196k of the 253k characters of tool definitions every agent loads. Software maps are off by default and expected to return in a different form, so the agent-facing tool now lists image and trace uploads only and the catalog drops to about 58k characters — while the host keeps accepting map uploads, so nothing a caller already does stops working.

  • Load the layout engine on the first layout over shipping it eagerly with the canvas

    ELK is 1.4 MB, about half of the 2.5 MB canvas bundle, and the C4 geometry module built an instance as soon as it was imported — so a review with no diagram paid anyway. Measured in Chromium, a canvas open went from 130 ms to 50 ms; reviews that do have a diagram pay the same cost as before, just later.

  • Warn about moved pins only for anchors in files that changed over warning for every retained source range

    A rebase onto a newer main flagged all 31 anchors across three reviews even though main had not touched any of their files, which made a genuine change under a link indistinguishable from the noise. The narrow version needed the files-changed-between provider that the previous scaffold had, and it kept the loud behaviour for the cases where the two commit sets cannot be compared at all.

  • Ship only English Chromium UI translations over shipping all roughly 220 locale folders

    About 48.8 MB of *.lproj inside the macOS framework, plus locales/*.pak on the other platforms, for an interface that is English only. Three exclude patterns in one already-divergent build file cover all three platforms, and the one visible consequence is stated rather than discovered: Chromium’s own strings, such as native context menus, are always English.

  • Publish identifiers as keys rather than as UUIDs over declaring them in UUID format in the schema agents read

    As z.uuid(), commandId and leaseId were emitted as a format plus a 250-character pattern — 19 copies, about a fifth of all tool schema text — for values the host only ever uses as keys, a receipt’s and a lease’s. They are now plain non-empty strings like the other identifiers, while upload ids stay UUIDs because the agent invents them and the host keys stored images and traces by them.

Read frompackages/review/src/review-api/blocks/*, packages/review/instructions/*, packages/review/README.md (6,674 bytes), packages/review/src/review-api/README.md (25,467 bytes), the packages/review/app/src/software-map/ module list, apps/review-desktop/scripts/linux/ARCH.md, AGENTS.md, docs/telemetry.md and docs/privacy.md, the README (6,581 bytes, retrieved in full through the GitHub API), and the bodies of thirty issues and pull requests.

Build log

6 stages
  1. 01

    Six weeks, an import, a rename, and a preview channel

    The repository was created on 2026-08-18 and its oldest commit, twenty-six minutes later, is titled Import Review Desktop — which is where the naming history starts. The month breakdown is lopsided: 56 commits in August and 519 in September. Eleven accounts appear as contributors and one dominates: thesiti92 with 292 commits, then ketan0 with 128 — 116 commits under the name Ketan Agrawal plus 12 under a second account the report lists separately — Sidharth Menon with 55, Milan Bhandari with 35, dependabot with 32, a GitHub Actions bot with 18 and a detail-app[bot] with 11. 125 commits carry a co-author trailer, and 64 of those name a model: Claude Opus 5.5 (1M context) 35 times, Claude Opus 5.5 14 times, Claude Fable 5.1 11 times and Claude Opus 5 (1M context) 4 times. Sixteen releases and twenty tags sit in the same six weeks. The release titles still carry the rename: review-desktop-v0.0.23 on the day the repository appeared, Review Desktop 0.1.3 on 2026-09-26, and Whiteboard 0.1.5 on 2026-09-28, the first release under the current name. Beside them run preview tags with a date and a build number, v0.0.34-preview.20260924.56 through v0.1.6-preview.20260929.79, which is a channel that ships rather than a version line that waits.

  2. 02

    The canvas is not boxes and arrows, it is fourteen typed blocks

    The block definitions live in packages/review/src/review-api/blocks/, one file each, and there are fourteen of them: sequence, flow_diagram, database_lens, software_map, code, code_peek, call_stack_diff, trace_quote, markdown, callout, divider, image, section and tutorial. Each has a JSON fixture under fixtures/blocks/, a shared definition.ts, a 2,375-byte index.ts and an ids.ts for identity. So this is a document format with a fixed vocabulary rather than a drawing surface. A sequence block is backed by sequence-steps.ts. The software map is a C4 model, with c4-projection.ts at 28 KB, c4-layout-geometry.ts at 83 KB, c4-node-measurement.ts and c4-edge-label-geometry.ts layered over an ELK layout, and a 104 KB SoftwareMap.tsx renderer. database_lens is the entity relationship diagram, with a 36 KB renderer, a 4.3 KB schema and its own store. section is the one that nests: pull request 820 records that its schema needed $ref for sections nesting blocks. The drawing half lives in packages/review/app/src, where diagrams.tsx is 36 KB, trace-document.tsx 36 KB, flow-graph.tsx 23 KB and blocks.tsx 12 KB — and the README gives the reason: clicking a sequence diagram, an entity relationship diagram or a quote from the agent’s trace jumps straight to the underlying code, with keybindings and LSP from the vendored editor.

  3. 03

    An anchor is a claim about a commit, and a repin can drown it

    Every block that points at code carries a source anchor, and the anchor is the load-bearing part of the format. As agents wrote it before 2026-09-30 it was an object, {file, start: {side, line}, end: {side, line}, pins?}. Pull request 821 replaced that with the strings an agent already knows how to write for a markdown link: head/path#L10-L24, base/path#L7, and GitHub’s diff-anchor form diff/path#L84-R90 when a range crosses sides. The host parses them into the same selection object as before, so storage and the canvas are unchanged, and the object form is still accepted from tests, the tutorial and older callers. A string cannot carry pins, so blocks with anchors take a block-level pins, as markdown blocks already did, and an anchor is validated against the pinned commits when it is written. Pull request 822 is about what happens when those pins move: a repin warned for every retained range even when its file was byte-identical at the new commits, so a rebase onto a newer main flagged all 31 anchors across three reviews, none of whose files main had touched, and a real change under a link read exactly like the noise. The host now asks which files changed between the old and new commits on each side, through a filesChangedBetween provider backed by local-vcs, and warns only for anchors in those files; ranges that fail validation at the new pins still always report.

  4. 04

    An agent interface measured in characters

    The agent surface is a tool catalog whose size is a design variable, and the pull requests state the cost in characters. Pull request 819: session_upload’s map kind carried the whole software-map model schema, about 196k of the 253k characters of tool definitions every agent loads; because software maps are off by default and expected to come back in another form, the agent-facing tool now offers image and trace uploads only — the catalog drops to about 58k characters — while the host still accepts map uploads. Pull request 820: session_edit’s published schema spelled out every block kind and needed $ref for nested sections — 25,424 characters, over half the catalog — so agents now see content as an object that names its type from a list, with the per-kind fields moved into the tool description, one line each; the host still parses the full editSchema, so what is accepted is unchanged, and both schemas come from the same function. Pull request 825, still open, would delete the tools that read code, since an agent can only reach Whiteboard from the machine that holds the repository, where git or jj reads the same commits anyway; what they enforced lives in four files under packages/review/instructions/.

  5. 05

    Community rounds: a package conflict, a line-ending bug, a roadmap

    Two of the three outside bug reports in the sample are packaging and rendering faults, and both were answered the same day. Issue 802, from LeFelps: installing from the signed pacman repository aborts because the package ships /usr/bin/review, which archlinux-contrib also owns. The maintainer replied twenty-nine minutes later — “just an alias right now, the main cli moved to whiteboard” — and pull request 806 then removed the review and review-preview aliases from Arch, RPM and DEB at once, adding “glad we renamed lol”. Issue 805, from mhebert-inkbit, arrived with a reproduction: on Windows with core.autocrlf=true, a CRLF checkout was compared raw against LF blobs, so Markdown showed every line as changed. The cause was in the Rust diff viewer, a separate project pinned here as @dev.fast/diffr: version 0.1.8 reads working-tree files through Git’s clean filters, and the same file measured 200 changed lines on 0.1.7 and one on 0.1.8. Two smaller outside contributions sit in the sample: issue 796, that Find in the hybrid board-and-diff view is slow, and pull request 794, from KappaShilaff, widening a panel resizer’s grab area to 26px. The project also published a roadmap: ROADMAP.md in pull request 811, linked from the README in 813, then moved to a wiki page, with a comment noting the notifications had been checked off.

  6. 06

    Performance as a stated number, and subtraction as a habit

    Performance here is measured and written down, and the pull requests carry the numbers. Pull request 799: ELK, elkjs/lib/elk.bundled.js at 1.4 MB, was about half of the 2.5 MB canvas bundle, and c4-layout-geometry.ts constructed an instance when the module loaded, so every canvas open paid for a diagram it might not have; a new src/elk.ts exposes a loadElk() that imports it once and caches one shared instance, which measured 130 ms down to 50 ms per canvas open in Chromium when the review has no diagram. Pull request 809: Find on a whiteboard with code peeks searched every peek on every keystroke and recomputed each structural diff, where utf16Column allocated a TextEncoder per character — roughly 480 ms of each 526 ms peek search — so peeks are now searched once typing pauses for 150 ms; the typing journey went from 5,970 ms with the renderer blocked for 5,493 ms to about 515 ms and 100 ms blocked. Pull request 808 is the one worth reading twice: about 250 tests, roughly 4.4k lines across 109 files, were deleted as change-detector, tautological or redundant, keeping only source-scan invariant guards for repository identity, UI-state storage, transport boundary and vendor integrity; the 373-byte AGENTS.md tells contributors to delete such a test rather than update it.

Adjacent records

All records →