progterm

command module
v0.0.0-...-29efef4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 4, 2026 License: MIT Imports: 2 Imported by: 0

README

progterm

A desktop terminal that is a progressive terminal host: your own shell, on a real pty on this machine, drawn by websh's host in a browser app window.

Native programs run as they do in any terminal: vim, htop, ssh, git, whatever your shell runs. A progressive terminal program, one that asks its terminal what it offers (websh's PROTOCOL.md), gets more here than in a desktop terminal:

  • real pictures over its cells (kitty's graphics protocol);
  • widgets it ships itself: HTML or wasm, run in a sandboxed iframe, talking to the program both ways over its own output and input;
  • an accessible rendition of what it shows, for screen readers;
  • sound, notifications, the clipboard and file drops.

The same program, unchanged, falls back to cells in a terminal that offers none of that.

make build        # builds the host page (wasm) and the binary that embeds it
./progterm        # opens a window with your shell

websh/cmd/progdemo built natively is the program to try in it: it shows each capability beside what it does where a terminal cannot.

How it works

progterm starts one HTTP server on a loopback address. It serves the host page, which is websh's host built to wasm and embedded in the binary, and opens it as an app window: a Chromium-family browser's --app, which has no address bar or tabs. The page connects back over a WebSocket, and the bridge starts your shell ($SHELL -l) on a pty for it. Binary messages carry the pty's bytes both ways, and a text message carries the window's size. Each window is its own shell, and the bridge exits when the last one does.

TERM is xterm-256color and TERM_PROGRAM is progterm.

Safety

The window is a shell on your machine, so only the page progterm opened may reach it:

  • the server listens on loopback only, and refuses a non-loopback --addr;
  • each launch makes a random 256-bit token, carried in the window's link fragment, which no HTTP request includes, and removed from the address once read;
  • the pty endpoint requires the token and an Origin of the page's own;
  • every request must name the server's own Host, which stops a page elsewhere from reaching it by pointing a DNS name at 127.0.0.1.

Trust

The host cannot see whether the bytes on the pty are this machine's or those of an ssh session running inside your shell. No desktop terminal can. So progterm's output gets websh's remote rules, and programs are told so in their caps? reply:

  • it may not change the font or the page;
  • a clipboard write or a file it offers asks you first;
  • notifications are rate-limited.

It may set the window's title, as every desktop terminal lets output do. In websh's terms this is the terminal source (PROTOCOL.md, Trust).

Flags

Flag
--shell the shell to run (default $SHELL, else /bin/sh); --shell websh runs websh itself on this machine
--browser the browser to open the window with (default: the first of brave, chromium, google-chrome, microsoft-edge on PATH, else xdg-open)
--no-open print the window's address instead of opening it
--addr the loopback address to serve on (default 127.0.0.1:0, any free port)

Without a browser: progterm gio

progterm gio                 # websh if installed, else $SHELL
progterm gio --shell bash --font-size 15
progterm gio --font "DejaVu Sans Mono 10"
progterm gio --in-process     # websh in this process, one per tab

The same shell on a pty, in a window Gio draws instead of a page: xterm-go's terminal core (vt) fed by the pty, its cells drawn into one image (braille drawn, since fonts often have none). It is the host for where no browser runs, a phone's app first: the terminal (glterm) knows nothing of Gio, which is only the window, input, clipboard and on-screen keyboard underneath (gioterm).

It draws cells only. A progressive program finds no host to ask and draws as in any terminal, and TUIs (skywire cli visor hv tui, live views) work as they do in one. Drag selects (double click a word, triple a line); right click opens Copy, Paste and Select All (Ctrl+Shift+C, V, A); middle click and Shift+Insert paste the last selection; the wheel and Shift+PageUp/Down scroll back. A program that asks for the mouse gets it; Shift takes it back for selecting. It needs cgo, and X11 or Wayland.

The font is --font "Family Size", found with fontconfig (fc-match) in its regular, bold, italic and bold italic styles, a missing style drawn with the regular one. Without --font it is the desktop terminal's: xfce4-terminal's when it has its own, then GNOME's monospace font, then fontconfig's monospace. Go Mono is built in and is used where none of that works. The size is in points at the screen's DPI (Xft.dpi on X11), so 10 is the size it is in other terminals. The window opens 100 by 30 cells of that font, fewer where the screen has no room for them.

Shells open as tabs in one window, as in the browser desk. Ctrl+Shift+T or the + opens one, Ctrl+Shift+W or a middle click on its tab closes it, and a tab goes when its program exits; the window closes with the last. Click a tab, use Ctrl+Tab and Ctrl+Shift+Tab or Ctrl+PageDown and PageUp, or Alt+1 to Alt+9 to change tabs. A program embedding gioterm or x11term opens more at the start with Options.Tabs, each running its own command.

progterm gio --in-process runs websh in the window's own process, one per tab, each on a pty the process opens itself (glterm.StartFunc). It is the shape of an app with no shell binary to start, as on Android, where an app may open ptys but not run files it wrote. The kernel signals no one for Ctrl+C on such a pty, so the window reads the pty's settings and, while they say the kernel would (ISIG on, as while a command runs), passes Ctrl+C and Ctrl+\ to that tab's websh as signals (console.Options.Signals). At a prompt or in a full-screen program they stay keys.

With no cgo: progterm x11

progterm x11                 # the same flags as gio

The same terminal, tabs and shortcuts as progterm gio, in a window on $DISPLAY (an X server or XWayland, local or remote). x11term speaks the X protocol itself in Go (xgb), so it needs no cgo and no X libraries, and a CGO_ENABLED=0 build has it. It sends only the rows of the image that changed, with plain PutImage. Keys come through the server's keymap, so a layout's characters type as they do elsewhere; there is no input method or compose key. Copy and paste use the CLIPBOARD and PRIMARY selections, up to what one request holds (no INCR transfers). The font follows Xft.dpi.

Status

Verified on Linux, in Brave:

  • a real shell on a pty: tty, size changes, and TERM_PROGRAM;
  • window titles from the shell;
  • the guards: a wrong Host and a missing token are both refused;
  • the native progdemo running in it: discovery reports the remote trust level; the picture is drawn sharply over its cells; and the shipped slider drives the program's cells.

Not yet:

  • Other platforms: macOS (the pty library supports it, but it is untested) and Windows (no pty here; ConPTY would be needed).
  • Shipping the binary: the host page is built locally by make, not committed, so go install alone does not give a working binary yet.

License

MIT.

Dependency Graph

Made with goda:

# GOOS=js: the import edges of a wasm program live in js/wasm-tagged
# files and are invisible to a host-context run
GOOS=js GOARCH=wasm go run github.com/loov/goda@latest graph github.com/0magnet/progterm/... | dot -Tsvg -o docs/progterm-goda-graph.svg

Dependency Graph

Lines of Code

Made with gocloc (excludes vendor/, node_modules/, .git/):

gocloc --not-match-d='(vendor|node_modules|\.git)' .
-------------------------------------------------------------------------------
Language                     files          blank        comment           code
-------------------------------------------------------------------------------
Go                               3             41             50            431
Makefile                         1             23             52            116
Markdown                         1             27              0             99
YAML                             1              0              7             98
Bourne Shell                     1              8             17             31
HTML                             1              0              0             21
-------------------------------------------------------------------------------
TOTAL                            8             99            126            796
-------------------------------------------------------------------------------

Documentation

Overview

Command progterm is a desktop progressive terminal: your shell on a real pty, drawn by websh's host in a browser window. See the commands package.

Directories

Path Synopsis
Package commands is the progterm command, a desktop progressive terminal: your shell, on a real pty on this machine, drawn by websh's host in a browser window — so native programs (vim, htop, ssh, anything) run as in any terminal, and a progressive one (PROTOCOL.md in websh) gets pictures, widgets it ships, events and the rest, as it does in websh.
Package commands is the progterm command, a desktop progressive terminal: your shell, on a real pty on this machine, drawn by websh's host in a browser window — so native programs (vim, htop, ssh, anything) run as in any terminal, and a progressive one (PROTOCOL.md in websh) gets pictures, widgets it ships, events and the rest, as it does in websh.
Package gioterm is glterm's terminal in a Gio window: the same session, grid, selection and menu, with Gio as the platform layer underneath — window, input, clipboard and the on-screen keyboard.
Package gioterm is glterm's terminal in a Gio window: the same session, grid, selection and menu, with Gio as the platform layer underneath — window, input, clipboard and the on-screen keyboard.
Package glterm is a terminal drawn without a browser: xterm-go's terminal core (vt) fed by a shell on a pty, its cells drawn with the Go fonts into an image a window puts on the screen (gioterm, on Gio).
Package glterm is a terminal drawn without a browser: xterm-go's terminal core (vt) fed by a shell on a pty, its cells drawn with the Go fonts into an image a window puts on the screen (gioterm, on Gio).
The host page: websh's progressive terminal host, whose one command joins the bridge's pty.
The host page: websh's progressive terminal host, whose one command joins the bridge's pty.
Package x11term is glterm's terminal in an X11 window, spoken to over the X protocol in Go: no cgo and no X libraries, so any build can open one, on an X server or XWayland, local or remote.
Package x11term is glterm's terminal in an X11 window, spoken to over the X protocol in Go: no cgo and no X libraries, so any build can open one, on an X server or XWayland, local or remote.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL