scrawl
scrawl
A tldraw canvas floating over your entire screen — the drawing surface of Annotate with tldraw's tooling, drivable by coding agents the way tldraw offline is.
- Hotkey (
Alt+Shift+A, orSCRAWL_HOTKEY) toggles between click-through and drawing.Alt+Shift+Cclears every display. Esc returns the mouse to whatever is underneath. - Menu bar
✏︎icon (✎while drawing): every tool with its keyboard shortcut, colour, thickness, fade duration, undo/redo, clear, quit. There is no Dock icon. - Marks you draw fade after 5 seconds by default — change or disable it under Fade in the menu.
- The on-screen chrome is optional. Interface switches the toolbar, style panel, menu, zoom
controls, and helper buttons off individually or all at once, down to bare canvas. Your choices and
the fade duration persist in
~/.scrawl/prefs.json. - Agents read and edit the live canvas over a local HTTP bridge — see
.agents/skills/scrawl/.
pnpm install && pnpm dev # or: pnpm build && pnpm start
Agent skill
.agents/skills/scrawl/SKILL.md teaches a coding agent to drive the overlay — how to authenticate,
what each endpoint does, and where it departs from tldraw offline. Link it into wherever your agent
looks for skills:
ln -s "$PWD/.agents/skills/scrawl" ~/.claude/skills/scrawl
Install it globally rather than per-project: it operates the running app from whatever repo you are in, which is rarely this one.
How it works
One transparent, borderless window per display, each running its own tldraw editor. The window sits
at screen-saver level with type: 'panel' so it floats over other apps' fullscreen spaces, and
ignores mouse events until you activate it — so it is invisible to your clicks in its resting state.
Decisions
- Electron over Tauri. The three macOS behaviours this app is made of — floating above fullscreen spaces, click-through toggling, and per-display placement — are one-line Electron APIs and objc glue in Tauri.
- The camera is locked. Page coordinates are screen pixels, so an annotation stays on the thing it points at. An unlocked camera would let a stray scroll slide every mark off its target.
- The agent bridge mirrors tldraw offline's dialect (bearer token in a
server.json,/api/search,/api/doc/:id/exec) instead of inventing one, so the existingtldraw-offlineskill's snippets and habits carry over. It listens on 7237 to stay out of that app's way. executeJavaScriptrather than a per-tool API. One endpoint hands agents the whole tldrawEditor; a hand-maintained tool surface would be strictly smaller and constantly out of date.- Overlays are ephemeral. Annotation is throwaway by nature — there are no files, no persistence,
and
helpers.saveDoc()exists only so tldraw offline snippets don't crash. - Fade only applies to marks made while the overlay has the mouse. Anything drawn through the bridge lands while the overlay is click-through and therefore persists: a gesture at something on screen should evaporate, an agent's diagram should not dissolve while you read it.
- The menu bar is the manual. Every tool sits in the tray menu with the shortcut tldraw already binds to it, so the shortcuts are discoverable without a tutorial and without a second keymap to maintain — the menu documents tldraw's own handling rather than duplicating it. It is also what makes hiding the on-screen chrome safe: with every panel switched off, the menu bar still drives every tool, colour, and action.
Security
The bridge binds to 127.0.0.1 and requires a per-launch token from ~/.scrawl/server.json (mode
0600). Anything holding that token can run arbitrary JavaScript in the overlay renderer. That is the
feature, and the reason it is not exposed off-machine.
License
scrawl's own code is MIT. The tldraw SDK it depends on is not: the
tldraw license permits development use and
renders a "get a license for production" watermark, which the license forbids removing or interfering
with. Production use or distribution needs a license key from tldraw.dev —
drop it into the licenseKey prop in src/renderer/App.jsx.
