Skip to content

Commit b230fb6

Browse files
feat: Auto-start webhook/ngrok on CLI startup + add notifications spec
- Auto-start webhook and ngrok when notifications enabled - Display webhook URL on startup - Save ngrok URL to ~/.stackmemory/ngrok-url.txt - Add NOTIFICATIONS_SPEC.md for productization - Add ngrok config template
1 parent fe404ae commit b230fb6

3 files changed

Lines changed: 413 additions & 0 deletions

File tree

config/ngrok.yml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# StackMemory ngrok configuration
2+
# Copy your authtoken from https://dashboard.ngrok.com/get-started/your-authtoken
3+
4+
version: "3"
5+
agent:
6+
# Your authtoken (required for stable tunnels)
7+
# authtoken: YOUR_AUTHTOKEN_HERE
8+
9+
tunnels:
10+
stackmemory-webhook:
11+
proto: http
12+
addr: 3456
13+
# Uncomment for paid ngrok plans with reserved domains:
14+
# domain: your-domain.ngrok.io

docs/NOTIFICATIONS_SPEC.md

Lines changed: 319 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,319 @@
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

Comments
 (0)