Date: 2026-05-11
Time: 15:51
ftl2_htop.py is a distributed system monitoring TUI — essentially a remote htop built on FTL2's event-driven gate protocol. It connects to remote hosts via FTL2's SSH subsystem, streams real-time system metrics (CPU, memory, disk, network, processes) using psutil on the remote side, and renders them as a live-updating terminal dashboard using rich. It also supports WebSocket broadcasting for PWA clients and an optional Textual TUI mode.
The script is invoked via uv run as an inline-dependency script or through the cli() entry point:
# Monitor specific hosts (builds inventory dynamically)
uv run ftl2_htop.py web1.example.com web2.example.com
# Use an inventory file
uv run ftl2_htop.py -i inventory.yml
# Load hosts from a state file
uv run ftl2_htop.py -S .ftl2-state.json
# Filter to specific host groups
uv run ftl2_htop.py -i inventory.yml -g webservers databases
# Debug mode — raw events to stderr, no TUI
uv run ftl2_htop.py -i inventory.yml --debug
# WebSocket broadcast for live dashboards
uv run ftl2_htop.py -i inventory.yml --ws-port 8765
The core flow: cli() → main() → opens automation() context → calls proxy.monitor() on each group → registers SystemMetrics event handlers → runs rich.Live display loop concurrently with ftl.listen().
CLI Arguments:
| Argument | Description |
|---|---|
| hosts (positional) | Hostnames to monitor; builds inventory dict dynamically |
| -i, --inventory | Path to inventory YAML file |
| -S, --state | State file (.ftl2-state.json) to load hosts from |
| -g, --groups | Host groups to monitor (default: all groups) |
| --interval | Metrics sampling interval in seconds (default: 2.0) |
| --no-processes | Exclude process list from metrics (reduces bandwidth) |
| --debug | Print raw events to stderr, disable TUI |
| --tui | Use Textual TUI (for textual-serve compatibility) |
| --ws-port | WebSocket port for live metrics broadcast (e.g. 8765) |
Environment Variables:
FTL2_TELEMETRY=off — disables Segment telemetry on startupPrerequisite on remote hosts:
await ftl.hosts.dnf(name="python3-psutil", state="present")
--inventory → --state → falls back to "localhost,".gatesubsystem=True). Calls proxy.monitor(interval=..., includeprocesses=...) on each group, then listens for SystemMetrics events via proxy.on("SystemMetrics", handler).▁▂▃▄▅▆▇█).--ws-port is set, starts a WebSocket server that pushes the full metrics_store as JSON to all connected clients every 2 seconds.--tui flag delegates to ftl2htoptui.run_tui(args) for a Textual-based interface (required for textual-serve).phonehome() sends a single anonymous Segment event with app name and git commit hash. Never crashes on failure.KeyboardInterrupt is caught silently at the top level.ftl2.automation — The core dependency. Uses automation() async context manager, ftl.hosts.groups, ftl[group] proxy access, proxy.monitor(), proxy.on() event subscription, and ftl.listen().ftl2htoptui — Separate module providing a Textual-based TUI, imported lazily when --tui is passed.rich — Live, Panel, Table, Text, Group for terminal rendering.psutil — Listed as a dependency but used on the *remote* side via the gate; the local script only consumes the metrics dict.websockets — Lazily imported when --ws-port is set for broadcasting metrics.segment.analytics — Optional telemetry dependency, imported inside phonehome().monitor() method and emit SystemMetrics events containing CPU, memory, swap, disk, network, uptime, and process data.