This package is the browser-side annotation library. It builds to a browser IIFE that adds a floating toolbar, lets users select elements, captures comments and optional screenshots, and sends everything to the OpenCode Annotate plugin over WebSocket.
bun add @opencode-annotate/clientdist/index.js ESM package entry for bundlers
dist/index.d.ts TypeScript declarations
dist/annotate.global.js Browser global bundle for script tags
Build both outputs with:
bun run buildCheck the npm package contents without publishing:
bun run pack:dry-runPublish after logging in to the npm registry:
bun publish --access publicsrc/index.ts Public init function, queue state, caching, send logic
src/global.ts Browser global entry that exposes window.AnnotateClient
src/types.ts Client-local WebSocket protocol types
src/ws-client.ts WebSocket wrapper, reconnects, heartbeat, acks
src/annotator.ts Hover, click, drag-box selection, selector building
src/popup.ts Inline editor and queue/steer switch
src/toolbar.ts Floating draggable toolbar and queue controls
src/badges.ts Numbered badges for queued annotations
src/capture.ts html2canvas screenshot capture
src/logger.ts DEBUG-gated browser logging
src/styles.ts Injected scoped CSS
Add the built bundle to a page:
<script
src="./node_modules/@opencode-annotate/client/dist/annotate.global.js"
data-session="YOUR_SESSION_CODE"
data-server="ws://localhost:10300"
data-screenshots="true"
data-debug="false"
data-hotkeys="true"
></script>Attributes:
data-session: required session code from/annotate.data-server: optional WebSocket URL. Defaults tows://localhost:10300. Use the exact URL returned by/annotatewhen multiple OpenCode processes are running or the plugin binds to10301+.data-screenshots: set totrueto enable screenshots when using script-tag auto-initialization.data-debug: set totrueto enable browser console diagnostics. Defaults tofalse.data-hotkeys: set tofalseto disable global annotation hotkeys. Defaults totrue.
The global bundle exposes window.AnnotateClient, so a non-module page can also initialize manually:
<script src="./node_modules/@opencode-annotate/client/dist/annotate.global.js"></script>
<script>
window.AnnotateClient.init({
session: "YOUR_SESSION_CODE",
server: "ws://localhost:10300",
captureScreenshots: true,
debug: false,
hotkeys: true,
})
</script>Bundled apps can import the ESM package entry:
import { init } from "@opencode-annotate/client"
init({
session: "YOUR_SESSION_CODE",
server: "ws://localhost:10300",
captureScreenshots: true,
debug: false,
hotkeys: true,
})Options:
session: required session code.server: optional WebSocket URL. Defaults tows://localhost:10300.captureScreenshots: optional boolean. Defaults totruefor directinit()calls.debug: optional boolean. Defaults tofalse.hotkeys: optional boolean. Defaults totrue.
The package also exports teardown() for explicitly disconnecting the WebSocket, removing the toolbar, clearing popup UI, and unregistering hotkeys before reinitializing.
- Click the floating orb to open the toolbar.
- Enable annotation mode from the toolbar, or double-click the orb.
- Toggle annotation mode with
Cmd+Shift+Aon macOS orCtrl+Shift+Aon Windows/Linux. - Hover elements to highlight them.
- Click an element to open the annotation popup.
- Drag a box to select elements fully contained inside that box.
- Enter a comment and press
Enter, or click the submit button. - Send immediately in
Steermode, or collect multiple annotations inQueuemode and clickSend.
Queued annotations show numbered badges on their target elements. Clicking a badge reopens the annotation for editing.
Selected elements stay highlighted while the popup is open. Drag-box selections use a screenshot cropped to the selected page area when screenshots are enabled.
x: cancel the annotation.- Text input: write the annotation.
Entersubmits andShift+Enterinserts a newline. - Queue/steer icon: switch between queued batch mode and immediate send mode.
- Send icon: add or send the annotation.
Queue: stores annotations locally until the user sends them as oneannotate_batchmessage.Steer: sends each annotation immediately as anannotatemessage.
The selected mode is cached in sessionStorage per session and page path.
The client stores unsent queued annotations in sessionStorage using keys scoped to:
- Session code.
- Page origin.
- Page path.
When a batch is sent, it is first copied to a pending cache. If the WebSocket disconnects, the server returns an error, or an ack is not received within 10 seconds, the pending annotations are restored so the user can retry.
The client sends a ping with the session code after connecting, then every 15 seconds. It retries WebSocket connection attempts up to three times with delays of 0ms, 1000ms, and 2000ms. Reinitializing the client calls teardown() first so old sockets and UI are removed before a new connection is created.
Annotation messages include:
- Current page URL and title.
- Generated CSS selector.
- Element text.
- Element bounding rectangle.
- User comment.
- Optional PNG data URL screenshot.
The repo root includes test.html, which loads:
<script src="client/dist/annotate.global.js" data-session="test" data-screenshots="true" data-debug="true"></script>To use it, build the client, start OpenCode with the plugin loaded, and create a matching session:
/annotate test