The free, open-source visual UI for Beads — Steve Yegge's
graph-based issue tracker for AI coding agents.
Brainstorm, create, and organize work in the same place your AI agent does.
🌐 Website ·
![]() Detail drawer — inline edit, deps & comments |
![]() Live dependency graph |
A local, single-user web UI for beads
(bd) — Steve Yegge's distributed graph issue tracker. beads ships a powerful CLI
but no interactive visualizer that also lets you create work. This app is that
visualizer: a fast, graph-aware task board for humans, on top of a tracker built
for AI agents.
- Board — a five-column view (Backlog · Ready · In Progress · Blocked · Done)
with dense cards showing id, type, priority, assignee, dep/comment counts, and an
origin badge. Filter by type / priority / origin, full-text search, and a
show/hide-archived toggle. Keyboard:
nnew,/search,Escclose. - Backlog ↔ Ready drag-and-drop — drag cards between columns to change status
(Backlog =
deferred, Done =bd close); updates are optimistic. - Create / edit — add tasks and epics (type, priority, description, assignee, labels, parent epic, start-in-backlog) and edit status/priority inline.
- Epics & progress — epics with live
closed ÷ childrenprogress bars and expandable child lists; add a child straight into an epic. - Dependencies & graph — view/add/remove typed dependencies in the detail drawer, plus an interactive React Flow dependency graph (drag node→node to link).
- Comments — author-stamped comment threads with a composer on every bead.
- Archive & delete — archive (reversible
bd close+archivedlabel) or delete (bd delete, behind a confirm). - Human-vs-agent attribution — every bead and comment shows 👤 (human) or 🤖 (agent), derived from a configurable human allowlist.
- Settings — repo path, human actor + allowlist, poll interval, and light/dark theme. Live polling keeps the board fresh when agents change data underneath you.
- beads has no HTTP API, so the app shells out to the
bdCLI (bd … --json,BD_JSON_ENVELOPE=1).bdstays the single source of truth — the app adds zero new persisted schema. The only adapter islib/bd.ts; see the spec indesign/design.md. - The UI was designed in Claude Design and rebuilt faithfully here with
Next.js + shadcn/Tailwind. The original export and a screen/token map live in
design/ui-export/.
- Backlog maps to beads' built-in
deferredstatus; Ready = open & unblocked. Dragging between columns runsbd update --status/bd close. - beads has no human-vs-agent flag, so the UI stamps its own writes with a
configured human actor (
BEADS_ACTOR); anyone in the human allowlist renders as 👤, everyone else as 🤖. Archive =bd close+ anarchivedlabel (reversible); Delete =bd delete.
Prerequisites: Node 20+ and npm. For live mode you also need the
bd binary on your PATH and a .beads
repo (bd init). No bd? The app falls back to demo mode automatically.
npm install
npm run dev # http://localhost:3000- With real data: run from (or point Settings at) a directory containing a
.beadsrepo, withbdon yourPATH. Override the repo withBEADS_REPO=/path/to/projectand the binary withBD_BIN=/path/to/bd. - Demo mode: if
bdisn't installed (or you setBEADS_DEMO=1), the app runs against an in-memory dataset seeded from the design export — so you can explore every feature without beads. The sidebar shows which mode is active.
Set the human actor / allowlist, repo path, and theme in Settings (stored under your OS config dir, not in beads).
docker build -t bead-me-up-scotty .
docker run -p 3000:3000 bead-me-up-scotty # → http://localhost:3000The build runs
npm ci, which needs the committedpackage-lock.jsonfor reproducible installs. The lockfile is tracked in the repo (a.gitignorenegation keeps it that way even if your global gitignore excludes lockfiles), so a clean clone builds without a priornpm install.
The image includes the bd CLI, so real data works out of the box — just
mount your project directory and point BEADS_REPO at it:
BEADS_REPO=/path/to/project
docker run -d -p 3000:3000 \
--name beads_ui \
-v $BEADS_REPO:/data \
-e BEADS_REPO=/data \
bead-me-up-scottyThe container runs as a non-root nextjs user with HOME=/home/nextjs and
XDG_CONFIG_HOME=/home/nextjs/.config, so bd and app settings have a valid
runtime config directory. On Linux, if bd fails with permission errors writing
to the mounted .beads directory, run as your host user: --user $(id -u):$(id -g)
(the config dirs are world-writable, so settings keep working). Settings live
inside the container, so they are lost when it is recreated — bind-mount the
config dir to keep them:
-v "$HOME/.config/bead-me-up-scotty:/home/nextjs/.config/bead-me-up-scotty"Container limitations:
- The image has no
git, so Dolt remote sync (refs/dolt/data) andbd initdon't work inside it — run those on the host. UI edits (create/update/close) work fine; they just won't auto-push until you sync from the host. - Refine with AI shells out to the Claude Code CLI, which isn't bundled; the button shows an error in the container.
- The bundled
bdversion is pinned in the Dockerfile (ARG BD_VERSION); override with--build-arg BD_VERSION=<version>to match your host.
Install once from a clone, then run scotty (or bead-me-up-scotty) from any
directory. It starts the production server on a free port (default 3000) and opens
your browser. Run it from a folder that has a .beads repo to jump straight to
that project; otherwise you get the project picker. Requires Node 20+.
Flags: -p, --port <n> · --no-open · --help.
Recommended — npm link (keep the clone):
git clone <repo-url> bead-me-up-scotty
cd bead-me-up-scotty
npm install
npm run build
npm link
scotty # from anywhereThe global command is a symlink to the clone, so keep it on disk and re-run
npm run build after pulling changes. Uninstall: npm rm -g bead-me-up-scotty.
Alternative — global copy (clone is deletable):
git clone <repo-url> bead-me-up-scotty
cd bead-me-up-scotty
npm install
rm -rf .next # ensure a clean build (only the prod build is shipped)
npm run build
npm install -g .
scotty # from anywhere; the clone can now be deletedTo update, rebuild and re-run npm install -g .. If npm install -g . hits a
permissions error, use a user-owned npm prefix:
npm config set prefix ~/.npm-global and add ~/.npm-global/bin to your PATH.
Next.js 16 (App Router) · React 19 · TypeScript · Tailwind v4 · shadcn/ui ·
TanStack Query (polling + optimistic DnD) · dnd-kit (board) · @xyflow/react
(dependency graph) · Zod (validates bd output and forms).
app/ # pages + API route handlers (the only server entry points)
api/beads/** # GET list, POST create, [id] PATCH/DELETE, status, comments, deps, archive
api/doctor, config # bd preflight + local config
lib/
bd.ts # the ONLY bd CLI bridge (execFile, JSON envelope, write mutex)
demo-store.ts # in-memory fallback seeded from the export
store.ts # picks bd vs demo
schema.ts # Zod schemas + types (bd data model)
beads-view.ts # pure view-model helpers (status/priority colors, blocked, epic progress)
attribution.ts # human-vs-agent origin
components/ # sidebar, board (dnd), detail drawer, create modal, epics, graph, settings
npm run build # typecheck + production build
npm run lint # eslintMIT © Brendan

