npx claudepluginhub frankjoshua/agent-canvasLive browser UI for Claude Code sessions, driven by a watched JSON state file.
A Claude Code channel plugin that gives a running session a live browser UI. Claude writes a JSON file, and the browser updates instantly.
claude plugin marketplace add frankjoshua/agent-canvas
claude plugin install agent-canvas
This installs the channel plugin, MCP server, and /canvas skill. No other setup needed.
Optionally create .canvas/ui-default.json in your project to define a starting layout.
cd /path/to/agent-canvas
bun install
CANVAS_PORT=8766 bun channel/index.ts --dev --project /path/to/your-project
Runs the HTTP server and file watcher only. Edit .canvas/ui-state.json by hand and see the browser update live.
The server binds to 0.0.0.0 by default — accessible from any device on the same network (phones, tablets, other machines via Tailscale, etc.). Override with CANVAS_HOST if needed.
Create .canvas/ui-state.json in your project:
{
"version": 1,
"title": "My Dashboard",
"theme": "dark",
"layout": "stack",
"components": [
{
"id": "greeting",
"type": "html",
"content": "<div class='card bg-base-200'><div class='card-body'><h2 class='card-title'>Hello</h2><p>Edit this file to update the UI.</p></div></div>"
}
]
}
html -- raw HTML with full DaisyUI + Tailwind classesmarkdown -- renders markdown to HTML, supports raw HTML passthroughform -- structured input form, submissions flow back as channel eventslog -- scrolling append-only log panelAdd data-input-event to any element in an html component to make it interactive:
<button class="btn btn-primary" data-input-event="confirm">Confirm</button>
Clicks send a channel event to Claude with the event name and parent component ID.
Each session gets its own port. The URL is printed to stderr and injected into the Claude Code session on startup.
--dangerously-load-development-channels flag (channels are in research preview)