Skip to main content

Web Terminal

XShell includes a browser-based terminal that uses the same core engine as the native shell. It's powered by Flask and Socket.IO for real-time bidirectional communication.

Demo video (web UI): youtu.be/LNP0p5zTUro — see also Demos & Screenshots for the native walkthrough and a full screenshot gallery.

Starting the web terminal

python main.py --web # opens on http://127.0.0.1:5000
python main.py --web --port 8080 # custom port

The browser opens automatically. If it doesn't, navigate to http://127.0.0.1:<port>.

In a source checkout, the web server resolves templates/ and static/ from the repository root rather than the shell's current working directory. That means python /full/path/to/main.py --web works even when launched from another folder.

Features

FeatureDescription
ANSI coloursFull 16-colour ANSI rendering, including bold and dim
Theme switcherClick 🎨 in the title bar to change themes live
HistoryArrow keys navigate history; ghost text shows suggestions
Ctrl+LClear the terminal output
Ctrl+CSend ^C and clear input
Status barShows connection status, CWD, current theme, last exit code
Resize-awareLayout adapts to window size

Architecture

Browser Server (Python)
──────────────────────────────────────────────────
user types command

├─ socket.emit('command') ──→ handle_command()
│ │
│ captures stdout/stderr
│ runs shell.execute_line()
│ │
│ ←── socket.emit('output') ───────┘

renders ANSI text in <div>

Each browser tab gets its own _WebShell session with isolated history, aliases, and working directory.

Theme switching via socket

browser ──→ socket.emit('get_themes') ──→ server sends list
browser ──→ socket.emit('set_theme', {theme: 'gruvbox'}) ──→ server switches theme

Limitations vs native shell

FeatureNativeWeb
Tab completionFullNot yet (planned)
PTY / interactive programsNoNo
Ctrl+R history searchYesNo
ANSI truecolor (24-bit)Terminal-dependentNo (16-colour only)
Concurrent sessionsN/AYes (one per tab)

Security note

The web server runs on 127.0.0.1 (localhost only) by default and executes shell commands with your user permissions. Do not expose it on a public network interface without adding authentication and HTTPS.

For team/remote use, add a reverse proxy (nginx, Caddy) with auth in front of it.

Running as a background service

# Keep it running after terminal closes
nohup python main.py --web --port 5000 &

# Or with a process manager like PM2
pm2 start "python main.py --web" --name xshell-web