Parallel sessions
Each card is its own live agent process. Type any time: messages queue while the agent or its sub-agents work.
- Fix reconnectworking
- Migrate settingsneeds approval
- Write release notesdone
Drawa is a canvas workspace for coding agents, Claude Code, OpenCode, Codex and Antigravity. Run several sessions side by side, watch every file they read, edit and run appear wired to the session that touched it, and open any change in one click. It all runs on your machine.
curl -fsSL https://raw.githubusercontent.com/HimalayanNomads/drawa/main/install.sh | sh
Why does a reload drop the stream?
A reload re-attaches from its last line, but events.go skips cards that aren't live yet.
Fixed. A reload mid-stream now starts the card's process and picks up where it left off.
func (l *Live) Snapshot(from int) []Line { l.mu.Lock()
- lv, ok := live.Get(c.ID); if !ok { continue }+ lv, ok := live.Get(c.ID)+ if !ok { lv = live.Start(c.ID) }
func TestReattach(t *testing.T) { // reload mid-stream
$ go test ./... ok drawa/internal/live 0.41s
Drag a tab to move a window
Everything else on the canvas stays neutral, so what the agent did is readable from across the room.
Sessions, files, diffs, notes and Git share one canvas. Pan, zoom, and put things where they make sense to you.
Each card is its own live agent process. Type any time: messages queue while the agent or its sub-agents work.
Click a file for its changes from every session, plus the file itself with Markdown and Mermaid preview.
@@ config.ts- const port = 8765+ const port = Number(env.DRAWA_PORT ?? 8765)
Every sub-agent gets a window of its own that fills in as it works, and you can message it directly.
Built-in tools let Claude read, create, edit and link canvas items: a diagram of the flow it traced, a note on what's left. Changes go through the usual approval.
Sticky notes, a Markdown scratchpad, Mermaid diagrams, pictures, pinned snippets and freehand ink. @-mention any of them in a message, or drop one on a card.
Browse status and history, commit and push. Open pull requests and issues through gh, and send a PR, its failing checks or its reviews straight to a session.
Resume past sessions from history. The layout survives a reload, and a reload re-attaches to sessions that are still running.
Light and dark, with Rosé Pine, Catppuccin, Tokyo Night, Gruvbox, Nord, Kanagawa, Everforest, Solarized and GitHub schemes. Try one on this page:
The pencil on a file window, or a double-click on its text, turns it into an editor. CtrlS saves, and only while the file on disk still matches what you opened. Turn on Vim motions in Settings for :w, gd and yanks that reach your clipboard.
41 func (s *Server) events(w http.ResponseWriter) { 42 lv, ok := live.Get(c.ID)
Under each card's message box: tools loaded, context used, and rings for the 5-hour and weekly usage windows on Claude and ChatGPT plans. When a turn ends or an agent waits on you while you're in another tab, the tab title counts it and, if you allow them, a notification says so.
A folder of cloned repos? The Git window finds each one, up to four folders deep, with its own commit box and pull request. Each repo's header lists its worktrees: pick one to switch to it, or remove one you're done with.
An agent's edit isn't a line in a transcript. Each one is numbered inside its file, with line numbers and real context, next to the edits every other session made to it.
Get · 4 references
Get in the diff to try it.+ and −, ready to @-mention in a message.In plan mode, Claude's plan opens as a document on the canvas. Comment on any block, or draw on it, then approve it or send your notes back. The revision lands in the same window, with what changed marked word by word.
Keep the stream across reloads
A group is a named frame around windows: a session, the files it touched, a note, a diagram. Drag the frame's tab and everything inside comes along. Fold it away when you're done.
- if !ok { continue }+ lv = live.Start(c.ID)
Check the phone layout once this lands.
Checks passed, ready to merge
Group the selection. Groups inside it merge into one. With nothing selected, you get an empty frame to drop windows into.
Drop in to join, drag out to leave. A window dropped into a frame keeps its spot and the frame grows to fit. Dragged out, it leaves at once, with a notice that puts it back.
Never on top of each other. Frames wrap their windows as they grow, and make room instead of overlapping another group.
Drawings and pictures belong too. Ink, arrows and pictures inside a frame move with it, and a session's files, commands and plan windows open inside the group its card is in.
Layers. Bring a window forward or send it back, past the next one it overlaps; with Shift, all the way. Inside a group, they reorder its windows.
Nothing is lost. Deleting a group can be undone with its frame intact, and a frame stays when its last window leaves. CtrlShiftG ungroups.
Real screenshots, in light or dark to match this page. Click one for full view, as you would a picture on the canvas.
--net and open the printed link or QR code: the same canvas, starting in Hand mode so a drag pans.Each card picks its agent and its model when you start it, from New session ▾. At launch Drawa lists the agents it finds, and warns if a version isn't the one it was tested with.
| Claude CodeClaude Pro or Max | OpenCodeAny provider, or free models | CodexChatGPT plan or API key | AntigravityGoogle sign-in | |
|---|---|---|---|---|
| Sign in with | Your Claude subscription | opencode auth login; its own free models need no key | codex login | Your Google sign-in, via agy in a terminal |
| Tested with | Not pinned | 1.18.32 | 0.158.0 | 1.2.16 |
| Approvals, file and command windows, canvas tools, history | Yes | Yes | Yes looking at the canvas never asks | Files, commands and history no approvals: edits are turned down unless in Allow everything; no canvas tools |
| Pasted images | Yes | Yes | Yes | No |
| Sub-agents | Own window | Own window | One row, not their own window | No |
| Auto mode | Yes | No | No | No |
| Effort setting | Yes | No | No uses its default | No models name their own level |
| Usage windows in the status line | Yes | No | No | No |
| Take back a queued message | Yes | No | No | No |
| Memory per session | Its own claude process | About 300 MB its own opencode server | About 250 MB its own codex app-server | Its own agy process |
A session's prompts, and the files it reads, go to the provider you pick. OpenCode's free models are run by third parties that may use what you send to improve their models (see OpenCode Zen's terms), so don't use them on code you can't share.
A local folder is marked trusted for Codex, so its .codex/ settings and AGENTS.md load, as with Claude Code. A cloned GitHub repo you didn't trust is marked untrusted, so they don't. Nothing is written to ~/.codex/config.toml.
agy can't ask for approval when run headless, so edits and most commands are turned down and listed under the reply, unless you start the session in Allow everything. No Stop, no mode or model switch mid-session, no pasted images, no slash commands and no canvas tools. See #34.
No agent has its own process limit: set DRAWA_MAX_LIVE if your machine needs one. In the Git window, Write with ▾ picks which agent writes commit messages and pull request descriptions.
.git, .codex, .agents or .claude, and not renames out of it.DRAWA_MAX_LIVE; it asks again after resuming). Drawa doesn't save Codex's permanent command rules, and canvas changes ask each time.Drawa is one binary. It drives the claude, opencode, codex or agy CLI on your PATH with your login, settings, skills and MCP servers, and serves the page on 127.0.0.1.
Host and Origin on every request, and file access stays inside the folder you opened.drawa --net prints a network link with a one-time token and a QR code.$ drawa --net . - Local: http://127.0.0.1:8765 - Network: http://192.168.1.23:8765/?token=fpKZrzCN $ drawa https://github.com/owner/repo cloned into the cache, opened in your browser
Single keys for the common moves, following Excalidraw's where the tool exists. They never fire while you're typing. In the app, ? lists them all and CtrlK runs any action by name.
Enter after C puts you in that session's message box.
They act on the selected window, else the one in front. W selects, so Delete, the arrows and CtrlG act on it.
Start editing with the pencil on a file window, a double-click on its text, or Edit in the file inspector. The pencil again stops, and asks first if there are unsaved changes. Vim motions are off until you turn them on in Settings.
Hold Shift for a square, a circle or a 45° line.
Grouping windows that hold groups merges them. With nothing selected, CtrlG makes an empty group.
The arrows walk through the messages and ! commands you sent in this session; past the newest is your draft. Prefer CtrlEnter to send? Pick it in Settings.
The command line, what Drawa needs, and how to configure it. The full story is in the README and INSTALL.md.
drawahttp://127.0.0.1:8765 in your browser. Press N for a new session and start typing.drawa ~/some/projectdrawa --net .?token= plus a QR code for your phone. --net works in any position.drawa https://github.com/owner/repo/tree/main/docs opens the repo on its default branch.drawa --cleandrawa --updateTrusting a repo. Opening a GitHub URL, or a folder inside its clone, asks on each launch whether to trust it. Answer n (the default) and its .claude/ settings, hooks, .mcp.json, CLAUDE.md, OpenCode project config, and Codex's .codex/ and AGENTS.md are ignored, since they could run commands on your machine.
In the message box, / opens skills and slash commands and @ references files or canvas items. The toolbar picks the model and the permission mode.
| Claude Code | One agent required claude on PATH and logged in, for your Claude subscription. |
|---|---|
| OpenCode | Or, instead or as well: opencode on PATH, for any other provider or its free models. Tested with 1.18.32. |
| Codex | Or: codex on PATH and logged in, for your ChatGPT plan or an OpenAI API key. Tested with 0.158.0. |
| Antigravity | Or: agy on PATH, signed in once by running agy in a terminal. Limited: no approvals or canvas tools. Tested with 1.2.16. |
git | Optional 2.36 or later. Powers the Git window, file history and find references. |
gh | Optional Powers the GitHub window. |
| universal-ctags | Optional Code symbols: CtrlK finds functions, classes and the like by name, and clicking a name in a diff shows where it's defined. brew install universal-ctags on a Mac; turn it off in Settings. |
| OS | macOS or Linux. Windows isn't supported natively yet, but Drawa runs inside WSL2. |
| From source | Go 1.22+ and Node 20.19+ (or 22.12+). See Build from source. |
| Variable | Default | Purpose |
|---|---|---|
DRAWA_PORT | 8765 | Port to serve on. Set it to run two projects at once. |
CLAUDE_CONFIG_DIR | ~/.claude | Claude Code's config directory, if you keep a separate login or set of skills for Drawa. |
DRAWA_NET_TOKEN | fresh each run | The --net token. Drawa sets it itself so the token survives its self-restarts; set it only to pick your own. |
DRAWA_MAX_LIVE | no cap | Most agent processes kept running at once (each takes a few hundred MB). Past it, the least recently used idle session closes; its next message resumes it. Idle sessions close after 30 minutes either way. |
DRAWA_DEV | unset | 1 trusts the Vite dev server's origin (port 5173). npm run dev sets it; see CONTRIBUTING.md. |
$ DRAWA_PORT=8766 CLAUDE_CONFIG_DIR=$HOME/.claude-work drawa ~/other/project
Settings that follow you to every project and browser live in ~/.drawa/config.json. Drawa writes the defaults the first time it starts, and the Settings panel (the gear) changes it. Hand edits apply on the next reload; a file that isn't valid JSON is left alone and the defaults apply until it's fixed.
// ~/.drawa/config.json { "darkScheme": "claude-dark", "lightScheme": "claude-light", "symbols": "auto", "theme": "system", "ui": "full", "vim": "off" }
uifullfull shows every window's title tab; minimal shows a tab only when you hover or focus its window. A card waiting for your approval keeps its tab either way.themesystemsystem follows your computer's light or dark mode; light or dark fixes it.lightScheme, darkSchemeclaude-light, claude-darkrose-pine-dawn, catppuccin-mocha or nord. Try them on this page.symbolsautoauto reads code symbols with universal-ctags when it's installed; off never runs it.vimoffon gives the file editor and scratchpads Vim motions. Yanks and deletes go to the system clipboard, and a yank flashes so you see what it took.Drawa is built to run locally, for one user.
127.0.0.1 unless you pass --net, and checks the Host header on every request either way.--net, the network address also needs its one-time ?token=, checked once, then kept in a cookie and dropped from the address. Five wrong guesses lock that address out for a few minutes. Treat the link like a password, and only use --net on a network you trust.Origin.claude can call them.Found a vulnerability? Please open a private security advisory rather than a public issue. See SECURITY.md.
Everyone who has committed to Drawa, opened an issue or pull request, or joined the discussion, most active first. Add your face here.
$ cat contributors.json counting…
Downloads the release binary for your OS to ~/.local/bin/drawa. No Go or Node needed. Update later with drawa --update.
curl -fsSL https://raw.githubusercontent.com/HimalayanNomads/drawa/main/install.sh | sh
cd ~/my/project && drawapress N and typecurl -fsSL https://claude.ai/install.sh | bashnpm install -g @openai/codexcurl -fsSL https://opencode.ai/install | bashagygit and gh are optional.drawa: command not found? Add ~/.local/bin to your PATH, or see manual downloads and building from source.A star on GitHub helps more people find it. Hit a bug or have an idea? Tell us, it shapes what gets built next.