Automated App Store review monitor, reply drafter, and pattern detector. Monitors App Store Connect for new reviews, drafts warm on-brand replies for 1–3★ reviews using Claude, surfaces repeat-complaint patterns as bug alerts, and delivers a daily Telegram approval queue at 8am.
text
skills/review-reply/
├── SKILL.md # This file — AI instructions & skill spec
├── README.md # Full usage docs and setup guide
├── scripts/
│ ├── monitor.py # Polls App Store Connect API for new reviews
│ ├── draft_reply.py # Drafts warm on-brand replies via Claude
│ ├── pattern_detector.py # Surfaces repeat-complaint patterns as bug alerts
│ └── queue_manager.py # Manages approval queue, Telegram 8am digest
├── references/
│ ├── app-store-connect-api.md # API auth setup (JWT, keys, endpoints)
│ └── reply-guidelines.md # Brand voice, tone, dos/don'ts
├── templates/
│ └── reply-prompts.md # Claude prompt templates per star rating
└── data/
├── reviews.json # Raw review store (auto-created)
├── queue.json # Pending approval queue (auto-created)
└── metrics.json # Response rate, timing, rating trends (auto-created)
Script: scripts/monitor.py
/v1/apps/{id}/customerReviewsdata/reviews.json (skips already-seen IDs)draft_reply.py automaticallypattern_detector.pydata/metrics.jsonpython3 scripts/monitor.pyjson
{
"id": "string",
"app_id": "string",
"app_name": "string",
"rating": 1,
"title": "string",
"body": "string",
"reviewer": "string",
"territory": "string",
"created_date": "ISO8601",
"fetched_at": "ISO8601",
"reply_status": "pending|drafting|approved|posted|rejected|skipped",
"draft_reply": "string|null",
"approved_reply": "string|null",
"replied_at": "ISO8601|null"
}
Script: scripts/draft_reply.py
templates/reply-prompts.md based on star ratingdata/queue.json with status pendingskipped)json
{
"review_id": "string",
"app_name": "string",
"rating": 2,
"review_title": "string",
"review_body": "string",
"draft_reply": "string",
"drafted_at": "ISO8601",
"status": "pending",
"approved_reply": null,
"posted_at": null
}
Script: scripts/pattern_detector.py
data/reviews.jsontext
🚨 *Pattern Alert — FeedFare*
Complaint: "Feed not refreshing / stuck on loading"
Count: 5 reviews in the last 7 days
Rating avg: 1.8★
Recent examples:
• "App is broken, feed never loads" — 1★ (2026-02-18)
• "Stuck on spinning wheel for days" — 2★ (2026-02-17)
• "Used to work great, now broken" — 2★ (2026-02-16)
👉 Likely bug. Recommend investigating feed refresh logic.
data/metrics.json under pattern_alertsScript: scripts/queue_manager.py
Every morning at 8:00 AM local time, queue_manager.py sends a Telegram message summarizing all pending replies:
text
📱 *ReviewReply Morning Queue — 3 Pending*
━━━━━━━━━━━━━━━━━━━
1️⃣ *FeedFare* — 2★ by @user123 (Feb 18)
"App crashes every time I open it"
📝 *Draft Reply:*
"Hi there! We're so sorry to hear about the crashes — that's definitely not the experience we want for you. Our team just pushed a fix in v2.1.1 that addresses the crash on launch. Please update and let us know if it helps! 🙏"
✅ /approve_1 ✏️ /edit_1 ❌ /reject_1
━━━━━━━━━━━━━━━━━━━
2️⃣ *FeedFare* — 1★ by @disappointed_dev (Feb 18)
...
━━━━━━━━━━━━━━━━━━━
📊 Stats: 12 reviewed · 8 replied · 67% response rate
/approve_N — marks reply as approved, posts to App Store Connect/edit_N <new text> — replaces draft with edited text, marks approved/reject_N — marks as rejected (no reply sent), removes from queue/skip_N — marks as skipped (no reply ever), removes from queuetext
new review
│
▼
[drafting] → draft failed → [error]
│
▼
[pending] ←→ [edited]
│
├─ approve → [approved] → post API → [posted]
├─ reject → [rejected]
└─ skip → [skipped]
When a reply is approved:
queue_manager.py calls App Store Connect API → POST /v1/customerReviewResponsesposted in data/queue.jsonreplied_at timestamp for metricsData file: data/metrics.json
MetricDescriptiontotal_reviewsAll-time review count per appreviews_this_weekRolling 7-day countavg_ratingCurrent average star rating per apprating_trendDirection vs previous 7-day periodresponse_rate% of 1-3★ reviews with approved/posted repliesavg_response_time_hrsAverage hours between review and reply postedpending_countCurrently in queueposted_countSuccessfully repliedrejected_countIntentionally skippedpattern_alertsHistory of pattern alerts sent
Say "review metrics" or "how are my apps doing?" and the AI will read data/metrics.json and format a summary.
The AI handles these conversational patterns:
User SaysAI Action"check for new reviews"Run python3 scripts/monitor.py"show pending replies"Read data/queue.json, list pending items"approve reply 3"Run python3 scripts/queue_manager.py --approve 3"edit reply 2: "Run python3 scripts/queue_manager.py --edit 2 then pass text via stdin or temp file — never interpolate user text directly into shell strings"reject reply 1"Run python3 scripts/queue_manager.py --reject 1"draft a reply for review X"Run python3 scripts/draft_reply.py --review-id X"how are my apps doing?"Read data/metrics.json, format summary"show me recent reviews"Read data/reviews.json, show last 10"any patterns this week?"Run python3 scripts/pattern_detector.py --report"response rate?"Read metrics, show response_rate per app"add app MyApp 1234567890"Add to APPS config in monitor.py
VariableDescriptionAPP_STORE_KEY_IDApp Store Connect API Key IDAPP_STORE_ISSUER_IDApp Store Connect Issuer IDAPP_STORE_PRIVATE_KEY_PATHPath to .p8 private key fileANTHROPIC_API_KEYClaude API key for reply draftingTELEGRAM_BOT_TOKENTelegram bot token for notificationsTELEGRAM_CHAT_IDYour Telegram chat ID
Store these in ~/.openclaw/.env or export in shell profile.
text
# App Store review monitor — every 4 hours
0 */4 * * * cd /Users/nick/.openclaw/workspace && python3 skills/review-reply/scripts/monitor.py >> /tmp/review-reply.log 2>&1
# Daily approval queue — 8am every day
0 8 * * * cd /Users/nick/.openclaw/workspace && python3 skills/review-reply/scripts/queue_manager.py --send-digest >> /tmp/review-reply.log 2>&1
See README.md for LaunchAgent plist setup.
All data lives in data/ and is plain JSON — easy to inspect, backup, and migrate.
FilePurposedata/reviews.jsonAll fetched reviews, one object per reviewdata/queue.jsonActive reply queue (pending/approved/rejected items)data/metrics.jsonAggregated metrics, pattern alert history
bash
cp -r skills/review-reply/data/ ~/review-reply-backup/