Terminal backend · Rust

The browser terminal that doesn't fake it.

xterm.rs is a tiny Rust backend that streams a real PTY over a WebSocket. Job control, Unix signals, full-screen TUIs and live resize — the things web terminals usually only pretend to do. The window on the right is an actual shell — locked down for the public, but real. Go on.

Restricted sandbox · non-root · no network · type help

demo@fenrir:~ — bash · live over xterm.rs
shell back-end not reachable
start it with docker compose up, then refresh
try: help · htop · btop · sleep 30 then Ctrl-C · ⛶ Fullscreen for more room
The difference

Most "web terminals" are a transcript. This is a process.

A lot of in-browser terminals match your input against a script and print canned output. It looks right until you press Ctrl-C or open an editor. xterm.rs spawns a genuine shell on a PTY with a controlling terminal, so the kernel — not a lookup table — decides what happens.

Faked terminal

  • × Output matched from a fixed command list
  • × Ctrl-C does nothing — no signals
  • × vim, htop, tmux can't render
  • × Resizing the window changes nothing
  • × No job control, no /dev/tty

xterm.rs

  • A real bash on a real PTY
  • Ctrl-C / Ctrl-Z deliver SIGINT / SIGTSTP
  • Full-screen TUIs just work
  • Window resize fires a real SIGWINCH
  • Session leader with a controlling terminal
What you get

Small surface, real terminal.

One static binary, an xterm.js frontend, and a WebSocket between them. That's the whole stack.

01

Real PTY

Each connection gets its own pseudo-terminal, set up as a session leader with the slave as its controlling terminal.

02

Signals & job control

Ctrl-C, Ctrl-Z, background jobs, fg, tcsetpgrp — the line discipline is the kernel's, not a polyfill.

03

Full-screen TUIs

vim, htop, tmux, less, nano — anything cursor-addressed renders byte-for-byte the same as a native term.

04

Live resize

The frontend reports cols and rows; the backend issues TIOCSWINSZ and the process gets a SIGWINCH.

05

Run any command

Point --cmd at a shell, a single program, or your own lesson launcher. Optionally exit when it does.

06

One binary + xterm.js

The backend is a single self-contained Rust binary — no runtime, no dependencies to install, just drop it in and run. The browser side is xterm.js talking to it over a WebSocket.

Built to teach

hack.courses runs on it.

Every IT and ethical-hacking lab on hack.courses is a real machine in a browser tab, powered by xterm.rs. No VMs to install, nothing to configure — learners land in a working terminal and start breaking (and fixing) things from the first minute.

Explore hack.courses ↗

IT & ethical hacking, hands-on.

From the workshop

Made in-house at fenrir.pro.

We build xterm.rs and run it across our own security training and tooling. Want a real terminal inside your product, or a hand getting it deployed and locked down? We're happy to help.

Contact fenrir.pro ↗

fenrir.pro/contact · enquiries & support