Disclaimer: A small project born from a vibecoding session, expanding on an older handcoded system monitor. Not production software — run it, hack it, break it.
Amazigh for "eye." System monitor built for Raspberry Pi 5 inside an Argon V3 NVMe case.
Terminal UI + web dashboard. Monitors CPU, RAM, disk, network, SSD health, and controls the Argon V3 fan via I2C. Stores history in SQLite. Sends alerts via ntfy.
| Live Dashboard | Reporting |
|---|---|
![]() |
![]() |
| SSD Health | ntfy Alerts |
|---|---|
![]() |
![]() |
Terminal UI
- Raspberry Pi 5
- Argon V3 NVMe case (fan control via I2C)
- NVMe SSD at
/dev/nvme0n1 - I2C enabled on the Pi
- Docker (recommended) or Python 3.11+
Enable I2C:
sudo raspi-config
# Interface Options → I2C → EnableInstall Docker:
curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker $USER
# log out and back ingit clone https://github.com/ZTF666/Tit.git tit
cd tit
cp .env.example .env
nano .env # set your password, adjust if needed
docker compose up -dWeb dashboard: http://<pi-ip>:8080
Default credentials: admin / changeme — change these in .env before exposing externally.
pip install -r requirements.txt
sudo apt install smartmontools
# Web server + background collector
TIT_DB_PATH=./tit.db TIT_DISK_PATH=/ python -m tit web
# Terminal UI only
python -m tit tui
# Both at once (web in background thread, TUI in foreground)
TIT_DB_PATH=./tit.db TIT_DISK_PATH=/ python -m tit
TIT_DISK_PATHshould point to your root filesystem (/). The Docker default is/host(a bind mount of the Pi's root).
When running manually, smartctl needs either sudo access or a sudoers rule:
echo "$USER ALL=(root) NOPASSWD: /usr/sbin/smartctl" | sudo tee /etc/sudoers.d/tit-smartctl
sudo chmod 440 /etc/sudoers.d/tit-smartctl| Variable | Default | Description |
|---|---|---|
TIT_USERNAME |
admin |
Web UI username |
TIT_PASSWORD |
changeme |
Web UI password |
TIT_PORT |
8080 |
Web server port |
TIT_HOST |
0.0.0.0 |
Bind address |
TIT_DB_PATH |
/data/tit.db |
SQLite path |
TIT_I2C_BUS |
1 |
I2C bus (GPIO I2C on Pi 5) |
TIT_SMART_DEVICE |
/dev/nvme0n1 |
NVMe device for SMART |
TIT_DISK_PATH |
/host |
Path to monitor for disk usage |
TIT_NTFY_HOST |
(empty) | ntfy server URL |
TIT_NTFY_TOPIC |
tit-alerts |
ntfy topic |
TIT_NTFY_ENABLED |
false |
Enable ntfy alerts |
TIT_COLLECT_INTERVAL |
30 |
Snapshot interval (seconds) |
| Command | What runs |
|---|---|
python -m tit web |
FastAPI + background collector + SMART poller |
python -m tit tui |
Textual TUI, reads metrics live via psutil |
python -m tit |
Both — web in thread, TUI in foreground |
The web server is the canonical collector: it writes snapshots to SQLite every 30 seconds. The TUI reads metrics directly and does not require the web server.
- Set up ntfy or use ntfy.sh.
- In the web UI Settings tab, enter your ntfy host and topic, and enable alerts.
- Set thresholds (CPU temp, CPU %, RAM %, disk %).
Alerts fire for: CPU temperature spikes, sustained high CPU (>60s), RAM pressure, disk usage, and SSD health degradation.
To access the dashboard remotely without opening ports:
curl -L https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-arm64 \
-o cloudflared && chmod +x cloudflared && sudo mv cloudflared /usr/local/bin/
cloudflared tunnel login
cloudflared tunnel create tit
cloudflared tunnel route dns tit tit.yourdomain.com
cloudflared tunnel run titThe web UI is protected by HTTP Basic Auth so it's safe to expose publicly.
| Key | Action |
|---|---|
q |
Quit |
r |
Force refresh |
f |
Focus fan panel |




