Keep every endpoint in sight.
EyeNine is a lightweight, local-first endpoint uptime and SLA monitor built with Python, SQLite, and PySide6. It watches web URLs, devices, and network services from a polished desktop dashboard while keeping all monitoring history on the machine running it.
- Dashboard with live state, 24-hour SLA rollups, response time, and status-page-style history bars
- Endpoint detail view with 24-hour and 30-day SLA, latency trends, check history, configuration summary, manual checks, and copying for configuration variants
- Guided endpoint wizard with plain-language defaults and advanced controls
- HTTP, TCP, ICMP/ping, and DNS monitoring strategies
all,any, and numeric-threshold success policies for combined strategies- Configurable interval, timeout, accepted HTTP codes, required response content, TLS verification, TCP port, DNS address, and latency threshold
- Per-endpoint desktop alerts, consecutive-failure thresholds, recovery notifications, and optional SMTP email alerts
- Clickable native notifications that return to the affected endpoint
- SQLite history, configurable scheduled retention, and manual cleanup
- Per-endpoint or global CSV and JSON exports
- System-aware light/dark appearance with manual override
- Immediate theme preview, consistent pointer cursors, and bundled dropdown/spin-control indicators
- EyeNine Brand System v1.0 colors, artwork, and bundled OFL typography (Manrope, Inter, and JetBrains Mono)
- Background monitoring from the system tray
- Single-instance protection so two processes cannot write the same monitoring database
- PyInstaller configuration for Linux, Windows, and macOS
Python 3.11 or newer is required.
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
python -m pip install -e ".[dev]"
eyenineEyeNine stores its database and settings in the operating system's standard per-user application-data directory. Set EYENINE_DATA_DIR=/path/to/folder to use a portable or test location.
The ICMP strategy invokes the operating system's ping utility. Install the package supplying it if it is missing (commonly iputils-ping). EyeNine does not require root privileges.
Each endpoint has one or more strategies:
| Strategy | Use it to verify | Important options |
|---|---|---|
| HTTP | A web page, API, or health route responds correctly | GET/HEAD, status ranges, required content, TLS validation |
| TCP | A service accepts a connection | Port |
| Ping | A device answers an ICMP echo request | Timeout |
| DNS | A hostname resolves | Optional expected address |
The endpoint's success policy combines those results. A latency threshold can then turn an otherwise successful check into DEGRADED. New endpoints use a 1,000 ms threshold by default, and degraded checks count as uptime in SLA calculations; both behaviors are configurable per endpoint.
Checks run concurrently in a bounded worker pool. Network work never runs on the Qt UI thread. Results return through a queued Qt signal and are committed to SQLite on the application thread.
Desktop notifications are enabled for new endpoints. EyeNine alerts once when a failure incident opens, then stays quiet until recovery instead of sending a message on every failed check. Configure a higher consecutive-failure count to reduce transient alerts.
EyeNine uses Qt's native notification and system-tray integration. Notification display remains subject to the desktop's notification permissions and do-not-disturb settings. KDE Plasma, GNOME, COSMIC, Windows, and macOS use their corresponding native notification surface; clicking a notification opens EyeNine on the endpoint involved. EyeNine leaves status-notifier discovery and registration to Qt so each desktop can use its native tray path. If no usable tray host exists, closing the window exits instead of leaving monitoring hidden without an accessible icon.
- Obtain the SMTP server, port, security mode, and optional login from your email provider.
- Open Settings → Email alerts · SMTP.
- Enter the connection details, sender, and recipients, then choose Test and save.
- Enable email for the desired endpoints in their edit wizard.
The SMTP password is stored in the operating system credential vault through keyring where available. A permission-restricted local fallback is used when the platform has no usable credential backend. EyeNine tests the connection and login without sending mail before it saves the configuration. Email is delivered asynchronously and never blocks monitoring or the UI.
The history table is indexed by endpoint and check time. Deleting an endpoint cascades to its history and incident state after a confirmation dialog. Cleanup defaults to 90 days and runs at most once per calendar day; it can be disabled, changed, or set to Forever in Settings. Exports prompt for a preset or custom time range, then default to a descriptive filename in Documents before writing CSV or JSON.
CSV exports flatten strategy detail into a JSON column. JSON exports use this envelope:
{
"schema_version": 1,
"checks": []
}Timestamps are stored as timezone-aware ISO 8601 UTC values and rendered in the user's local timezone.
The core test suite uses only the Python standard library and runs without a display server:
PYTHONPATH=src python -m unittest discover -s tests -vThe suite covers database round trips and cascading deletion, local HTTP monitoring, combined success criteria, SLA calculation, cleanup, exports, and alert incident transitions.
EyeNine includes a repeatable visual-smoke harness which seeds long endpoint names, URLs, timestamps, and failure messages, then renders every major screen in both themes. It scans visible labels and buttons for clipped text while saving screenshots for human inspection.
QT_QPA_PLATFORM=offscreen PYTHONPATH=src python tests/visual_smoke.pyThe release matrix covers the main window's 980×700 minimum, the normal 1180×820 size, and the wizard's 720×600 minimum. Run a high-DPI pass with QT_SCALE_FACTOR=1.25. A normal workstation with PySide6 installed does not need the diagnostic EGL shim used by unusually minimal containers.
Install development dependencies on the target operating system, then build there:
python -m pip install -e ".[dev]"
pyinstaller --clean --noconfirm packaging/eyenine.specPyInstaller outputs dist/EyeNine/ on Linux and Windows, and an application bundle on macOS. Builds are intentionally produced on each target OS because Qt and notification integrations are platform-specific.
Copy packaging/linux/eyenine.desktop into ~/.local/share/applications/ and the matching PNGs from packaging/linux/hicolor/ into ~/.local/share/icons/hicolor/ when making a local installation. Distribution packages should install the same files system-wide.
Build on 64-bit Windows with Python 3.11+. For a distributable installer, wrap the generated dist/EyeNine directory with WiX, Inno Setup, or MSIX. Code-sign the executable and installer for a production release.
Build on the oldest macOS release you intend to support. Sign and notarize EyeNine.app before distribution. macOS notification permission is requested/managed by the operating system; a signed bundle provides the stable application identity needed for notification settings.
src/eyenine/
alerts.py Incident state, secrets, and SMTP delivery
app.py Application entry point and data location
brand.py Bundled artwork, typography, and platform icon helpers
database.py SQLite schema and persistence API
exporter.py CSV/JSON historical exports
main_window.py Navigation, scheduling, tray, and notifications
models.py Typed domain models
monitor.py Monitoring strategies and concurrent scheduler
pages.py Dashboard, detail, and settings pages
styles.py Brand-token-driven light/dark design system
widgets.py Status bars, charts, badges, and reusable cards
wizard.py Add/edit endpoint flow
tests/ Headless core tests
packaging/ PyInstaller and Linux desktop integration
resources/ Runtime logo, icon, tray, and OFL font assets (inside the package)
- Monitoring runs while the EyeNine process is active; it is not a system daemon.
- HTTP response-content matching reads at most 1 MiB.
- SLA is check-based: each scheduled check has equal weight. Gaps while the application is not running are not counted as downtime.
- SMTP servers that require STARTTLS, implicit SSL/TLS, or an unencrypted local connection are supported. OAuth-only email providers are outside the current scope.
MIT