ralphex can send notifications when plan execution completes (success or failure). Notifications are optional, disabled by default, and best-effort - failures are logged but never affect the exit code.
- Add channels to your config (
~/.config/ralphex/configor.ralphex/config):
notify_channels = telegram
notify_telegram_token = 123456:ABC-DEF
notify_telegram_chat = -1001234567890- Run ralphex as usual. A notification fires after execution finishes.
# comma-separated list of channels: telegram, email, slack, webhook, custom
notify_channels = telegram, webhook
# send notification on failure (default: true)
notify_on_error = true
# send notification on success (default: true)
notify_on_complete = true
# total timeout for all notification channels in milliseconds (default: 10000)
notify_timeout_ms = 10000Setting notify_channels to empty (or omitting it) disables notifications entirely. All channel-specific settings are ignored unless the corresponding channel is listed in notify_channels.
Create a bot and get a chat ID:
- Message @BotFather on Telegram and create a new bot with
/newbot - Copy the bot token (looks like
123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11) - Add the bot to your channel or group
- Get the chat ID - send a message in the chat, then visit
https://api.telegram.org/bot<TOKEN>/getUpdatesand look for"chat":{"id":...} - For public channels, use the channel name with
@prefix (e.g.,@mychannel)
Config:
notify_channels = telegram
notify_telegram_token = 123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11
notify_telegram_chat = -1001234567890The chat value can be a numeric chat ID or a channel name like @mychannel.
Config for Gmail with app password:
notify_channels = email
notify_smtp_host = smtp.gmail.com
notify_smtp_port = 587
notify_smtp_username = you@gmail.com
notify_smtp_password = your-app-password
notify_smtp_starttls = true
notify_email_from = you@gmail.com
notify_email_to = you@gmail.com, team@example.comFor Gmail, use an app password (not your regular password). Enable 2FA first, then generate an app password under Security > App passwords.
Generic SMTP:
notify_channels = email
notify_smtp_host = mail.example.com
notify_smtp_port = 587
notify_smtp_username = user@example.com
notify_smtp_password = password
notify_email_from = ralphex@example.com
notify_email_to = dev@example.comMultiple recipients are comma-separated in notify_email_to. Set notify_smtp_port explicitly (587 is typical for STARTTLS).
Create a Slack bot and get a token:
- Go to api.slack.com/apps and create a new app
- Under OAuth & Permissions, add the
chat:writescope - Install the app to your workspace
- Copy the Bot User OAuth Token (starts with
xoxb-) - Invite the bot to the target channel (
/invite @yourbot)
Config:
notify_channels = slack
notify_slack_token = xoxb-your-bot-token
notify_slack_channel = generalThe channel value is the channel name (without #) or channel ID.
ralphex sends the notification message as a plain text POST to each webhook URL.
Config:
notify_channels = webhook
notify_webhook_urls = https://hooks.example.com/notify, https://other.example.com/webhookMultiple URLs are comma-separated. Each URL receives the notification independently.
A custom script receives the full Result JSON on stdin and is expected to handle delivery itself. This lets you integrate with any notification service.
Config:
notify_channels = custom
notify_custom_script = ~/.config/ralphex/scripts/notify.shThe script:
- Receives
ResultJSON on stdin - Exit code 0 = success, non-zero = failure (logged as warning)
- Timeout controlled by
notify_timeout_ms
JSON schema piped to stdin:
{
"status": "success",
"mode": "full",
"plan_file": "docs/plans/add-auth.md",
"branch": "add-auth",
"duration": "12m 34s",
"files": 8,
"additions": 142,
"deletions": 23
}The error field is present only on failure (omitted on success).
Example script:
#!/bin/bash
# read JSON from stdin and send to a custom endpoint
jq -c '.' | curl -s -X POST -H "Content-Type: application/json" -d @- https://hooks.example.com/ralphexExample script using ntfy.sh:
#!/bin/bash
# read JSON from stdin, extract status and plan, send to ntfy.sh
DATA=$(cat)
STATUS=$(echo "$DATA" | jq -r '.status')
PLAN=$(echo "$DATA" | jq -r '.plan_file')
curl -s -d "ralphex ${STATUS}: ${PLAN}" ntfy.sh/my-ralphex-topicChannels can be combined freely:
notify_channels = telegram, webhook, custom
notify_telegram_token = 123456:ABC-DEF
notify_telegram_chat = -1001234567890
notify_webhook_urls = https://hooks.example.com/notify
notify_custom_script = ~/.config/ralphex/scripts/notify.shEach channel is independent - if one fails, others still fire.
# enable telegram and email notifications
notify_channels = telegram, email
# send on both success and failure
notify_on_error = true
notify_on_complete = true
# 15 second total timeout for all channels
notify_timeout_ms = 15000
# telegram
notify_telegram_token = 123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11
notify_telegram_chat = -1001234567890
# email via gmail
notify_smtp_host = smtp.gmail.com
notify_smtp_port = 587
notify_smtp_username = you@gmail.com
notify_smtp_password = your-app-password
notify_smtp_starttls = true
notify_email_from = you@gmail.com
notify_email_to = you@gmail.comNotifications use a plain text format.
Success:
ralphex completed on myhost
plan: docs/plans/add-auth.md
branch: add-auth
mode: full
duration: 12m 34s
changes: 8 files (+142/-23 lines)
Failure:
ralphex failed on myhost
plan: docs/plans/add-auth.md
branch: add-auth
mode: full
duration: 5m 12s
error: runner: task phase: max iterations reached
The custom script channel receives structured JSON instead of this text format (see custom script section above).
- Notifications are best-effort. Delivery failures are logged as warnings but never cause ralphex to fail or change its exit code.
- Misconfigured channels (missing required fields) are detected at startup and cause an immediate error. However, channels that require a live API call during initialization (e.g., Telegram's bot token verification) are gracefully skipped with a warning if the call fails, since notifications are best-effort.
- Telegram initialization verifies the bot token via a synchronous API call (up to 30s timeout). If the API is unreachable or the token is invalid, the channel is disabled with a warning. Note that this verification blocks startup for the duration of the attempt.
- The hostname in the message is resolved once at startup. If resolution fails, "unknown" is used.
- Notifications are not sent in plan creation mode (
--plan). If plan creation transitions to execution, the notification fires after execution completes. - Built-in channels (telegram, email, slack, webhook) use go-pkgz/notify under the hood. Refer to that library for advanced channel-specific behavior.