hop3-tui
Terminal User Interface for Hop3 PaaS.
Overview
A modern, keyboard-driven terminal interface for managing Hop3 applications, built with turbodesk.
Features
- Dashboard overview: System stats, app summary, recent activity
- Application management: List, filter, start/stop/restart apps
- Environment variables: View, add, edit, delete with sensitive value hiding
- Live log polling: Filter logs, pause/resume, auto-scroll
- Chat interface: Interactive command line with tab completion
- System monitoring: CPU, memory, disk usage and service status
- Addon management: Create, attach, detach PostgreSQL, Redis, MySQL
- Backup management: Create, restore, delete app backups
- Connection status indicator: Visual feedback for server connectivity
Installation
pip install hop3-tui
Quick Start
# Set your server URL
export HOP3_SERVER_URL="https://hop3.example.com"
export HOP3_TOKEN="your-api-token"
# Run the TUI
hop3-tui
Configuration
Configuration via environment variables or ~/.config/hop3/tui.toml:
| Variable | Description | Default |
|---|---|---|
HOP3_SERVER_URL |
Server URL | http://localhost:5000 |
HOP3_TOKEN |
API authentication token | - |
HOP3_TUI_THEME |
Color theme (dark/light) |
dark |
Config File
[server]
url = "https://hop3.example.com"
token = "your-api-token"
[display]
theme = "dark"
refresh_interval = 5
Keyboard Shortcuts
Global
| Key | Action |
|---|---|
d |
Dashboard |
a |
Apps list |
s |
System status |
o |
Addons |
b |
Backups |
c |
Chat interface |
? |
Help |
q |
Quit |
Navigation
| Key | Action |
|---|---|
j/Down |
Move down |
k/Up |
Move up |
Enter |
Select |
Escape |
Go back |
/ |
Filter |
R |
Refresh |
Apps
| Key | Action |
|---|---|
s |
Start app |
S |
Stop app |
r |
Restart app |
l |
View logs |
e |
Environment variables |
Architecture
hop3-tui/
├── src/hop3_tui/
│ ├── __main__.py # Entry point
│ ├── app.py # Main Hop3TUI class with connection state
│ ├── config.py # Configuration loading (env vars + TOML)
│ ├── api/
│ │ ├── client.py # JSON-RPC client with error handling
│ │ └── models.py # Pydantic data models
│ ├── screens/ # One `render(ui, hop3, size, ...) -> View` per screen
│ │ ├── _common.py # bind(), halves(), rows(), fill() — what CSS used to do
│ │ ├── _logview.py # The pane behind both logs.py and system_logs.py
│ │ ├── dashboard.py # Overview with app counts
│ │ ├── apps.py # App list and management
│ │ ├── app_detail.py # Single app view
│ │ ├── logs.py # Live log polling
│ │ ├── env_vars.py # Environment variable editor
│ │ ├── system.py # System status
│ │ ├── addons.py # Addon management
│ │ ├── backups.py # Backup management
│ │ ├── processes.py # Running processes
│ │ ├── system_logs.py# System-wide logs
│ │ └── chat.py # Command interface
│ └── widgets/
│ ├── chrome.py # Header, footer, panel frames
│ ├── status_panel.py # Resource meters
│ ├── status_badge.py # Status indicators
│ └── util.py # Bar gauges, and the "not reported" marker
└── tests/ # pytest test suite (235 tests)
Immediate mode
There is no widget tree. The app is a function (UI) -> View that turbodesk re-runs
whenever a frame is marked dirty, and a screen is a function of its arguments — so
there is no compose(), no reactive/watch_*, no query_one, and no stylesheet.
Layout is arithmetic (halves, rows), and state lives in ui.state hooks matched
between frames by call order. Each screen renders inside its own ui.scope, which is
what keeps those slots from being handed to the next screen on a switch.
Rendering has no side effect on the screen, so a test calls the app function at any size and asserts on what came out — no pilot, no event loop, no async harness:
to_text(render(app(hop3), size=Size(90, 26)))
Nothing is invented
A panel shows what the server reported or says that it does not know
(not reported by the server); it never shows a plausible-looking constant. The log
pane's heading drops from LIVE to UNREACHABLE when a poll fails, rather than
going on looking live over a dead connection. tests/test_no_fabricated_data.py
holds that line.
Connection Handling
The TUI tracks connection state to the Hop3 server:
- Connected (green indicator): Server is reachable
- Disconnected (red indicator): Connection lost, will retry
- Connecting (yellow indicator): Attempting to connect
Connection failures are tracked and the state updates automatically. The UI continues to show cached data while disconnected.
Development
# Run it
uv run hop3-tui
# Run tests (from the workspace root)
uv run pytest packages/hop3-tui/tests
# Lint and format
uv run ruff check src/
uv run ruff format src/
Documentation
Related Packages
- hop3-server - The server that hop3-tui communicates with
- hop3-cli - Alternative command-line interface
License
Apache-2.0 - Copyright (c) 2024-2026, Abilian SAS
Metadata
Release files for hop3-tui 0.7.4
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| hop3_tui-0.7.4.tar.gz | 32.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| hop3_tui-0.7.4-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 81.5 kB
Release files / hop3_tui-0.7.4.tar.gz
| Download URL | hop3_tui-0.7.4.tar.gz |
|---|---|
| Size | 32.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
ea8818744e2a3e0b52a333a04e5ba95128e9f39a138a9192865e9cd01d45bf7e
|
|
BLAKE2b-256 checksum How to use checksums |
9a43ab5cd43323aa8c84060c993c4e2c83d2e4f3bfb5d7e803c0e587b51d98a7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.13
|
Release files / hop3_tui-0.7.4-py3-none-any.whl
| Download URL | hop3_tui-0.7.4-py3-none-any.whl |
|---|---|
| Size | 49.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
0da6580826f35cc3e2959a6d47f71d5b2ec14fd3ed18f6214c0813768b17638c
|
|
BLAKE2b-256 checksum How to use checksums |
cf432f270d08d8eb24a305bbb9ece23ed91566aeb94e6487d4dd287fed5bf156
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.13
|