(../static/logos/dolly.ico) (../static/logos/dolly.svg) (https://tangled.org/static/logos/dolly.png) (https://avatar.tangled.sh) (https://camo.tangled.sh) (../pwa-manifest.json) (https://tangled.org/static/fonts/InterVariable.woff2) (../static/tw.css@3a29b5e9.css) yanndegat.tngl.sh/drawgent at main · Tangled (drawgent.html) (https://tangled.org/) alpha (https://tangled.org/login) Login or (https://tangled.org/signup) Join now (https://tangled.org/yanndegat.tngl.sh) () yanndegat.tngl.sh / (drawgent.html) drawgent Star (https://tangled.org/yanndegat.tngl.sh/drawgent/stars) (Starred by) 8 (https://tangled.org/yanndegat.tngl.sh/drawgent/fork) Fork (https://tangled.org/yanndegat.tngl.sh/drawgent/forks) (Forked by) 1 Atom Configure Feed Issues Pull Requests Commits Tags Feed URL (/yanndegat.tngl.sh/drawgent/feed.atom) (Copy to clipboard) Select the types of activity you want to include in your feed. This repository has no description Star (https://tangled.org/yanndegat.tngl.sh/drawgent/stars) (Starred by) 8 (https://tangled.org/yanndegat.tngl.sh/drawgent/fork) Fork (https://tangled.org/yanndegat.tngl.sh/drawgent/forks) (Forked by) 1 Atom Configure Feed Issues Pull Requests Commits Tags Feed URL (/yanndegat.tngl.sh/drawgent/feed.atom) (Copy to clipboard) Select the types of activity you want to include in your feed. (https://tangled.org/yanndegat.tngl.sh/drawgent/) Overview (https://tangled.org/yanndegat.tngl.sh/drawgent/issues) Issues (https://tangled.org/yanndegat.tngl.sh/drawgent/pulls) Pulls (https://tangled.org/yanndegat.tngl.sh/drawgent/pipelines) Pipelines (Rust 78.0%) (JavaScript 17.2%) (CSS 2.3%) (Makefile 1.1%) (Nix 0.6%) (Dockerfile 0.6%) (HTML 0.3%) Rust 78.0% JavaScript 17.2% CSS 2.3% Makefile 1.1% Nix 0.6% Dockerfile 0.6% HTML 0.3% (Branches (1)) (main) main (Tags (0)) No tags found (https://tangled.org/yanndegat.tngl.sh/drawgent/compare?base=main) (Compare branches or tags) (Find files or code...) (https://tangled.org/yanndegat.tngl.sh/drawgent/commits/main) 9 (https://tangled.org/yanndegat.tngl.sh/drawgent/branches) 1 (https://tangled.org/yanndegat.tngl.sh/drawgent/tags) 0 Code Clone this repository Use permalink HTTPS https://tangled.org/yanndegat.tngl.sh/drawgent https://tangled.org/did:plc:3zklierfkckthy6sodbm4af3 (Copy to clipboard) SSH git@tangled.org:yanndegat.tngl.sh/drawgent git@tangled.org:did:plc:3zklierfkckthy6sodbm4af3 (Copy to clipboard) For self-hosted knots, clone URLs may differ based on your setup. (https://tangled.org/yanndegat.tngl.sh/drawgent/archive/main.tar.gz) Download tar.gz (https://tangled.org/yanndegat.tngl.sh/drawgent/archive/main.zip) Download .zip (https://tangled.org/yanndegat.tngl.sh/drawgent/tree/main/docs) docs (https://tangled.org/yanndegat.tngl.sh/drawgent/commit/9018835df1c0540c894db2e9537dcc3a69b17332) (Sep 27, 2026, 8:10 AM +0200) 1 hour ago (https://tangled.org/yanndegat.tngl.sh/drawgent/tree/main/scripts) scripts (https://tangled.org/yanndegat.tngl.sh/drawgent/commit/122afbaf6f1af0ed4e8c1a3f30de05464888f223) (Sep 27, 2026, 6:28 AM UTC) 50 minutes ago (https://tangled.org/yanndegat.tngl.sh/drawgent/tree/main/src) src (https://tangled.org/yanndegat.tngl.sh/drawgent/commit/f4b0e5cbcd565932e0b2ae39f7724ab867e7beb0) (Sep 27, 2026, 6:28 AM UTC) 50 minutes ago (https://tangled.org/yanndegat.tngl.sh/drawgent/tree/main/web) web (https://tangled.org/yanndegat.tngl.sh/drawgent/commit/122afbaf6f1af0ed4e8c1a3f30de05464888f223) (Sep 27, 2026, 6:28 AM UTC) 50 minutes ago (https://tangled.org/yanndegat.tngl.sh/drawgent/blob/main/.dockerignore) .dockerignore (https://tangled.org/yanndegat.tngl.sh/drawgent/commit/e76f88fe7541caaf61b2fdb80ad260d3b55a5dc5) (Sep 26, 2026, 3:08 PM UTC) 16 hours ago (https://tangled.org/yanndegat.tngl.sh/drawgent/blob/main/.env.example) .env.example (https://tangled.org/yanndegat.tngl.sh/drawgent/commit/e76f88fe7541caaf61b2fdb80ad260d3b55a5dc5) (Sep 26, 2026, 3:08 PM UTC) 16 hours ago (https://tangled.org/yanndegat.tngl.sh/drawgent/blob/main/.gitignore) .gitignore (https://tangled.org/yanndegat.tngl.sh/drawgent/commit/e76f88fe7541caaf61b2fdb80ad260d3b55a5dc5) (Sep 26, 2026, 3:08 PM UTC) 16 hours ago (https://tangled.org/yanndegat.tngl.sh/drawgent/blob/main/Cargo.lock) Cargo.lock (https://tangled.org/yanndegat.tngl.sh/drawgent/commit/e76f88fe7541caaf61b2fdb80ad260d3b55a5dc5) (Sep 26, 2026, 3:08 PM UTC) 16 hours ago (https://tangled.org/yanndegat.tngl.sh/drawgent/blob/main/Cargo.toml) Cargo.toml (https://tangled.org/yanndegat.tngl.sh/drawgent/commit/e76f88fe7541caaf61b2fdb80ad260d3b55a5dc5) (Sep 26, 2026, 3:08 PM UTC) 16 hours ago (https://tangled.org/yanndegat.tngl.sh/drawgent/blob/main/Dockerfile) Dockerfile (https://tangled.org/yanndegat.tngl.sh/drawgent/commit/e76f88fe7541caaf61b2fdb80ad260d3b55a5dc5) (Sep 26, 2026, 3:08 PM UTC) 16 hours ago (https://tangled.org/yanndegat.tngl.sh/drawgent/blob/main/Makefile) Makefile (https://tangled.org/yanndegat.tngl.sh/drawgent/commit/e76f88fe7541caaf61b2fdb80ad260d3b55a5dc5) (Sep 26, 2026, 3:08 PM UTC) 16 hours ago (https://tangled.org/yanndegat.tngl.sh/drawgent/blob/main/README.md) README.md (https://tangled.org/yanndegat.tngl.sh/drawgent/commit/3bb42f16ff8c59157881bcc0574ac512c0c4c7ef) (Sep 27, 2026, 8:10 AM +0200) 1 hour ago (https://tangled.org/yanndegat.tngl.sh/drawgent/blob/main/docker-compose.yml) docker-compose.yml (https://tangled.org/yanndegat.tngl.sh/drawgent/commit/e76f88fe7541caaf61b2fdb80ad260d3b55a5dc5) (Sep 26, 2026, 3:08 PM UTC) 16 hours ago (https://tangled.org/yanndegat.tngl.sh/drawgent/blob/main/flake.lock) flake.lock (https://tangled.org/yanndegat.tngl.sh/drawgent/commit/e76f88fe7541caaf61b2fdb80ad260d3b55a5dc5) (Sep 26, 2026, 3:08 PM UTC) 16 hours ago (https://tangled.org/yanndegat.tngl.sh/drawgent/blob/main/flake.nix) flake.nix (https://tangled.org/yanndegat.tngl.sh/drawgent/commit/e76f88fe7541caaf61b2fdb80ad260d3b55a5dc5) (Sep 26, 2026, 3:08 PM UTC) 16 hours ago (https://tangled.org/yanndegat.tngl.sh/drawgent/blob/main/package-lock.json) package-lock.json (https://tangled.org/yanndegat.tngl.sh/drawgent/commit/e76f88fe7541caaf61b2fdb80ad260d3b55a5dc5) (Sep 26, 2026, 3:08 PM UTC) 16 hours ago (https://tangled.org/yanndegat.tngl.sh/drawgent/blob/main/package.json) package.json (https://tangled.org/yanndegat.tngl.sh/drawgent/commit/e76f88fe7541caaf61b2fdb80ad260d3b55a5dc5) (Sep 26, 2026, 3:08 PM UTC) 16 hours ago (https://tangled.org/yanndegat.tngl.sh/drawgent/blob/main/vite.config.mjs) vite.config.mjs (https://tangled.org/yanndegat.tngl.sh/drawgent/commit/e76f88fe7541caaf61b2fdb80ad260d3b55a5dc5) (Sep 26, 2026, 3:08 PM UTC) 16 hours ago (https://tangled.org/yanndegat.tngl.sh/drawgent/commits/main) Commits 9 (https://tangled.org/yanndegat.tngl.sh/drawgent/commit/f4b0e5cbcd565932e0b2ae39f7724ab867e7beb0) Explain why an agent process died; launch adapters with node's absolute path - acp: keep the agent's last stderr lines and exit status and report them("agent process exited (exit status: 1): ") in the log, the chatpanel and to pending requests, instead of a bare "agent process exited".- setup: record node's absolute path and launch `node `,so `up` works where node isn't on PATH (e.g. setup ran in a nix shell);warn when Node is older than the adapter's declared >= 22.- up: check every absolute path of the bridge still exists.Co-Authored-By: Claude Opus 5.5 (https://tangled.org/yanndegat.tngl.sh/drawgent/commit/f4b0e5cbcd565932e0b2ae39f7724ab867e7beb0) f4b0e5cb (mailto:yann.degat@pm.me) yann.degat +1 (Sep 27, 2026, 6:28 AM UTC) 50 minutes ago main (https://tangled.org/yanndegat.tngl.sh/drawgent/commit/122afbaf6f1af0ed4e8c1a3f30de05464888f223) Laser zones: all strokes join the pending zone, discard removes them all A new stroke used to start its own zone once 4 s had passed, orphaningearlier traces that the chip's × could no longer remove. Strokes now jointhe pending zone until it is sent or discarded, and traces already on thecanvas when the editor (re)connects are merged into one pending zone.laser-e2e covers both cases.Co-Authored-By: Claude Opus 5.5 (https://tangled.org/yanndegat.tngl.sh/drawgent/commit/122afbaf6f1af0ed4e8c1a3f30de05464888f223) 122afbaf (mailto:yann.degat@pm.me) yann.degat +1 (Sep 27, 2026, 6:28 AM UTC) 50 minutes ago (https://tangled.org/yanndegat.tngl.sh/drawgent/commit/3bb42f16ff8c59157881bcc0574ac512c0c4c7ef) add images in readme (https://tangled.org/yanndegat.tngl.sh/drawgent/commit/3bb42f16ff8c59157881bcc0574ac512c0c4c7ef) 3bb42f16 (mailto:yann.degat@ovhcloud.com) Yann Degat (Sep 27, 2026, 8:10 AM +0200) 1 hour ago (https://tangled.org/yanndegat.tngl.sh/drawgent/commit/9018835df1c0540c894db2e9537dcc3a69b17332) README: add architecture diagram Co-Authored-By: Claude Opus 5.5 (https://tangled.org/yanndegat.tngl.sh/drawgent/commit/9018835df1c0540c894db2e9537dcc3a69b17332) 9018835d (mailto:yann.degat@ovhcloud.com) Yann Degat +1 (Sep 27, 2026, 8:10 AM +0200) 1 hour ago (https://tangled.org/yanndegat.tngl.sh/drawgent/commit/34832fd6853a230cdd600c79890b792da3749d0a) README: show the network overview example Co-Authored-By: Claude Opus 5.5 (https://tangled.org/yanndegat.tngl.sh/drawgent/commit/34832fd6853a230cdd600c79890b792da3749d0a) 34832fd6 (mailto:yann.degat@ovhcloud.com) Yann Degat +1 (Sep 27, 2026, 8:10 AM +0200) 1 hour ago (https://tangled.org/yanndegat.tngl.sh/drawgent/commit/44d3b3e68a095ea869cdcd6bdc8a54ac58de0956) docs: add network overview diagram PNG Exported from the drawgent canvas: the hand sketch and its redrawnNetwork overview (Internet -> gateway -> 3 k8s nodes on vRack 10.0.0.0/8).Co-Authored-By: Claude Opus 5.5 (https://tangled.org/yanndegat.tngl.sh/drawgent/commit/44d3b3e68a095ea869cdcd6bdc8a54ac58de0956) 44d3b3e6 (mailto:yann.degat@ovhcloud.com) Yann Degat +1 (Sep 27, 2026, 8:10 AM +0200) 1 hour ago (https://tangled.org/yanndegat.tngl.sh/drawgent/commit/a1774af57c085b617a1306056d3631736164fc26) Laser zones: point at part of the diagram, then tell the agent what to do The editor records Excalidraw laser gestures (onPointerUpdate) and keepsthem as a locked red freedraw trace tagged customData.drawgentZone. Thechat panel opens focused with a chip listing the covered elements; thenext message is sent with the zone, and the server adds the zone boundsand covered elements (most covered first) to the prompt. The trace isremoved when that turn ends (managed sessions) or when a live attachedsession goes idle again. get_scene reports traces as type "zone".Adds scripts/laser-e2e.mjs.Co-Authored-By: Claude Opus 5.5 (https://tangled.org/yanndegat.tngl.sh/drawgent/commit/a1774af57c085b617a1306056d3631736164fc26) a1774af5 (mailto:yann.degat@pm.me) yann.degat +1 (Sep 26, 2026, 5:40 PM UTC) 13 hours ago (https://tangled.org/yanndegat.tngl.sh/drawgent/commit/bfe0315074a2312504b5fd5dc802f2db31528c11) Log browser connections on both ends to diagnose slow UI startup Server logs each WebSocket request and connection; the editor logstimed [drawgent +Nms] lines in the browser console (page script,connecting/open/closed, init received) and shows an orange"connecting" dot in the chat panel.Co-Authored-By: Claude Opus 5.5 (https://tangled.org/yanndegat.tngl.sh/drawgent/commit/bfe0315074a2312504b5fd5dc802f2db31528c11) bfe03150 (mailto:yann.degat@pm.me) yann.degat +1 (Sep 26, 2026, 5:22 PM UTC) 13 hours ago (https://tangled.org/yanndegat.tngl.sh/drawgent/branches) Branches 1 (https://tangled.org/yanndegat.tngl.sh/drawgent/tree/main) main (Sep 27, 2026, 6:28 AM UTC) 50 minutes ago Default README.md drawgent: your coding agent on a live Excalidraw canvas(drawgent.html#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(drawgent.html#how-it-works) # (drawgent architecture: the browser, the drawgent server, your coding agent and its MCP canvas tools) Quick start(drawgent.html#quick-start) # Prerequisite: one of claude , codex or opencode installed and logged in. The Claude and Codex bridges also need Node.js ≥ 18 (npm). 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 Example :)(drawgent.html#example-) # (A hand sketch on the canvas (left) and the clean diagram the agent drew from it (right)) drawgent setup (drawgent.html#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 (drawgent.html#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 scene is kept in .drawgent/scene.json , which is git-ignored automatically. drawgent up --attach [id] (drawgent.html#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: agent discovery how the canvas reaches it Claude Code claude agents --json (interactive and background sessions) fork : a new session carrying the full conversation, driven by drawgent over ACP. Your terminal session is left untouched opencode opencode servers listening locally: start the TUI with opencode --port 4096 (or opencode serve ) live : messages go into your running session (you see them in your TUI); drawgent adds its MCP tools to that server at runtime; replies, tool calls and prompts you type in the TUI are mirrored into the chat panel Codex sessions in ~/.codex/sessions live : codex queue --thread ; replies are mirrored from the session's rollout file. The session needs the drawgent MCP (registered by setup, loaded when Codex starts) Using the canvas(drawgent.html#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. 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. Prompts are queued and run one at a time. A queued note that was already handled is skipped. excalidraw.com rooms(drawgent.html#excalidrawcom-rooms) # drawgent up --room 'https://excalidraw.com/#room=,' 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.html#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(drawgent.html#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(drawgent.html#build-from-source) # npm ci && npm run build # editor + renderer pages -> dist/ (embedded into the binary) cargo install --path . # or: cargo build --release Agent tools (MCP)(drawgent.html#agent-tools-mcp) # get_scene , get_screenshot (vision; zoom with element_ids ), 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), delete_elements , clear_canvas , list_instructions , resolve_instruction , set_status . API(drawgent.html#api) # GET /api/health · GET /api/scene · GET /api/screenshot?ids=&padding=&max= · POST|PATCH|DELETE /api/elements · POST /api/mermaid · POST /api/clear · GET /api/instructions · POST /api/instructions/{id}/resolve · POST /api/status · POST /api/chat {agent?, text} · WS /ws (browser sync + chat events) Tests(drawgent.html#tests) # cargo test # fractional indices, room crypto/framing node scripts/smoke.mjs [ url] # chat turn + AGENT: note against a running drawgent node scripts/e2e-browser.mjs [ url] # real browser: chat panel + note typed on the canvas node scripts/room-e2e.mjs # fresh excalidraw.com room ↔ drawgent, both directions node scripts/laser-e2e.mjs # laser zone → chat → agent edits only that zone (needs setup claude) Layout(drawgent.html#layout) # src/ (Rust): main.rs : CLI. setup.rs , config.rs , chrome.rs : setup, config, renderer install. attach.rs : session discovery and picker. agents.rs + acp.rs : ACP driver (new / fork sessions). live.rs : live opencode / Codex drivers. hub.rs : routing, notes, chat log. scene.rs : store and edit operations. renderer.rs : Chrome over CDP. mcp.rs : MCP server. room.rs : excalidraw.com client. fractional.rs , geometry.rs , el.rs : helpers. web/ : editor (main.jsx , chat.jsx , laser.js ) and renderer page (render.jsx ). Limits(drawgent.html#limits) # The renderer needs Chrome (a native renderer is planned). Claude "attach" is a fork, because Claude Code has no public way to inject into a running terminal session. Codex live attach is implemented, but was not yet tested against a logged-in Codex. One scene per workspace. Images/files are not synced. (https://tangled.org/) © 2026 Tangled Labs Oy. (https://blog.tangled.org) Blog (https://docs.tangled.org) Docs (https://tangled.org/tangled.org/core) Source (https://tangled.org/brand) Brand (https://chat.tangled.org) Discord (https://bsky.app/profile/tangled.org) Bluesky (https://x.com/tangled_org) Twitter (X) (https://tangled.org/terms) Terms (https://tangled.org/privacy) Privacy