aio-html-interactivelisted
Install: claude install-skill aiocean/claude-plugins
# aio-html-interactive — bridge Claude to a browser via Monitor + WebSocket
## The problem this solves
Claude runs in a turn-by-turn CLI loop. It has no event loop, can't
`addEventListener` on a browser, can't block on `await userClick()`. So
how does an interactive UI — one the user is actually clicking on right
now — drive Claude's behavior while a task is in progress?
The answer two channels, both fronted by a single Bun HTTP + WebSocket
server:
- **Browser → Claude (input channel).** `RT.send(type, payload)` in the
browser POSTs `/api/event`; the server writes one line
`MSG::{instance,type,payload}` to stdout. The **Monitor tool** is
configured to pattern-match `MSG::` lines on that server's stdout and
surface each one as a notification. Notifications are how a turn-based
agent gets a "user-clicked-X" event without an event loop.
- **Claude → browser (output channel).** Claude POSTs
`/api/push {type,payload}` from any shell tool call; the server
broadcasts that JSON verbatim over WebSocket to every connected tab.
The runtime processes a small built-in vocabulary (`state` merge,
`toast`, `html`, `js`, `reload`) before dispatching to
app-registered handlers.
UI is vendored Vue 3 + Tailwind, no build step. Claude only writes the
**APP REGION** of `app.html`; the runtime, server, and vendor blocks
are frozen so the protocol stays intact across edits.
## Workflow
1. **Copy scaffold** —
`cp -r ${CLAUDE_PLUGIN_ROOT}/skills/aio-html-interactive/scaff