#37

feat: add @wterm/search for grid and scrollback find

Openmvanhornwants to merge intofrom

Adds @wterm/search, a new package that finds text across the visible grid and the 1000-line WASM scrollback ring buffer.

Closes the Ctrl+F gap today: the browser's native find only matches DOM-rendered rows, so anything scrolled out of view (which in wterm lives in the WASM ring buffer, not the DOM) is silently unmatchable.

Usage

import { WTerm } from "@wterm/dom";
import { Search } from "@wterm/search";

const term = new WTerm();
term.open(document.getElementById("terminal")!);

const search = new Search(term);
const next = search.findNext("ERROR");
const prev = search.findPrevious("ERROR");
const all  = search.findAll("ERROR", { caseSensitive: false, regex: false, wholeWord: false });

Each match returns { row, col, length, source: "grid" | "scrollback" }, so callers can layer an overlay, jump-to, or count UI on top.

Scope

v1 returns match positions. Overlay rendering (CSS Highlight API) is deliberately out of scope for this PR to keep the surface small; it can land as a follow-up that consumes these positions.

Approach

  • New package only: packages/@wterm/search/
  • Zero runtime deps
  • Reads grid and scrollback through existing @wterm/core exports
  • Options: caseSensitive, regex, wholeWord

Testing

New tests in packages/@wterm/search/src/__tests__/:

  • findNext / findPrevious wrap-around behavior
  • findAll across grid + scrollback boundary
  • case, regex, whole-word options
  • empty needle and no-match paths

Full repo CI is green: pnpm test, pnpm format:check, pnpm typecheck, pnpm build all clean.

Demo

Search finds ERROR across the live grid and the scrollback buffer. The faded rows on the right live in the WASM ring buffer, not the DOM, so browser Ctrl+F misses them and findNext("ERROR") reaches them.

Notes

  • No changes to @wterm/core or @wterm/dom
  • No new runtime dependencies
  • Docs page and API reference entry added per AGENTS.md

🤖 Generated with Claude Code

Activity

4
vercel[bot]6mo ago

@mvanhorn is attempting to deploy a commit to the Vercel Labs Team on Vercel.

A member of the Team first needs to authorize it.

socket-security[bot]2mo ago
mvanhorn2mo ago

Rebased onto main. The only conflict was pnpm-lock.yaml, which I regenerated with pnpm 10.11.0 to match the pinned packageManager.

Worth flagging that regenerating re-resolved 22 transitive packages beyond this PR's own additions. pnpm install --frozen-lockfile validates, but if you would rather keep the lockfile churn out of this PR, say so and I will pin it back to main's and let your release tooling pick it up.