cron-status-alert

July 16, 2026 · View on GitHub

[beta] — new; adoption feedback welcome — issues open.

Standalone Hermes plugin that watches your cron jobs and DMs you when a Discord-delivering job fails to deliver or runs overdue. Also provides /cron-status for on-demand health.

Listed in awesome-hermes-agent.

Installs into ~/.hermes/plugins/ — no core edits.

Why

Hermes marks a cron job ok when the agent finished, not when Discord actually received the post. So an image job can 429, emit [SILENT], and still show green in hermes cron list while your channel gets nothing. You find out when someone asks where the 12:30 post is — three days later.

This plugin closes that gap. It watches the delivery-status fields Hermes already tracks (last_delivery_error, overdue next_run_at) and DMs you the moment a Discord-delivering job fails or runs late, then tells you when it recovers. No more silent misses.

Example alert DM

Prerequisite: get your DM channel id

Alerts are sent via send_message_tool with:

target: discord:<dm_channel_id>

discord:<user_id> does not work. The send path treats the digits as a channel snowflake. A user id fails with “channel not found” and the plugin will log that loudly — but you will not get the alert.

How to obtain the DM channel snowflake

  1. Enable Discord Developer Mode (User Settings → App Settings → Advanced → Developer Mode).
  2. Open a DM with the Hermes bot (send it any message if needed so the DM channel exists).
  3. Right-click the DM channel in the sidebar (or the channel header) → Copy Channel ID.
  4. That value is the DM channel id (not your user id).

Confirm the form Hermes already stores for DM sessions looks like discord:dm:<chat_id> — the <chat_id> portion is what you want after discord: in config.

Example config value:

target: "discord:123456789012345678"

1. Install the plugin

Copy this folder to:

cp -R cron-status-alert ~/.hermes/plugins/cron-status-alert

2. Configure

Add to ~/.hermes/config.yaml:

cron_status_alert:
  enabled: true
  target: "discord:<dm_channel_id>"   # REQUIRED for alerts
  poll_seconds: 60
  grace_seconds: 120
  watch: []                # optional job-id allowlist (replaces default scope)
  ignore: []               # optional job-id denylist
  notify_recovery: true
  persistent_realert_hours: 24

Default watch scope: enabled, non-paused jobs whose deliver starts with discord:. Non-empty watch replaces that set; ignore always subtracts.

If enabled is true but target is unset, the slash command still works and the plugin logs a clear warning — no crash, no silent DMs to nowhere.

3. Enable

hermes plugins enable cron-status-alert

4. Restart the gateway

Restart so the plugin loads and the poll thread starts.

5. Verify

In Discord:

/cron-status
/cron-status all
/cron-status <job-name-or-id>

You should see one line per watched job (or a summary if you have many).

6. How alerts work (v1)

  • Poll-driven every poll_seconds (default 60). There is no post-delivery hook in Hermes core yet; this plugin owns a daemon thread.
  • Conditions per job:
    • RUN_FAILEDlast_status == "error"
    • DELIVERY_FAILEDlast_delivery_error set
    • OVERDUEnow > next_run_at + grace_seconds (default grace 120s)
  • Edge-triggered: fires once when a condition becomes active, silent while it stays active, recovery notice when it clears (if notify_recovery), and a single re-alert after persistent_realert_hours (default 24h) if still bad.
  • State is persisted at $HERMES_HOME/cron_status_alert_state.json so a gateway restart does not re-DM every currently broken job.

Development

cd cron-status-alert
pytest tests/ -q

Tests use stdlib + pytest + unittest.mock only (no network).

License

MIT License — see LICENSE.