diff --git a/README.md b/README.md index 92ff272..213f20e 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ Serve terminal sessions and Textual apps over the web with a simple CLI command. This is heavily based on [textual-web](https://github.com/Textualize/textual-web), but specifically focused on serving a persistent terminal session in a way that you can host behind a reverse proxy (and some form of authentication). -Built on top of [textual-serve](https://github.com/Textualize/textual-serve), this package provides an easy way to expose terminal sessions and Textual applications via HTTP/WebSocket with automatic reconnection support. +Built on [xterm.js](https://xtermjs.org/) 6.0, this package provides an easy way to expose terminal sessions and Textual applications via HTTP/WebSocket with automatic reconnection support. Coupled with [`agentbox`](https://github.com/rcarmo/agentbox), you can use it to keep track of several containerized AI coding agents: @@ -18,6 +18,7 @@ Coupled with [`agentbox`](https://github.com/rcarmo/agentbox), you can use it to - 🐍 **Textual app support** - Serve Textual apps directly from Python modules - 🔄 **Session reconnection** - Refresh the page and reconnect to the same session - 🎨 **Full terminal emulation** - Colors, cursor, and ANSI codes work correctly +- 📜 **Scrollback history** - Scroll back through terminal output (configurable) - 📐 **Auto-sizing** - Terminal automatically resizes to fit the browser window - 📸 **Live screenshots** - Dashboard shows real-time SVG screenshots of terminals - 📊 **CPU sparklines** - Dashboard displays 30-minute CPU history for Docker containers @@ -162,14 +163,34 @@ make install-dev - Lint: `make lint` - Format: `make format` - Tests: `make test` -- Coverage (fail_under=80): `make coverage` +- Coverage (fail_under=79): `make coverage` - Full check (lint + coverage): `make check` +### Frontend Development + +The terminal UI is built with [xterm.js](https://xtermjs.org/) 6.0. The pre-built bundle is committed to the repo, so users can `pip install` without needing Node.js. + +To rebuild the frontend after modifying `terminal.ts`: + +```bash +# Requires Bun (https://bun.sh) +bun install +bun run build +# Or simply: +make bundle +``` + +For development with auto-rebuild: + +```bash +make bundle-watch +``` + ### Notes -- WebSocket protocol (browser <-> server) is JSON: `["stdin", data]`, `["resize", {"width": w, "height": h}]`, `["ping", data]`. -- Static assets are provided by `textual-serve`; this project does not add custom static files. -- Screenshots use [pyte](https://github.com/selectel/pyte) for ANSI interpretation and [Rich](https://github.com/Textualize/rich) for SVG rendering. +- WebSocket protocol (browser ↔ server) is JSON: `["stdin", data]`, `["resize", {"width": w, "height": h}]`, `["ping", data]`. +- Frontend source is in `src/textual_webterm/static/js/terminal.ts`. +- Screenshots use [pyte](https://github.com/selectel/pyte) for ANSI interpretation and custom SVG rendering. - CPU stats are read directly from Docker socket using asyncio (no additional dependencies). ## Requirements @@ -184,6 +205,5 @@ MIT License - see [LICENSE](LICENSE) for details. ## Related Projects - [Textual](https://github.com/Textualize/textual) - TUI framework for Python -- [textual-serve](https://github.com/Textualize/textual-serve) - Serve Textual apps on the web -- [Rich](https://github.com/Textualize/rich) - Rich text formatting for terminals +- [xterm.js](https://xtermjs.org/) - Terminal emulator for the web - [pyte](https://github.com/selectel/pyte) - PYTE terminal emulator diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index 0450fcf..2c58b13 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -186,6 +186,17 @@ JSON-encoded messages over WebSocket: ## Key Design Decisions +### Why bundle xterm.js directly? + +We bundle xterm.js 6.0 directly rather than using textual-serve because: + +- **Full configuration control** - fontFamily, scrollback, theme are configurable +- **No workarounds needed** - xterm.js uses canvas rendering which ignores CSS fonts +- **Smaller footprint** - No unused fonts or images from textual-serve +- **Latest features** - xterm.js 6.0 includes ligature support, synchronized output, etc. + +The pre-built `terminal.js` bundle is committed to the repo so users can `pip install` without needing Node.js/Bun. + ### Why custom SVG exporter? Rich's `export_svg()` had alignment issues with box-drawing characters and varied font rendering across browsers. The custom exporter: @@ -214,7 +225,7 @@ Unlike traditional web terminals, sessions survive page refreshes: ``` src/textual_webterm/ -├── cli.py # Typer CLI entry point +├── cli.py # Click CLI entry point ├── config.py # Configuration parsing (YAML manifests) ├── local_server.py # Main HTTP/WebSocket server ├── session_manager.py # Session registry and routing @@ -228,5 +239,11 @@ src/textual_webterm/ ├── identity.py # Session ID generation ├── slugify.py # URL-safe slug generation ├── types.py # Type aliases -└── constants.py # Platform constants +├── constants.py # Platform constants +└── static/ + ├── monospace.css # Font stack CSS variables + ├── css/xterm.css # xterm.js styles + └── js/ + ├── terminal.ts # xterm.js client source (TypeScript) + └── terminal.js # Pre-built bundle (committed) ```