hiw3c AI 日报
Hacker News Top 网页快照

Drawgent:实时Excalidraw画布上的编码代理

原文标题 · Drawgent: Coding agent on a live Excalidraw canvas

HN Ÿ 98 · 32 评论

来源:Hacker News Top · tangled.org

正文为英文,可一键机器翻译(仅首次需要等待)

Configure Feed

Select the types of activity you want to include in your feed.

Configure Feed

Select the types of activity you want to include in your feed.

Clone this repository

For self-hosted knots, clone URLs may differ based on your setup.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

Bottom-left of the canvas: each gesture drawn as a small red stroke with its meaning; collapses to a Gestures button, remembered in the browser. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

- Laser gestures (canvas/gesture.rs): dots (taps are kept now), crosses, arrows (one stroke or shaft + head), lines, check marks, circles, circle + arrow (move), strikes (zigzag, scribble or a line through an element) and double arrows (more room). Each is tied to the elements at its ends; a strike carries what deleting would break (dangling arrows, flows to bridge, gaps to close, frames, code links). The zone chip shows them, the agent prompt explains them. - delete_elements reconnect: drops attached arrows and bridges flows (A -> X -> B => A -> B). - make_space: pushes the diagram at a point apart along an axis (other diagrams stay), grows frames and areas that span it; bound arrows follow. - Undo: agent edits are journaled per agent and turn (canvas/history.rs). undo_changes (last edit or turn), POST /api/undo, and an Undo button under turns that changed the canvas; elements a human changed since are kept. Browsers put agent edits on their undo stack (Ctrl+Z), laser traces and markers excluded; shortcuts are handled globally. - Workspace files come from the ignore crate: .gitignore at every level, info/exclude and the global gitignore, with or without git, also for tracked-then-ignored files (repo map, Code tab, search). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

- check_layout (canvas/lint.rs): geometry lint for overlaps, labels overflowing or broken mid-word, arrow labels too long / on shapes, arrows through shapes or clipped by their frame, fonts under 14, low contrast, near-misalignment and crowding; most issues carry an update_elements patch. Edit replies include the issues they introduce. - add_graph (canvas/autolayout.rs): nodes, edges and groups placed by a layered layout (cycle breaking, longest-path ranks, dummy bends, barycenter ordering, one band per group drawn as a frame). Arrows between frames are no longer put in one frame (it clipped them); update_elements takes frameId. - get_scene returns only what changed since the session's last read (the agent's own edits are not repeated); full: true for everything. - Screenshots default to 1000 px (max_size to change it) and element_ids crops to the area. - Chat panel: tokens, context window and cost under each turn, from ACP usage_update and the prompt result. ACP responses now travel behind earlier notifications so a turn's last updates arrive before its end; permission requests no longer block the pump. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Boards, diagram files, code links, build and pointing now live in the role folders: canvas/{boards,build,diagram}.rs, code/{mod,repomap}.rs, cli/check.rs. Agents report board-scoped zone clears through the event channel; the scene's progress markers go through the Layout trait. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

- cli/ (setup, attach, up), sync/ (hub, server, room), agents/ (mod, acp, opencode, codex), canvas/ (scene, el, geometry, fractional), render/ (renderer, chrome); config.rs and mcp.rs stay at the root. - main.rs only parses the CLI; up/serve/run_server move to cli/up.rs. - live.rs is split into agents/opencode.rs and agents/codex.rs. - agents no longer call into the hub: they send agents::Event (chat, statuses, handled zones) on a channel the hub forwards, and share the scene with it. - scene no longer imports the renderer: it asks a canvas::scene::Layout, which render::Renderer implements. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

A drawing_guide tool (called once per session, per the protocol) with colours by role, background zones, sizes, layout rules and the common mistakes to check in screenshots; adapted from excalidraw/excalidraw-mcp's read_me (MIT), keeping only what applies to a live canvas (no camera, streaming or checkpoints). The palette moves out of add_elements' description. Measured with Claude on the same request: a first version made label fonts smaller and invited labels on short arrows; after tuning (default label size, label arrows only when meaningful and long enough, keep connected shapes aligned) both runs had no small text, no label collisions and no overlaps, plus titles, layer zones and consistent role colours. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

drawgent: your coding agent on a live Excalidraw canvas #

drawgent connects your own Claude Code, Codex or opencode (your install, login, config and repo) to an Excalidraw whiteboard. Ask for a diagram in the chat panel, or write AGENT: … next to the part of a drawing you want changed. The agent looks at the canvas (screenshot + scene), edits it live, checks the result, and marks the note DONE .

How it works #

Quick start #

Prerequisite: one of claude , codex or opencode installed and logged in. The Claude and Codex bridges also need Node.js ≥ 22 with npm (the Claude adapter requires it; setup warns below that).

drawgent setup claude # once per agent: claude | codex | opencode cd ~/my-repo drawgent up # new agent session in this repo + canvas in your browser drawgent up --attach # or: pick one of your running sessions and connect the canvas to it

Demo #

drawgent setup <agent> #

Checks everything once, fails with the exact fix when something is missing, and writes ~/.config/drawgent/config.toml :

The agent CLI. Your claude / codex / opencode on PATH.

Login. claude auth status , codex login status or opencode auth list .

ACP bridge. opencode speaks ACP itself ( opencode acp ).

Claude Code and Codex use the official ACP adapters. They are installed once into ~/.cache/drawgent/adapters (~60 MB), without their bundled agent binaries, and pointed at your CLI ( CLAUDE_CODE_EXECUTABLE , CODEX_PATH ).

Setup then verifies the ACP handshake.

Canvas tools for attached sessions. Only Codex needs a change: codex mcp add drawgent -- drawgent mcp . Claude and opencode get the tools at attach time.

Headless Chrome for the renderer. Setup uses your Chrome/Chromium if you have one. Otherwise it proposes: downloading Chrome Headless Shell (Chrome for Testing, ~120 MB, no sudo) into ~/.cache/drawgent/chrome , and telling you exactly which system libraries are missing, if any;

installing Chromium with your package manager ( apt , snap , dnf , pacman , zypper , apk , brew , or nix without sudo).

Non-interactive: --chrome download | system | /path/to/chrome .

drawgent up refuses to start until setup succeeded for that agent, or if something setup recorded disappeared.

drawgent up #

Runs in the current directory (the workspace):

starts the editor + API on 127.0.0.1:7300 (next free port if taken);

starts a new session of your agent over ACP, working in the workspace;

opens your browser. On a headless box it prints the ssh -L command instead.

The live scene and its sync state are kept in .drawgent/scene.json , which is git-ignored automatically.

Diagrams linked to code #

Shapes can point at the code they stand for: a file, a line range and a symbol (function, type, class…).

Linking: the agent links shapes when it draws your repo. You can link one yourself from the Code tab: open a file, click (or shift-click) the lines, select one shape on the canvas, then Link the selected shape . The symbol on the first selected line is detected.

Browsing code from the diagram: clicking a shape's link icon opens its code in the Code tab at the right lines;

a file lists the shapes linked to it (click one to jump to it on the canvas);

the tab also has file search, full-text search, and VS Code to open the file locally.

Staying correct: The Code tab lists every link on the board with its status: ✅ ok, ↕ moved (the symbol is now at other lines), ⚠ stale (the symbol is gone), ❌ missing (the file is gone; a same-name file elsewhere is suggested).

Check drift with the agent asks your agent to repair links and mark components or arrows that no longer match the code with DRIFT: notes.

In CI: drawgent check # the workspace's diagram (or: drawgent check docs/diagrams/) drawgent check --fix # repair moved symbols and renamed files in the .excalidraw file drawgent check exits with 1 when links are broken; use --json for tooling.

Pointing at code #

Point at code instead of typing paths. Everything you point at lands in the context basket (chips at the top of the panel, visible on every tab). It is sent with your next chat message: excerpts with line numbers for code, listings for folders.

In the Code tab: Browsing: a real folder tree, Files of this board (the files linked from the board), and Ctrl+P to go to a file (fuzzy).

Laser: switch on the laser (🔴, or the canvas laser K ) and scribble over folders, files or lines. The rows you scribble over become chips; rows you merely cross don't.

Buttons: + ctx adds a folder, a file or the selected lines to the basket.

On the canvas: Cards: 📌 pins a file (from a given line) or a folder as a live card. Resize it to show more; double-click it, then ▲▼ scrolls it for everyone.

Laser: the canvas laser over a card sends exactly the lines, or folder entries, it covers, together with the diagram around them.

Repo map: 🗺 Map repo draws the workspace as a board, a treemap where top-level folders are frames and files are boxes sized by line count, all linked to the code. Pointing at an area with the laser sends that folder or file. Gitignored files are left out of the map, the Code tab and search, even ones still tracked; every .gitignore level, .git/info/exclude and the global gitignore apply, even outside a git repo.

Build what I drew #

Change the diagram, then let the agent change the code to match it.

Draw the change: add a box between two others, rename a component, re-wire an arrow.

Click 🔨 Build what I drew: it's above the chat input and counts the changes since the last build ( what changed? lists them). Point at part of the diagram with the laser first to build only that zone.

The agent receives the semantic changes, not pixels. It gets shapes and arrows added, removed, relabelled or re-wired, plus new notes; moves and restyling are ignored.

It plans, implements and reports on the canvas: Each changed element gets a marker (📝 planned → 🔧 in progress → ✅ done with the files it touched, or ⛔ blocked).

New shapes are linked to the code it wrote.

Removed shapes are proposed, never deleted from the code without your confirmation.

The baseline: changes count from the committed diagram file ( git HEAD ), or from when drawgent first saw the board, and each build moves the baseline forward. Mark as built resets it when the code already matches. Progress markers stay out of the committed .excalidraw file; clear markers removes them.

Several whiteboards #

A workspace can hold several boards, for the "one big whiteboard with many diagrams" habit without the mess:

Boards tab in the side panel: switch boards (the URL keeps ?board=<id> ), create, rename, delete.

Move or copy a selection to another board: select a diagram, part of one, or a frame, then use Move here / Copy on the target board. Labels, frame children and arrows between the moved shapes come along.

Split by frames turns every frame of a big board into its own board.

Agents work on the board you talk to them from. They can also list_boards , use_board , create_board and move_elements .

Keeping the diagram in the repo: --diagram #

drawgent up --diagram docs/architecture.excalidraw # the main board, remembered for this workspace drawgent up --diagram docs/diagrams/ # a folder: one <board>.excalidraw per board

new boards create files, and renaming a board renames its file;

a file that appears in the folder (e.g. after git pull ) becomes a board.

What's written: a standard .excalidraw file (it opens on excalidraw.com) that follows the canvas. It holds only the live drawing (no deleted elements, no laser traces), pretty-printed and without per-edit sync fields, so it diffs cleanly and is rewritten only when the drawing changes. Commit it like any other source file.

Changes from git: if the file changes outside drawgent ( git pull , checkout, a hand edit), it wins. The canvas updates live, deletions included, and a file already on disk at start is applied too. A file that doesn't parse (e.g. merge-conflict markers) is reported in the chat panel and ignored until fixed.

Picking the file: a drawgent.excalidraw at the workspace root is used automatically, so a fresh clone needs no flag.

Rooms: --diagram can't be combined with --room , where excalidraw.com holds the drawing.

drawgent up --attach [id] #

Connects the canvas to a session you already run. Without an id it lists the sessions it finds (current directory first) and lets you pick one:

Using the canvas #

Chat panel (right side): send a request, watch replies and tool calls stream in, approve permission prompts, press Stop to cancel a turn. Under each turn: the tokens it used (input, of which cached, and output), how full the agent's context window is, and what the turn cost, when the agent reports them (Claude does).

On the canvas : write a text starting with AGENT: next to or inside a shape, or draw an arrow from the note to a shape. It fires about 2.5 s after you stop typing, with its position, what it points at and what is nearby. The agent resolves it into a green DONE: … note. Edit it back to AGENT: to send it again.

Laser zones : pick Excalidraw's laser ( K ) and circle or scribble over part of the diagram. The trace stays on the canvas as a red outline, and the chat panel opens ready for your instruction, with a chip listing what is under the zone ( 🔴 Laser zone · API, Redis × ). Your next message goes to the agent together with the zone (bounds and covered elements), and the trace disappears when the agent is done. Strokes within 4 s of each other form one zone; × discards it.

Laser gestures : drawgent reads what the strokes mean, shows it on the zone chip, and tells the agent (with the elements at each end). A help card with these gestures shows in the bottom-left corner while the laser is on (× hides it; the Gestures button brings it back): Gesture Meaning tap (dot), ✕ this spot (empty space: put it here) or this element arrow (one stroke, or a line plus a head) from → to: move, connect, insert, data flow line join its two ends zigzag, scribble, or a line through an element cross it out. The agent also learns what deleting it breaks: dangling arrows, the flow to bridge, the gap to close, frame contents, code links ✓ approve / keep circle select what it encloses circle plus an arrow out of it move what it holds there ↔ / ↕ (a line with a head at each end) more room here: that diagram is pushed apart along the axis, and its frames and areas grow

Undo : agent edits land on the editor's undo stack, so Ctrl+Z reverts them one edit at a time. A turn that changed the canvas has ↶ Undo N canvas changes under it in the chat, and the agent has undo_changes (its last edit, or a whole turn). Elements a human changed since are kept as they are.

Prompts are queued and run one at a time. A queued note that was already handled is skipped.

excalidraw.com rooms #

drawgent up --room 'https://excalidraw.com/#room=<id>,<key>'

drawgent joins the room as a collaborator ( 🤖 Agent , with a cursor that follows its edits). Humans can stay on excalidraw.com: their AGENT: notes reach your agent, and its edits appear there live.

Traffic is end-to-end encrypted with the room key. Empty rooms are loaded from and saved to excalidraw's Firestore storage.

The local editor mirrors the room and still has the chat panel.

Other commands #

drawgent mcp : stdio MCP server with the canvas tools. Agents launch it; it finds the running drawgent up by itself.

drawgent serve : low-level server with explicit agents ( --agent claude,codex,opencode as set up, or name=command for any ACP agent); for scripts and containers.

Options for up / serve : --port , --room , --token (API bearer + ?token= in the URL), --permissions canvas|ask|all (default canvas : drawing tools auto-approved, anything else asked in the chat panel), --data , --settle-ms .

Optional: Docker #

docker compose up --build runs a canvas server (drawgent + Chromium, no agents ), e.g. to host a shared canvas or a room bridge on a server. Agents are never bundled: they always run with your own setup.

Build from source #

npm ci && npm run build # editor + renderer pages -> dist/ (embedded into the binary) cargo install --path . # or: cargo build --release

Release builds ( nix develop -c make … provides the toolchain, or rustup + cargo-zigbuild):

How the macOS build is made: it's cross-built from Linux with zig and no Apple SDK (drawgent links only libSystem , libiconv and libcharset ).

Signing: the arm64 slice is ad-hoc signed by the linker. It is not notarized, so after downloading run xattr -d com.apple.quarantine drawgent once.

Status: not yet tested on a real Mac.

Small machines: use JOBS=1 . One dependency ( chromiumoxide_cdp ) needs a lot of memory to compile.

Agent tools (MCP) #

drawing_guide (colours by role, sizes, layout, common mistakes; adapted from the official excalidraw-mcp guide, MIT), get_scene (after the first read: only what changed since, minus the agent's own edits; full for everything), check_layout (geometry lint: overlaps, overflowing / broken labels, arrows through shapes or clipped by frames, small or low-contrast text, near-misalignment, crowding; fixes as update patches; edit replies carry the issues they introduce), add_graph (nodes, edges, groups → layered auto-layout with frames), make_space (push a diagram apart along an axis at a point), undo_changes (revert the agent's last edit or turn), get_screenshot (vision, 1000 px by default; element_ids crops to the area, max_size ), link_code , check_links , get_diagram_changes , mark_progress , map_repo , list_boards , use_board , create_board , move_elements , add_elements (Excalidraw skeletons; arrows bind by id and are routed edge-to-edge), add_mermaid (auto-layout), update_elements (labels follow shapes, bound arrows re-route, frameId ), delete_elements ( reconnect : drop attached arrows and bridge the flow), clear_canvas , list_instructions , resolve_instruction , set_status .

API #

GET /api/health · GET /api/scene · GET /api/screenshot?ids=&padding=&max= · POST|PATCH|DELETE /api/elements · POST /api/mermaid · POST /api/graph · GET /api/lint?ids= · GET /api/zone?zone= · POST /api/space · POST /api/undo {scope|turn} · POST /api/clear · GET /api/instructions · POST /api/instructions/{id}/resolve · POST /api/status · POST /api/chat {agent?, text}