Skip to main content

Cross-platform process monitor with Telegram notifications and remote control

Project description

qara banner
PyPI version Python versions License CI

Watch any process. Get notified on Telegram. Control it remotely.

qara is a lightweight daemon that monitors processes and sends real-time notifications to Telegram. Start a long-running job, close your laptop, and stay in control from your phone.

Built for ML practitioners who run multi-hour training jobs, but works with any process.

qara run python train.py --name "gpt-finetune"
# => Telegram: "Process 'gpt-finetune' started (PID 41592)"
# => ... hours later ...
# => Telegram: "Process 'gpt-finetune' finished (exit 0, 3h 42m)"

Features

  • Spawn or attach — start a new process with qara run or monitor an existing one with qara attach <pid>
  • Telegram notifications — get notified on start, finish, and crash with configurable stdout tail
  • Remote control — send /status, /kill, /history, /logs from Telegram
  • Plugin system — extend with plugins via entry points (e.g. qara-ml for GPU metrics and loss tracking)
  • Daemon mode — runs as a user-level service (systemd, launchd) — no root required
  • JSON output--format json on status and history for scripting

Quickstart

Install

pip install qara

# Or with uv (recommended)
uv pip install qara

# With ML plugin (GPU metrics + loss tracking)
pip install qara-ml

Configure

qara config init

This creates ~/.config/qara/config.toml. Open it and add your Telegram bot token and user ID:

[telegram]
bot_token = "123456:ABC-DEF..."
allowed_user_ids = [your_telegram_user_id]
How to get a bot token and user ID
  1. Message @BotFather on Telegram and send /newbot
  2. Follow the prompts to name your bot — you'll receive a token like 123456:ABC-DEF...
  3. To find your user ID, message @userinfobot and it will reply with your numeric ID
  4. Important: Send any message to your new bot first so it can message you back

Start the daemon

qara daemon start

Run a process

qara run python train.py --name "experiment-1"

That's it. You'll receive Telegram notifications when the process starts, finishes, or crashes.

Usage

Process management

# Run a process
qara run python train.py --name "my-job"

# Attach to an existing process
qara attach 12345 --name "background-job"

# List watched processes
qara status
qara status --format json

# View completed runs
qara history --last 10
qara history --format json

Telegram commands

Once the daemon is running, send these commands to your bot:

Command Description
/status List all watched processes
/kill <name> Send SIGTERM to a process (escalates to SIGKILL)
/history Show recent completed runs
/logs <name> Get last N lines of stdout

Daemon management

qara daemon start              # Start in background
qara daemon start --foreground  # Start in foreground (for systemd/launchd)
qara daemon stop               # Stop the daemon
qara daemon status             # Check if daemon is running

Install as a system service

# Auto-detects systemd (Linux) or launchd (macOS)
qara install

# Preview what would be installed
qara install --dry-run

# Remove the service
qara uninstall

Configuration

Full config.toml reference:

[daemon]
log_level = "INFO"  # DEBUG, INFO, WARNING, ERROR

[telegram]
bot_token = "YOUR_BOT_TOKEN"
allowed_user_ids = [123456789]

[telegram.notifications]
on_start = true
on_finish = true
on_crash = true
stdout_tail_lines = 20  # lines of stdout included in finish notification

[commands]
enabled = ["status", "kill", "restart"]
kill_timeout_seconds = 10

[commands.allowed_scripts]
# alias = "/absolute/path/to/script.py"

[plugins]
enabled = ["ml"]

[plugins.ml]
gpu_poll_interval_seconds = 5
loss_pattern = ""  # custom regex, leave empty for default

ML Plugin

The qara-ml plugin adds GPU monitoring and training loss tracking:

pip install qara-ml

Enable it in config.toml:

[plugins]
enabled = ["ml"]

After a training run finishes, you'll receive an additional summary:

GPU summary:
  Peak VRAM: 18204 MB / 24576 MB
  Avg GPU util: 94%
  Peak temp: 78°C

Training summary:
  Final loss: 0.0342
  Best loss: 0.0298 (step 4200)

The loss tracker matches common patterns like loss=0.123, train_loss: 0.456, etc. You can provide a custom regex via loss_pattern in the config.

Architecture

qara daemon start
      │
      ▼
┌─────────────┐     ┌──────────────┐     ┌──────────────┐
│   Watcher    │────▶│  EventEngine │────▶│  Telegram    │
│  (per proc)  │     │  (pub/sub)   │     │  Channel     │
└─────────────┘     └──────┬───────┘     └──────────────┘
                           │
                    ┌──────┴───────┐
                    │   Plugins    │
                    │ (GPU, loss)  │
                    └──────────────┘
      ▲
      │ IPC (Unix socket)
      │
  qara run / qara status / ...
  • Watcher spawns or attaches to processes via asyncio.create_subprocess_exec
  • EventEngine is sequential async pub/sub — handlers receive events in subscription order
  • Plugins subscribe directly to the engine and receive all events including stdout/stderr lines
  • NotificationBus filters internal events before routing to channels
  • IPC uses newline-delimited JSON over Unix sockets (Linux/macOS)

Development

git clone https://github.com/warptengood/qara
cd qara
uv sync --group dev

# Run checks
uv run ruff check src/       # lint
uv run ruff format src/      # format
uv run mypy src/             # type check
uv run pytest                # tests

See CONTRIBUTING.md for guidelines.

License

MIT — see LICENSE for details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

qara-0.1.1.tar.gz (2.1 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

qara-0.1.1-py3-none-any.whl (29.0 kB view details)

Uploaded Python 3

File details

Details for the file qara-0.1.1.tar.gz.

File metadata

  • Download URL: qara-0.1.1.tar.gz
  • Upload date:
  • Size: 2.1 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for qara-0.1.1.tar.gz
Algorithm Hash digest
SHA256 7c09c84f7780b221ffd08fae7535df1849a754d26115aadd43b25cf2df2f00dc
MD5 a8d192bb840aa7914ec94b54c3154948
BLAKE2b-256 c430d904245a72514ad5bbd1665c7dab5c4e688cf444ed51720b8f86240de790

See more details on using hashes here.

Provenance

The following attestation bundles were made for qara-0.1.1.tar.gz:

Publisher: publish.yml on warptengood/qara

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file qara-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: qara-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 29.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for qara-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 1c4549fa98d6df56e52d6bf7535f5e59461dcc2b04a5d4a99be2ffbe353016de
MD5 63e512c69122073da121646dd89dec27
BLAKE2b-256 8d420e09efb97b31945b1bd4757d28e2fc9323c6b1f9563db27d3e22147cf71d

See more details on using hashes here.

Provenance

The following attestation bundles were made for qara-0.1.1-py3-none-any.whl:

Publisher: publish.yml on warptengood/qara

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page