Metadata-Version: 2.4
Name: jobmonitor-cli
Version: 0.1.1
Summary: Monitor any command with periodic Slack, Discord, or email notifications
Author: Raimon Padros
License: MIT
Keywords: monitoring,notifications,slack,discord,email,gpu
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: POSIX :: Linux
Classifier: Topic :: System :: Monitoring
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Provides-Extra: dev
Requires-Dist: pytest; extra == "dev"
Dynamic: license-file

# Job Monitor

A CLI tool that wraps any command (or attaches to a running process) and sends periodic notifications with job status, system resource usage, and recent terminal output. Supports Slack, Discord, and email backends.

## Installation

### From PyPI

```bash
pip install jobmonitor-cli
```

### From source

```bash
# Create the conda environment
conda env create -f environment.yml

# Install the package
conda activate jobmonitor
pip install -e .

# (Optional) Make available system-wide for all users
sudo ln -s $(which jobmonitor) /usr/local/bin/jobmonitor
```

## Backend Setup

You can configure backends via CLI flags, environment variables, or a config file (`~/.jobmonitorrc`). Priority: **CLI flags > env vars > config file > defaults**.

### Slack (default)

1. Go to [api.slack.com/apps](https://api.slack.com/apps) > Create New App > From scratch
2. Go to Incoming Webhooks > Toggle On > Add New Webhook to Workspace
3. Pick a channel and copy the webhook URL
4. Add to your `~/.bashrc`:

```bash
export SLACK_WEBHOOK_URL="https://hooks.slack.com/services/YOUR/WEBHOOK/URL"
```

### Discord

1. In your Discord server, go to a channel's settings > Integrations > Webhooks > New Webhook
2. Copy the webhook URL
3. Add to your `~/.bashrc`:

```bash
export DISCORD_WEBHOOK_URL="https://discord.com/api/webhooks/YOUR/WEBHOOK/URL"
```

### Email

Email uses SMTP to send notifications. If your machine has `postfix` or `sendmail` running, it works out of the box with `localhost`.

Add to your `~/.bashrc`:

```bash
export JOBMONITOR_EMAIL_TO="you@example.com"
# Optional — defaults shown:
# export SMTP_SERVER="localhost"
```

For external SMTP (e.g., Gmail), set `--smtp-server` and `--smtp-port` flags. Note: Gmail requires an [app password](https://support.google.com/accounts/answer/185833).

### Changing the default backend

By default, `jobmonitor` uses Slack. To change the default, add to your `~/.bashrc`:

```bash
export JOBMONITOR_BACKEND="discord"   # or "email"
```

You can always override per-invocation with `--backend`.

## Config File

Instead of environment variables, you can create `~/.jobmonitorrc` to set persistent defaults:

```ini
[defaults]
backend = slack
interval = 2h
tail = 20
cpu = false
disk = false
no-gpu = false
no-ram = false

[slack]
webhook_url = https://hooks.slack.com/services/YOUR/WEBHOOK/URL

[discord]
webhook_url = https://discord.com/api/webhooks/YOUR/WEBHOOK/URL

[email]
to = you@example.com
from = jobmonitor@yourmachine
smtp_server = localhost
smtp_port = 25
```

All sections and keys are optional. CLI flags and environment variables always take priority over the config file.

## Usage

### Wrap a new command

```bash
jobmonitor --interval 2h --name "experiment-1" -- python train.py --epochs 100
jobmonitor --interval 1h --name "full-sweep" -- bash experiments.sh

# Using Discord
jobmonitor --backend discord --interval 2h -- python train.py

# Using email
jobmonitor --backend email --email-to user@example.com -- python train.py
```

### Attach to an already-running process

```bash
# Find the PID
ps aux | grep train

# Attach to it
jobmonitor --pid 12345 --interval 2h --name "experiment-1"

# Optionally tail a log file for output context
jobmonitor --pid 12345 --interval 2h --log path/to/logfile.log
```

## Options

| Flag | Default | Description |
|------|---------|-------------|
| `--interval` | `2h` | Notification interval (e.g. `30m`, `1h30m`, `2h`) |
| `--backend` | `slack` | Notification backend: `slack`, `discord`, or `email` |
| `--webhook-url` | config/env | Webhook URL for Slack or Discord |
| `--name` | auto | Job name shown in notifications |
| `--tail` | `20` | Number of recent output lines to include |
| `--pid` | - | Attach to an existing process by PID |
| `--log` | - | Log file to tail (used with `--pid`) |
| `--no-gpu` | - | Skip GPU info in notifications |
| `--no-ram` | - | Skip RAM info in notifications |
| `--cpu` | - | Include CPU usage in notifications |
| `--disk` | - | Include disk usage in notifications |
| `--email-to` | config/env | Recipient email (email backend) |
| `--email-from` | `user@hostname` | Sender email (email backend) |
| `--smtp-server` | `localhost` | SMTP server (email backend) |
| `--smtp-port` | `25` | SMTP port (email backend) |

## Notifications

Each notification includes:
- Job status (started / running / completed / failed / cancelled)
- Elapsed time
- Hostname
- RAM usage (unless `--no-ram`)
- GPU utilization, memory, and temperature (unless `--no-gpu`)
- CPU usage (opt-in with `--cpu`)
- Disk usage (opt-in with `--disk`)
- Last N lines of terminal output
- The command being monitored

A notification is sent immediately when monitoring begins, then at every `--interval`, and once more when the job finishes.

## Running tests

```bash
conda activate jobmonitor
pytest tests/ -v
```

## Publishing to PyPI

```bash
pip install build twine
python -m build
twine upload dist/*
```

Requires a [PyPI account](https://pypi.org/account/register/) and API token.
