Whiteboards

Create, search, edit, and render durable Excalidraw boards through client.whiteboards.

client.whiteboards is the typed namespace over the host's whiteboards RPC — the same boards the desktop tab, the CLI, and scratchpad embeds use. See Whiteboards for the user-facing tour.

const board = await client.whiteboards.create({
  worktreeId,
  title: "Request flow",
  scene: { type: "excalidraw", version: 2, elements: [], appState: {}, files: {} },
});
// Whiteboard { id, worktreeId, title, scene, version, createdAt, updatedAt }

const boards = await client.whiteboards.list({ worktreeId });
const hits = await client.whiteboards.search({ worktreeId, query: "gateway" });
const one = await client.whiteboards.get({ worktreeId, id: board.id });

search matches titles and the scene's text elements. Every id-based call also takes the worktreeId — boards are worktree-scoped and a mismatched pair is rejected.

Edit

const next = await client.whiteboards.edit({
  worktreeId,
  id: board.id,
  title: "Request flow v2",
  scene: revisedScene,
  version: board.version,
});

Edits are optimistic: the version you pass must still be the stored one, so a concurrent writer fails the call instead of losing work. Re-get, reconcile, retry. Scenes are stored losslessly — preserve fields you don't understand rather than dropping them.

Render

const png: Uint8Array = await client.whiteboards.view({
  worktreeId,
  id: board.id,
  dark: true, // Excalidraw's dark export palette
});

The host renders natively and the client decodes the response's base64 data into PNG bytes for you.

Delete

await client.whiteboards.delete({ worktreeId, id: board.id });

Nothing warns you that a scratchpad embeds the board, so check before deleting one.

Scene and input types (Whiteboard, ExcalidrawScene, WhiteboardCreateInput, …) come from @pragma-sh/constants and are re-exported by the SDK, so TypeScript and Rust agree by construction.

On this page