Skip to content
vercel-labsPublic

About

A terminal emulator for the web

Resources

Contributing

Stars

3.7k stars

Watchers

8 watching

Forks

Repository files navigation

wterm

Vercel Labs Experiment npm version: @wterm/core License: Apache-2.0 npm downloads per month: @wterm/core

A terminal emulator for the web.

wterm ("dub-term") renders terminal rows as DOM text, so native text selection, copy and paste, browser find, and screen readers work on the mounted rows. The core is a VT parser written in Zig and compiled to a ~49 KB WASM binary.

Install

npm install @wterm/dom @wterm/react

For Vue or Svelte, install @wterm/vue or @wterm/svelte with @wterm/dom instead of the React package. Vanilla JavaScript needs only @wterm/dom. The WASM binary is embedded in the package, so no extra file needs to be served.

Quick start

import { Terminal } from "@wterm/react";
import "@wterm/react/css";

function App() {
  return <Terminal />;
}

In vanilla JavaScript, mount a terminal on an element:

import { WTerm } from "@wterm/dom";
import "@wterm/dom/css";

const term = new WTerm(document.getElementById("terminal"));
await term.init();

To connect a shell, send keyboard input from onData to a PTY backend and write its output back with term.write(), or use WebSocketTransport from @wterm/core. The SSH and local shell examples show both ends. Every framework is covered in Get started.

How it works

A terminal core parses escape sequences and holds the screen and scrollback. The DOM renderer reads the core's dirty rows on each animation frame and updates only those rows. History is a ring buffer, and only a bounded window of it is mounted in the DOM.

There are two cores. The built-in Zig core loads by default. @wterm/ghostty swaps in libghostty for fuller VT compatibility, including Kitty images, OSC 133 shell integration, and reflow of soft-wrapped lines. Both implement the TerminalCore interface, so the renderer and framework components work with either (Pluggable cores).

For pages with many busy terminals, renderer: "webgl" paints from one shared WebGL2 context while DOM text keeps selection, find, and screen readers working, and WorkerCore moves parsing off the main thread (WebGL renderer, Worker core).

Packages

Package Description
@wterm/core Headless WASM bridge, TerminalCore interface, WebSocket transport
@wterm/dom DOM renderer and input handler for vanilla JavaScript
@wterm/react React component and useTerminal hook
@wterm/vue Vue 3 component and template ref API
@wterm/svelte Svelte component and callback API
@wterm/ghostty VT emulation core powered by libghostty
@wterm/just-bash In-browser Bash shell powered by just-bash
@wterm/markdown Render Markdown in the terminal

For AI agents

Set webmcp on a terminal to register WebMCP tools. In-page agents can then list terminals, read the screen and scrollback, wait for output, type commands, and press keys:

<Terminal webmcp={{ name: "shell" }} onData={send} />

Add readOnly: true to the webmcp options when agents should read a terminal without typing into it or pressing keys.

term.readText() returns a text snapshot of retained history and the active screen. The docs are also available as Markdown from wterm.dev/llms.txt.

Documentation

Topic Docs
Install and first terminal Get started
Options, renderers, cores, WebSocket transport Configuration
Built-in themes and CSS custom properties Themes
Methods, events, selection, search, images API reference
Framework bindings React, Vue, Svelte, Vanilla JS
Ghostty core, image limits, shell integration Ghostty
In-browser shell and Markdown output just-bash, Markdown
Agent tools WebMCP
Runnable apps examples/
Release notes Changelog

Development

This repo is a pnpm workspace with Turborepo. Use Zig 0.16.0 or later, Node.js 24 or later, and pnpm 11. Dev servers run behind portless, installed globally.

pnpm install
zig build test
pnpm build
pnpm test

zig build -Doptimize=ReleaseSmall writes zig-out/bin/wterm.wasm and web/wterm.wasm. The committed binary is packages/@wterm/core/wasm/wterm.wasm, and CI fails when it does not match the Zig sources, so copy the release build there, run pnpm --filter @wterm/core build to regenerate the embedded copy, and commit the binary with any change under src/.

CONTRIBUTING.md covers the Ghostty WASM build, the docs site, the examples, and the PTY, replay, and performance suites. AGENTS.md lists the files to update with each change and the release process.

License

Apache-2.0

About

A terminal emulator for the web

Resources

Contributing

Stars

3.7k stars

Watchers

8 watching

Forks

Releases

Packages

Used by

Contributors

Languages