bb plugin screenshot: plan and capture marketplace listing screenshots from the running app - #2250
Draft
brsbl wants to merge 4 commits into
Draft
bb plugin screenshot: plan and capture marketplace listing screenshots from the running app#2250brsbl wants to merge 4 commits into
brsbl wants to merge 4 commits into
Conversation
A marketplace listing has to show the plugin's own UI, but nothing today tells an author which screenshots to take, and the entry has nowhere to put them. This adds the half that can be worked out without running anything: what to photograph, and where each shot lives. `bb plugin screenshot [path]` reads the plugin's frontend source, finds the surfaces it registers, and plans one shot per surface with the route to capture and the file to write. Source rather than dist/, because a submission screenshot has to be plannable before the plugin is built or installed anywhere. Surfaces split by how they are reached. A nav panel owns a URL, and homepage/settings/thread-list/sidebar surfaces render on a route or in chrome every route paints, so those are navigable. The rest only exist once a thread, composer, or open file is in a particular state; they are planned against one shared capture fixture, so every plugin's listing is shot against the same workspace and no author has to build one. Without a fixture thread they are reported rather than planned, so a listing never photographs the empty app. A plugin that registers no visual surface plans nothing and exits clean: an agent-tool or provider plugin has no UI to show, and its listing must not wait on a screenshot that cannot exist. The detector reads source text rather than parsing: it only has to answer whether the plugin paints somewhere, a false positive costs one skipped shot, and every plugin vendors SDK declarations that name every slot — which the walk skips along with dist/ and node_modules.
`bb plugin screenshot --capture <outDir>` now takes the pictures. A headless Electron window (the desktop package's own Electron — no new dependency) loads the author's running bb, asks the renderer which surfaces the plugin actually registered, navigates to each one, and writes one PNG per surface. Enumeration moved from source scanning to the running app. The author submitting a plugin has it installed, and the renderer is the one place that knows the real registrations — including the facts the scanner could not see: each nav panel's path, a directive's id, a file opener's extensions. The scanner remains only for the no-server plan printout. The app exposes one hook for this: `window.__bbPluginSlotSnapshot` in plugin-slots.ts, returning the existing snapshot. The harness reads ids and paths from it, never components. The harness (apps/desktop/scripts/plugin-capture.cjs) is deliberately not part of desktop main: capture needs a window and a URL, not the owned-runtime lifecycle. It requires Electron lazily so its planning half runs under plain node, where the CLI suite tests it against the same catalog the CLI plans from — one mapping test guarantees every capturable surface has a snapshot key. Verified end to end: the built CLI spawned the harness against a page exposing the hook, enumeration found three surfaces, and three PNGs of the right routes were written at 1440x900@2x.
Plugin frontends mount after the shell, so the harness was reading the slot snapshot before any plugin had registered and reporting "no surfaces" for every plugin. It now waits until the target plugin shows up in the snapshot, and on timeout says which plugins did register so a miss is debuggable. --app-url covers source dev instances, where Vite serves the app shell on a different port than the server; it defaults to the server URL, which is what a packaged bb serves.
brsbl
marked this pull request as draft
August 21, 2026 19:58
Capturing eight real plugins on a dev instance showed the gap this command actually has: six of the eight shots were empty states. The command finds the right surfaces and photographs them faithfully, and the result is still unusable for a listing, because nothing seeded the plugin's data first. The skill (plugin-listing-screenshots) is the missing judgement: which screens to lead with for each kind of plugin, what to seed before shooting, and what makes a shot unusable — an empty panel, a skeleton row, a lonely single item, a real secret. It names the seeding path that already exists: `bb.cli` is a plugin surface, eleven bundled plugins register one, and `bb tasks seed-demo` shows the convention worth copying. submit-a-plugin and the plugins guide both point at it. Two capture fixes came out of the same run. Re-check registration after navigating, not only before: seeding restarts a plugin's service, and a plugin that is briefly unregistered renders a blank route. Then wait for the DOM to stop changing rather than a fixed delay, so a panel that fetches after mounting is photographed with its content. Neither fix makes capture infallible — a panel that never finishes loading is still photographed mid-load — so the skill tells authors to open every image, and the command's own docs say the same.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds
bb plugin screenshot, which produces the screenshots a marketplace listing needs, plus the skill that says which ones are worth taking.Draft. The capture works end to end; the fixture-thread slice and a packaged-bb Electron path are not in it yet.
What it does
A headless window — the desktop package's own Electron, no new dependency — loads the running bb, asks the renderer which surfaces the plugin registered, navigates to each, and writes a PNG. Enumeration comes from the live app rather than parsing source: the author submitting a plugin has it installed, and only the renderer knows the real registrations, including a nav panel's path, a directive's id, and a file opener's extensions.
A plugin with no visual surface prints "no listing screenshots to take" and exits clean. That is the common case for agent-tool and provider plugins, and their listings should not wait on an image that cannot exist.
Testing it on real plugins is what shaped this
Eleven bundled plugins on a dev instance built from this branch. Eight captures — and six were empty states:
bb tasks seed-demo --yesThat gap is the point of the skill. The command finds the right surfaces and photographs them faithfully; whether the result sells the plugin depends on data existing first.
Two capture bugs came out of the same run, both fixed here:
Other captures, unseeded, showing surfaces that need no data:
connectsettingsconnectsidebar footergithub— an empty state the skill would rejectThe skill
plugin-listing-screenshotscovers what the command cannot decide: which screens to lead with for each kind of plugin, what to seed first, and what makes a shot unusable — an empty panel, a skeleton row, a single lonely item, a real secret or private repo.Its seeding advice names a path that already exists rather than inventing one:
bb.cliis a plugin surface, eleven of bb's bundled plugins register one, andbb tasks seed-demois the convention worth copying. The skill asks plugin authors with data to ship aseed-demosubcommand — a few lines that make their own listing images one command, and give reviewers a way to see the plugin working.submit-a-pluginand the plugins guide both point at it.Shape
packages/domainapps/app/src/lib/plugin-slots.tswindow.__bbPluginSlotSnapshot, over the existing snapshotapps/desktop/scripts/plugin-capture.cjscapturePageapps/clibb plugin screenshot [path] [--capture <dir>] [--app-url <url>] [--fixture-thread <id>] [--json]plugin-listing-screenshotsThe harness sits beside desktop rather than inside
main.tsbecause capture needs a window and a URL, not the owned-runtime lifecycle. It requires Electron lazily so its planning half runs under plain node, where the CLI suite tests it against the same catalog the CLI plans from.Verification
461 CLI tests, 154 domain tests, app/CLI/domain typecheck. The guide durability test enforces that the new subcommand and both flags are documented.
Not in this PR
--fixture-thread; the shared fixture that creates that thread, with a message carrying the plugin's directive id and a file of its claimed extensions, is the next slice.BB_ELECTRONcovers other cases.Found while testing, not fixed here
The Tasks panel renders placeholder rows that never resolve in a fresh window, though the sidebar shows the seeded counts and the DOM is quiet with no
animate-pulsenodes. Worth a look independent of this PR.BB-Thread-ID: thr_yrs6swfgtc
🤖 Generated with Claude Code