ainnotations
v0.1.2
Published
Framework-agnostic visual feedback overlay for local dev — draw, highlight and comment on the running page; notes land in a markdown file for your coding agent to process.
Maintainers
Readme
AInnotations
Point at what's wrong on your running app. Your coding agent fixes it.
Draw on the page, highlight a phrase, drop a comment — each note lands in
annotations.md, indexed with the exact element, the quoted text and a
screenshot. No screenshots to crop, no "the third card on the left", no drag‑and‑drop.
The 30 seconds you keep losing
You spot something off in the browser. Today, telling your agent about it costs:
spot it → crop a screenshot → switch to chat → drag it in →
type "the pricing card, third bullet, the one on the left…" →
agent hunts for the element in the pixels → sometimes guesses wrong → repeatWith AInnotations you circle it, say what's wrong, and move on. The selector, the exact words and the picture are captured for you.
| | screenshot + drag‑and‑drop | AInnotations |
| --- | --- | --- |
| point at the element | describe it in words, hope | draw / select — captured exactly |
| what the agent receives | a flat image + your prose | element selector · quoted text · sketch · shot · viewport |
| locate the source | agent eyeballs the screenshot | grep the quote → lands on the line |
| per fix | ~90 s | ~12 s |
| a pass of 8 fixes | ~12 min, and fragile | ~2 min, then process the annotations |
Illustrative, not a benchmark — but the shape is real: the cost isn't the typing, it's making the agent find the thing you're already looking at.
Where CLIs and chat fall apart: the batch
Leave ten remarks across three pages in one pass. In a chat you'd paste ten crops and a numbered list — then hope the agent reconciles shot #5 with instruction #5, on the right button, on the right page. It's a guessing game that gets worse the more you add.
AInnotations doesn't guess. Every note is self‑contained and addressed:
## `a1b2c3` · /pricing · 2026-08-13 09:40 · 1440×778
- **Note** swap these two paragraphs
- **Element** `main > article > div.prose > p:nth-of-type(3)`
- **At** 0.12,0.30
- **Draw** M40,10L80,60 M50,10L55,40
- **Shot** annotations/a1b2c3.png
- **Text** « the passage that was selected »There's nothing to reconcile: each entry already knows its page, its element and its words. The agent reads the list, applies each one in order, and clears it. That's real indexing, not a pile of pictures.
Quick start
No SDK, no code change, no account. It's a proxy in front of your dev server — so it doesn't care whether you run Astro, Next, Nuxt, SvelteKit, Vue, Rails or Django.
# dev server on :4321 → browse the annotated app on :4000
npx ainnotations --target 4321Open http://localhost:4000 instead of your dev server. The overlay appears at the bottom‑left. That's it.
| flag | default | meaning |
| --- | --- | --- |
| --target | — (required) | port your dev server already runs on |
| --port | 4000 | port to serve the annotated app on |
| --file | annotations.md | where notes are written (relative to cwd) |
Install it for good
npx is perfect for a one‑off. To keep it in a project and give your coding
agent the skill permanently:
npm i -D ainnotations # pin the CLI in your project
npx ainnotations init # copy the skill into .claude/skills/ainnotations/init installs the companion Claude Code skill at project scope, so anyone
working on the repo can say "start ainnotations" and the agent runs the whole
loop — start → process the annotations → stop. Commit
.claude/skills/ainnotations/ to share it with the team.
Want it in every project instead of one? Install the skill globally:
mkdir -p ~/.claude/skills/ainnotations
cp node_modules/ainnotations/skill/SKILL.md ~/.claude/skills/ainnotations/The overlay
- draw — freehand over a region (circle it, arrow it — multiple strokes), then ✓ to comment. The ink is persistent and scrolls with the page. On send, a screenshot of your sketch over the page is attached to the note (one screen share grant per session, reused) — so the agent sees the intent, not raw path data. Decline it and the note still saves, minus the image.
- text — select words; the exact quote is captured and stays highlighted until the note is handled. It's the best search key there is — grep it, land on the line.
- list — opens a panel of every pending note; tap one to scroll straight to its pin and open it. The pins stay on the page the whole time — click any pin directly to read, edit or delete its note.
Dictation (🎤) and paste‑the‑selection are built in, and it all works on a phone. The toolbar itself is draggable: grab the handle to move it anywhere, and drop it against the left or right edge to stand it up vertically — its spot is remembered between reloads.
How it works
browser ──▶ :4000 ainnotations proxy ──▶ :4321 your dev server
├─ injects the overlay <script> into every HTML response
├─ serves /__ainnotations/client.js
├─ /__ainnotations/notes (GET/POST/PUT/DELETE) ⇄ annotations.md
└─ tunnels WebSocket upgrades, so HMR keeps workingThe overlay is pure DOM, so it runs anywhere. The proxy handles the two things the browser can't: injecting itself into the page, and writing the file on disk.
For the agent
Notes accumulate in annotations.md. Read the Shot image (it's the user's view
with the sketch), locate the source via Text (grep) or Element, apply Note,
then remove the entry — deleting a note also deletes its screenshot.
A companion Claude Code skill (skill/SKILL.md) automates the whole loop —
npx ainnotations init drops it into your project (see Install).
Then start → process the annotations → stop. Say "start AInnotations" or
"traite la liste" and it runs.
License
MIT © Florian Dupuis
