IQ

ian-q/napkin

Developer tools
0 stars Quality 39 Trend 8

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:

  1. 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 --install if you have never needed them) that needs no Accessibility permission. Or a line in skhd, or none.
  2. The Claude Code skill, which teaches agents to read napkins and draw on them.
  3. A short note in ~/.claude/CLAUDE.md telling agents to draw their reading back on your sketch when they are unsure, instead of guessing. It sits between napkin:start/napkin:end markers (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 with NAPKIN_HOTKEY_KEYCODE set to a macOS virtual key code.
  • skhd: --hotkey skhd, or add ctrl + alt - n : ~/.local/bin/napkin hotkey to ~/.skhdrc.
  • Raycast: add extras/raycast as a Script Commands directory and give “Napkin” a hotkey. Raycast cannot tell a hold, so give napkin history a second hotkey if you want it.
  • Linux: bind ~/.local/bin/napkin new in 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.

View this README on GitHub

Recommended Tools

Try a different keyword or remove a filter.

Install

npx skillfish add ian-q/napkin