
Booking Notify
- 117 installs
- 62 repo stars
- Updated August 3, 2026
- terrylica/cc-skills
Use booking-notify for development tasks
About
booking-notify: A skill for development. This provides functionality for development workflows.
- booking-notify
Booking Notify by the numbers
- 117 all-time installs (skills.sh)
- Ranked #2,871 of 4,347 Backend & APIs skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/terrylica/cc-skills --skill booking-notifyAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 117 |
|---|---|
| repo stars | ★ 62 |
| Last updated | August 3, 2026 |
| Repository | terrylica/cc-skills ↗ |
What it does
Use booking-notify for development tasks
Files
Booking Notifications (Dual-Channel)
Automated booking notifications via two channels:
| Channel | Delivery | Format | Use Case |
|---|---|---|---|
| Telegram | Scheduled | HTML | Interactive commands, daily digest, search |
| Pushover | Real-time | Plain text | Emergency alerts with custom sound (dune) |
Self-Evolving Skill: This skill improves through use. If instructions are wrong, parameters drifted, or a workaround was needed — fix this file immediately, don't defer. Only update for real, reproducible issues.
Mandatory Preflight
Step 1: Check Sync Script Exists
ls -la "$HOME/.claude/plugins/marketplaces/cc-skills/plugins/calcom-commander/scripts/sync.ts" 2>/dev/null || echo "SCRIPT_NOT_FOUND"Step 2: Verify Environment (Required)
echo "CALCOM_OP_UUID: ${CALCOM_OP_UUID:-NOT_SET}"
echo "TELEGRAM_BOT_TOKEN: ${TELEGRAM_BOT_TOKEN:+SET}"
echo "TELEGRAM_CHAT_ID: ${TELEGRAM_CHAT_ID:-NOT_SET}"
echo "HAIKU_MODEL: ${HAIKU_MODEL:-NOT_SET}"All must be SET. If any are NOT_SET, run the setup command first.
Step 3: Verify Pushover (Optional)
echo "PUSHOVER_APP_TOKEN: ${PUSHOVER_APP_TOKEN:+SET}"
echo "PUSHOVER_USER_KEY: ${PUSHOVER_USER_KEY:+SET}"
echo "PUSHOVER_SOUND: ${PUSHOVER_SOUND:-dune}"
echo "WEBHOOK_RELAY_URL: ${WEBHOOK_RELAY_URL:-NOT_SET}"If NOT_SET: Pushover is optional. Telegram-only operation still works. To enable, see pushover-setup.md.
Step 4: Verify Cal.com CLI Binary
ls -la "$HOME/.claude/plugins/marketplaces/cc-skills/plugins/calcom-commander/scripts/calcom-cli/calcom" 2>/dev/null || echo "BINARY_NOT_FOUND"If BINARY_NOT_FOUND: Build it:
cd "$HOME/.claude/plugins/marketplaces/cc-skills/plugins/calcom-commander/scripts/calcom-cli" && bun install && bun run buildNotification Channels
Telegram (Scheduled Sync)
6h polling via launchd. Sends HTML-formatted messages for:
| Category | Examples |
|---|---|
| NEW BOOKING | New interview scheduled, new consultation booked |
| CANCELLATION | Booking cancelled by attendee, host cancelled |
| UPCOMING | Booking starting in 1 hour, today's schedule |
| RESCHEDULED | Booking moved to new time, date changed |
Pushover (Real-Time Webhook)
Instant notifications via Cloud Run webhook relay:
| Event | Priority | Sound | Must Acknowledge? |
|---|---|---|---|
| New booking | 2 (Emergency) | dune | Yes |
| Rescheduled | 2 (Emergency) | dune | Yes |
| Cancelled | 0 (Normal) | dune | No |
Webhook Relay
The webhook relay is a lightweight Cloud Run service that bridges Cal.com webhooks to Pushover. See webhook-relay.md for deployment.
Running Manually
cd ~/own/amonic && bun run "$HOME/.claude/plugins/marketplaces/cc-skills/plugins/calcom-commander/scripts/sync.ts"Sync Behavior
1. Fetches bookings from Cal.com API (last 6h window) 2. Compares against last-known state (file-based) 3. Detects new bookings, cancellations, and reschedules 4. Sends Telegram notification (HTML) for each change 5. Sends Pushover notification (plain text) if credentials configured 6. Updates state file for next sync cycle 7. Circuit breaker prevents cascade failures on API errors
mise Configuration (Agnostic Wiring)
Any repository can adopt these notifications by adding to .mise.local.toml:
[env]
# Required (Telegram)
CALCOM_OP_UUID = "<1password-uuid>"
TELEGRAM_BOT_TOKEN = "<bot-token>"
TELEGRAM_CHAT_ID = "<chat-id>"
# Optional (Pushover dual-channel)
PUSHOVER_APP_TOKEN = "<pushover-app-token>"
PUSHOVER_USER_KEY = "<pushover-user-key>"
PUSHOVER_SOUND = "dune"
WEBHOOK_RELAY_URL = "https://calcom-pushover-webhook-XXXXX.us-central1.run.app/"References
- notification-templates.md — Dual-channel message templates
- pushover-setup.md — Pushover credential setup guide
- webhook-relay.md — Webhook relay deployment + management
- sync-config.md — Sync interval and state management
Post-Change Checklist
- [ ] YAML frontmatter valid (no colons in description)
- [ ] Trigger keywords current
- [ ] Path patterns use $HOME not hardcoded paths
- [ ] Pushover graceful degradation verified (works without Pushover creds)
Post-Execution Reflection
After this skill completes, reflect before closing the task:
0. Locate yourself. — Find this SKILL.md's canonical path before editing. 1. What failed? — Fix the instruction that caused it. 2. What worked better than expected? — Promote to recommended practice. 3. What drifted? — Fix any script, reference, or dependency that no longer matches reality. 4. Log it. — Evolution-log entry with trigger, fix, and evidence.
Do NOT defer. The next invocation inherits whatever you leave behind.
Evolution Log
Convention: Reverse chronological order (newest on top, oldest at bottom). Prepend new entries.
---
2026-02-26: Initial Evolution Log
Status: Skill is in use and maintained. Track improvements here.
Purpose
This evolution log tracks updates to the skill. Each entry should note:
- What changed (content, structure, tooling)
- Why it changed (bug fix, feature request, best practice)
- Files affected
How to Use
1. When updating SKILL.md or references, add an entry here with the date 2. Keep entries reverse-chronological (newest first) 3. Link to ADRs or GitHub issues when relevant 4. Reference specific line changes when helpful
---
Notification Templates
Dual-channel message templates for booking notifications.
Critical: Telegram uses HTML, Pushover uses plain text. Build in HTML first, then strip for Pushover using stripHtmlForPushover().
Channel Differences
| Aspect | Telegram | Pushover |
|---|---|---|
| Format | HTML (parse_mode) | Plain text only |
| Bold | <b>text</b> | UPPERCASE or _text_ |
| Strike | <s>text</s> | ~~text~~ |
| Newline | \n | \n |
| Priority | N/A (always delivered) | 0=normal, 1=high, 2=EM |
---
Telegram Templates (HTML)
New Booking
<b>New Booking</b> <b>Event:</b> {{eventTitle}}
<b>Attendee:</b> {{attendeeName}} ({{attendeeEmail}}) <b>When:</b> {{startTime}}
- {{endTime}} <b>Timezone:</b> {{timezone}} {{#if notes}}<b>Notes:</b>
{{notes}}{{/if}}Cancellation
<b>Booking Cancelled</b> <b>Event:</b> {{eventTitle}}
<b>Attendee:</b> {{attendeeName}} <b>Was scheduled:</b> {{startTime}} {{#if
cancellationReason}}<b>Reason:</b> {{cancellationReason}}{{/if}}Upcoming Reminder
<b>Upcoming in {{minutesUntil}} min</b> <b>Event:</b> {{eventTitle}}
<b>With:</b> {{attendeeName}} <b>Time:</b> {{startTime}} - {{endTime}}Rescheduled
<b>Booking Rescheduled</b> <b>Event:</b> {{eventTitle}}
<b>Attendee:</b> {{attendeeName}} <b>Old time:</b> <s>{{oldStartTime}}</s>
<b>New time:</b> {{newStartTime}} - {{newEndTime}}Daily Summary
<b>Today's Bookings ({{count}})</b> {{#each bookings}} {{time}} — {{title}} with
{{attendee}} {{/each}}Emoji Map
| Category | Emoji |
|---|---|
| NEW BOOKING | 📅 |
| CANCELLATION | ❌ |
| UPCOMING | ⏰ |
| RESCHEDULED | 🔄 |
| DAILY | 📋 |
---
Pushover Templates (Plain Text)
These are auto-generated by stripHtmlForPushover() from the HTML templates above. For reference:
New Booking (Pushover)
NEW BOOKING
Event: {{eventTitle}}
Attendee: {{attendeeName}} ({{attendeeEmail}})
When: {{startTime}} - {{endTime}}
Timezone: {{timezone}}Priority: 2 (Emergency) — requires acknowledge, "dune" sound, retry every 30s for 5 min.
Cancellation (Pushover)
BOOKING CANCELLED
Event: {{eventTitle}}
Attendee: {{attendeeName}}
Was scheduled: {{startTime}}Priority: 0 (Normal) — "dune" sound, respects quiet hours.
Upcoming Reminder (Pushover)
UPCOMING IN {{minutesUntil}} MIN
Event: {{eventTitle}}
With: {{attendeeName}}
Time: {{startTime}} - {{endTime}}Priority: 1 (High) — bypasses quiet hours.
Rescheduled (Pushover)
BOOKING RESCHEDULED
Event: {{eventTitle}}
Attendee: {{attendeeName}}
Old time: {{oldStartTime}}
New time: {{newStartTime}} - {{newEndTime}}Priority: 2 (Emergency) — requires acknowledge.
Pushover Setup Guide
Complete setup for Pushover dual-channel notifications alongside Telegram.
Prerequisites
- Pushover account (<https://pushover.net/>)
- Pushover app on iOS/Android
- 1Password CLI (
op) configured
Step 1: Create Pushover Application
1. Go to <https://pushover.net/apps/build> 2. Create a new application (e.g., "Cal.com Booking Alerts") 3. Note the API Token/Key (30 characters, e.g., a14t3ngicf...)
Step 2: Get Your User Key
1. Log into <https://pushover.net/> 2. Your User Key is shown on the dashboard (30 characters, e.g., ury88s1def...)
Step 3: Upload Custom Sound (Optional)
1. Go to <https://pushover.net/> dashboard 2. Scroll to "Custom Sounds" section 3. Upload an audio file (e.g., "dune.wav") 4. Note the sound name (e.g., dune)
Step 4: Store in 1Password
op item create --category "API Credential" \
--title "Pushover - Cal.com Booking Alerts" \
--vault "Claude Automation" \
"username=<your-user-key>" \
"password=<your-app-token>"Note the item UUID from the output.
Step 5: Configure mise
Add to .mise.local.toml (gitignored):
[env]
PUSHOVER_OP_UUID = "<uuid-from-step-4>"
PUSHOVER_SOUND = "dune"To load the actual tokens at runtime, add to your project's .mise.local.toml:
[env]
PUSHOVER_APP_TOKEN = "{{ exec(command='op item get <uuid> --vault \"Claude Automation\" --fields password --reveal') }}"
PUSHOVER_USER_KEY = "{{ exec(command='op item get <uuid> --vault \"Claude Automation\" --fields username --reveal') }}"
PUSHOVER_SOUND = "dune"Step 6: Test
curl -s --form-string "token=$PUSHOVER_APP_TOKEN" \
--form-string "user=$PUSHOVER_USER_KEY" \
--form-string "title=Test Alert" \
--form-string "message=Pushover integration working" \
--form-string "sound=$PUSHOVER_SOUND" \
--form-string "priority=0" \
https://api.pushover.net/1/messages.jsonExpected: {"status":1,...} and notification on your device.
Priority Levels
| Priority | Name | Behavior |
|---|---|---|
| 0 | Normal | Default sound, respects quiet hours |
| 1 | High | Bypasses quiet hours, alert sound |
| 2 | Emergency | Repeats until acknowledged, requires retry + expire |
Critical Rules
- Pushover is plain text only — never send HTML tags
- Build messages in HTML for Telegram, then use
stripHtmlForPushover()for Pushover - Emergency priority (2) requires
retry(seconds between retries) andexpire(seconds until stop) - Custom sounds must be uploaded to your Pushover account first
Sync Configuration
Configuration for the scheduled booking sync process.
Sync Interval
Default: Every 6 hours (21600 seconds) via launchd StartInterval.
State Management
The sync process maintains a state file to track previously seen bookings:
- Location:
~/own/amonic/state/calcom-sync-state.json - Format: JSON object with
lastSyncAttimestamp andknownBookingIdsarray - Rotation: State file is overwritten each cycle
{
"lastSyncAt": "2026-02-14T12:00:00Z",
"knownBookingIds": [12345, 12346, 12347],
"lastBookingCount": 3
}Change Detection
1. Fetch all bookings since lastSyncAt 2. Compare against knownBookingIds 3. New IDs = NEW BOOKING notification 4. Missing IDs = check status (CANCELLED or RESCHEDULED) 5. Update state file
Circuit Breaker
- File:
/tmp/calcom-sync-circuit.json - Threshold: 3 consecutive failures
- Cooldown: 10 minutes
- Auto-reset: On successful sync
Audit Logging
All sync events logged to NDJSON:
sync.started— Sync cycle beginssync.bookings_found— Number of bookings fetchedsync.new_booking— New booking detectedsync.cancellation— Cancellation detectedsync.completed— Sync cycle endssync.error— Error during sync
Retention: 14 days with auto-pruning.
Webhook Relay Deployment
The webhook relay is a lightweight Cloud Run service that bridges Cal.com webhooks to Pushover emergency alerts. It provides real-time booking notifications without polling.
Architecture
Cal.com → Webhook POST → Cloud Run (webhook-relay) → Pushover API → Phone alertSource Location
plugins/calcom-commander/scripts/webhook-relay/
├── main.py ← Python HTTP server (stdlib only, no dependencies)
└── Dockerfile ← Python 3.14 slim containerDeploy to Cloud Run
Step 1: Set Environment
echo "CALCOM_GCP_PROJECT: ${CALCOM_GCP_PROJECT:-NOT_SET}"
echo "CALCOM_GCP_REGION: ${CALCOM_GCP_REGION:-NOT_SET}"
echo "PUSHOVER_APP_TOKEN: ${PUSHOVER_APP_TOKEN:+SET}"
echo "PUSHOVER_USER_KEY: ${PUSHOVER_USER_KEY:+SET}"Step 2: Deploy
RELAY_SOURCE="$HOME/.claude/plugins/marketplaces/cc-skills/plugins/calcom-commander/scripts/webhook-relay"
gcloud run deploy calcom-pushover-webhook \
--source "$RELAY_SOURCE" \
--project="$CALCOM_GCP_PROJECT" \
--account="$CALCOM_GCP_ACCOUNT" \
--region="$CALCOM_GCP_REGION" \
--platform managed \
--allow-unauthenticated \
--set-env-vars="PUSHOVER_TOKEN=$PUSHOVER_APP_TOKEN,PUSHOVER_USER=$PUSHOVER_USER_KEY,PUSHOVER_SOUND=${PUSHOVER_SOUND:-dune}" \
--memory=128Mi \
--cpu=1 \
--min-instances=0 \
--max-instances=1 \
--timeout=30 \
--quietNote the Service URL from the output.
Step 3: Verify Health
curl -s "$WEBHOOK_RELAY_URL" | python3 -m json.tool
# Expected: {"status": "healthy", "service": "calcom-pushover-webhook"}Step 4: Test with Simulated Booking
curl -s -X POST "$WEBHOOK_RELAY_URL" \
-H "Content-Type: application/json" \
-d '{"triggerEvent":"BOOKING_CREATED","payload":{"title":"Test Meeting","attendees":[{"name":"Test User"}],"startTime":"2026-01-01T10:00:00Z","endTime":"2026-01-01T10:30:00Z"}}'Expected: Pushover emergency alert with "dune" sound.
Register Cal.com Webhook
After deploying the relay, register it with Cal.com:
# Using Cal.com API v1
CALCOM_API_KEY=$(op item get "$CALCOM_OP_UUID" --vault "Claude Automation" --fields password --reveal)
curl -s -X POST "https://api.cal.com/v1/webhooks?apiKey=$CALCOM_API_KEY" \
-H "Content-Type: application/json" \
-d "{\"subscriberUrl\":\"$WEBHOOK_RELAY_URL\",\"eventTriggers\":[\"BOOKING_CREATED\",\"BOOKING_RESCHEDULED\",\"BOOKING_CANCELLED\"],\"active\":true}"List/Manage Webhooks
# List all webhooks
curl -s "https://api.cal.com/v1/webhooks?apiKey=$CALCOM_API_KEY" | python3 -m json.tool
# Delete a webhook
curl -s -X DELETE "https://api.cal.com/v1/webhooks/<webhook-id>?apiKey=$CALCOM_API_KEY"Update Relay
To redeploy after code changes:
gcloud run deploy calcom-pushover-webhook \
--source "$RELAY_SOURCE" \
--project="$CALCOM_GCP_PROJECT" \
--region="$CALCOM_GCP_REGION" \
--quietEvent Trigger Behavior
| Cal.com Event | Pushover Priority | Sound | Must Acknowledge? |
|---|---|---|---|
BOOKING_CREATED | 2 (Emergency) | dune | Yes |
BOOKING_RESCHEDULED | 2 (Emergency) | dune | Yes |
BOOKING_CANCELLED | 0 (Normal) | dune | No |
mise Configuration
Store the relay URL in .mise.local.toml for other tools to reference:
[env]
WEBHOOK_RELAY_URL = "https://calcom-pushover-webhook-XXXXX.us-central1.run.app/"