DEV Community

Cover image for XtermChat | A Terminal Chat App With a Built-in Server Monitoring Bot
Ketut Dana
Ketut Dana

Posted on

XtermChat | A Terminal Chat App With a Built-in Server Monitoring Bot

A few months ago I got tired of giving my team's conversations to third-party servers. So I built XtermChat — a self-hosted chat system that runs entirely in the terminal.

Since then, it has grown into something I didn't originally plan: a full client-server chat system with a terminal TUI, a web admin panel, and a bot that monitors your VPS and sends alerts directly into your chat rooms.

This post is about what it became.


What XtermChat Is Now

At its core, XtermChat is still simple: a Python Flask server, a SQLite database, and a CLI client. But it now ships with three ways to use it.

1. Terminal TUI — the original interface. Run xtc start:chat @general and you get a full terminal UI with three panels, dual-focus mode, emoji shortcuts, link detection, and clipboard copy.

2. Web Admin Panel — run xtc start:web and open localhost:5000. Full admin panel with dashboard, room management, chat with link previews (OG image, title, description), and bot management.

3. Bot System — run xtc start:bot and a setup wizard walks you through configuring a monitoring bot that runs as a background process on your VPS.


The Bot System

This is the part I'm most excited about. The idea is simple: instead of setting up a separate alerting tool, XtermChat already has rooms and messaging — so why not use that infrastructure for server monitoring too?

$ xtc start:bot

┌──────────────────────────────────────┐
│   XTERMCHAT  ·  BOT SETUP            │
└──────────────────────────────────────┘

▸ SELECT ROOM
  1. @general    OPEN   by KETUT
  2. @alerts     OPEN   by KETUT

▸ Bot name: MONITOR

▸ SELECT BOT TASKS
  1.  Resource Monitor     CPU, RAM, Disk usage
  2.  Process Monitor      Watch if a service dies
  3.  Uptime Watchdog      Ping a URL every N minutes
  4.  Port Checker         Verify ports are open
  5.  SSL Cert Checker     Alert before cert expires
  6.  Log Watcher          Tail a log for keywords
  ...

▸ Select tasks: 1,3

✓ Config saved  (bot_id: 1)
✓ Bot started on server  (PID: 24891)
Enter fullscreen mode Exit fullscreen mode

The bot runs as a background process on the VPS. It reads its config from the database, checks at the configured interval, and sends alerts as normal messages to any room you choose.

An alert looks like this in your chat:

⚠️ RESOURCE ALERT on srv1260384 [15 Mar 2026 08:30:00]
  CPU   85%  (limit 80%)
  RAM   91%  (limit 85%)
Enter fullscreen mode Exit fullscreen mode

Because it's just a message in a room, you can see it from the terminal TUI, the web admin, or any client connected to the server.


The Architecture

The whole thing is two repos.

xtc-server — lives on your VPS:

xtc-server/
├── server.py       Flask app, all API + bot routes
├── db.py           SQLite init (users, rooms, messages, bots)
├── room.py         Room CRUD, bcrypt passwords
├── connection.py   Message save/retrieval
└── bot_runner.py   Bot background process
Enter fullscreen mode Exit fullscreen mode

xtc-client — lives on your machine:

xtc-client/
├── xtc.py          CLI entry point, command dispatcher
├── utils.py        Hardware UUID identity
├── commands/
│   ├── chat.py     Terminal TUI
│   ├── bot.py      Bot setup wizard
│   ├── bot_stop.py Stop/list bots
│   ├── listBots.py List all registered bots
│   └── deleteBot.py Delete bots
└── web/
    ├── app.py      Flask web server (port 5000)
    └── html/       5 admin pages
Enter fullscreen mode Exit fullscreen mode

The client sends a POST /bot/start to the server, which spawns bot_runner.py as a background process. The bot reads its config from the database and starts monitoring. Stop it with xtc stop:bot 1 which sends POST /bot/kill — the server kills the PID and updates the database.


The Web Admin

The web admin surprised me with how useful it turned out. I built it for team members who don't use the terminal, but I ended up using it myself because the chat bubble UI with link previews is genuinely nicer for long conversations.

The chat page fetches Open Graph metadata for any URL shared in a message — image, title, description, favicon. It's cached per session so the same URL isn't fetched twice.

One thing worth noting: the web admin uses a 5-digit PIN you choose at login, while the CLI uses a hardware UUID auto-generated from your machine. Both work with the same server and the same rooms. The difference is that CLI identity is device-bound (if you reinstall your OS, your PIN changes), while web identity is portable.


What I Learned

SQLite is underrated. The entire server state — users, rooms, messages, bot configs — lives in one file. Backup is cp xtc.db backup.db. For a team of 2–50 people on a $5 VPS, it's more than enough.

REST over WebSocket was the right call. Polling every 2 seconds is fine for this use case and dramatically simpler to implement, debug, and extend. The bot just makes HTTP requests too — same pattern everywhere.

Hardware UUID as identity is surprisingly clean. No passwords to remember. Your machine is your identity. The tradeoff is that switching devices requires an admin to reset your entry, but for a small team that's a non-issue.


Try It

Setup takes about 10 minutes. The docs cover everything from server setup to HTTPS to the full bot task reference.

If you run a small team, manage a homelab, or just want your chat data to stay on your own infrastructure — give it a try. And if you find something broken or have a feature idea, issues and pull requests are very welcome.


Built with Python · Runs on a $5 VPS · MIT License

Top comments (0)