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/coreexports - Options:
caseSensitive,regex,wholeWord
Testing
New tests in packages/@wterm/search/src/__tests__/:
findNext/findPreviouswrap-around behaviorfindAllacross 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/coreor@wterm/dom - No new runtime dependencies
- Docs page and API reference entry added per
AGENTS.md
🤖 Generated with Claude Code
Activity
4Review the following changes in direct dependencies. Learn more about Socket for GitHub.
| Diff | Package | Supply Chain Security | Vulnerability | Quality | Maintenance | License |
|---|---|---|---|---|---|---|
| npm/@types/node@24.12.2 ⏵ 24.13.3 | +1 | +1 | -1 | |||
| npm/@vue/test-utils@2.4.6 ⏵ 2.4.11 | +6 | |||||
| npm/@tailwindcss/vite@4.2.2 ⏵ 4.3.3 | +1 | |||||
| npm/@vitejs/plugin-vue@6.0.6 ⏵ 6.0.8 | +1 | |||||
| npm/vue-tsc@3.2.7 ⏵ 3.3.9 | +1 |
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.
@mvanhorn is attempting to deploy a commit to the Vercel Labs Team on Vercel.
A member of the Team first needs to authorize it.