Content
# ✳ agent-sidecar
[](https://github.com/smarchetti/agent-sidecar/actions/workflows/ci.yml)
[](https://www.npmjs.com/package/agent-sidecar)
[](https://agent-sidecar.vercel.app/docs.html)
**A visual canvas for coding agents.** Your agent shows you interactive HTML — design options, forms, previews, dashboards — in your browser, and your clicks flow straight back into the conversation. Works with Claude Code, Cursor, Codex, or any MCP client.
[](https://agent-sidecar.vercel.app/)
> *"Show me three layout options for the settings screen"* → three clickable mockups appear on the canvas → you click one → Claude continues with your choice.
agent-sidecar is an MCP server with an embedded web server, packaged as a Claude Code plugin — and usable from [any MCP client](#use-with-other-agents). It needs no push mechanism (works on orgs where Claude Code channels are blocked): the browser-to-agent return path is a long-poll the server turns into ordinary tool output.
**Website & full docs → [agent-sidecar.vercel.app](https://agent-sidecar.vercel.app/)** ([documentation](https://agent-sidecar.vercel.app/docs.html))
## Quick start
Requires [Bun](https://bun.sh) on your PATH. In any Claude Code session:
```
/plugin marketplace add smarchetti/agent-sidecar
/plugin install agent-sidecar@agent-sidecar
```
Restart Claude Code, then ask for something visual: *"show me three layout options for a pricing page on the canvas."* The browser opens, the artifact renders, and clicking it answers Claude.
## Use with other agents
agent-sidecar is a standard MCP stdio server, so any MCP client can run it — the plugin is just Claude Code packaging. Point your agent at:
```json
{ "mcpServers": { "agent-sidecar": { "command": "bunx", "args": ["agent-sidecar"] } } }
```
| Agent | Config file |
| --- | --- |
| Cursor | `.cursor/mcp.json` (project) or `~/.cursor/mcp.json` (global) |
| VS Code (Copilot) | `.vscode/mcp.json` — same entry under a `"servers"` key |
| Codex CLI | `~/.codex/config.toml` — `[mcp_servers.agent-sidecar]` with `command`/`args` |
| Gemini CLI | `~/.gemini/settings.json` |
| Windsurf | `~/.codeium/windsurf/mcp_config.json` |
Everything transfers: the tools, the canvas, the token auth, the `.sidecar/` files. Two Claude-flavored details to know: the injected browser helper is still named `claude.send()`, and the background-watcher pattern requires an agent that can run shell commands in the background — the blocking `await_interaction` tool works everywhere.
## How it works
One process, two faces:
```
Claude Code ⇄ MCP/stdio ⇄ agent-sidecar ⇄ HTTP 127.0.0.1 ⇄ browser canvas
│
└── POST /api/webhook ← CI, scripts, anything
```
1. **Claude shows** — `create_artifact` puts a complete HTML document on the canvas (SSE-live; new artifacts take focus, updates hot-reload).
2. **You click** — every artifact gets a `claude.send(payload)` helper injected. It crosses a postMessage bridge out of the sandboxed iframe; the canvas shell forwards it to the webhook with the session token.
3. **Claude continues** — either a blocking `await_interaction` call returns your payload in-turn (quick decisions), or a background `curl /api/wait` watcher re-invokes Claude when you click (long waits, Claude keeps working meanwhile).
Every interaction is also appended to `.sidecar/interactions.jsonl` — a durable, `tail -f`-able audit log.
## Reference (short version)
**MCP tools** — `create_artifact`, `update_artifact`, `await_interaction` (blocking, `artifact_id` filter), `get_interactions` (drain), `list_artifacts`, `remove_artifact`.
**HTTP** — `GET /` canvas · `GET /events` SSE · `GET /artifact/:id` · `POST /api/webhook` (token) · `GET /api/wait` long-poll (token) · `GET /health`.
**Sessions** — each agent session runs its own agent-sidecar: port `8765` preferred, ephemeral fallback if taken. Coordinates (port, URL, auth token) live in `.sidecar/session.json`, which is how external systems push events in:
```bash
url=$(jq -r .url .sidecar/session.json); token=$(jq -r .token .sidecar/session.json)
curl -X POST -H "X-Sidecar-Token: $token" -d "build failed on main" "$url/api/webhook"
```
Full parameter tables, artifact-authoring patterns, and the security model are in the **[docs](https://agent-sidecar.vercel.app/docs.html)**.
## Security in one paragraph
Localhost-only binding; a random per-session token required on `/api/webhook` and `/api/wait` (defeats cross-site POSTs from web pages at localhost); artifacts run in an opaque-origin sandboxed iframe with no access to the token, the canvas shell, storage, or same-origin network — `claude.send()` is their only output channel. Don't tunnel or port-forward the server: anything that reaches the webhook is eventually placed in front of Claude. [Details.](https://agent-sidecar.vercel.app/docs.html#security)
## Development
```bash
bun install
bun test # 24 end-to-end tests over real MCP stdio
claude --mcp-config dev.mcp.json # run your working copy live (disable the plugin first)
```
Source is `src/sidecar.ts` (the whole server) and `src/canvas.html` (the browser shell, inlined into the bundle). Releases: bump `package.json`, the `agent-sidecar@<version>` pin in `.claude-plugin/plugin.json`, and CHANGELOG, then push and tag `vX.Y.Z` — GitHub Actions tests, publishes to npm with provenance, and cuts the release.
## License
MIT