SPEC-0004: Apprise Notification Abstraction
Overview
Claude Ops uses the Apprise CLI as a universal notification abstraction layer, enabling operators to receive alerts and reports through any combination of 80+ notification services (email, Slack, Discord, Telegram, ntfy, PagerDuty, etc.) via a single environment variable. This specification defines the requirements for notification integration, event categories, message formatting, and graceful degradation when notifications are not configured.
Definitions
- Apprise: An open-source Python CLI and library that provides a unified notification interface for 80+ services. Each notification target is configured as a URL with a service-specific scheme (e.g.,
ntfy://,slack://,mailto://). - Apprise URL: A URL conforming to Apprise's service-specific scheme that identifies a notification target and its credentials (e.g.,
ntfy://ntfy.sh/my-topic). - Notification Event: A categorized event that triggers a notification. Claude Ops defines three categories: daily digest, auto-remediation report, and human attention alert.
- Daily Digest: A periodic summary of all health check results and system uptime statistics.
- Auto-Remediation Report: An immediate notification sent after the system successfully fixes an issue, describing the problem, action taken, and verification result.
- Human Attention Alert: An immediate notification sent when remediation fails or cooldown limits are exceeded, requiring manual operator intervention.
- Graceful Degradation: The system behavior when
CLAUDEOPS_APPRISE_URLSis empty or unset: notifications are silently skipped without errors.
Requirements
REQ-1: Single Environment Variable Configuration
The system MUST configure all notification targets through a single environment variable: CLAUDEOPS_APPRISE_URLS. This variable MUST accept one or more comma-separated Apprise URLs.
The system MUST NOT require any additional configuration files, per-service credential blocks, or service-specific setup for notifications.
Scenario: Single notification target
Given an operator sets CLAUDEOPS_APPRISE_URLS=ntfy://ntfy.sh/ops-alerts
When the system sends a notification
Then the notification is delivered to the ntfy topic ops-alerts
Scenario: Multiple notification targets
Given an operator sets CLAUDEOPS_APPRISE_URLS=ntfy://ntfy.sh/ops-alerts,mailto://user:pass@smtp.example.com?to=ops@example.com
When the system sends a notification
Then the notification is delivered to both the ntfy topic and the email address
Scenario: Notification target change without rebuild
Given an operator modifies CLAUDEOPS_APPRISE_URLS in the .env file
When the container is restarted
Then the new notification targets are used on the next run
And no image rebuild or prompt modification is required
REQ-2: Graceful Degradation When Unconfigured
When CLAUDEOPS_APPRISE_URLS is empty or unset, the system MUST silently skip all notification operations. No errors, warnings, or log noise MUST be generated due to missing notification configuration.
The system MUST NOT fail a health check run or remediation cycle because notifications cannot be sent.
Scenario: No notification URLs configured
Given CLAUDEOPS_APPRISE_URLS is not set in the environment
When the system reaches a notification step (daily digest, remediation report, or alert)
Then the notification is silently skipped
And the health check or remediation cycle continues normally
Scenario: Empty notification URLs string
Given CLAUDEOPS_APPRISE_URLS is set to an empty string
When the system attempts to send a notification
Then no Apprise CLI invocation occurs
And no error is logged
Scenario: Notification failure does not block remediation
Given CLAUDEOPS_APPRISE_URLS points to a misconfigured target
When the Apprise CLI invocation fails
Then the remediation cycle continues
And the failure is logged but does not interrupt operations
REQ-3: CLI-Based Invocation
Notifications MUST be sent using the apprise CLI tool invoked via shell commands. The system MUST NOT use Apprise as a Python library or import it programmatically.
The invocation format MUST be:
apprise -t "<title>" -b "<body>" "$CLAUDEOPS_APPRISE_URLS"
This requirement aligns with Claude Ops' execution model where all operations are shell commands embedded in markdown prompts that the agent executes.
Scenario: Agent sends notification via CLI
Given the Tier 2 agent has successfully remediated a service
When the agent sends a notification
Then the agent executes apprise -t "..." -b "..." "$CLAUDEOPS_APPRISE_URLS" via Bash
And the notification is delivered to all configured targets
Scenario: Notification command is executed from markdown prompt context
Given a tier prompt file contains notification instructions
When the agent follows the prompt instructions to send a notification
Then the agent constructs and executes an apprise CLI command
And does not use Python import statements or library calls
REQ-4: Environment Variable Passthrough to Agent
The CLAUDEOPS_APPRISE_URLS environment variable MUST be passed to the Claude agent's execution context so the agent can reference it in shell commands.
The entrypoint script MUST include CLAUDEOPS_APPRISE_URLS in the environment context appended to the system prompt, but only when the variable is set and non-empty.
Scenario: Apprise URLs passed to agent context
Given CLAUDEOPS_APPRISE_URLS=ntfy://ntfy.sh/my-topic is set
When the entrypoint script builds the environment context
Then CLAUDEOPS_APPRISE_URLS is included in the --append-system-prompt value
And the agent can reference $CLAUDEOPS_APPRISE_URLS in its shell commands
Scenario: Apprise URLs omitted when unset
Given CLAUDEOPS_APPRISE_URLS is not set
When the entrypoint script builds the environment context
Then CLAUDEOPS_APPRISE_URLS is not included in the system prompt
And the agent sees no Apprise configuration
REQ-5: Three Notification Event Categories
The system MUST support three distinct notification event categories, each with its own trigger conditions and urgency level:
- Daily Digest -- sent once per day summarizing all health check results and uptime statistics.
- Auto-Remediation Report -- sent immediately after a successful remediation, describing the issue, action taken, and verification result.
- Human Attention Alert -- sent immediately when remediation fails or cooldown limits are exceeded, indicating that manual intervention is required.
Scenario: Daily digest is sent once per day
Given the system has completed a health check cycle
When a daily digest has not been sent in the current day (checked via last_daily_digest in cooldown state)
Then the agent composes a summary of all services, their health status, and uptime
And sends it via Apprise with a descriptive title
And updates last_daily_digest in the cooldown state
Scenario: Daily digest is skipped when already sent today
Given a daily digest was already sent during the current day When the next health check cycle completes Then no daily digest is sent And the agent proceeds with normal operations
Scenario: Auto-remediation report sent after fix
Given the Tier 2 agent successfully restarts a crashed container
When the agent verifies the service is healthy after the restart
Then the agent sends a notification via Apprise with title "Claude Ops: Auto-remediated
Scenario: Human attention alert sent on cooldown exceeded
Given a service has exceeded its restart cooldown limit (2 restarts in 4 hours)
When the agent determines another restart would violate cooldown
Then the agent sends a notification via Apprise with title "Claude Ops: Needs human attention --
REQ-6: Notification Message Format
Notifications MUST include both a title (-t flag) and a body (-b flag).
The title MUST follow the format: Claude Ops: <action> <service_name> where action is one of:
Auto-remediatedfor successful remediationsRemediated ... (Tier 3)for Tier 3 remediationsNeeds human attention --for failed remediations or cooldown-exceeded situations- A descriptive summary for daily digests
The body MUST include contextually appropriate details:
Auto-remediation reports MUST include:
- What was wrong (the detected issue)
- What action was taken (the remediation performed)
- Verification result (the post-remediation health check result)
Human attention alerts MUST include:
- Issue description
- What was attempted (remediation actions tried)
- Why it failed or why remediation was stopped
- Current system state or recommended next steps
Tier 3 remediation reports MUST include:
- Root cause analysis
- Actions taken (step by step)
- Verification result
- Recommendations for follow-up
Daily digests MUST include:
- Total services checked
- Count of healthy, degraded, down, and in-cooldown services
- Details for any non-healthy services
Scenario: Auto-remediation notification has required fields
Given the Tier 2 agent has restarted a container and verified it is healthy When the agent composes the notification body Then the body contains the issue description (e.g., "Container was in CrashLoopBackOff") And the body contains the action taken (e.g., "Restarted container via docker restart") And the body contains the verification result (e.g., "Service now responding HTTP 200")
Scenario: Human attention alert has required fields
Given the Tier 2 agent cannot fix a service and cooldown is exceeded When the agent composes the notification body Then the body contains the issue description And the body contains what was attempted And the body contains why remediation was stopped (e.g., "Cooldown limit exceeded: 2/2 restarts in 4h window")
Scenario: Tier 3 notification includes root cause analysis
Given the Tier 3 agent has remediated a complex multi-service failure When the agent composes the notification body Then the body contains the root cause analysis And the body contains step-by-step actions taken And the body contains the verification result And the body contains recommendations for follow-up
REQ-7: Tier-Specific Notification Permissions
Tier 1 MAY send daily digest notifications and cooldown-exceeded alerts.
Tier 2 MUST send auto-remediation reports after successful remediations. Tier 2 MUST send human attention alerts when remediation fails or cooldown limits are exceeded.
Tier 3 MUST send detailed remediation reports after any remediation attempt (successful or not). Tier 3 MUST always send a notification at the end of its execution, regardless of outcome.
Scenario: Tier 1 sends daily digest
Given all services are healthy and a daily digest is due When the Tier 1 agent completes its observation cycle Then the agent sends a daily digest via Apprise summarizing all check results
Scenario: Tier 1 sends cooldown alert
Given a service is in cooldown and requires human attention When the Tier 1 agent observes the service is still failing Then the agent sends a "needs human attention" alert via Apprise
Scenario: Tier 2 sends remediation report
Given the Tier 2 agent successfully restarted a container When the agent verifies the service is healthy Then the agent sends an auto-remediation notification
Scenario: Tier 3 always reports
Given the Tier 3 agent has completed its work When the agent reaches its reporting step Then the agent always sends a notification via Apprise And the notification reflects whether remediation succeeded or requires human attention
REQ-8: Docker Image Installation
The Apprise CLI MUST be installed in the Docker image via pip3 install --break-system-packages apprise. The Docker image MUST include the python3 and pip3 prerequisites.
The Apprise installation MUST NOT require running additional services or sidecars.
Scenario: Apprise is available in the container
Given the Docker image is built from the Dockerfile
When a shell command apprise --version is executed inside the container
Then Apprise responds with its version number
And no additional services need to be running
Scenario: Apprise works without external dependencies
Given the container is running with no sidecar services When the agent executes an Apprise CLI command Then the notification is sent directly from the container And no message broker, queue, or relay service is required
REQ-9: Multiple Simultaneous Notification Targets
The system MUST support sending the same notification to multiple targets simultaneously via comma-separated Apprise URLs. All configured targets MUST receive the same notification content.
Scenario: Notification delivered to all targets
Given CLAUDEOPS_APPRISE_URLS=ntfy://ntfy.sh/ops,slack://token_a/token_b/token_c
When the agent sends a remediation notification
Then both the ntfy topic and the Slack channel receive the notification
And both receive the same title and body content
Scenario: One target failure does not prevent delivery to others
Given one of multiple configured Apprise URLs is invalid When the agent sends a notification Then Apprise attempts delivery to all configured targets And valid targets receive the notification regardless of failures on other targets
REQ-10: No Delivery Guarantee or Retry
The system does NOT provide built-in delivery confirmation or retry logic. If an Apprise CLI invocation fails, the agent MUST continue its current cycle without re-attempting the notification.
The system MAY log the notification failure but MUST NOT treat it as a blocking error.
Scenario: Failed notification does not block agent
Given the Apprise CLI invocation fails (e.g., network error to notification service) When the agent continues its health check or remediation cycle Then the agent proceeds to the next step without retrying the notification And the cycle completes normally
Scenario: Notification failure is logged
Given the Apprise CLI returns a non-zero exit code
When the agent observes the failure
Then the failure appears in the run log in $CLAUDEOPS_RESULTS_DIR
And the agent does not retry the command