Reviews → GitHub issues
Turns recent negative App Store / Google Play reviews into deduplicated GitHub issues – one issue per problem topic, with linked and quoted reviews, new reviews added as comments to the existing issue instead of duplicates. Uses AppGoat review data and the gh CLI (or the GitHub MCP server).
Reads the app's recent 1–3★ reviews, groups them into problem topics (a crash, a confusing paywall, a missing feature), and keeps exactly one GitHub issue per topic up to date. Running it again never duplicates: issues carry a hidden marker, and reviews already linked are skipped.
It can also run on AppGoat events (negative_review_spike, review_spike, rating_drop from a
watch on the app) instead of a schedule; see Automate it.
Install
The appgoat/skills repository is private until its public release, so the plugin and git commands below are coming soon. Today, run the playbooks as prompts of the AppGoat MCP server (Claude, Cursor, ChatGPT) or download the SKILL.md from this page.
Install the AppGoat plugin (all playbooks plus the AppGoat MCP server), then run /mcp to sign in.
/plugin marketplace add appgoat/skills
/plugin install appgoat-playbooks@appgoatRun it by asking for it in plain words, or by name:
/reviews-to-github-issues <app> <repo> [since]Add the connector: Settings → Connectors → Add custom connector → https://api.appgoat.ai/mcp.
Pick reviews-to-github-issues from the “+” menu → AppGoat (it is served as a prompt), or upload the skill folder as a zip in Settings → Capabilities → Skills.
Add the MCP server to .cursor/mcp.json:
{ "mcpServers": { "appgoat": { "url": "https://api.appgoat.ai/mcp" } } }Type / in the chat and pick reviews-to-github-issues, or save the SKILL.md as .cursor/rules/reviews-to-github-issues.mdc.
In developer mode (Settings → Apps & Connectors → Advanced), add a connector with https://api.appgoat.ai/mcp and sign in. Then ask:
Use the AppGoat list_playbooks tool and run the reviews-to-github-issues playbook.Copy the skill folder into your agent’s skills directory and add the MCP server:
git clone https://github.com/appgoat/skills /tmp/appgoat-skills
cp -r /tmp/appgoat-skills/skills/reviews-to-github-issues ~/.claude/skills/
claude mcp add --transport http appgoat https://api.appgoat.ai/mcpWhen to use
- The user wants app store feedback in their issue tracker, once or on a schedule.
- Not for answering reviews (use
reply-to-every-reviewwith a connected store account) or for a one-off sentiment summary (useapp-audit-lite).
Inputs
app(required): store URL, Apple id, Play package, bundle id or name.repo(required):owner/nameof the GitHub repository. Default: the current repo (gh repo view --json nameWithOwner -q .nameWithOwner).since(optional): ISO date; default 7 days ago. Overlapping windows are safe (dedupe by review id).
Limits per run unless the user says otherwise: country us (add others on request), at most
5 new issues per run, at most 3 review pages.
Steps
Costs in AppGoat credits; GitHub calls are free. Without the MCP, use the REST equivalents in the REST calls below.
get_app{app} - 1 (+1 if refreshed). Note store, app_id, title, current version.- Existing topics (free):
gh issue list --repo <repo> --label appgoat-reviews --state all --limit 200 --json number,title,state,body. Read the<!-- appgoat:topic=<slug> app=<store:id> -->markers so you reuse existing slugs for the same problem instead of inventing new ones. get_reviews{app, country: "us", rating: "1-3", since, limit: 100} - 1 per page (+1 if the US reviews are refreshed). Follownext_cursorfor up to 3 pages. Reviews carry AI tags (sentiment,intent,severity0–3,topic) once tagged; untagged ones have them null. Use a tagged review'stopicas the starting point for the slug andseverity≥ 2 as "high". Do not filter byintent/topichere: the filters drop untagged reviews, so read the whole 1–3★ window and classify the untagged ones yourself.- Group the reviews into topics (no calls). A topic is one concrete problem ("login loop after
update", "widget doesn't refresh"), not a mood ("bad app"). Give each a lowercase slug
(
login-loop), reuse an existing slug when it is the same problem. Skip praise, spam, pure pricing rants with no actionable ask, and reviews under 20 characters. - For each topic, from most reviews to fewest:
bash scripts/upsert_issue.sh find --repo <repo> --app <store:app_id> --topic <slug>prints the issue (ornone) and the review ids it already links. Drop those reviews.- Apply the decision rules, write the body to a temp file, then
bash scripts/upsert_issue.sh upsert --repo <repo> --app <store:app_id> --topic <slug> --title "<title>" --body-file <file> [--reopen]. - With the GitHub MCP server instead of gh:
search_issueswithrepo:<repo> label:appgoat-reviews "appgoat:topic=<slug>" in:body, thenadd_issue_comment,update_issue(state open) orcreate_issuewith the marker as the first line of the body and the labelappgoat-reviews.
- Report what was created, commented and skipped.
Budget: 2–10 credits per run (1 app lookup + 1–3 review pages + refreshes).
Decision rules
- New issue when the topic has no issue yet and either ≥ 2 reviews in the window, or 1 review mentioning a crash, data loss, a payment/subscription charge problem, a login lockout or a security/privacy problem. Otherwise list it under "watching" in the run report, no issue.
- Comment on the open issue when it exists and there are new (not yet linked) reviews.
- Closed issue: reopen (
--reopen) when a new review is for a version released after the issue was closed or names the same symptom within 30 days of closing; otherwise create a new issue (the script links the old one). - Never paste reviewer names or any personal data into issues; quote at most 200 characters per review; do not edit or close issues; do not assign people.
- Title:
<Problem> (<n> reviews, <store>), ≤ 80 characters, e.g.Login loop after 3.2 update (4 reviews, App Store). - Labels: always
appgoat-reviews; addbugfor crashes/errors orenhancementfor feature requests only if those labels already exist in the repo. - Severity line:
high= crash, data loss, payment, lockout;medium= a broken feature with a workaround;low= UX friction or a feature request. - Stop after 5 new issues; mention the remaining topics in the report.
Review links: Play https://play.google.com/store/apps/details?id=<package>&reviewId=<review_id>;
Apple has no per-review URL, so use https://apps.apple.com/<country>/app/id<app_id>?see-all=reviews
and give the review id. Always write review:<review_id> on the review's line so later runs dedupe.
Output format
New issue body (the script prepends the marker):
**Severity:** high · **Store:** App Store (us) · **Versions:** 3.2.0, 3.2.1 · **First seen:** 2026-10-18
<2-3 sentences: what users experience, when it started, any pattern (device, OS, version).>
### Reviews
- ★1 · v3.2.1 · 2026-10-20 · "Since the update it logs me out every time I open it…" · [store](https://apps.apple.com/us/app/id284882215?see-all=reviews) · review:11223344
- ★2 · v3.2.0 · 2026-10-19 · "…" · [store](…) · review:11223399
### Suggested next step
<one concrete debugging or product step>
_From AppGoat review data. Updated automatically; new reports are added as comments._
Comment on an existing issue:
**<n> new reviews** (<since> → <today>), versions <v>:
- ★1 · v3.2.1 · 2026-10-21 · "…" · [store](…) · review:11224000
Run report (to the user):
Reviews → issues for <app> since <date>: <n> reviews read, <t> topics.
- Created #123 Login loop after 3.2 update (4 reviews)
- Commented #98 Widget not refreshing (+2)
- Watching: dark mode request (1), price complaint (1)
Credits used: <sum>.
Automate it
Daily triage in the repository that should receive the issues.
GitHub Action (.github/workflows/appgoat-reviews.yml, secrets ANTHROPIC_API_KEY, APPGOAT_API_KEY):
name: AppGoat reviews to issues
on:
schedule:
- cron: "0 6 * * *"
workflow_dispatch:
permissions:
contents: read
issues: write
jobs:
triage:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install AppGoat playbooks
run: |
git clone --depth 1 https://github.com/appgoat/skills /tmp/appgoat-skills
mkdir -p .claude/skills
cp -r /tmp/appgoat-skills/skills/* .claude/skills/
- uses: anthropics/claude-code-action@v1
env:
GH_TOKEN: ${{ github.token }}
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
prompt: |
Use the reviews-to-github-issues skill for app <app link>, repo ${{ github.repository }}, since 2 days ago.
The helper script is at .claude/skills/reviews-to-github-issues/scripts/upsert_issue.sh.
claude_args: |
--mcp-config '{"mcpServers":{"appgoat":{"command":"npx","args":["-y","@appgoat/mcp"],"env":{"APPGOAT_API_KEY":"${{ secrets.APPGOAT_API_KEY }}"}}}}'
--allowedTools mcp__appgoat__get_app,mcp__appgoat__get_reviews,mcp__appgoat__get_job,Write,Bash(gh issue list:*),Bash(gh label list:*),Bash(bash .claude/skills/reviews-to-github-issues/scripts/upsert_issue.sh:*)
On events instead of a schedule: a watch on the app plus either a kind: github webhook that
starts events/appgoat-events.yml through repository_dispatch (paid
plans), or a routine that polls get_events / GET /v1/events (free, every plan, state kept by
scripts/poll_events.sh). Setup, curl calls and routine prompts: events/README.md.
Claude Code routine (with the AppGoat connector and GitHub access):
/schedule weekdays 08:00 - Run the reviews-to-github-issues playbook for <app link> into <owner/repo>, since the previous run (default 3 days). Post the run report as a summary.
Without MCP: the REST calls
Without the AppGoat MCP server, call the API directly. Base URL https://api.appgoat.ai/v1,
header x-api-key: $APPGOAT_API_KEY (create a key at https://dash.appgoat.ai). Responses are
{ "data": …, "meta": { "credits_used", "credits_remaining", "next_cursor", … } }; errors carry error.hint.
| MCP tool | REST call |
|---|---|
get_app | GET /apps/{app} |
get_reviews | GET /apps/{app}/reviews?country=us&rating=1-3&since=YYYY-MM-DD&limit=100 (next page: &cursor=<meta.next_cursor>) |
get_job | GET /jobs/{id} (free) |
APP=com.spotify.music
curl -s -G -H "x-api-key: $APPGOAT_API_KEY" "https://api.appgoat.ai/v1/apps/$APP/reviews" \
-d country=us -d rating=1-3 -d since=2026-10-15 -d limit=100 \
| jq -r '.data[] | "\(.rating)★ v\(.version) \(.created_at) review:\(.review_id) \(.body[0:200])"'
Review fields: review_id, country, rating, title, body, version, thumbs_up, reply,
replied_at, created_at, and the AI tags sentiment (positive|neutral|negative), intent (bug|crash|feature_request|pricing|ux|praise|spam|other), severity (0–3), topic, confidence (null until a review is tagged). author is present
but must not be copied into issues.
More playbooks
/app-audit-lite~25–40 credits a runApp audit (lite)
Runs a quick App Store / Google Play audit of one app with live AppGoat data – listing quality, ratings trend, recent complaints, keyword rankings, competitors and their recent changes – and ends with a prioritized fix list.
/find-app-ideas~150–250 credits a runFind app ideas
Finds underserved App Store / Google Play niches with live AppGoat data – search demand (keyword popularity) against weak supply (low ratings, abandoned incumbents, few strong apps) – and returns a ranked shortlist of app ideas with evidence and user pain points.
/aso-keywords-metadata-rewrite~40–80 credits a runASO keywords → metadata rewrite
Researches App Store / Google Play keywords for one app with live AppGoat data (current ranks, competitor keyword gaps, popularity, difficulty, relevance) and rewrites the title, subtitle, keyword field and description within the store character limits.
/competitor-digest~15–55 credits a runCompetitor digest
Writes a weekly competitor digest for one App Store / Google Play app from an AppGoat competitor watch – what each competitor changed (title, subtitle, description, screenshots, icon), price and in-app purchase changes, new versions with release-note summaries, rating and chart moves, keyword gains and losses against the user's app, keyword gaps and review themes – and ends with 3 recommended actions linked to other playbooks. Sets up or reuses the competitor_set watch.
/reply-to-every-review~1–3 + 1 per posted reply credits a runReply to every review
Drafts a reply to every unanswered App Store and Google Play review of the user's own app, in the app's voice, through their connected App Store Connect / Play Console account – each reply is a dry run with a before/after diff and AppGoat guardrail scores (policy, tone, claims), and only the replies the user approves are posted.
/apple-ads-optimizer~5–8 per campaign + 1 per applied change credits a runApple Ads optimizer
Optimizes the user's Apple Ads (Search Ads) campaigns through their connected Apple Ads account – reads the last 14 days of keyword and search term reports, raises bids on keywords that convert under the target CPA (capped +30% per run), lowers or pauses keywords that spend without installs, adds converting search terms as exact keywords and wasteful ones as negatives – every change a dry run with a diff the user approves.
/localization-push~35–60 per locale + 1 per applied change credits a runLocalization push
Localizes the user's own App Store / Google Play listing into new languages through their connected App Store Connect or Play Console account – picks target locales from markets with demand, researches the keywords people actually search in each country with AppGoat, writes a localized name, subtitle, keyword field and promotional text (Play title, short and full description) within the store limits, and pushes each locale as a dry run with a before/after diff the user approves.