Drawa Star

Your coding agent's work, drawn as a map.

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
View the source

Open source, AGPL-3.0 macOS and Linux Claude Code, OpenCode, Codex or Antigravity

Four colors, and each one means something.

Everything else on the canvas stays neutral, so what the agent did is readable from across the room.

  1. ReadFiles the agent opened to understand the problem. Dotted, because nothing changed.
  2. EditFiles it changed. Click one for the diff, from every session that touched it.
  3. WriteFiles it created from nothing, like the test that proves the fix.
  4. RunCommands it ran, collected beside the card with their output.

A whole workspace around the agent.

Sessions, files, diffs, notes and Git share one canvas. Pan, zoom, and put things where they make sense to you.

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

Diffs everywhere

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)

Sub-agents in the open

Every sub-agent gets a window of its own that fills in as it works, and you can message it directly.

Claude uses the canvas too

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.

A whiteboard around your code

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.

Git and GitHub built in

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.

Picks up where you left off

Resume past sessions from history. The layout survives a reload, and a reload re-attaches to sessions that are still running.

Your colors

Light and dark, with Rosé Pine, Catppuccin, Tokyo Night, Gruvbox, Nord, Kanagawa, Everforest, Solarized and GitHub schemes. Try one on this page:

Edit files in place

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)
NORMALevents.go:w

Limits at a glance

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.

5h 49% week 12% 38% context

Every repo, every worktree

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.

See all features Review, groups, editing, Git and more, with what each agent supports.

Review it like a pull request, before it is one.

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.

events.go2 edits · 2 sessions
Fix reconnect +2 −1 Retry backoff +1 −0 Show in file
for _, c := range cards {
if c.Closed { continue }
// re-attach from its last line
@@ −41,3 +41,4 @@ #1 Fix reconnect
lv, ok := live.(c.ID); if !ok { continue }
lv, ok := live.(c.ID)
if !ok { lv = live.Start(c.ID) }
lv.Replay(w, c.From)
@@ −52,2 +53,3 @@ #2 Retry backoff
for try := 0; try < 5; try++ {
time.Sleep(backoff(try))
}

Get · 4 references

  1. internal/live/registry.go22
  2. internal/server/events.go41
  3. internal/server/cardops.go87
  4. internal/live/live_test.go130
  • Every session, one file. Click a file for each change made to it, numbered and labeled with the session that made it. Line numbers open the file at that line.
  • More context on demand. Long unchanged stretches fold into a row you click. In Git and GitHub diffs, a hunk's header shows ten more lines at a time, as a pull request review does.
  • Jump from a name. Click a name in an agent's edit for its definition. In a Git or GitHub diff, get every place it's used, each opening at its line in a small peek window.
  • Pin a hunk. Select part of a diff and pin it to the canvas. It stays a diff, with its + and −, ready to @-mention in a message.
  • Approve from the card. An edit waiting on you shows its diff inside the card: deny, allow once, or always.
  • Discard a file. Modified and deleted files in the Git window get a discard button: a change goes back to what's staged, a staged one to the last commit.

Plans you can mark up.

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.

Planv2 · 1 added · 1 edited

Keep the stream across reloads

  1. Store each card's last event id.
  2. On reload, poll every card re-attach from that id.You What about cards that never went live?
  3. Start cards that aren't live yet, then replay.
  4. Add a test that reloads mid-stream.
Notes for Claude… Send notes Approve

Group the canvas by what you're working on.

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.

Reconnect fix3 windows
Fix reconnectopus
  • Readlive.go
  • Editevents.go+2 −1
  • Rungo test ./...
events.go+2 −1
- if !ok { continue }+ lv = live.Start(c.ID)
Note

Check the phone layout once this lands.

Release 0.92 windows
Release notescodex
  • WriteCHANGELOG.md
  • Rungit tag v0.9.0
GitHub#153

Checks passed, ready to merge

  1. CtrlG

    Group the selection. Groups inside it merge into one. With nothing selected, you get an empty frame to drop windows into.

  2. 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.

  3. Never on top of each other. Frames wrap their windows as they grow, and make room instead of overlapping another group.

  4. 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.

  5. ][

    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.

  6. CtrlZ

    Nothing is lost. Deleting a group can be undone with its frame intact, and a frame stays when its last window leaves. CtrlShiftG ungroups.

See all features Every feature, by category, with what each agent supports.

See it in the app.

Real screenshots, in light or dark to match this page. Click one for full view, as you would a picture on the canvas.

Several agents at once. Each session is a card. The files its agent read, edited and wrote fill a window wired to it, with whatever else you put on the canvas beside them.
Your work, drawn as a map. Files are linked to the card that touched them and colored by what happened. Commands collect in their own window below.
Review in place. An edit waiting for approval shows its diff inside the card. Deny it, allow it once, or always.
Agents use the canvas too. They read, create, edit and link canvas items through built-in tools, like this Mermaid diagram of the code it traced.
Git and GitHub built in. Pin the GitHub window beside a card. Send a pull request, its failing checks or its reviews straight to a session, or merge it.
Works on your phone. Start with --net and open the printed link or QR code: the same canvas, starting in Hand mode so a drag pans.
Pick an agent per session. New session ▾ lists every agent Drawa finds on your PATH, so Claude Code, OpenCode, Codex and Antigravity can work side by side.

Bring the agent you already pay for.

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.

Compare agents

one is enough
What each agent supports in Drawa
Claude CodeClaude Pro or Max OpenCodeAny provider, or free models CodexChatGPT plan or API key AntigravityGoogle sign-in
Sign in withYour Claude subscriptionopencode auth login; its own free models need no keycodex loginYour Google sign-in, via agy in a terminal
Tested withNot pinned1.18.320.158.01.2.16
Approvals, file and command windows, canvas tools, historyYesYesYes looking at the canvas never asksFiles, commands and history no approvals: edits are turned down unless in Allow everything; no canvas tools
Pasted imagesYesYesYesNo
Sub-agentsOwn windowOwn windowOne row, not their own windowNo
Auto modeYesNoNoNo
Effort settingYesNoNo uses its defaultNo models name their own level
Usage windows in the status lineYesNoNoNo
Take back a queued messageYesNoNoNo
Memory per sessionIts own claude processAbout 300 MB its own opencode serverAbout 250 MB its own codex app-serverIts own agy process
  • OpenCode privacy

    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.

  • Codex trust

    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.

  • Antigravity is limited

    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.

  • Limits and commits

    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.

How the permission modes map onto Codex
Ask first
Asks before edits, and before any command Codex doesn't consider safe.
Plan only
Never asks, and nothing it runs can write. It doesn't hand you a plan to approve: it answers in the chat.
Allow edits
Approves file changes inside the project only: not in .git, .codex, .agents or .claude, and not renames out of it.
Always allow
Covers a command or edit until the card's Codex process closes (after 30 idle minutes, or to stay under DRAWA_MAX_LIVE; it asks again after resuming). Drawa doesn't save Codex's permanent command rules, and canvas changes ask each time.
Changing modes
Applies from the next turn (a message sent mid-turn joins the running one), except that leaving Allow everything stops a running turn, since it can't lose full access mid-turn.

Runs on your machine, with the agent you already set up.

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.

  • Stays local. The server checks Host and Origin on every request, and file access stays inside the folder you opened.
  • Reach it from your phone. drawa --net prints a network link with a one-time token and a QR code.
  • No Claude subscription? Start OpenCode sessions with any provider it supports or its free models, Codex with your ChatGPT plan, or Antigravity with your Google sign-in.
Terminal~/code/api
$ 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

Keep your hands on the keyboard.

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.

N
New session
C
Next session
CtrlK
Find a window, file, symbol or command
D
Draw on the canvas
S
Scratchpad
G
Git
Shift1
Fit everything
Space+ drag
Pan
Vor1
Select
H
Hand (pan with a drag)
Spacehold
Pan for a moment
Shift1
Fit all
Shift2
Zoom to selection
Shift0
Zoom to 100%
F
Fit
+or-
Zoom in / out
←→↑↓
Pan (Shift: bigger steps)
N
New session
CorShiftC
Next / previous session (Enter to type)
T
Sticky note
S
Scratchpad
9
Insert a picture
G
Git
ShiftG
GitHub
ShiftH
History & files
CtrlK
Find a window, file, code symbol or command
?
All shortcuts

Enter after C puts you in that session's message box.

WorShiftW
Next / previous window
M
Collapse or expand
ShiftF
Full view
F2
Rename
ShiftP
Pin to the sidebar
ShiftS
Stick to the screen
]or[
Bring forward / send backward
Shift]orShift[
Bring to front / send to back

They act on the selected window, else the one in front. W selects, so Delete, the arrows and CtrlG act on it.

Ctrl/⌘S
Save
:w
Save (Vim)
:q
Stop editing (Vim)
:q!
Drop unsaved changes (Vim)
:wqor:x
Save and stop (Vim)
gdorgD
Where a name is declared, in the function / file (Vim)
CtrlO
Jump back (Vim)
EscthenTab
Leave the editor

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.

D
Toggle Draw mode
Por7
Pen
Aor5
Arrow between items
Eor0
Eraser
Tor8
Text
Ror2
Rectangle
3
Diamond
Oor4
Ellipse
Lor6
Line
CtrlZ
Undo
Esc
Stop

Hold Shift for a square, a circle or a 45° line.

Ctrl/⌘A
Select all
←→↑↓
Nudge (Shift: 10px)
Delete
Remove
Esc
Clear
Ctrl/⌘G
Group the selected windows
Ctrl/⌘ShiftG
Ungroup the selected groups

Grouping windows that hold groups merges them. With nothing selected, CtrlG makes an empty group.

Enter
Send
ShiftEnter
New line
Esc
Leave the box
↑
Previous message, at the start
↓
Next message, at the end
/
Skills and slash commands
@
Reference a file or canvas item

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.

  • Drag the background to select in Select mode, or to pan in Hand mode. Phones start in Hand mode.
  • The middle button and the wheel always pan. Shift + scroll goes sideways.
  • Ctrl + scroll or a pinch zooms, and the zoom is saved with the canvas.
  • Jumping to a window with CtrlK, C or a notification keeps the zoom, unless the window would be under 50% or wouldn't fit: then it zooms to fit, at most 100%.
  • Click a picture or diagram for full view, and click again to zoom and pan it.

The details, when you need them.

The command line, what Drawa needs, and how to configure it. The full story is in the README and INSTALL.md.

drawa
Opens the current folder at http://127.0.0.1:8765 in your browser. Press N for a new session and start typing.
drawa ~/some/project
Any other folder.
drawa --net .
Also listens on your network address, like a Vite or Next.js dev server, and prints a link with a one-time ?token= plus a QR code for your phone. --net works in any position.
drawa https://github.com/owner/repo
Clones the repo into a cache folder and opens it; reruns reuse the clone. A folder link like /tree/main/docs opens the repo on its default branch.
drawa --clean
Removes cached clones, or pass one repo's URL. Keeps any clone with uncommitted, unpushed, stashed or ignored files. Don't run it while a Drawa is open on that clone.
drawa --update
Updates to the latest release.

Trusting 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.

Requirements
Claude CodeOne agent required claude on PATH and logged in, for your Claude subscription.
OpenCodeOr, instead or as well: opencode on PATH, for any other provider or its free models. Tested with 1.18.32.
CodexOr: codex on PATH and logged in, for your ChatGPT plan or an OpenAI API key. Tested with 0.158.0.
AntigravityOr: agy on PATH, signed in once by running agy in a terminal. Limited: no approvals or canvas tools. Tested with 1.2.16.
gitOptional 2.36 or later. Powers the Git window, file history and find references.
ghOptional Powers the GitHub window.
universal-ctagsOptional 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.
OSmacOS or Linux. Windows isn't supported natively yet, but Drawa runs inside WSL2.
From sourceGo 1.22+ and Node 20.19+ (or 22.12+). See Build from source.
Environment variables
VariableDefaultPurpose
DRAWA_PORT8765Port to serve on. Set it to run two projects at once.
CLAUDE_CONFIG_DIR~/.claudeClaude Code's config directory, if you keep a separate login or set of skills for Drawa.
DRAWA_NET_TOKENfresh each runThe --net token. Drawa sets it itself so the token survives its self-restarts; set it only to pick your own.
DRAWA_MAX_LIVEno capMost 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_DEVunset1 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"
}
uifull
full 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.
themesystem
system follows your computer's light or dark mode; light or dark fixes it.
lightScheme, darkSchemeclaude-light, claude-dark
The color scheme for each mode, such as rose-pine-dawn, catppuccin-mocha or nord. Try them on this page.
symbolsauto
auto reads code symbols with universal-ctags when it's installed; off never runs it.
vimoff
on 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.
Per browser
Fonts, and which key sends a message.

Drawa is built to run locally, for one user.

  • Localhost only. The server listens on 127.0.0.1 unless you pass --net, and checks the Host header on every request either way.
  • A token for the network. With --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.
  • Same-origin changes. Any request that changes something must come from Drawa's own page, with a matching Origin.
  • Confined files. File access stays inside the project folder you opened.
  • Per-process tool tokens. Claude's canvas tools use a token per process, so only that session's own claude can call them.

Found a vulnerability? Please open a private security advisory rather than a public issue. See SECURITY.md.

Built in the open.

Everyone who has committed to Drawa, opened an issue or pull request, or joined the discussion, most active first. Add your face here.

drawamain
$ cat contributors.json
counting…

Install it in one line.

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
  1. Open a projectcd ~/my/project && drawa
  2. Start a sessionpress N and type
  • Claude Pro or Max planClaude Codecurl -fsSL https://claude.ai/install.sh | bash
  • ChatGPT plan or OpenAI API keyCodexnpm install -g @openai/codex
  • No paid plan, or another providerOpenCodecurl -fsSL https://opencode.ai/install | bash
  • Google accountAntigravityagy
  • One agent, logged in. Any of the four on your PATH is enough. git and gh are optional.
  • On Windows? It isn't supported natively yet, but it runs inside WSL2. Install your agent there too.
  • drawa: command not found? Add ~/.local/bin to your PATH, or see manual downloads and building from source.

Like Drawa?

A star on GitHub helps more people find it. Hit a bug or have an idea? Tell us, it shapes what gets built next.