|
| 1 | +# StackMemory Notifications Spec |
| 2 | + |
| 3 | +## Overview |
| 4 | + |
| 5 | +StackMemory Notifications enables SMS/WhatsApp alerts for AI coding workflows with interactive prompts and response handling. This creates a human-in-the-loop system where developers can approve, reject, or direct AI actions remotely. |
| 6 | + |
| 7 | +## Architecture |
| 8 | + |
| 9 | +``` |
| 10 | +┌─────────────────┐ ┌──────────────┐ ┌─────────────┐ |
| 11 | +│ StackMemory │────▶│ Twilio │────▶│ User Phone │ |
| 12 | +│ CLI/Hooks │ │ API │ │ (SMS/WA) │ |
| 13 | +└─────────────────┘ └──────────────┘ └─────────────┘ |
| 14 | + ▲ │ |
| 15 | + │ │ |
| 16 | + │ ┌──────▼──────┐ |
| 17 | + │ │ ngrok │ |
| 18 | + │ │ tunnel │ |
| 19 | + │ └──────┬──────┘ |
| 20 | + │ │ |
| 21 | + └──────────────────────┘ |
| 22 | + Webhook response |
| 23 | +``` |
| 24 | + |
| 25 | +## Features |
| 26 | + |
| 27 | +### Notification Types |
| 28 | +- **Task Complete**: Alert when long-running tasks finish |
| 29 | +- **Review Ready**: Prompt for code review with options |
| 30 | +- **Error Alert**: Notify on failures with context |
| 31 | +- **Custom Prompt**: Yes/No or numbered options |
| 32 | + |
| 33 | +### Interactive Prompts |
| 34 | +``` |
| 35 | +Review Ready: PR #123 |
| 36 | +
|
| 37 | +Feature: Add user authentication |
| 38 | +
|
| 39 | +What would you like to do? |
| 40 | +1. Approve and merge |
| 41 | +2. Request changes |
| 42 | +3. Skip for now |
| 43 | +
|
| 44 | +Reply with number to select |
| 45 | +``` |
| 46 | + |
| 47 | +### Response Handling |
| 48 | +1. User replies via SMS/WhatsApp |
| 49 | +2. Webhook captures response |
| 50 | +3. Action queued for execution |
| 51 | +4. Claude Code hook processes action |
| 52 | + |
| 53 | +## Configuration |
| 54 | + |
| 55 | +### Environment Variables |
| 56 | + |
| 57 | +```bash |
| 58 | +# Required - Twilio Credentials |
| 59 | +TWILIO_ACCOUNT_SID=ACxxxxx |
| 60 | +TWILIO_AUTH_TOKEN=xxxxx |
| 61 | + |
| 62 | +# Channel Selection (whatsapp recommended) |
| 63 | +TWILIO_CHANNEL=whatsapp # or 'sms' |
| 64 | + |
| 65 | +# WhatsApp Numbers |
| 66 | +TWILIO_WHATSAPP_FROM=+14155238886 # Twilio sandbox or business number |
| 67 | +TWILIO_WHATSAPP_TO=+1234567890 # User's phone |
| 68 | + |
| 69 | +# SMS Numbers (fallback) |
| 70 | +TWILIO_SMS_FROM=+1234567890 # Twilio number (requires A2P 10DLC) |
| 71 | +TWILIO_SMS_TO=+1234567890 # User's phone |
| 72 | +``` |
| 73 | + |
| 74 | +### Config File |
| 75 | + |
| 76 | +`~/.stackmemory/sms-notify.json`: |
| 77 | +```json |
| 78 | +{ |
| 79 | + "enabled": true, |
| 80 | + "channel": "whatsapp", |
| 81 | + "notifyOn": { |
| 82 | + "taskComplete": true, |
| 83 | + "reviewReady": true, |
| 84 | + "error": true, |
| 85 | + "custom": true |
| 86 | + }, |
| 87 | + "quietHours": { |
| 88 | + "enabled": true, |
| 89 | + "start": "22:00", |
| 90 | + "end": "08:00" |
| 91 | + }, |
| 92 | + "responseTimeout": 300 |
| 93 | +} |
| 94 | +``` |
| 95 | + |
| 96 | +## Setup Guide |
| 97 | + |
| 98 | +### Quick Start (WhatsApp Sandbox) |
| 99 | + |
| 100 | +1. **Create Twilio Account** |
| 101 | + ```bash |
| 102 | + # Get credentials from https://console.twilio.com |
| 103 | + export TWILIO_ACCOUNT_SID=ACxxxxx |
| 104 | + export TWILIO_AUTH_TOKEN=xxxxx |
| 105 | + ``` |
| 106 | + |
| 107 | +2. **Join WhatsApp Sandbox** |
| 108 | + - Go to: https://console.twilio.com/us1/develop/sms/try-it-out/whatsapp-learn |
| 109 | + - Send join code from your phone to sandbox number |
| 110 | + - Note the sandbox number (e.g., +14155238886) |
| 111 | + |
| 112 | +3. **Configure StackMemory** |
| 113 | + ```bash |
| 114 | + export TWILIO_WHATSAPP_FROM=+14155238886 |
| 115 | + export TWILIO_WHATSAPP_TO=+1234567890 # Your phone |
| 116 | + export TWILIO_CHANNEL=whatsapp |
| 117 | + |
| 118 | + stackmemory notify enable |
| 119 | + stackmemory notify test |
| 120 | + ``` |
| 121 | + |
| 122 | +4. **Set Up Webhook Loop** |
| 123 | + ```bash |
| 124 | + # Auto-setup (starts webhook + ngrok) |
| 125 | + ./scripts/setup-notify-webhook.sh |
| 126 | + |
| 127 | + # Configure Twilio webhook URL (shown in output) |
| 128 | + # https://xxx.ngrok.io/sms/incoming |
| 129 | + ``` |
| 130 | + |
| 131 | +### Production Setup |
| 132 | + |
| 133 | +1. **Register WhatsApp Business** (or use Twilio toll-free for SMS) |
| 134 | +2. **Deploy webhook** to public server (Railway, Vercel, etc.) |
| 135 | +3. **Configure Twilio** with permanent webhook URL |
| 136 | + |
| 137 | +### SMS Setup (A2P 10DLC Required) |
| 138 | + |
| 139 | +US carriers require 10DLC registration for business SMS: |
| 140 | + |
| 141 | +1. Register brand at: https://console.twilio.com/us1/develop/sms/settings/compliance |
| 142 | +2. Register campaign for notifications |
| 143 | +3. Wait for approval (1-7 days) |
| 144 | +4. Configure SMS numbers |
| 145 | + |
| 146 | +## CLI Commands |
| 147 | + |
| 148 | +```bash |
| 149 | +# Configuration |
| 150 | +stackmemory notify status # Show config status |
| 151 | +stackmemory notify enable # Enable notifications |
| 152 | +stackmemory notify disable # Disable notifications |
| 153 | +stackmemory notify channel <type> # Set channel (whatsapp|sms) |
| 154 | + |
| 155 | +# Send Notifications |
| 156 | +stackmemory notify test # Send test message |
| 157 | +stackmemory notify send "Message" # Custom notification |
| 158 | +stackmemory notify review "PR #123" # Review prompt with options |
| 159 | +stackmemory notify ask "Deploy?" # Yes/No prompt |
| 160 | +stackmemory notify complete "Task name" # Task complete alert |
| 161 | + |
| 162 | +# Webhook Management |
| 163 | +stackmemory notify webhook -p 3456 # Start webhook server |
| 164 | +stackmemory notify pending # List pending prompts |
| 165 | +stackmemory notify actions # List queued actions |
| 166 | +stackmemory notify run-actions # Execute pending actions |
| 167 | + |
| 168 | +# Setup |
| 169 | +stackmemory notify install-hook # Install notify hook |
| 170 | +stackmemory notify install-response-hook # Install response handler |
| 171 | +``` |
| 172 | + |
| 173 | +## Claude Code Integration |
| 174 | + |
| 175 | +### Hooks |
| 176 | + |
| 177 | +Add to `~/.claude/settings.json`: |
| 178 | + |
| 179 | +```json |
| 180 | +{ |
| 181 | + "hooks": { |
| 182 | + "pre_tool_use": [ |
| 183 | + "node ~/.claude/hooks/sms-response-handler.js" |
| 184 | + ], |
| 185 | + "PostToolUse": [ |
| 186 | + { |
| 187 | + "matcher": "Task", |
| 188 | + "hooks": [{ |
| 189 | + "type": "command", |
| 190 | + "command": "stackmemory notify complete '$TASK_NAME'" |
| 191 | + }] |
| 192 | + } |
| 193 | + ] |
| 194 | + } |
| 195 | +} |
| 196 | +``` |
| 197 | + |
| 198 | +### Programmatic Usage |
| 199 | + |
| 200 | +```typescript |
| 201 | +import { |
| 202 | + sendNotification, |
| 203 | + notifyReviewReady, |
| 204 | + notifyWithYesNo, |
| 205 | + notifyTaskComplete |
| 206 | +} from '@stackmemoryai/stackmemory/hooks/sms-notify'; |
| 207 | + |
| 208 | +// Simple notification |
| 209 | +await sendNotification({ |
| 210 | + type: 'custom', |
| 211 | + title: 'Build Complete', |
| 212 | + message: 'All tests passing' |
| 213 | +}); |
| 214 | + |
| 215 | +// Review with options |
| 216 | +await notifyReviewReady('PR #123', 'Feature: Auth', [ |
| 217 | + { label: 'Approve', action: 'gh pr merge 123' }, |
| 218 | + { label: 'Reject', action: 'gh pr close 123' } |
| 219 | +]); |
| 220 | + |
| 221 | +// Yes/No prompt |
| 222 | +await notifyWithYesNo( |
| 223 | + 'Deploy', |
| 224 | + 'Deploy to production?', |
| 225 | + 'npm run deploy', // Yes action |
| 226 | + 'echo "Skipped"' // No action |
| 227 | +); |
| 228 | +``` |
| 229 | + |
| 230 | +## Webhook API |
| 231 | + |
| 232 | +### Endpoints |
| 233 | + |
| 234 | +| Endpoint | Method | Description | |
| 235 | +|----------|--------|-------------| |
| 236 | +| `/health` | GET | Health check | |
| 237 | +| `/sms/incoming` | POST | Receive messages | |
| 238 | +| `/sms/status` | POST | Delivery status callbacks | |
| 239 | +| `/status` | GET | Notification status | |
| 240 | + |
| 241 | +### Incoming Message Format (Twilio) |
| 242 | + |
| 243 | +``` |
| 244 | +POST /sms/incoming |
| 245 | +Content-Type: application/x-www-form-urlencoded |
| 246 | +
|
| 247 | +From=whatsapp:+1234567890 |
| 248 | +To=whatsapp:+14155238886 |
| 249 | +Body=1 |
| 250 | +MessageSid=SMxxxxx |
| 251 | +``` |
| 252 | + |
| 253 | +### Response Format (TwiML) |
| 254 | + |
| 255 | +```xml |
| 256 | +<?xml version="1.0" encoding="UTF-8"?> |
| 257 | +<Response> |
| 258 | + <Message>Got it! Action queued.</Message> |
| 259 | +</Response> |
| 260 | +``` |
| 261 | + |
| 262 | +## Pricing |
| 263 | + |
| 264 | +### WhatsApp (Recommended) |
| 265 | +- Conversation-based pricing (~$0.005-0.015 per 24h window) |
| 266 | +- User-initiated conversations are cheaper |
| 267 | +- No carrier registration required |
| 268 | + |
| 269 | +### SMS |
| 270 | +- Per-message pricing (~$0.0079/segment) |
| 271 | +- Requires A2P 10DLC registration (US) |
| 272 | +- $2-15/month for number + campaign fees |
| 273 | + |
| 274 | +## Security |
| 275 | + |
| 276 | +- Credentials stored in environment variables only |
| 277 | +- Config file excludes sensitive data |
| 278 | +- Phone numbers masked in logs/status |
| 279 | +- Webhook validates Twilio signature (optional) |
| 280 | + |
| 281 | +## Limitations |
| 282 | + |
| 283 | +- WhatsApp Sandbox: Must re-join every 72 hours of inactivity |
| 284 | +- SMS: Requires 10DLC registration (US carriers block unregistered) |
| 285 | +- ngrok free: URL changes on restart (use paid for static URL) |
| 286 | +- Response timeout: 5 minutes default (configurable) |
| 287 | + |
| 288 | +## Troubleshooting |
| 289 | + |
| 290 | +### Message Not Received |
| 291 | + |
| 292 | +1. Check `stackmemory notify status` - verify enabled and configured |
| 293 | +2. For SMS: Check A2P 10DLC registration status |
| 294 | +3. For WhatsApp: Verify sandbox join is active |
| 295 | +4. Check Twilio console for error codes |
| 296 | + |
| 297 | +### Webhook Not Receiving |
| 298 | + |
| 299 | +1. Verify ngrok running: `curl http://localhost:4040/api/tunnels` |
| 300 | +2. Check webhook URL in Twilio console matches ngrok URL |
| 301 | +3. Test endpoint: `curl -X POST http://localhost:3456/sms/incoming` |
| 302 | + |
| 303 | +### Common Error Codes |
| 304 | + |
| 305 | +| Code | Meaning | Fix | |
| 306 | +|------|---------|-----| |
| 307 | +| 30034 | Message blocked | Register for 10DLC (SMS) or use WhatsApp | |
| 308 | +| 21608 | Unverified number | Verify destination in Twilio console | |
| 309 | +| 63016 | WhatsApp not opted-in | User must send join code first | |
| 310 | + |
| 311 | +## Future Enhancements |
| 312 | + |
| 313 | +- [ ] Slack/Discord integration |
| 314 | +- [ ] Email fallback |
| 315 | +- [ ] Voice call for critical alerts |
| 316 | +- [ ] Multi-user routing |
| 317 | +- [ ] Response analytics dashboard |
| 318 | +- [ ] Scheduled quiet hours per user |
| 319 | +- [ ] Template library for common prompts |
0 commit comments