diff --git a/CHANGELOG.md b/CHANGELOG.md index 62e490a..3f9bde9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.14.0 + +Adds the ability to replace a Push Notification you already sent with a new one. + ## 1.13.0 Adds custom icons and interruption levels for Push Notifications. Set `--icon` to show a service logo or avatar on the notification, and `--interruption-level` to deliver it as `passive`, `active`, or `time-sensitive`. diff --git a/README.md b/README.md index 6220cd1..fb36ce8 100644 --- a/README.md +++ b/README.md @@ -210,6 +210,22 @@ activitysmith push \ --interruption-level "time-sensitive" ``` +### Replace a Push Notification + +Every `push` prints a `Notification ID`. Pass it to `--replace` to update a Push Notification you already sent, for example when an incident you alerted on is resolved. The replacement takes the old notification's place on the Lock Screen and in history instead of stacking a second one. It arrives silently, without sound or waking the screen, and goes to the same recipients as the original, so `--channels` and `--interruption-level` don't apply. + +```bash +activitysmith push \ + --title "🚨 checkout-api is down" \ + --message "500 errors on 62% of requests." +# Notification ID: Xk3pQ8mV2nR7tL9wB4yZ + +activitysmith push \ + --replace "Xk3pQ8mV2nR7tL9wB4yZ" \ + --title "✅ checkout-api recovered" \ + --message "Error rate is back to normal. Incident resolved." +``` + ## Live Activities Choose the Live Activity type that matches what you want to show: diff --git a/package.json b/package.json index 4ee31d1..98aaf80 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "activitysmith-cli", - "version": "1.13.0", + "version": "1.14.0", "description": "Command-line interface for ActivitySmith. Send Push Notifications, start, update, and end Live Activities, and set App Icon Badge Counts from your terminal.", "keywords": [ "activitysmith", @@ -42,7 +42,7 @@ "test": "node --test" }, "dependencies": { - "activitysmith": "^1.13.0", + "activitysmith": "^1.14.0", "commander": "^12.1.0" } } diff --git a/skills/activitysmith/SKILL.md b/skills/activitysmith/SKILL.md index bbd53db..484e951 100644 --- a/skills/activitysmith/SKILL.md +++ b/skills/activitysmith/SKILL.md @@ -34,6 +34,7 @@ export ACTIVITYSMITH_API_KEY="..." ## Pick The Right Signal - Push Notification: one important event, completion, blocker, review request, or handoff. +- Push Notification replacement: an earlier Push Notification is out of date and should be swapped, not stacked. - Push Notification with redirection: tapping the notification should open a URL or run a specific Shortcut that already exists on the user's iPhone. - Push Notification with actions: long-press should show up to 4 buttons. - Live Activity: a real-time metric, operational state, or ongoing task should stay visible. @@ -65,6 +66,22 @@ Use this when the user says "notify me when done" or when a long task completes. -m "Your agent finished the task." ``` +### Replace A Notification When The Status Changes + +Use this to update a Push Notification you already sent, for example when an incident you alerted on is resolved. Every push prints a `Notification ID`. Pass it with `-R` to swap the old notification for the new one on the Lock Screen and in history. The replacement is silent and goes to the same recipients. + +```bash +./skills/activitysmith/scripts/send_push.sh \ + -t "🚨 checkout-api is down" \ + -m "500 errors on 62% of requests." +# Output includes: Notification ID: Xk3pQ8mV2nR7tL9wB4yZ + +./skills/activitysmith/scripts/send_push.sh \ + -R "Xk3pQ8mV2nR7tL9wB4yZ" \ + -t "✅ checkout-api recovered" \ + -m "Error rate is back to normal. Incident resolved." +``` + ### Notify With A Shortcut Tap Target Use this when tapping the notification should run a specific Shortcut that already exists on the user's iPhone. diff --git a/skills/activitysmith/scripts/send_push.sh b/skills/activitysmith/scripts/send_push.sh index bfd436d..ff685b4 100755 --- a/skills/activitysmith/scripts/send_push.sh +++ b/skills/activitysmith/scripts/send_push.sh @@ -3,7 +3,7 @@ set -euo pipefail usage() { cat <<'USAGE' -Usage: send_push.sh -m "message" [-t "title"] [-s "subtitle"] [-c "channels"] [-g "tags"] [-M "media"] [-r "redirection"] [-a "actions-json"] [-A "actions-file"] +Usage: send_push.sh -m "message" [-t "title"] [-s "subtitle"] [-c "channels"] [-g "tags"] [-M "media"] [-r "redirection"] [-a "actions-json"] [-A "actions-file"] [-R "notification-id"] Required: -m Push message @@ -17,6 +17,8 @@ Optional: -r Redirection HTTPS or shortcuts:// URL (opened on notification tap) -a Actions JSON array string (max 4 actions) -A Path to actions JSON array file + -R Notification ID to silently replace instead of sending a new push + (cannot be combined with -c) USAGE } @@ -29,8 +31,9 @@ media="" redirection="" actions_json="" actions_file="" +replace_id="" -while getopts ":m:t:s:c:g:M:r:a:A:h" opt; do +while getopts ":m:t:s:c:g:M:r:a:A:R:h" opt; do case "$opt" in m) message="$OPTARG" ;; t) title="$OPTARG" ;; @@ -41,6 +44,7 @@ while getopts ":m:t:s:c:g:M:r:a:A:h" opt; do r) redirection="$OPTARG" ;; a) actions_json="$OPTARG" ;; A) actions_file="$OPTARG" ;; + R) replace_id="$OPTARG" ;; h) usage; exit 0 ;; \?) echo "Unknown option: -$OPTARG"; usage; exit 1 ;; :) echo "Missing value for -$OPTARG"; usage; exit 1 ;; @@ -65,6 +69,12 @@ if [[ -n "$media" && ( -n "$actions_json" || -n "$actions_file" ) ]]; then exit 1 fi +if [[ -n "$replace_id" && -n "$channels" ]]; then + echo "Replacements go to the original recipients; -c cannot be combined with -R." + usage + exit 1 +fi + # shellcheck disable=SC1091 source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/common.sh" load_env_if_present @@ -72,6 +82,9 @@ require_api_key require_cli cmd=(push --title "$title" --message "$message") +if [[ -n "$replace_id" ]]; then + cmd+=(--replace "$replace_id") +fi if [[ -n "$subtitle" ]]; then cmd+=(--subtitle "$subtitle") fi diff --git a/src/cli.js b/src/cli.js index 93af172..39f6f20 100755 --- a/src/cli.js +++ b/src/cli.js @@ -1257,8 +1257,12 @@ const outputResult = (payload, options, lines) => { program .command("push") - .description("Send a push notification") + .description("Send a push notification, or replace one you already sent") .requiredOption("--title