| name | proto-buddy |
| description | Use when designing UI, comparing HTML layout options, or running a visual review with human-in-the-loop annotation. Triggers on "/proto-buddy", "design companion", "visual review", "compare designs", "brainstorm designs", "mockup feedback". Overrides superpowers:brainstorming visual companion for design review workflows.
|
Proto Buddy — Design Companion
Interactive design review server. Each HTML file in a watched directory becomes a browser tab; the user clicks elements to annotate; annotations land in a JSONL file that you consume through a blocking watcher script. You edit, tabs hot-reload, repeat.
Preflight
Both are REQUIRED. Check before starting:
command -v fswatch || echo "MISSING: brew install fswatch"
command -v node || echo "MISSING: node v18+"
Use command -v node, not node --version — on nvm-managed shells the node shell function can recurse and crash even though node works fine.
If fswatch is missing, watch-one.sh exits instantly with no output — indistinguishable from "no feedback yet". Do not skip this check.
Startup Sequence
1. Resolve the directory as an ABSOLUTE path
Default: <project-root>/.ai/brainstorm. The server resolves relative paths against its own cwd — if you start the server with one relative path and Write files with another, the server watches an empty directory and reports no error. Use one absolute <DIR> everywhere below.
2. Start the server
${CLAUDE_PLUGIN_ROOT}/scripts/start.sh --dir <DIR> --port 3333
Optional: --actions "keep,remove,size-up,size-down,recolor" to customize quick actions.
On success it prints server info JSON. On "Server failed to start": the real cause is in <DIR>/.dc.log — read it. Common causes:
- Port in use → retry with
--port 3334 (note: stop.sh only kills the server whose PID file is in the SAME dir; a server started from another dir holds the port until killed by its own PID file or manually).
- Node missing/old.
3. Open the browser
open http://localhost:3333
If open fails (headless, non-macOS), just tell the user the URL.
4. Write design options
Each .html file in <DIR> becomes a tab, hot-reloaded on every write.
- Full documents (starting with
<!doctype or <html) are served as-is.
- Anything else is a fragment and gets wrapped in a synthetic
<html><body> — element selectors the user generates will include that wrapper.
5. Arm the watcher — ALWAYS in the background
${CLAUDE_PLUGIN_ROOT}/scripts/watch-one.sh <DIR>
Run this with run_in_background: true. It blocks indefinitely until one new event arrives, prints all unread events, and exits — running it in the foreground hangs the session until the user happens to click. If unread events already exist, it returns them immediately. You are notified automatically when it completes; read its output then.
Do NOT consume feedback by reading .events directly — that does not advance the cursor, so the next watcher call returns duplicates. .events is history reference only.
Feedback Loop
When the watcher completes:
- Parse each JSONL line.
- Locate the element in the source file named by
tab. The selector is a generated CSS path (div > ul > li:nth-child(3)) — it is NOT text you can grep for. Walk the file's DOM structure to find the target; use comment text and coords as corroboration. Selectors captured before your last edit may no longer resolve — prefer the comment's meaning over a stale path.
- Apply the
action, address the comment, Write the file. Tab hot-reloads.
- Re-arm the watcher (background again). Loop until the user says they're done.
Empty watcher output is normal — always re-arm. Your own file writes append tab-reloaded events, which the watcher filters out; it can therefore exit with zero output. That is NOT "the user is done" and NOT an error — re-arm immediately.
Live vs Batch
- Live (default): each annotation arrives as its own event. React immediately.
- Interact: clicks and keys pass through to the design (inspector suppressed); use to operate keyboard-driven prototypes. No events are emitted.
Cmd+. toggles from anywhere — the topbar or inside the iframe.
- Batch: the user accumulates annotations, then clicks Apply Page (flushes active tab: N comments + one
apply-all for that tab) or Apply All (flushes every annotated tab: comments + one apply-all PER tab). The flush is a burst of writes and the watcher can return a PARTIAL batch. In batch mode, do not start editing until you've seen the apply-all sentinel(s) — if the watcher exits without one in its output (including EMPTY output), re-arm immediately and keep draining.
Event Schema
<DIR>/.events — append-only JSONL:
{"type":"comment","tab":"option-a.html","selector":"body > div > h1","coords":[340,120],"comment":"too much padding","action":"size-down"}
{"type":"update-comment","tab":"option-a.html","selector":"body > div > h1","comment":"better now","action":"keep"}
{"type":"apply-all","tab":"option-a.html"}
{"type":"tab-reloaded","tab":"option-a.html"}
update-comment has no coords; apply-all carries only tab.
- The watcher filters out
tab-reloaded — its output is user events only, a strict subset of .events.
Health & Recovery
Symptom Check Fix
Watcher exits instantly, empty output, repeatedly command -v fswatch brew install fswatch, re-arm
No events ever arrive kill -0 $(cat <DIR>/.dc.pid) Server died — read <DIR>/.dc.log, restart via start.sh
Tabs don't appear for written files Compare server's watched dir (<DIR>/.dc-info) with where you're Writing Use one absolute path everywhere
Duplicate events returned Did you read .events manually? Only consume via watch-one.sh; cursor lives in .events.cursor
Artifacts in <DIR>
File Purpose
.events Annotation history (JSONL, append-only)
.events.cursor Watcher read position — do not edit
.dc.pid Server PID
.dc.log Server stdout/stderr — first stop for any failure
.dc-info Server startup info JSON (port, dir)
Browser Reference
- Tab bar with per-tab comment badges; "NEW" indicator when you push changes the user hasn't viewed
- Mode toggle Live/Batch/Interact; Apply Page + Apply All buttons in batch
- History panel (
H), DevTools-style hover inspector, numbered annotation badges (click to edit)
- Alignment guides — the popover carries an "Align guides" row (top/bottom/left/right); each toggles a persistent full-viewport line on that edge of the selected element for eyeballing alignment. Visual only — guides emit no events; Clear All removes them alongside badges
- Shortcuts:
1-9 tabs · L/B mode · Cmd+. toggle Interact · H history · in popover: Enter submit, Shift+Enter newline · in batch outside popover: Enter = Apply Page, Shift+Enter = Apply All · Escape close popover
Shutdown
When the session ends:
${CLAUDE_PLUGIN_ROOT}/scripts/stop.sh --dir <DIR>