Web Terminal
Access TUIOS from any browser with WebGL rendering (separate tuios-web binary)
Access TUIOS from any modern web browser with hardware-accelerated rendering and low-latency connections.
Powered by Sip
The web terminal is powered by sip, a standalone library for serving Bubble Tea apps through the browser. You can use sip to serve your own Bubble Tea applications on the web!
Separate Binary
The web terminal functionality is provided as a separate tuios-web binary for security isolation. This prevents the web server from being used as a potential backdoor in the main TUIOS binary.
Installation
brew install tuios-webyay -S tuios-web-bin
# or
paru -S tuios-web-bingo install github.com/Gaurav-Gosain/tuios/cmd/tuios-web@latestQuick Start
Start the web server
tuios-webThis starts:
- HTTP server on
http://localhost:7681(static files, WebSocket) - WebTransport server on
https://127.0.0.1:7682(QUIC/UDP)
Open in browser
open http://localhost:7681The browser will automatically connect using the best available transport (WebTransport if supported, WebSocket otherwise).
Features
- WebGL Rendering - GPU-accelerated terminal at 60fps
- Dual Protocols - WebTransport (QUIC) with WebSocket fallback
- Bundled Fonts - JetBrains Mono Nerd Font included
- Settings Panel - Configure transport, renderer, font size
- Mouse Support - Full interaction with cell-based optimization
- Auto-Reconnect - Automatic reconnection with backoff
- Read-Only Mode - View-only sessions for demos
Command Reference
tuios-web [flags]Flags
| Flag | Default | Description |
|---|---|---|
--port | 7681 | HTTP server port |
--host | localhost | Server bind address |
--read-only | false | Disable client input |
--max-connections | 0 | Max concurrent sessions (0=unlimited) |
TUIOS Flags
All TUIOS flags are forwarded to the spawned instance:
# With theme
tuios-web --theme dracula
# With show-keys overlay
tuios-web --show-keys
# Disable animations for instant transitions
tuios-web --no-animations
# Multiple flags
tuios-web --theme nord --ascii-only --debugClient Settings
Click the ⚙ button in the top-right corner to access settings:
Transport
| Option | Description |
|---|---|
| Auto | Prefer WebTransport, fallback to WebSocket |
| WebTransport | Force QUIC (lower latency) |
| WebSocket | Force WebSocket (wider compatibility) |
Renderer
| Option | Description |
|---|---|
| Auto | Prefer WebGL, fallback to Canvas/DOM |
| WebGL | GPU-accelerated (best performance) |
| Canvas | 2D canvas (good compatibility) |
| DOM | Standard DOM (most compatible) |
Font Size
Adjustable from 10px to 24px. Settings persist in localStorage.
Architecture
Message Protocol
| Type | Code | Direction | Description |
|---|---|---|---|
| Input | 0 | C→S | Keyboard/mouse input |
| Output | 1 | S→C | Terminal output data |
| Resize | 2 | C→S | Terminal size change |
| Ping | 3 | C→S | Keep-alive ping |
| Pong | 4 | S→C | Keep-alive response |
| Title | 5 | S→C | Window title update |
| Options | 6 | S→C | Session configuration |
| Close | 7 | S→C | Session ended |
Reverse Proxy Setup
For production deployments, put TUIOS behind a reverse proxy with proper TLS.
Important
WebTransport requires HTTP/3 (QUIC) support. Most reverse proxies only support WebSocket, so WebTransport connections will fall back to WebSocket when proxied.
Cloudflare Tunnel
Cloudflare Tunnels provide secure access without opening ports.
Install cloudflared
# macOS
brew install cloudflare/cloudflare/cloudflared
# Linux
curl -L https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64 -o cloudflared
chmod +x cloudflared
sudo mv cloudflared /usr/local/bin/Authenticate
cloudflared tunnel loginCreate tunnel
cloudflared tunnel create tuiosConfigure tunnel
Create ~/.cloudflared/config.yml:
tunnel: <your-tunnel-id>
credentials-file: /path/to/credentials.json
ingress:
- hostname: tuios.yourdomain.com
service: http://localhost:7681
- service: http_status:404Start TUIOS and tunnel
# Terminal 1: Start TUIOS web server
tuios-web --host 127.0.0.1
# Terminal 2: Start tunnel
cloudflared tunnel run tuiosAdd DNS record
cloudflared tunnel route dns tuios tuios.yourdomain.comAccess at https://tuios.yourdomain.com
Nginx
server {
listen 80;
server_name tuios.example.com;
location / {
proxy_pass http://127.0.0.1:7681;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_read_timeout 86400;
}
}server {
listen 443 ssl http2;
server_name tuios.example.com;
ssl_certificate /etc/letsencrypt/live/tuios.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/tuios.example.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:7681;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 86400;
proxy_send_timeout 86400;
}
}
server {
listen 80;
server_name tuios.example.com;
return 301 https://$server_name$request_uri;
}Caddy
Caddy automatically handles TLS certificates:
tuios.example.com {
reverse_proxy localhost:7681
}Traefik
# docker-compose.yml
services:
tuios:
image: ghcr.io/gaurav-gosain/tuios:latest
command: web --host 0.0.0.0
labels:
- "traefik.enable=true"
- "traefik.http.routers.tuios.rule=Host(`tuios.example.com`)"
- "traefik.http.routers.tuios.entrypoints=websecure"
- "traefik.http.routers.tuios.tls.certresolver=letsencrypt"
- "traefik.http.services.tuios.loadbalancer.server.port=7681"Security Considerations
Development Mode
By default, TUIOS generates a self-signed certificate for WebTransport:
- Valid for 10 days (Chrome requirement for
serverCertificateHashes) - Certificate hash provided via
/cert-hashendpoint - No browser warning for WebTransport connections
Production Recommendations
Security Tips
- Always use a reverse proxy with proper TLS for production
- Bind to localhost:
tuios-web --host 127.0.0.1 - Limit connections:
tuios-web --max-connections 10 - Use read-only for demos:
tuios-web --read-only - Add authentication at the reverse proxy level
Basic Auth with Nginx
location / {
auth_basic "TUIOS";
auth_basic_user_file /etc/nginx/.htpasswd;
proxy_pass http://127.0.0.1:7681;
# ... rest of proxy config
}Create password file:
htpasswd -c /etc/nginx/.htpasswd usernamePerformance
Server Optimizations
- Buffer Pools - Reusable buffers reduce GC pressure
- Atomic Counters - Lock-free connection counting
- Direct Streaming - No intermediate buffering
- Structured Logging - charmbracelet/log with configurable levels
Client Optimizations
- requestAnimationFrame Batching - Writes batched per frame
- Mouse Deduplication - Only sends on cell position change
- Pre-allocated Buffers - Reusable send/receive buffers
- Cached DOM Elements - No repeated queries
Typical Metrics
| Metric | Value |
|---|---|
| Latency (local) | <5ms |
| Latency (LAN) | <20ms |
| Mouse events filtered | 80-95% |
| Memory (per session) | ~10MB |
Troubleshooting
WebTransport Not Connecting
- Check browser support - Chrome 97+, Edge 97+
- Verify UDP port - Port 7682 must be accessible
- Check console - Look for certificate hash errors
- Force WebSocket - Use settings panel to switch
Blank Terminal
- Check console - Look for JavaScript errors
- Verify fonts - Check if fonts loaded
- Try different renderer - Switch in settings
- Check server logs - Verify TUIOS process started
High Latency
- Check network - Run speed test
- Prefer WebTransport - Lower latency than WebSocket
- Use WebGL - Hardware acceleration
- Check server CPU - May be overloaded
Session Not Closing
When TUIOS quits (pressing q), the web session should close automatically. If not:
- Check browser console for errors
- Verify server logs show session cleanup
- Refresh browser to start new session
Debug Mode
tuios-web --debugServer logs include:
- Connection attempts
- Session lifecycle
- Bytes sent/received
- Terminal resize events
- Error details
Examples
Public Demo Server
# Read-only with connection limit
tuios-web \
--host 0.0.0.0 \
--port 7681 \
--read-only \
--max-connections 50 \
--theme draculaDevelopment with Hot Reload
# With debug logging
tuios-web --debug --show-keysDocker Deployment
docker run -it --rm \
-p 7681:7681 \
-p 7682:7682/udp \
ghcr.io/gaurav-gosain/tuios:latest \
web --host 0.0.0.0Systemd Service
# /etc/systemd/system/tuios-web.service
[Unit]
Description=TUIOS Web Terminal
After=network.target
[Service]
Type=simple
User=tuios
ExecStart=/usr/local/bin/tuios-web --host 127.0.0.1 --port 7681
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.targetsudo systemctl enable tuios-web
sudo systemctl start tuios-web