RPQA · Terminal Engineering · 2026-06-12
Short version: a custom terminal built on xterm.js + node-pty (likely in Electron) is a completely normal terminal as far as Claude Code is concerned — and it adds five capability classes that no native macOS terminal offers. The deepest unlock isn't visual: it's that the terminal stops being a character stream and becomes structured data.
Other version: examples edition (plain English + challenge/solution)
xterm.js + node-pty VS Code's exact stackxterm.js renders the terminal in a DOM; node-pty spawns a real zsh behind it; a thin pipe connects them. Microsoft maintains both, and this is literally how VS Code's integrated terminal works — so "will Claude Code / vim / tmux run in it" is a settled question. Other production users: Wave, Tabby, Hyper, Azure Cloud Shell, JupyterLab, Codespaces, Replit.
github.com/xtermjs/xterm.js · github.com/microsoft/node-ptyIt's three Lego pieces: a part that draws the terminal on screen, a part that runs a real shell behind the scenes, and a wire between them. These are the exact same parts VS Code's built-in terminal is made of — and Microsoft maintains them — so there's no mystery about whether it works. You used Claude Code inside VS Code for months; that was this.
Sidebars, buttons, lists, web content — with a live JavaScript bridge to terminal state. Every native terminal tops out at styled text in a character grid. The lone partial exception is iTerm2's toolbelt webview, which can dock a panel but only "loads a URL," with no real bridge.
You can put normal app stuff — a sidebar, buttons, lists, even a small web page — right next to the terminal, and it can see and react to what's happening inside the terminal. Regular terminals can only ever show you text in a grid; they have no place to put a real button.
Tabs, headers, layout, proportional type — and one design system spanning the UI and the terminal (Coda tokens could style both). Natives offer config options, never new widgets.
Every pixel of the window is yours to design — the tabs, the title area, the layout, the fonts. The terminal and the rest of the app can share one look (your Coda styling could cover both). With normal terminals you can change colors and fonts, but the window furniture is whatever the vendor decided.
The Decorations API anchors a real DOM element to any buffer line — it scrolls with the text and disposes when the line scrolls off. That's how VS Code draws its exit-code dots. A "rerun" button or "ask Claude about this error" affordance on any line is the same mechanism.
xtermjs.org · Terminal APIYou can glue a button or badge to a specific line of terminal output, and it stays glued — scrolls with the text, disappears when the line does. Those little green/red dots next to commands in VS Code? That's this. Imagine an "ask Claude about this error" button appearing right on the error line.
Register custom escape-sequence handlers (registerOscHandler) and any CLI tool or shell function can talk straight to your UI — printf a message, a sidebar panel updates. No native terminal lets you define new sequences without forking.
Scripts and command-line tools can send invisible messages to your app — nothing appears on screen, but a sidebar panel updates. It's a private walkie-talkie channel between the shell and your UI. No off-the-shelf terminal lets you invent new messages like this.
Serialize the whole buffer to HTML or escape codes: save/restore sessions across restarts, export styled output, share a command + its output as a permalink (Warp's party trick), or serve the same app to a phone — Tabby ships a web build of itself; Codespaces runs this stack entirely in-browser.
Everything in the terminal — every command, all its output, with colors — can be saved like a document. Restore a session after a restart, export output as a styled web page, share a link to one command and its result, or open the same terminal on your phone.
Shell integration is the highest-leverage capability and it's invisible. A small script injected into zsh emits markers (OSC 133/633 — the public standard VS Code's terminal uses), and the app then knows, for every command: its text, where its output starts and ends, its exit code, its working directory, its duration.
Everything "smart" hangs off this: exit-code decorations, jump-between-commands navigation, sticky scroll, quick fixes, collapsible output, Warp-style blocks, a sidebar that reacts to failures. The terminal becomes data you can build product on.
Normally a terminal is a firehose of characters — it has no idea where one command ends and the next begins. A tiny tweak to the shell adds invisible bookmarks, so the app knows exactly: here's a command, here's its output, it succeeded (or failed), it ran in this folder, it took this long.
Once the app knows that, the terminal stops being a wall of text and becomes a list of things that happened — which you can navigate, collapse, decorate, and build features on. This is the single most valuable idea in the whole report.
| Capability | Best native answer | Verdict |
|---|---|---|
| Scriptable panes, send-text | WezTerm CLI, kitty remote control, iTerm2 Python | Natives fine |
| Styled status / tab bars, pickers, popups | WezTerm Lua, kitty kittens, tmux popups | Natives fine |
| Inline images, GLSL eye-candy | kitty graphics, OSC 1337, Ghostty shaders | Natives fine |
| Output-reactive triggers | iTerm2 regex triggers | Mostly fine |
| Interactive GUI sidebar / panel | iTerm2 toolbelt webview (~20% of the way) | Web only |
| Restyle the chrome itself | None — config options at best | Web only |
| DOM decoration of output lines | None — hyperlinks/images at best | Web only |
| Custom escape-sequence protocol | None without forking | Web only |
| One design system, UI + terminal | None | Web only |
To be fair to the terminals you already use: they're good at a lot. Controlling panes from scripts, fancy status bars, pop-up pickers, inline images, visual effects — all covered. That's the green half of the table.
The red half is the point: none of them can host a real sidebar, let you redesign the window itself, attach buttons to output, accept custom invisible messages, or share one design across UI and terminal. That's not "harder on native" — it's impossible without forking the terminal's source code.
WezTerm has quietly stalled — no stable release since Feb 2024, nightlies only; the sidebar request is open and unimplemented, and a user asking for "xterm.js-style UI buttons, AI panels" got zero replies. Ghostty will never do this by design — Mitchell Hashimoto explicitly rejected a do-anything extension API. kitty's kittens and panels always terminate at another character grid. Warp open-sourced its client (AGPL, Apr 2026) — proof that block/AI UX requires owning the whole app.
wezterm #5171 (sidebar request) · ghostty #2353 · warp.dev · open sourceSome news from the research worth knowing: WezTerm — your current terminal — has gone quiet. No proper release in over two years, and requests for exactly the kind of UI you want sit unanswered. Ghostty's creator has said flat-out he'll never add a plugin system. And Warp — the closest commercial product to this idea — had to build an entire terminal from scratch to do it, which rather proves the point.
Raw speed: VS Code-terminal-class, not Ghostty-class. The xterm.js maintainers themselves acknowledge the JS parser ceiling (they're exploring adopting libghostty's WASM core). Fine for Claude Code workloads; a purist daily-driver concern only.
Edge cases: compound-emoji width (experimental addon), no RTL, weaker screen-reader support than native, occasional IME quirks.
Ownership: it's an Electron app — auto-update, crash handling, node-pty rebuilds on Electron upgrades. Mitigated by a ~150-line core and two Electron apps already maintained.
xterm.js #5686 · "Explore adopting libghostty"The trade-offs, honestly: it's a touch slower than the fastest native terminals — about as fast as VS Code's terminal, which you used happily, so you almost certainly won't notice. A few rare quirks with unusual emoji and non-Western text. And it's an app you own — updates and maintenance are on you, though the core is tiny and you already maintain two Electron apps.
Wave Terminal Apache-2.0 · activeThe closest shipped product to "terminal + sidebar blocks + AI" — terminal blocks beside AI chat (Vercel AI SDK), web panes, Monaco editors, and charts, on Electron + xterm.js 6 + React 19. Best used as a source-code reference; fork only if its block/layout model is exactly the desired UX.
github.com/wavetermdev/wavetermSomeone already built almost exactly this idea — terminal panels next to AI chat, web pages, and editors — and gave the code away free. It proves the concept works. We'd read their code for answers rather than build on top of it, because their layout isn't quite what you want.
Hyper read, don't forkThe cleanest "all chrome is React" architecture — its plugin API proves the whole concept — but effectively unmaintained since January 2023.
github.com/vercel/hyperAnother existing project with a beautiful architecture worth learning from — but it's been abandoned for three years, so we wouldn't build on it.
~150 lines to a first working shell; every capability above is incremental from there. Maximum ownership, zero inherited architecture, and existing Electron patterns (window-state persistence, automation port, deep links) port directly.
The recommendation: start fresh. A working terminal is about 150 lines of code, and everything else gets added piece by piece. You own all of it, inherit nobody's decisions, and reuse patterns from your existing apps.
TERM=xterm-256color; VS Code's terminal is the same stack and runs it daily.Bottom line: Claude Code will run in it exactly as it does in WezTerm — it can't tell the difference. The payoff is a terminal that's also an app: your design, your sidebar, buttons on error lines, scripts that talk to panels, sessions you can save and share.
The costs are real but small for your use. The smart path is building it fresh (it starts tiny) while cribbing from the open-source project that already proved the idea.
The one decision deliberately not made yet: whether this becomes the successor to WezTabs + WezTerm as your daily Claude Code home. That's yours to sit with.