Web browser in your terminal using Kitty graphics protocol
  • Zig 70.1%
  • TypeScript 13.2%
  • Svelte 8.3%
  • JavaScript 7.2%
  • Shell 0.4%
  • Other 0.8%
Find a file
teamchong 26899a1fd5 security: add max connection limits to HTTP and WebSocket servers
Prevents thread-exhaustion DoS by rejecting connections beyond 512
concurrent limit on both HTTP and WebSocket servers.
2026-03-10 04:27:49 -04:00
.github/workflows build: add platform-specific libghostty directories and CI 2026-02-04 11:57:32 -05:00
benchmarks docs: formatting 2026-02-11 08:19:29 -05:00
bin feat: bundle native modules in npm package 2026-01-25 22:34:31 -05:00
docs perf: only update navigation state on click events, not every frame 2026-01-03 15:15:27 -05:00
examples fix: increase WebSocket timeout to 15s for remote environments 2026-01-23 16:29:14 -05:00
lib feat(sdk): add Tauri-style invoke, events, channels, and fs APIs 2026-01-31 20:37:07 -05:00
packages security: add max connection limits to HTTP and WebSocket servers 2026-03-10 04:27:49 -04:00
patches/ghostty fix: reduce rapid-input latency (holding backspace lag) 2026-02-17 18:32:05 -05:00
scripts chore: npm packaging and remove doctor command 2026-01-22 09:35:43 -05:00
src feat: replace Tailscale with Cloudflare Tunnel 2026-03-09 23:27:40 -04:00
tests fix: add URL percent-decoding for tmux API query params + unit tests 2026-02-16 00:54:03 -05:00
tools fix: correct mouse coordinate mapping for Chrome viewport 2026-01-24 21:12:02 -05:00
ui/html perf: only update navigation state on click events, not every frame 2026-01-03 15:15:27 -05:00
vendor fix: reduce rapid-input latency (holding backspace lag) 2026-02-17 18:32:05 -05:00
.gitignore feat(mux): update .gitignore and remove obsolete Playwright test images 2026-02-10 07:18:35 -05:00
.gitmodules feat(mux): migrate WebSocket compression from libdeflate to zstd 2026-02-02 20:53:01 -05:00
build.zig feat(auth): add per-IP rate limiting for failed auth attempts 2026-02-11 14:37:57 -05:00
LICENSE fix(mux): fix renderer data race, signal handler deadlock, and UI title updates 2026-02-05 22:11:09 -05:00
Makefile test(mux): add integration test for tmux shim Unix socket API 2026-02-11 14:44:19 -05:00
package.json feat(sdk): add Tauri-style invoke, events, channels, and fs APIs 2026-01-31 20:37:07 -05:00
pnpm-lock.yaml feat(mux): integrate mux into single termweb binary 2026-02-02 19:52:24 -05:00
pnpm-workspace.build.json feat: add allowedHotkeys option and dashboard process view 2026-01-25 18:25:36 -05:00
pnpm-workspace.yaml feat: add terminal editor packages and SDK improvements 2026-01-24 06:37:18 -05:00
README.md feat: auth hardening, panel access control, Shift+Enter/Tab fix, sync download UI, README shortcuts 2026-02-17 13:16:23 -05:00

termweb

Stream Ghostty to any browser. A headless terminal multiplexer that runs Ghostty on your server and streams pixel-perfect H.264 video to web clients over WebSocket.

Demo

https://github.com/user-attachments/assets/70b86b29-19b4-458b-8d5d-683f5e139908

Why

Ghostty is a fantastic terminal emulator, but it's a native desktop app. termweb turns it into a streaming service — run Ghostty headlessly on a server, and connect from any device with a browser: laptop, iPad, phone. No native app install required.

  • One server, many clients — multiple users can connect to the same session simultaneously
  • Access from anywhere — any device with a browser becomes a Ghostty terminal
  • Native rendering quality — libghostty renders to GPU, hardware-encodes to H.264, streams pixels (not text)
  • Real terminal — full mouse tracking, shell integration, split panes, tabs — not a web terminal approximation

How It Works

┌─────────────────────────────────────────────────────────────┐
│                    Browser / Any Client                     │
│                                                             │
│  WebSocket ──→ Zstd decompress ──→ WebCodecs H.264 decode   │
│  ──→ WebGPU / Canvas 2D render                              │
│                                                             │
│  Keyboard/Mouse ──→ WebSocket ──→ Server                    │
└─────────────────────────────────────────────────────────────┘
                      │ WebSocket (single port)
                      ↓
┌─────────────────────────────────────────────────────────────┐
│                    Server (Zig + libghostty)                │
│                                                             │
│  libghostty ──→ GPU surface ──→ Hardware H.264 encode       │
│  ──→ Zstd compress ──→ WebSocket broadcast                  │
│                                                             │
│  macOS:  IOSurface → VideoToolbox                           │
│  Linux:  EGL → VA-API                                       │
└─────────────────────────────────────────────────────────────┘

Features

Streaming

  • Hardware H.264 encoding — VideoToolbox (macOS) / VA-API (Linux), not software encode
  • Low latency — WebCodecs decodes directly to canvas, no MSE buffering
  • Adaptive quality — AIMD algorithm adjusts quality per-panel based on available bandwidth
  • WebGPU rendering — GPU-accelerated frame display with Canvas 2D fallback for iOS Safari
  • Zstd compression — all WebSocket frames compressed for lower bandwidth

Multiplexer

  • Tabs — multiple tabs with LRU switching on close
  • Split panes — horizontal/vertical splits with draggable dividers, zoom to maximize
  • Quick terminal — dropdown terminal overlay
  • Shell integration — pwd tracking, running command indicators
  • Scale to zero — Ghostty initializes on first panel, frees resources when last one closes

Input

  • Full mouse support — hover, click, scroll, drag with modifier keys
  • Mobile touch — tap, drag, two-finger scroll, pinch-to-zoom on iOS/Android
  • Virtual keyboard — on-screen accessory bar with Esc, Tab, Ctrl, Alt, Cmd, arrow keys
  • Keyboard shortcuts — native-feeling key bindings (see below)

Collaboration

  • Multi-client sessions — multiple browsers connect to the same session
  • Access control — session management with share links and viewer/editor roles
  • File transfer — upload/download with rsync-like options (exclude patterns, delete, preview)

Quick Start

# Build (requires Zig 0.14.0+)
make

# Run
./zig-out/bin/termweb mux

Open http://localhost:8080 in any modern browser.

Browser support: Chrome, Edge, Safari (including iOS), Firefox — requires WebCodecs.

Building

From Source

git clone https://github.com/nichochar/termweb
cd termweb
make
./zig-out/bin/termweb mux

Linux Dependencies

# VA-API for hardware H.264 encoding
sudo apt-get install libva-dev

# Intel GPU driver (if using Intel graphics)
sudo apt-get install intel-media-va-driver

Keyboard Shortcuts

Uses Cmd on macOS, Super/Meta on Linux/Windows. Shortcuts are customizable via Ghostty config.

Tabs & Panes

Shortcut Action
Cmd+/ New Tab
Cmd+. Close Pane
Cmd+Alt+. Close Tab
Cmd+Shift+. Close Window
Cmd+D Split Right
Cmd+Shift+D Split Down
Cmd+[ / Cmd+] Previous/Next Split
Cmd+Shift+Arrow Select Split by Direction
Cmd+Shift+Enter Zoom Split (maximize)
Cmd+1-9 Switch to Tab 1-9
Cmd+Shift+[ / Cmd+Shift+] Previous/Next Tab
Cmd+Shift+A Show All Tabs
Cmd+Shift+F Toggle Full Screen
Cmd+Alt+\ Quick Terminal

Edit

Shortcut Action
Cmd+C Copy
Cmd+V Paste
Cmd+Shift+V Paste Selection
Cmd+A Select All

View

Shortcut Action
Cmd+= Increase Font Size
Cmd+- Decrease Font Size
Cmd+0 Reset Font Size

Tools

Shortcut Action
Cmd+U Upload Files
Cmd+Shift+S Download Files
Cmd+Shift+K Command Palette
Cmd+Alt+I Toggle Inspector
Cmd+Shift+, Reload Config

Other Commands

termweb also includes a web browser for terminals:

# Browse the web in your terminal (Kitty graphics protocol)
termweb open https://example.com

See packages/mux/README.md for detailed protocol and architecture documentation.

License

MIT