A react-trace plugin that turns comments and
component inspections into beads
issues via the bd CLI.
- Comments — ships its own comments UI (menu + inline editor). Every
comment has a bead checkbox (on by default, controlled by the
auto-add-beadsetting). Checking creates a bead; unchecking finds it by its marker and hard-deletes it. Each comment also has priority and label dropdowns on top of the settings defaults. - Components — inspect an element and use Create bead in the action panel to file a bead with the component info and source path.
- Settings —
auto-add-bead, default labels, and default status / priority / epic. Status, epic, and label options are fetched live from the bd CLI.
Plugins run in the browser and cannot execute CLI commands. This package
ships a tiny zero-dependency bridge (react-trace-beads, Node http) that
runs the bd commands for the plugin over HTTP on localhost:4790.
import { Trace } from '@react-trace/core'
import { PreviewPlugin, OpenEditorPlugin, CopyToClipboardPlugin } from '@react-trace/kit' // optional
import { BeadsPlugin } from 'react-trace-plugin-beads'
export function AppWithTrace() {
return (
<>
<App />
<Trace
root={import.meta.env.VITE_ROOT}
plugins={[PreviewPlugin(), OpenEditorPlugin(), CopyToClipboardPlugin(), BeadsPlugin()]}
/>
</>
)
}Replace the official CommentsPlugin with BeadsPlugin() — the beads plugin
provides the comments UI with bead controls.
npm i -D react-trace-plugin-beads
npx react-trace-beads --directory . # port 4790, or BEADS_BRIDGE_PORTRun it alongside your dev server (add a "beads": "react-trace-beads --directory ." script). The bridge shells out to bd in the given directory (each request can override via the Trace root), so run it from the repo that contains your .beads database.
| Option | Default | Description |
|---|---|---|
bridgeUrl |
auto | Bridge base URL — absolute (http://localhost:4790) or same-origin path (/beads-api when proxied by the dev server). Resolution order: explicit option → port-forwarding proxy hostname (Coder-style 5175--app--user.example.com, derived by swapping the port to 4790) → http://localhost:4790 |
bridgeToken |
— | Bearer token for the bridge when it runs with --token / BEADS_BRIDGE_TOKEN (needed when the bridge port is exposed publicly) |
The bridge only ever runs fixed bd subcommands (create/update/delete/statuses/list — no arbitrary shell), but if the port is reachable by others it can still be abused to spam or delete beads. Keep it on 127.0.0.1 (default) — for remote/proxied setups prefer same-origin proxying so the port is never exposed:
// vite.config.ts
proxy: {
'/beads-api': {
target: 'http://localhost:4790',
changeOrigin: true,
rewrite: (p) => p.replace(/^\/beads-api/, ''),
},
}
// main.tsx
<Trace ... plugins={[..., BeadsPlugin({ bridgeUrl: '/beads-api' })]} />If you must expose the port publicly, protect it with a token:
BEADS_BRIDGE_TOKEN=$(openssl rand -hex 32) react-trace-beads --host 0.0.0.0
# plugin: BeadsPlugin({ bridgeToken: '<same token>' })/api/health stays unauthenticated (safe); every other route returns 401 without a valid token. Requests to other origins are blocked by CORS. Only bind 0.0.0.0 if you really need to.
- Title: filename from the path (
Button.tsx) — comments add:line(Button.tsx:42) - Description: comment/component info,
Path,Absolute, and a uniqueMarker: rtc-<uuid>line - Metadata:
rt_comment_id=<marker>for reliable find-and-delete - Type:
task; priority, labels, status, and epic (--parent) follow settings + per-comment overrides
Unchecking a comment's bead checkbox deletes that exact issue (bd delete --force after lookup by marker).
| Endpoint | Description |
|---|---|
GET /api/health |
Bridge + bd availability |
GET /api/options |
statuses, priorities, epics, labels from bd |
POST /api/issues |
create bead (title, description, priority, labels, status, epic, marker) |
PATCH /api/issues/:id |
update priority/labels |
GET /api/issues?marker= |
find bead by rt_comment_id marker |
DELETE /api/issues/:id |
hard-delete bead |
npm install
npm run build:bridge # bridge server -> dist-bridge/
npm run build # plugin -> dist/ (tsdown)
npm run typecheck
npm run lint