Help us improve
Share bugs, ideas, or general feedback.
From appmate
Generates a stage-diagnosed growth strategy for an app, including phase diagnosis and 3-5 actionable strategies. Auto-chains competitor-research when competitor data is missing.
npx claudepluginhub fengyiqicoder/appmate --plugin appmateHow this skill is triggered — by the user, by Claude, or both
Slash command
/appmate:growth-strategyThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
> This skill is the single authoritative reference for the growth strategy flow. Re-read it before every run.
Researches keywords, analyzes competitors, optimizes metadata, and tracks performance for Apple App Store and Google Play Store listings.
Provides ASO toolkit for keyword research, competitor analysis, metadata optimization, review sentiment, and performance tracking on Apple App Store and Google Play.
Conducts keyword research, optimizes metadata, and analyzes competitors for Apple App Store and Google Play Store listings. Helps improve app visibility and conversion rates.
Share bugs, ideas, or general feedback.
This skill is the single authoritative reference for the growth strategy flow. Re-read it before every run. v2: dropped the AppMate RAG dependency. Competitors now come from the
competitor-researchskill's output (auto-chained when missing), unifying the competitive signal withfeature-ideation. v1 had been the "RAG top-8 by seed word" design.
Every step in this skill calls App Store Connect APIs. Before any other step, run:
python3 scripts/appmate_config.py check
If exit code ≠ 0, STOP. Do not invoke any other part of this skill, do not run scripts/growth_strategy.py. Tell the user AppMate credentials are not configured, show the precheck output verbatim, and tell them to invoke the appmate-setup skill. The downstream script also enforces this gate (exits 2 with the same message).
competitor-research skill if missingThis workflow consumes data/competitors_<slug>.json, the final artifact produced by the competitor-research skill (invoked for the same <app>). Both skills compute slug via slugify(canonical_app_name, market), so passing the same app argument to both guarantees the slug matches.
Decision rule — before invoking growth_strategy.py:
<app> (read data/apps_full.json, call find_app(<arg>) → name, then pick main market via the largest 30-day downloads in sales_cache.json with the same fallbacks the script uses — primaryLocale, then US). Compute expected = data/competitors_<slugify(name, market)>.json.expected exists.competitor-research skill end-to-end for the same <app> argument first — all three stages: Stage 1 script analyze, Stage 2 LLM tokenization, Stage 3 LLM relevance pass + final-JSON + markdown write. Paste the rivals markdown back into the conversation per that skill's own rules. Then return here and proceed to Step 1 of growth-strategy. The user gets two reports out of one ask: rivals first, then the growth plan. That is intentional — both are useful, and the rivals card is the same competitive evidence the LLM will read in Step 2.competitors_generated_at; if it is > 30 days old, mention staleness when delivering the final growth report (do not auto-refresh unless the user asks).No RAG fallback. No placeholder competitors. The only two paths are: the cached file, or a fresh competitor-research skill run.
Safety net: growth_strategy.py exits 2 with competitors JSON not found if the file is missing at script-execution time. This catches the case where the script was invoked outside the skill (cron, manual CLI). When it fires, treat it the same way — invoke the competitor-research skill for the same app, then re-run.
Given a live app → the script aggregates sales trend + ASO state + reviews + competitors (4 evidence sources) and auto-determines which of 4 stages the app is in → the LLM reads the "methodology cheat-sheet" section of this skill → a markdown report with a stage diagnosis paragraph first, then 3-5 growth strategies, each with 4 executable steps.
| Workflow | What it does | Relationship to this workflow |
|---|---|---|
aso-optimize | single-app keyword / title / subtitle / keyword-field optimization | this workflow does not touch word-level keyword suggestions. If the diagnosis finds ASO is the bottleneck → a step can say "run aso_optimize_v2 once" |
feature-ideation | single-app product feature ideas | this workflow's strategies may include "add feature X", but only as one execution step under some growth strategy, not as the main act |
aso-daily-report / sales-daily-report | monitoring reports | this workflow consumes the data/sales_cache.json / data/aso_rank_snapshots.json they accumulate, not re-outputting "how is today's data" |
Core differentiator: feature-ideation outputs "what feature to build" (two sentences each); this workflow outputs "how to do growth" (a 4-step execution plan each).
| Item | Content |
|---|---|
| Trigger | the user says "run growth strategy for <app>" |
| Input | data/apps_full.json (reviews/locale) + data/sales_cache.json (sales) + data/aso_rank_snapshots.json (ASO state) + data/competitors_<slug>.json (from the competitor-research skill — auto-chained on first run for an app, then cached) + the "methodology cheat-sheet" section of this skill |
| Output | data/phase_a_growth_<slug>.json (intermediate) + data/growth_strategy_<slug>.md (final) + Claude pastes the full markdown back into the conversation |
| Intervention points | 2 (trigger + receive); optional follow-up "detail one strategy" |
growth_strategy.py) — app fuzzy match (reuses aso_optimize_v2) → sales trend (D30 / prior D30 / slope) → stage detection (4-stage rule) → ASO state extraction (locale / main-market ranking) → review-signal summary (rating distribution / negative feedback / wishlist) → load competitors from data/competitors_<slug>.json (Claude should have already auto-chained the competitor-research skill per §0.2 if the file was missing; script exits 2 as a safety net otherwise) → data/phase_a_growth_<slug>.json.stage from the phase_a JSON → read the 3-5 playbook items for that stage from the cheat-sheet below → use own data + competitor evidence + methodology to brainstorm 8-12 candidate strategies → anti-junk filter → internal ranking → take the top 3-5 → expand each into 4 executable steps.data/growth_strategy_<slug>.md → paste the full markdown back into the conversation.Reuses aso_optimize_v2.find_app() — accepts App Store ID / bundle ID / SKU / fuzzy name match. Main-market selection: largest 30-day downloads → primaryLocale country → US fallback.
Read data/sales_cache.json and for the anchored app compute: D30 (last 30 days total downloads), D30_prev (the 30 days before that), slope (D30 / max(D30_prev, 1)), total_reviews, market_concentration (main-market share of total downloads, 0-1).
| Stage | stage key emitted | Detection rule (priority top to bottom) |
|---|---|---|
| Cold start | cold_start | total_reviews < 20 or D30 < 100 (either satisfies) |
| Decline | decline | slope < 0.8 (down > 20% MoM) and D30 ≥ 100 |
| Early growth | early_growth | slope > 1.2 (up > 20% MoM) and D30 ≥ 100 |
| Plateau | plateau | 0.8 ≤ slope ≤ 1.2 and D30 ≥ 100 (fallback) |
The result is written to phase_a's stage field using the exact keys cold_start / decline / early_growth / plateau — they index the cheat-sheet below. When rendering the report, translate the stage to its friendly name in the user's conversation language (e.g. "Cold start", "Decline", "Early growth", "Plateau" in English; "冷启动" / "衰退" / "早期增长" / "平台期" in Chinese). Also write a stage_evidence array (3-5 human-readable evidence strings, in English as emitted by the script — the LLM translates them when rendering).
From data/apps_full.json + data/aso_rank_snapshots.json: current_locales, primary_market_top10_keywords (count of keywords ranking ≤ 10 in the main market's most recent snapshot), missing_locales_in_top_markets (high-volume countries lacking a matching locale).
rating_avg, negative_count_90d (last 90 days, rating ≤ 3 and len(body) ≥ 10), wishlist_count_90d (last 90 days, rating ≥ 4 and contains a trigger word from the static _WISH_TRIGGERS list in growth_strategy.py), top_negative_themes (simple clustering, or dump the first 10 bodies).
The bucketing helpers (
bucket_reviews,_has_wish_trigger, etc.) live inline ingrowth_strategy.py— they used to be imported fromfeature_ideate.py, but feature_ideate v3 dropped pre-bucketing and the helpers were moved here.
load_competitors(app_name, market) reads OUTPUT_DIR / f"competitors_{slugify(app_name, market)}.json". The file is the final artifact of the competitor-research skill (see skills/competitor-research/SKILL.md). Per §0.2, Claude should ensure this file exists before invoking the script — by auto-chaining that skill when it's missing.
| Step | Behavior |
|---|---|
| File missing | return None → build_phase_a returns None → main() prints a safety-net message pointing at the competitor-research skill and exits 2. Normally never fires when the skill flow was followed; fires if the script was invoked directly. |
| File present | read payload["filtered"] (already top-10 by threat_score, already passed the LLM relevance pass) and copy these fields per entry: name, description_short, outranked_keywords, relevance_reason, threat_score, rating, review_count |
| Stale data | the script does not check generated_at freshness; it surfaces the timestamp in phase_a so the LLM can flag staleness in the report if it looks old (> 30 days) |
v1 → v2 change: v1 called
appmate_rag_client.search(query=seed, region=market, top_k=8, ...)directly with a seed-word the script picked from the app's name. The seed-extraction was fragile (compound brand names lost context, English-only"app"fallback returned useless rivals) and the RAG result was a different shape than the SERP-overlap rivals produced by thecompetitor-researchskill. v2 reuses the already-curated, already-LLM-filtered result of that skill, so growth-strategy and feature-ideation produce a coherent picture of the same competitive landscape.
{
"app": "<name>", "app_id": "<id>", "bundle_id": "<bid>", "market": "<country>",
"generated_at": "2026-05-13T...",
"sales": {"D30": 850, "D30_prev": 420, "slope": 2.02, "market_concentration": 0.78},
"stage": "early_growth",
"stage_evidence": ["D30=850 (prior 30 days 420 → last 30 days 850)", "slope=2.02 → MoM up 102%", "reviews 145, past the cold-start threshold"],
"aso": {"current_locales": ["en-US", "zh-Hans"], "primary_market_top10_keywords": 6, "missing_locales_in_top_markets": ["es-MX", "pt-BR"]},
"reviews": {"total": 145, "rating_avg": 4.3, "negative_count_90d": 8, "wishlist_count_90d": 5, "top_negative_themes": ["同步丢失", "缺图片插入"]},
"competitors_source": "<absolute path to competitors_<slug>.json>",
"competitors_generated_at": "<timestamp from competitors_<slug>.json>",
"competitors": [
{"name": "...", "description_short": "...", "outranked_keywords": ["..."],
"relevance_reason": "...", "threat_score": 42, "rating": 4.7, "review_count": 1234}
]
}
⚠️ The phase_a JSON does not carry methodology content. The methodology lives in the static cheat-sheet below; the LLM looks up the section for the
stagefield when reasoning.
stage from the phase_a JSON.Each candidate scored 1-5: Impact (directly hits the core bottleneck → 5; side assist → 3; experience detail → 2), Executability (solo dev + can start in ≤ 2 weeks → 5; needs external resources → 3; > 1 month → 1), Evidence strength (reviews + competitors + methodology triangulate → 5; two → 3; single → 2), Stage fit (directly hits the stage in the cheat-sheet → 5; borrowed cross-stage → 3; forced → 1).
Composite score = Impact × Executability × Evidence × Stage-fit, for LLM internal ranking only.
| Rule | Application |
|---|---|
| ❌ Platform violation | a mac app proposing "add GPS / iOS sensor" → delete |
| ❌ Vague words | "do marketing" / "improve the brand" → must be specific to "where, who, how to measure" |
| ❌ Stage mismatch | a cold-start app proposing "raise prices / a B2B team plan" → delete |
| ❌ Overlap with an existing workflow | "change keyword X" / "add feature Y" → cannot be a standalone strategy; can be one step under some strategy |
| ❌ Non-executable step | "build the brand" with no action → must land on "do X, with tool Y, watch metric Z" |
Sort by composite score descending, take the top 3-5. Main list < 3 → add a ⚠️ "insufficient evidence, suggest completing the sales / review / competitor data first" warning at the top.
Core rules:
- Do not show any scores (4-dimension scores + composite score all hidden).
- No jargon:
RICE / Reach / Impact / Confidence / Effort— always plain prose in the user's conversation language.- Each strategy is its own
##heading; the body = a quote-block value description + numbered 4-step execution.- Blank line between each step; multi-element steps expand into sub-bullets (3-space indent), not crammed into one line.
- Arrange by composite score high to low (no score shown).
Rendered in the same language the user has been using in this conversation. Default to English; if the user has been writing in Chinese / Japanese / Spanish / etc., translate the template headers, labels and prose accordingly. App Store metadata strings (title / subtitle / keywords / competitor app names) must remain in the App Store's source locale (e.g. zh-Hans names stay zh-Hans) — only the surrounding explanation follows the user's conversation language.
The template below is written with English placeholders. Substitute the equivalent words in the user's conversation language when rendering.
# 📈 <App name> · Growth strategy
## Stage diagnosis
**Current stage: <Stage name>**
Data snapshot:
- 30-day downloads **<D30>** (prior 30 days <D30_prev> → last 30 days <D30>, <up/down> <pct>% MoM)
- Total reviews **<N>** / average rating **<X>**
- Main market **<country>** holds <pct>% of downloads, locales enabled: `<locale1>` / `<locale2>` ...
- <one extra fact: ASO / locale / review themes>
**Main bottleneck**
<one paragraph explaining where the app is stuck>
**Opportunity window**
<one paragraph indicating the biggest near-term opportunity>
---
## Strategy 1 · <Strategy title>
> <one sentence: what it is + why do it>
**1.** <execution step 1 title or action description>
- <optional sub-bullet 1>
- <optional sub-bullet 2>
<optional parenthetical: time budget / caveats>
**2.** <execution step 2>
<optional sub-bullet or quote emphasis>
**3.** <execution step 3>
**4. Measure**: <how you know it worked / which metric to watch / what to do if it misses>
---
## Strategy 2 · <Strategy title>
> <one-sentence value>
**1.** ...
... (3-5 strategies total, separated by `---`) ...
---
## Which one first
**#<N> <Strategy name>** <one sentence saying why this goes first>.
Execution order:
- **Weeks 1-2**: ...
- **From week 3**: ...
---
Want one expanded? Tell me the number and I can help break it into a mini-plan (resources / timeline / success metrics).
RICE / Reach / Impact / Confidence / Effort / Explore / Exploit / Onboarding / Delight — always plain prose in the user's conversation language.## headings: format ## Strategy N · <Title> (translated to the user's conversation language, e.g. ## 策略 N · <标题> in Chinese), not the inline **N. Title** form (too dense).> ..., visually separated from the execution steps.**1.**, **2.** ... **4. Measure** (translated to the user's conversation language), with a blank line between each step.**4. Measure**: <metric + threshold + what to do if missed> (translated to the user's conversation language).## (translated to the user's conversation language): contains a one-line top recommendation + an execution-order bullet list.Important: this section is the methodology library the LLM consumes directly in Step 2. No external RAG / MCP is called when running growth strategy — read the matching stage section directly. Maintenance: when a new growth tactic is worth solidifying, manually add a summary to the matching stage. This section is a purely static, self-maintained methodology library.
total_reviews < 20 or D30 < 100)slope > 1.2, D30 ≥ 100)0.8 ≤ slope ≤ 1.2, D30 ≥ 100)feature-ideation skill once to find a "feature that expands the use case" idea (do not polish, expand). Applies to: apps whose user awareness is saturated and need a new reason. Source: feature expansion casesslope < 0.8, D30 ≥ 100)aso-optimize skill once to check whether main keywords were lost; also run the aso-daily-report skill to see whether competitors overtook. Applies to: apps where ASO is the main traffic entry. Source: ASO maintenance cycle| File | Purpose |
|---|---|
scripts/growth_strategy.py | Step 1 script (no user intervention, runs by app name) |
data/phase_a_growth_<slug>.json | intermediate artifact (overwritten each run) |
data/growth_strategy_<slug>.md | final deliverable (overwritten each run) |
skills/growth-strategy/SKILL.md | this file: script rules + LLM reasoning rules + methodology cheat-sheet |
| Direction | Content |
|---|---|
| Upstream auto-chain | data/apps_full.json / data/sales_cache.json / data/aso_rank_snapshots.json + data/competitors_<slug>.json. When the competitors file is missing, this skill first invokes the competitor-research skill for <app> end-to-end (rivals markdown gets pasted back as a side effect), then continues. |
| Side-chain trigger | the aso-daily-report skill finds an app's keyword dropping out of the top 20 → trigger this flow for a "why did it drop / how to fix" analysis |
| Cross-workflow reference | decline-stage strategies may say "run the aso-optimize skill once"; early growth may say "run the feature-ideation skill once to find an expansion feature" |
| Methodology maintenance | when a new growth tactic is worth solidifying → manually update the matching stage of this skill's cheat-sheet |
# from the plugin repo root
# Step 1: run the script (produces the phase_a JSON)
python3 scripts/growth_strategy.py "<app>"
# the app argument accepts: App Store ID / bundle ID / SKU / fuzzy name match
# examples:
# python3 scripts/growth_strategy.py "Sticky Note Pro"
# python3 scripts/growth_strategy.py "com.fengyiqi.PostItnoteForMac"
# python3 scripts/growth_strategy.py "1482080766"
# Steps 2-3: Claude reads the phase_a JSON + this skill's cheat-sheet section, generates + renders per §2 / §3 rules
competitor-research skill was last run for this app — staleness shows up in competitors_generated_at; if it's > 30 days old, suggest re-running the prereq before trusting the report.## Strategy N · <Title> (translated to the user's conversation language)**4. Measure**: <metric + threshold + what to do if missed> (translated to the user's conversation language)RICE / Reach / Impact / Confidence / Effort / Explore / Exploit / Onboarding / DelightR / I / C / E## Strategy N · <Name> translated to the user's conversation language (not the inline **N. xxx** form)> quote block**1.** ... **4. Measure** (translated to the user's conversation language)aso-optimize / feature-ideationdata/growth_strategy_<slug>.md