Skip to content

Latest commit

 

History

84 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Wterm Terminal Preview for BB

CI

A Ghostty-backed terminal panel for BB. It attaches to a terminal session owned by the current BB thread, keeps the stock BB terminal untouched, and adds file transfer and terminal-specific font controls.

This repository is an early public preview. The plugin ID is wterm-terminal-preview, so it can coexist with BB's bundled wterm-terminal while the integration is evaluated.

The latest tag is v0.4.2, and it matches main: mouse-wheel travel is quantized before SGR forwarding, so a precision trackpad does not scroll a Herdr pane one notch per tiny browser event. Clickable OSC 8 web/file links and plain-text link detection are unchanged, as are bounded Kitty Graphics and the optional full-page Herdr/Wterm launchers.

Features

  • Ghostty terminal emulation through @wterm/ghostty 0.5.0 and WebAssembly.
  • Dark first paint while WASM and the Nerd Font load; leftover TUI colors are not kept on scrollback rows.
  • Composer shortcut: a terminal button in the chat footer. If a Wterm tab is already open in this thread, it reveals that panel. If none is open, it creates a new session. On BB hosts that support experimental_primarySurface, chat collapses so the terminal fills the thread; use Exit Full Screen to return. Packaged BB 0.40.0 does not include that host API, so the same button opens the side panel or session picker instead.
  • Optional full-page shortcuts in BB's left sidebar. Herdr launches herdr with its ram icon; Wterm launches a standalone shell. Each shortcut creates and owns an independent PTY.
  • Bundled Symbols Nerd Font Mono fallback for Powerline, Starship, and Nerd Font prompt icons; no local font installation is required.
  • Every Wterm terminal tab starts an independent thread-scoped terminal. + / a new tab always creates a new PTY. It never silently reopens the previous session from localStorage. Attach to an existing session only from the picker, by clicking that row.
  • The session picker distinguishes loading, a failed list (with Retry), and an empty list. Dead linked sessions show as unavailable/exited, not as running.
  • Select and restart existing thread-scoped BB terminal sessions when needed.
  • Keyboard, resize, wheel, click, and button-drag mouse input for terminal UIs.
  • Persistent font size controls from 10px to 24px.
  • Native, character-level text selection contained inside the terminal and copied on selection. The copy event is scoped to the terminal, so surrounding BB message rows are never included.
  • OSC 8 hyperlinks and plain-text link detection: see Terminal links.
  • Kitty Graphics direct PNG/RGB/RGBA output with bounded image storage and upstream placement/scrollback/resize handling.
  • OSC 52 clipboard writes from TUIs such as Herdr, plus cell-based copy-on-drag while mouse tracking is enabled. Copy uses a synchronous clipboard write during the pointer gesture so it still works when async clipboard permission is missing.
  • File upload by button or drag-and-drop, plus image upload from the clipboard.
  • Files are written on the terminal host and their quoted path is inserted at the prompt using bracketed paste.
  • Compatibility with BB hosts that expose the legacy terminal WebSocket.

Terminal links

Every clickable thing in the terminal goes through one handler, fed by two sources.

OSC 8 hyperlinks. When a program emits them, the anchor is rendered as given and clicked as given. Most TUIs only do that when they recognize the terminal, and a BB terminal session does not identify itself — pi-tui, for example, stays silent when TERM_PROGRAM is unset, which is the usual case here.

Plain-text links. Output that arrives as plain text is scanned after each render, and tokens that are plainly links become the same a.term-link anchors:

  • https://… / http://… URLs;
  • absolute paths such as /var/log/app.log or file:///tmp/notes.md;
  • workspace-relative paths such as docs/README.md;
  • path:line and path:line:column locations, which open at that position.

The scan runs per row on the rows that changed, inside a 4 ms per-frame budget, so a long scrollback is not held up. It stays deliberately narrow — a false link is worse than a missed one:

  • a token must contain a separator and end in something that looks like a file extension, so 3/4.5, and/or and v1.2.3 are left alone;
  • glob patterns (**/src/*.ts) are ignored;
  • a home shorthand (~/notes.md) is ignored, because it cannot be resolved without the home directory and a literal ~/notes.md would open the wrong file;
  • a link that a row wrap cut in two is stitched back together: rows that continue the same line are planned as one text, and each visible fragment becomes an anchor for the whole link. A row that filled its last column continues into the next one; while output is still streaming, a link whose last fragment sits on the final painted row is left alone until the next row settles it.

Where a link opens

Link Destination
http(s)://… BB's browser preference (navigate.openUrl), with window.open as the fallback. Only http: and https: are ever handed over, re-checked at the sink.
Path inside the thread's workspace BB's file-opener pipeline as a workspace file — the same identity rendered Markdown uses, so per-extension opener preferences apply.
Path outside the workspace, or a terminal with no thread workspace BB's file-opener pipeline as a host file, on the session's host.

A relative path is resolved against the directory the terminal was opened in (the panel asks the server for the thread workspace through the threadFileSource RPC). Segments that would climb out of the workspace fall back to the host route, and a relative path on a terminal without a workspace is not opened at all.

Choosing the viewer

BB renders the first applicable file opener for an extension unless one is pinned, so a third-party opener does not win on its own. To open terminal links in the Files plugin, pin it under Settings → Files for the extensions you care about (Automatic restores the built-in choice). BB's own preview and file-manager openers are the defaults for most extensions.

Terminal output is untrusted: any program can print a path or emit OSC 8. Both routes re-validate what they open, so a link can only ask BB to display a page or a file.

Requirements

  • BB 0.35.1 or newer with plugin SDK ^0.4.1 and host file writes.
  • Single-tab presentation requires a BB build that supports experimental_claimedTerminalId. Older hosts still work, but also show the same session in a native terminal tab.
  • git, npm, and bb available on PATH.
  • Network access to GitHub and the npm registry during installation.

Install

Install the pinned release:

bb plugin install 'git:github.com/Diffuzmetall/bb-wterm-terminal-plugin@v0.4.2' --yes
bb plugin source wterm-terminal-preview

To run the current main instead of a release tag, install @main.

Open a BB thread and choose Wterm terminal from the new-tab menu. Each activation, including + for another tab, creates a new terminal session. The picker in an existing tab can still attach to a running session.

To add full-page launchers to BB's left sidebar, open this plugin's settings page and enable either or both options under Configuration:

  • Show Herdr in the left sidebar — starts herdr in a full-page Wterm terminal.
  • Show Wterm in the left sidebar — starts a standalone shell in a full-page Wterm terminal.

Both options are off by default, so installing the plugin does not add sidebar items unless you ask it to. Closing or leaving either page closes only the PTY created by that page; existing Herdr workspaces and agents keep running inside the Herdr runtime.

The chat composer also has a terminal button. If a Wterm tab is already open, it reveals that panel; otherwise it creates a new session. On BB hosts that support experimental_primarySurface, it collapses chat so the terminal fills the pane (Exit Full Screen returns to chat). Packaged BB 0.40.0 ignores that flag and opens the side panel or picker instead; reloading the plugin cannot add full-screen Chat ↔ CLI to that app.

Update

Pinned release tags do not advance through bb plugin update. Replace an installed release explicitly:

bb plugin remove wterm-terminal-preview
bb plugin install 'git:github.com/Diffuzmetall/bb-wterm-terminal-plugin@v0.4.2' --yes
bb plugin source wterm-terminal-preview

To install from the latest commit on main instead of a release tag:

bb plugin install 'git:github.com/Diffuzmetall/bb-wterm-terminal-plugin@main' --yes
bb plugin source wterm-terminal-preview

Once the plugin is installed from main, update it with:

bb plugin update wterm-terminal-preview --yes

Release tags are recommended because a pinned source is reproducible. Updating a pinned tag, or switching between a tag and main, requires the remove-and-install sequence above.

Terminal controls

  • Use the - and + toolbar buttons to change the terminal font size. The setting is remembered in the browser.
  • In a normal shell, drag across characters to select text. The completed selection is copied even if the drag ends outside the grid, without copying surrounding BB rows.
  • When a TUI such as Herdr has enabled mouse tracking, click and drag are sent to the TUI. Dragging across cells copies the selected cell text immediately; it does not copy whole rendered rows. Hold Shift while dragging to use browser-native selection instead.
  • OSC 52 clipboard writes from the TUI (Herdr copy-on-select, Vim y, and similar) are applied to the system clipboard during the next terminal click if the browser blocked the original write. Clipboard queries are ignored.

Renderer and shell

The plugin uses libghostty through @wterm/ghostty as its VT and Unicode core. @wterm/dom paints that state as an HTML terminal grid, so settings from the native Ghostty application do not control this embedded terminal. The bundled Nerd Font fallback supplies prompt icons consistently across machines.

Seeing zsh is normal: it is the shell process running inside the Ghostty-backed terminal. A separate neighbouring native zsh tab is different; that means the BB host does not yet support experimental_claimedTerminalId.

File and image transfer

Use Upload file, drop a file over the panel, or paste an image. The plugin sends the bytes through an authenticated BB plugin route and bb.sdk.files to the host that owns the selected terminal. It does not implement a second SCP or SSH client.

Uploads are stored under <terminal cwd>/.bb-wterm-uploads/ with randomized names and mode 0600. The plugin verifies the returned size and SHA-256 before inserting the path. Images are limited to 10 MiB and other files to 25 MiB.

Hyperlinks and Kitty Graphics

OSC 8 links emitted by programs inside Wterm are clickable. HTTP(S) links open through BB's browser preference; absolute file:// links open in BB Files/file preview. The target must be reachable through the current BB host/workspace.

Test a web link:

printf '\033]8;;https://example.com\033\\WEB_TEST\033]8;;\033\\\n'

Test a file link by replacing the path with an existing host file:

printf '\033]8;;file:///absolute/path/to/README.md\033\\FILE_TEST\033]8;;\033\\\n'

Wterm also accepts direct Kitty Graphics PNG/RGB/RGBA sequences. A minimal RGB smoke test that displays a green rectangle is:

printf '\033_Ga=T,f=24,s=1,v=1,c=12,r=6,m=0;AP8A\033\\'

Uploading an image does not automatically display it as Kitty Graphics: upload stores the file and inserts its path in the shell. A Kitty-compatible client must send the graphics escape sequence, for example for a small PNG:

printf '\033_Ga=T,f=100;' && base64 -w0 ./image.png && printf '\033\\'

Large PNG payloads must be chunked according to the Kitty Graphics protocol.

Manage the plugin

bb plugin list
bb plugin reload wterm-terminal-preview
bb plugin disable wterm-terminal-preview
bb plugin enable wterm-terminal-preview
bb plugin remove wterm-terminal-preview

The two sidebar toggles live on the plugin's settings page under Configuration. Changes apply to the desktop sidebar immediately.

If the BB host daemon restarts and the selected terminal is no longer available, reopen the Wterm panel and select or restart a terminal session.

Security model

  • The WASM and upload endpoints require BB's per-plugin HTTP token.
  • An upload is accepted only when the terminal belongs to the requested thread.
  • File writes use the terminal's host and initial working directory as the BB file boundary.
  • Upload names are randomized; existing files are not overwritten.
  • The repository contains no credentials and the plugin does not persist BB tokens.

Before installing code from main, review the current commit. Prefer a signed or otherwise trusted release policy for production deployments.

Development

git clone https://github.com/Diffuzmetall/bb-wterm-terminal-plugin.git
cd bb-wterm-terminal-plugin
npm ci
npm test
npm run build

Before changing dependencies or the checked-in WASM, run the same fail-fast check used by npm run build:

npm run wterm:preflight

It compares installed @wterm/{core,dom,ghostty,react} package metadata with package.json and the root package-lock.json, then compares the repository ghostty-vt.wasm SHA-256 with the installed @wterm/ghostty copy. A mismatch stops before bb plugin build, so existing dist/ artifacts remain untouched. The build writes dist/wterm-build-provenance.json with the verified versions and WASM SHA-256. For safe dependency recovery, reinstall from the committed lockfile and rerun the check:

npm ci
npm run wterm:preflight

Do not bypass the check with a custom WASM; update the pinned dependency and repository asset together.

The standalone tests protect thread scoping, upload limits and integrity, safe host paths, terminal replay ordering, queued input and resize, and detach behavior. They run against this repository's sources without importing the BB workspace.

The build produces the frontend and server bundles in dist/ and copies ghostty-vt.wasm and the bundled Nerd Font from the repository. Generated dependencies and build output are intentionally not committed.

About Contributions

About Contributions: Please don't take this the wrong way, but I do not accept outside contributions for any of my projects. I simply don't have the mental bandwidth to review anything, and it's my name on the thing, so I'm responsible for any problems it causes; thus, the risk-reward is highly asymmetric from my perspective. I'd also have to worry about other "stakeholders," which seems unwise for tools I mostly make for myself for free. Feel free to submit issues, and even PRs if you want to illustrate a proposed fix, but know I won't merge them directly. Instead, I'll have Claude or Codex review submissions via gh and independently decide whether and how to address them. Bug reports in particular are welcome. Sorry if this offends, but I want to avoid wasted time and hurt feelings. I understand this isn't in sync with the prevailing open-source ethos that seeks community contributions, but it's the only way I can move at this velocity and keep my sanity.

License

MIT

This standalone plugin is derived from the Wterm integration originally developed in get-bb/bb, so it preserves that repository's MIT copyright notice.

The bundled Ghostty WASM renderer comes from @wterm/ghostty, which is distributed under the Apache-2.0 license.

The Herdr sidebar mark follows the official ram.svg from the Apache-2.0-licensed Herdr project.

SymbolsNerdFontMono-Regular.woff2 comes from Nerd Fonts v3.5.0 and is distributed under the included MIT license.

About

Ghostty-backed, thread-scoped terminal plugin for BB with file upload and font controls

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages