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)"
Telegram notifications for an attached process

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
  • 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

# Install globally (recommended)
pipx install qara

# Or with uv
uv pip install qara

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
Telegram /logs and /kill commands in action

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"

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.2.0.tar.gz (2.4 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.2.0-py3-none-any.whl (28.6 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for qara-0.2.0.tar.gz
Algorithm Hash digest
SHA256 dbd2a06dcf1477fe5b7ed94297296a1a62945acb2bbb2073726c45e440c0ee9b
MD5 6b1071438f965d623a0bec0b13d99f65
BLAKE2b-256 01cee34cfd1d51168edaf3f26aa5d3d1eda6283b6aea843307d57a8fad55187e

See more details on using hashes here.

Provenance

The following attestation bundles were made for qara-0.2.0.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.2.0-py3-none-any.whl.

File metadata

  • Download URL: qara-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 28.6 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.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 e48b24f82626a23a91eab361204efe00e06e34d1c76683855ee7902e1b02fdc0
MD5 8552784e942d4c1c3bae683be2c96539
BLAKE2b-256 3fee35e2feea5c7fa74fe8f3ce41dacdbdf8c3980b6f58d252e631bafcd0bee5

See more details on using hashes here.

Provenance

The following attestation bundles were made for qara-0.2.0-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