Collaborative terminal control plane

One terminal session. Many participants. Every byte multiplexed.

uterm creates, transports, secures, shares, records, replays, and arbitrates terminal sessions across browsers, WebSockets, telnet, SSH, local PTYs, and remote workers. xterm.js is the screen; uterm is the rest of the iceberg.

DLE/STX framing DeckMux presence MCP-native Durable Objects

Demo reel

All 17 demos โ€” control channel, DeckMux, MCP, graphical sessions โ€” concatenated.

1280x720 134.6s All demos โ†’

Recorded uterm sessions โ€” pick one and press play.

Each card opens a real recording produced by scripts/demos/record_*.py in the provide-uterm repo โ€” mp4 with playback-speed controls, or an asciinema cast that autoplays on scroll. Whichever reads best for the feature.

All demos โ†’

Nine things that are hard to glue together โ€” built into one stream.

uterm treats the terminal as a stateful, programmable data plane. Collaboration, security, recording, AI, edge, fleet operations, graphical consoles and tenant isolation share one inline control channel instead of a tangle of side-channels โ€” in four implementations that are tested against each other.

All features โ†’

Protocol

Inline control channel

DLE/STX framing multiplexes raw terminal bytes and JSON control frames onto a single WebSocket. No side-channels, no race conditions.

Collaboration

DeckMux presence + leases

Adjective-animal identities, deterministic HSL colors, role-based hijack leases, queued keystrokes shown as ephemeral overlays.

Backend

Edge-native Durable Objects

Run the same hub at the Cloudflare edge. Each session is a single Durable Object with attached SQLite storage for chat and annotations.

AI agents

MCP-native AI participants

28 tools exposed over Model Context Protocol. Agents discover sessions, request hijack, place annotations, drive a graphical target, and join the DeckMux chat.

Graphical

Remote consoles, same lease

Screenshot, click, drag and type against a remote desktop under the hijack lease that governs a PTY. Filtered VNC relay for humans, byte-identical PNG encoders across languages.

Fleet

Fan-out with divergence detection

Broadcast input across N sessions. Levenshtein-similarity deltas flag the outlier server immediately. Sequential mode halts on failure.

Isolation

Tenancy the server decides

Tenant scope comes from the authenticated principal, never a request body โ€” one is refused 422. Hosted deployments can refuse a tenant's reach into the operator's network.

Security

Pluggable authorization

LocalProvider for RBAC, WebhookProvider for enterprise integration. Tunnel tokens are in-memory, IP-bound, and rotated automatically.

Parity

Four implementations, one matrix

Python, Go, C# and TypeScript. Sixteen live cells โ€” every client against every server on a real socket โ€” each judged against the reference cell field for field.

Workers expose. The hub multiplexes. Everyone attaches.

A single WebSocket carries every byte and every control frame. Three roles in the dance โ€” and the protocol is the same whether you run it on your laptop, at the edge, or inside an agent.

  1. Workers expose a PTY

    A local or remote worker spawns a process behind a UNIX PTY. The HijackableMixin makes the session safe to hand off at checkpoints โ€” no torn state mid-command.

  2. TermHub multiplexes the stream

    The hub routes raw terminal bytes and JSON control frames through one WebSocket using DLE/STX framing. Leases, RBAC, presence, and annotations all live inline.

  3. Browsers, agents, fleets attach

    xterm.js, AI agents over MCP, and fan-out controllers attach as additional participants. Each gets the same snapshot view and obeys the same lease.

Eleven packages, one control plane.

Python, TypeScript, Go and C# โ€” four independent implementations of the same DLE/STX framing, held to each other by a live conformance matrix. The same protocol runs on the server, in the browser, at the edge, and inside the MCP server an AI agent uses.

provide-uterm Core brain

ANSI engine, screen state, DeckMux logic, control-channel framing โ€” shared by every other package.

Python 3.11+pyteaiosqlite
provide-uterm-server Reference hub

TermHub, FastAPI surface, RBAC + lease management, tunnels, gateway. CLI entry: `uterm`, with the hub behind the `uterm server` subcommand.

FastAPIuvicornwebsockets
provide-uterm-cloudflare Edge hub

Cloudflare Worker + Durable Object adapter. One DO per session, SQLite persistence for chat and annotations.

WorkersDurable ObjectsSQLite
provide-uterm-client SDK + AI

HTTP/WS client, telnet/SSH/WS transports, and the `uterm-mcp` server โ€” 28 tools for agents, covering sessions, hijack leases, fan-out, and the graphical surface.

httpxMCP SDKstdio
provide-uterm-platform Agent tier

PTY connector, PAM auth, LD_PRELOAD capture, External Management Tier (`uterm-manager`).

PTYPAMLD_PRELOAD
provide-uterm-annotation Annotation layer

Session annotations as their own package, with a 100% coverage gate and a dedicated CI job.

Python 3.11+100% coverage
provide-uterm-frontend Browser UI

Vanilla TypeScript on top of xterm.js. Renders the DeckMux UI, presence chips, and annotation overlays.

TypeScriptxterm.jsVanilla CSS
provide-uterm-app App shell

Packaging shell that bundles the frontend and server for distribution.

shellbundle
provide-uterm-ts TypeScript runtime

The hub ported to TypeScript โ€” services, lease routes, and the MCP tool surface, held to golden transcripts recorded off the Python reference.

TypeScript 7Node >= 26StrykerJS
provide-uterm-go Go port

Standalone Go implementation with its own module and toolchain โ€” outside the uv and npm workspaces, in the conformance matrix like every other port.

Go 1.26own CI
provide-uterm-csharp C# port

The .NET implementation, canonical for the graphical-target registry and multi-tenancy, with its own quality gate.

.NET 10Stryker.NET

Run a hub. Attach a worker. Open the browser.

uterm ships a reference TermHub in Python, a TypeScript browser frontend, standalone Go and C# servers, a Python client SDK, and an MCP server for AI agents. Pick the surface that matches your harness โ€” a live conformance matrix holds them all to the same control channel.

Open the full quickstart โ†’
git clone https://github.com/provide-io/provide-uterm.git
cd provide-uterm
uv sync --all-packages --all-extras --group dev
npm ci && npm run build:frontend

Run TermHub on 127.0.0.1:8780

uv run uterm server \
  --config scripts/uterm-server.example.toml
# Binds 127.0.0.1:8780, mode = "dev_token".
# Token: ~/.cache/uterm/dev_token

.mcp.json (project) or ~/.claude.json (global)

{
  "mcpServers": {
    "uterm": {
      "command": "uv",
      "args": [
        "--directory",
        "/abs/path/to/provide-uterm",
        "run",
        "uterm-mcp",
        "--url",
        "http://127.0.0.1:8780"
      ]
    }
  }
}

Deploy the Durable-Object backend

cd packages/provide-uterm-cloudflare
npx wrangler deploy
# Each session is a single Durable Object
# with attached SQLite for chat + annotations.

One stream. One brain. Many shells.

Inline control, not side-channels

Most terminal proxies juggle multiple WebSockets for I/O, control, and metadata. uterm multiplexes everything onto one stream โ€” Python server and TypeScript browser agree on the same framing, byte for byte.

Collaboration is the substrate

DeckMux treats observers as first-class. Presence, role-based leases, queued keystrokes, and shared annotations live in the protocol, not bolted on top.

Same brain, three deployments

Run the reference TermHub on your own server, deploy it to Cloudflare Durable Objects at the edge, or embed the core library inside an AI agent. The session model doesn't change.

Three commands cover the local loop.

Serve the hub. Attach a client. Expose the MCP surface for AI agents. Every surface in uterm reduces to one of these three.

$ uv run uterm server --config server.toml
$ curl -H "Authorization: Bearer $(cat ~/.cache/uterm/dev_token)" http://127.0.0.1:8780/api/sessions
$ uv run uterm-mcp --url http://127.0.0.1:8780