Terminal core licensing

A terminal session you can stream to every screen

Solo's terminal is split in two: a smart Rust core that owns the session, and a dumb, fast renderer that paints whatever the core tells it to. We built it for coding agents that run all day. Now the core is available to license.

No SDK and no price list yet. Just tell us what you're building.

Why it exists

The terminal was the hardest part of Solo

Solo runs coding agents next to your dev stack, and every one of those agents lives in a terminal. Some stay open all day, streaming output the entire time. Getting that terminal right took longer than anything else in the app. It wasn't close.

We didn't start from scratch. Solo started on ghostty-web, then moved to xterm.js v6 in February 2026. Both are good projects, and both put the whole terminal inside the webview: the parser, the screen, the scrollback, and the renderer.

That's where it fell apart for us. Switching tabs or reattaching meant replaying output into a fresh terminal. Heavy output caused flashing and constant repaints. And the webview, the most disposable part of a desktop app, held the only correct copy of the screen.

So in March 2026 we moved the terminal into Rust and deleted xterm.js, for a net change of 5,303 fewer lines. The webview became a renderer and nothing else.

Rust owns the truth. The screen just paints it.

How it works

A smart core and a dumb renderer

The core runs next to the process. It reads the PTY, keeps the screen and the scrollback, and turns every change into a small patch. A renderer never sees a raw byte.

01 · The process

A real PTY

A shell, an agent, or a full-screen TUI. macOS, Linux, and Windows through ConPTY.

raw bytes →

02 · The Rust core

Owns the session

  • Reads the PTY and parses every escape sequence
  • Owns the grid, cursor, modes, and scrollback
  • Diffs each frame into row and cell patches
  • Tracks each viewer's position and delivery credit

snapshots · patches · history →

03 · The viewers

Paint what they're told

  • Solo desktopShipping

    WebGL2 renderer with a Canvas 2D fallback

  • More attaches to the same sessionBuilt in

    Each with its own sequence, queue, and credit

  • Remote and mobile viewersIn development

    A headless host and a native iOS client on the same protocol

← receipts

What goes over the wire

Snapshot

The full visible grid, cursor, modes, title, and a tail of recent history. A viewer gets one on first attach, or any time it can't safely resume.

Frame patch

Only what changed: replaced rows or cell spans, inserted or deleted rows, and cursor or mode changes when they happen. Binary MessagePack, coalesced to about 60 per second per viewer.

History delta

New scrollback lines as they scroll off. A huge burst sends a marker instead, and the viewer pages in only what someone actually scrolls to.

Receipt

Every body carries a random 128-bit token. The viewer sends it back the moment the body arrives, which is how the core knows what was really delivered.

What it solves

Six problems you don't have to solve again

Sessions that never end

An agent can run all day and print far more than any screen can hold. The core keeps 10,000 lines of scrollback in compact 256-line pages. A viewer only holds a window around what you're looking at and fetches older pages when you scroll. Memory stays bounded whether the session is ten minutes old or ten hours old.

  • 10,000-line scrollback, paged
  • Viewers retain about 2,000 lines
  • Raw output capped at 10 MiB

One session, many screens

Viewers don't share a stream. Each attach has its own sequence numbers, queues, and delivery credit, so a slow viewer can't hold back a fast one. The core talks to viewers through a small sink interface. In Solo that's a Tauri channel, but nothing in the protocol assumes one.

  • Many attaches per terminal
  • Per-viewer state
  • Transport behind a sink trait

Floods that don't freeze the UI

When a build or an agent dumps megabytes of output, the core keeps reading the PTY and never waits on the UI. Each viewer can have at most 8 messages or 1 MiB of frame and history data in flight. Credit comes back only when the viewer confirms that exact body arrived. Not a timeout, and not a count. If a viewer falls too far behind, the core drops its queued patches and sends a fresh snapshot instead of a backlog.

  • Exact-receipt credit
  • Producers never block
  • Overflow recovers with a snapshot

Reattach without corruption

Reload the UI, switch tabs, or restart the process, and the viewer comes back to the right screen. Every attach says what it already has: run epoch, history generation, and screen sequence. If the core still holds the gap (up to 256 patches), the viewer resumes. Otherwise it gets a snapshot. Patches from an old run or an old attach are rejected, so a restart can't paint stale output over new output.

  • Run, history, and screen fences
  • Resume or snapshot, never a guess
  • Stale patches dropped

Fast rendering that doesn't think

The renderer paints cells. It never parses. Solo's renderer draws with WebGL2 from a glyph atlas and uploads only the rows that changed. It falls back to Canvas 2D when WebGL2 isn't available, the context is lost, or Linux is software rendering. Theme and font changes apply in place without restarting the session. And because the renderer is dumb, writing another one is a contained job.

  • WebGL2 + glyph atlas
  • Dirty-row uploads
  • Canvas 2D fallback

Emulation tested against other terminals

The core handles what agents and TUIs actually use: the alternate screen, synchronized output (mode 2026), bracketed paste, SGR mouse, focus events, the Kitty keyboard protocol, OSC 8 links, OSC 52 copy, true color, and wide characters. Its test suite imports cases from Alacritty, libvterm, xterm.js, and vttest, plus recorded sessions of lazygit, tmux, and vim.

  • Imported conformance cases
  • Property-based fuzzing
  • Real TUI recordings

Who it's for

Products where the terminal matters but isn't the product

Agent interfaces

Chat-style or IDE-style products that still need a real terminal for the agent, the shell, or the TUI the agent just launched. Sessions run for hours and have to look right in more than one place.

Remote and cloud dev environments

The process runs on a server and the screen is a browser tab, a desktop app, or a phone. The server should own the session, and every client should be cheap to start and safe to throw away.

Control panels for long-running processes

Workers, pipelines, lab equipment, robots: anything you watch and steer from more than one screen, and never want to restart because a dashboard reloaded.

The alternatives

What else you could use

There are good free options. Here's where each one fits, as fairly as we can put it.

xterm.js

Great for one terminal in one browser tab.

The default web terminal for good reason: MIT-licensed, mature, a deep addon ecosystem, and the terminal inside VS Code. It's built to be the whole terminal on the client, so every viewer gets raw bytes and parses its own copy. You can keep state on the server with @xterm/headless and restore it with the serialize addon (both marked experimental), which is roughly what VS Code does. Flow control across the network is yours to build.

Read the full xterm.js comparison

libghostty

The closest free alternative, and an excellent one.

libghostty-vt is a smart core too: a zero-dependency C and Zig library with terminal state, scrollback, reflow, per-row dirty tracking for renderers, and a snapshot format still in progress. We evaluated it for Solo. It's an emulator you embed, so what sits around it is yours to build: the patch protocol, receipt-based backpressure, reattach fences, history paging, and delivery to many clients at once. Its creator's new company, Superlogical, has said it will ship a multiplexer built on libghostty, so watch that space.

See libghostty

Build it yourself

Very doable. We did it.

Parsing escape sequences is the well-documented part. Delivery, recovery, scrollback, and rendering under heavy output are where our time went. If your product is the terminal, build it. If your product is the thing running inside the terminal, maybe don't.

Where it stands

What's true today

This page is us asking whether anyone wants this. We'd rather you know exactly what exists before you email.

It ships today

This is the terminal in Solo on macOS, Windows (through a pinned ConPTY), and Linux. It runs coding agents, dev servers, and TUIs all day.

It isn't a standalone library yet

The core lives inside Solo's Rust codebase. Packaging it for your product is part of the conversation, and we'd shape that around what you need.

Remote viewing is in development

A headless host and a native iOS client already speak the same patch and receipt protocol. A network transport between machines is the next step. Neither has shipped.

Some things it doesn't do

No image protocols (Sixel, Kitty graphics). OSC 52 is copy-only. Processes stop when Solo quits, so the core outlives a window or a reload, not the host app.

Questions

Terminal licensing FAQ

Can I download an SDK?

Not yet. There's no public SDK or package. Tell us what you're building and we'll talk through what licensing the core would look like for you.

How much does it cost?

There's no price list. It depends on what you need from the core and how you'd ship it. Email us and we'll figure it out together.

Does Solo use xterm.js?

No. Solo used xterm.js v6 for about seven weeks in early 2026, then replaced it with the Rust core and a custom renderer. Our test suite still imports escape-sequence cases from xterm.js, and we're grateful for them.

Can I use it with a browser client?

That's the shape it was designed for. The core runs next to the process, and viewers only receive snapshots, patches, and history. Solo's current renderer is TypeScript running in a webview, and the iOS client in development shows the protocol works outside one.

Is it open source?

No. The core is part of Solo's commercial desktop app. Licensing is how other teams would get it.

Why not just use libghostty?

You might! libghostty-vt is excellent and free. If you only need terminal state you can embed, start there. If you need that state streamed to several clients with backpressure and safe reattach, that's the part we've already built.

Tell us what you're building

What runs in the terminal, where the processes live, and how many screens need to see them. We'll tell you straight whether the core is a fit.

Email [email protected]