The local-first editor for human-AI collaboration on HTML artifacts.
Quick Start · How It Works · Features · Commands · API · Hooks
One review session keeps artifacts, revisions, feedback, questions, agent messages, and approval together.
git clone https://github.com/shabeeth2/duet.git
cd duet
pip install -e .
duet review path/to/artifact.html --request "Create the artifact"┌──────────┐ ┌──────────┐ ┌──────────┐
│ Agent │◄─HTTP─│ Server │──SSE─►│ Browser │
│ (CLI) │ poll │ (FastAPI)│ events│ (Chrome) │
└──────────┘ └──────────┘ └──────────┘
- Agent runs
duet review artifact.html --request "..."— server starts, browser opens - Browser loads the artifact in an iframe with the annotation SDK injected
- Human annotates elements, types messages, clicks "Send to Agent"
- Agent runs
duet poll— blocks until feedback arrives - Agent makes changes, publishes a new revision, answers questions, and the same review session tracks approval
| Feature | Description | |
|---|---|---|
| 🎯 | Live Annotation | Click any element to annotate — feedback queued instantly |
| 🧾 | Review Sessions | Persist revisions, feedback, agent messages, timeline events, and approval |
| 💬 | Sidebar Chat | Real-time conversation between human and agent via SSE |
| 🔄 | Long-Poll | Agent blocks until annotations, warnings, or messages arrive |
| 📦 | Export | Inline all CSS/JS/images into one portable HTML file |
| 🎨 | Whiteboard | Excalidraw scenes embedded alongside Mermaid diagrams |
| 🔍 | Layout Audit | Auto-detect clipped text, overflow, unreachable content |
| 🪝 | Agent Hooks | SessionStart hooks for Claude Code, Copilot, OpenCode, Codex |
| Command | Description |
|---|---|
duet open <file> |
Open or resume a session |
duet review <file> --request <text> |
Open or resume a persistent review session |
duet session <file> |
Show the stored review session state |
duet poll <file> |
Long-poll for human feedback |
duet export <file> |
Export as self-contained HTML |
duet share <file> |
Export and publish to ht-ml.app |
duet end <file> |
End the current session |
duet setup hooks |
Install agent hooks |
duet server |
Run server in foreground |
The server runs on http://127.0.0.1:4387 and exposes a JSON API. Any tool can integrate.
Key endpoints:
| Method | Endpoint | Purpose |
|---|---|---|
POST |
/api/review-sessions |
Create a review session |
GET |
/api/poll?file=<path>&timeoutMs=<ms> |
Long-poll for feedback |
POST |
/api/<key>/prompts |
Submit annotations from browser |
POST |
/api/<key>/artifacts |
Submit new artifact revision |
POST |
/api/<key>/agent-messages |
Send agent chat message |
POST |
/api/<key>/approve |
Approve the review |
POST |
/api/<key>/end |
End session |
GET |
/events/<key> |
SSE stream for live updates |
Quick integration:
import httpx
# Create review session
r = httpx.post("http://127.0.0.1:4387/api/review-sessions", json={
"file": "path/to/artifact.html",
"original_request": "Create the artifact"
})
key = r.json()["session_id"]
# Agent polls for feedback
r = httpx.get(f"http://127.0.0.1:4387/api/poll?file=path/to/artifact.html&timeoutMs=30000")
feedback = r.json() # {status, prompts, dom_snapshot}Install hooks for your agent to auto-open duet on session start:
duet setup hooksSupported: Claude Code, GitHub Copilot, OpenCode, Codex. The hook runs duet <file> when an artifact path is detected.
| Variable | Default | Description |
|---|---|---|
DUET_PORT |
4387 |
Server port |
DUET_HOST |
127.0.0.1 |
Bind host |
DUET_STATE_DIR |
~/.duet |
State directory |
DUET_IDLE_TIMEOUT_MS |
1800000 |
Auto-shutdown timeout |
git clone https://github.com/shabeeth2/duet.git
cd duet
pytestMIT License
