Throwaway Excalidraw sketch window for AI coding prompts: drag in images, mark them up, paste a small stamped JPEG. The agent can draw back.
Overview
A throwaway sketch window for showing an AI coding agent what you mean. Press a hotkey. An Excalidraw window opens, with any images you just copied already on it. Crop them, arrange them, circle the bit you mean in red. Press (⌘↵): the window closes and a small, flattened JPEG is on your clipboard, ready to paste into your prompt. Every flattened image carries a small stamp — napkin nk-0042 — and the editable canvas behind it is kept for a while. An agent that knows the convention can read the stamp, draw its own markup on your canvas ("do you mean this edge?") and pop the window back up for you. Needs bun, ImageMagick 7 and a Chromium-family browser (Chrome, Brave, Chromium, Edge or Vivaldi). macOS is the tested platform; Linux should work with wl-clipboard or xclip installed but has not been tested. That clones napkin into ~/.local/share/napkin/src, offers to install bun and ImageMagick with Homebrew if they are missing, builds it, links ~/.
README
napkin
A throwaway sketch window for showing an AI coding agent what you mean.
Press a hotkey. An Excalidraw window opens, with any images you just copied already on it. Crop them, arrange them, circle the bit you mean in red. Press Done (⌘↵): the window closes and a small, flattened JPEG is on your clipboard, ready to paste into your prompt.
yeah that makes sense, but for this airfoil I was thinking we have it
a bit more rounded here, kinda like this: [Image #1]
Every flattened image carries a small stamp — napkin nk-0042 — and the editable canvas behind
it is kept for a while. An agent that knows the convention can read the stamp, draw its own
markup on your canvas (“do you mean this edge?”) and pop the window back up for you.
Install
Needs bun, ImageMagick 7 and a Chromium-family
browser (Chrome, Brave, Chromium, Edge or Vivaldi). macOS is the tested platform; Linux should
work with wl-clipboard or xclip installed but has not been tested.
curl -fsSL https://raw.githubusercontent.com/Ian-q/napkin/main/install.sh | bash
That clones napkin into ~/.local/share/napkin/src, offers to install bun and ImageMagick with
Homebrew if they are missing, builds it, links ~/.local/bin/napkin, and asks three things:
- The hotkey. The default on macOS is a built-in ctrl+option+n: a tiny background helper
(compiled on the spot with Swift from Xcode’s command line tools;
xcode-select --installif you have never needed them) that needs no Accessibility permission. Or a line in skhd, or none. - The Claude Code skill, which teaches agents to read napkins and draw on them.
- A short note in
~/.claude/CLAUDE.mdtelling agents to draw their reading back on your sketch when they are unsure, instead of guessing. It sits betweennapkin:start/napkin:endmarkers (this text).
Run the same line again to update. --uninstall removes everything it added and leaves your
canvases. Prefer a checkout? git clone https://github.com/Ian-q/napkin && cd napkin && ./install.sh
works the same way (keep the folder where it is: the command points into it).
Answering up front, for scripts and dotfiles:
./install.sh --yes --hotkey builtin --claude-md # or --hotkey skhd|none, --no-claude-md, --no-skill
Hotkey
Tap it for a new canvas, hold it (about a third of a second) for the history. Anything that can
run a command on a keypress works: point it at ~/.local/bin/napkin hotkey.
- Built-in (macOS):
--hotkey builtin. ctrl+option+n. For another key (say, on a non-US layout), run the installer withNAPKIN_HOTKEY_KEYCODEset to a macOS virtual key code. - skhd:
--hotkey skhd, or addctrl + alt - n : ~/.local/bin/napkin hotkeyto~/.skhdrc. - Raycast: add
extras/raycastas a Script Commands directory and give “Napkin” a hotkey. Raycast cannot tell a hold, so givenapkin historya second hotkey if you want it. - Linux: bind
~/.local/bin/napkin newin your desktop’s keyboard settings.
napkin doctor shows which one is set up and whether it is running.
Using it
| Draw | The pen is selected and red when a new canvas opens. |
| Bring images in | Copy them first (select files in Finder and ⌘C, or copy a screenshot), then open a napkin: they are already on the canvas, laid out in a grid and selected, so Delete removes them if you didn’t mean it. Only what was copied since the last napkin comes in. macOS. |
| Add images | Drag them in or paste them. Several on one canvas is fine. HEIC and TIFF are converted on the way in. |
| Crop | Double-click an image, drag the handles, then press Enter or click outside it. The crop is not destructive: double-click again to widen it. |
| Done | ⌘↵ (Ctrl+Enter), or the red button. Flattens, copies, closes. |
| Abandon | Just close the window. The canvas is autosaved either way; one closed with nothing on it is handed out again next time. |
| History | Hold the hotkey, run napkin history, or click History in a canvas. Search finds typed text, ids and days; ↵ copies a past napkin to the clipboard again, ⌘O reopens it. |
| Library | Excalidraw’s library works and is shared by every canvas (~/.config/napkin/library.excalidrawlib). Excalidraw itself does not allow images in library items. |
Then paste into your prompt. In Claude Code that is Ctrl+V.
napkin [new] open a fresh canvas
napkin history browse, search, re-copy and reopen past canvases
napkin open reopen one
napkin list what is still in the rolling buffer
napkin path path of a canvas's flattened image
napkin doctor check the install
What ends up in context
The flattened image is resampled with Lanczos so its longest edge is at most 2000 px (never
upscaled) and saved as a quality-70 JPEG. For a vision model, the pixel dimensions are what
cost tokens; JPEG quality only affects bytes on disk and on the wire. Lower maxDim if you
want cheaper sketches.
The id stamp sits in its own strip under the drawing, so it never covers your sketch.
The round trip, for agents
Files live in ~/.cache/napkin/ ($XDG_CACHE_HOME and $NAPKIN_HOME are honoured):
| File | |
|---|---|
nk-0042.jpg |
the flattened image |
nk-0042.json |
sidecar: image size, and how image pixels map to canvas coordinates |
nk-0042.excalidraw |
the editable canvas (can be large: embedded images are base64) |
An agent draws in the coordinates of the image it was shown:
napkin annotate nk-0042 circle 640,420 90 "this edge?" arrow 300,500 520,410
napkin clear nk-0042 # remove the agent's markup again, never yours
napkin open nk-0042 # show the person
annotate re-flattens the canvas in a headless browser and prints the new image’s path, so the
agent can check its aim before showing you. --frac takes 0–1 fractions instead of pixels.
Agent markup is blue by default and tagged, so it can be removed without touching your strokes.
skill/SKILL.md teaches Claude Code all of this; the installer copies it to
~/.claude/skills/napkin/. For other agents, paste its body into their instructions.
Rolling buffer
Canvases are scratch paper. One is deleted once it is older than 30 days, or once there are 30
newer ones. Ids are never reused, so a stamp in an old conversation can never point at a
different sketch. napkin gc runs the cleanup by hand; it also runs whenever a canvas is opened.
Configuration
Optional, in ~/.config/napkin/config.json:
{
"maxDim": 2000,
"quality": 70,
"keepDays": 30,
"keepCount": 30,
"penColor": "#e03131",
"port": 47800,
"browser": null,
"clipboard": true,
"pasteOnOpen": true,
"holdMs": 350
}
browser is an app name on macOS ("Brave Browser") or a binary on Linux. pasteOnOpen brings
copied images into a new canvas. holdMs is how long napkin hotkey waits before it counts a press as a hold.
How it works
napkin starts a small server on 127.0.0.1 (it exits by itself about 90 seconds after the last
window closes) and opens the page in a chromeless browser window. The page is Excalidraw plus a
Done button. Done sends a PNG of the scene to the server, which resamples it with ImageMagick,
writes the sidecar and puts the JPEG on the clipboard. Nothing leaves your machine: Excalidraw’s fonts are served locally too.
The server only answers its own page and CLI. Each run generates a secret, kept in an owner-only file in the cache directory and handed to the window in the URL fragment; every request must carry it, requests from other origins are refused, and the CLI makes the server prove it holds the secret before trusting whatever is listening on the port.
Development
bun install
bun run build # web bundle → dist/web
bun test # unit tests, plus an end-to-end render through a headless browser
bun run dev # Vite dev server for the page, proxying the API to a running `napkin serve`
Licence
MIT. Excalidraw is MIT-licensed by its own authors.
Recommended Tools
Try a different keyword or remove a filter.
Install
npx skillfish add ian-q/napkin