← All playbooks
Playbook

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).

~2–10 credits a run/reviews-to-github-issues <app> <repo> [since]

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@appgoat

Run it by asking for it in plain words, or by name:

/reviews-to-github-issues <app> <repo> [since]

When 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-review with a connected store account) or for a one-off sentiment summary (use app-audit-lite).

Inputs

  • app (required): store URL, Apple id, Play package, bundle id or name.
  • repo (required): owner/name of 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.

  1. get_app {app} - 1 (+1 if refreshed). Note store, app_id, title, current version.
  2. 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.
  3. get_reviews {app, country: "us", rating: "1-3", since, limit: 100} - 1 per page (+1 if the US reviews are refreshed). Follow next_cursor for up to 3 pages. Reviews carry AI tags (sentiment, intent, severity 0–3, topic) once tagged; untagged ones have them null. Use a tagged review's topic as the starting point for the slug and severity ≥ 2 as "high". Do not filter by intent/topic here: the filters drop untagged reviews, so read the whole 1–3★ window and classify the untagged ones yourself.
  4. 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.
  5. 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 (or none) 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_issues with repo:<repo> label:appgoat-reviews "appgoat:topic=<slug>" in:body, then add_issue_comment, update_issue (state open) or create_issue with the marker as the first line of the body and the label appgoat-reviews.
  6. 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; add bug for crashes/errors or enhancement for 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 toolREST call
get_appGET /apps/{app}
get_reviewsGET /apps/{app}/reviews?country=us&rating=1-3&since=YYYY-MM-DD&limit=100 (next page: &cursor=<meta.next_cursor>)
get_jobGET /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 run

App 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 run

Find 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 run

ASO 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 run

Competitor 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 run

Reply 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 run

Apple 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 run

Localization 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.