aso-craft
Skill0 starsChanged 9 days agoMITView on GitHub
App Store Optimization for iOS and Android from one per-locale Markdown source. Probes keyword candidates against live App Store data for competitor density, incumbent difficulty and search intent (free, no API key), assigns each surviving term to the surface that actually indexes it per store, then lints the listing: hard character limits, target-keyword coverage gaps, keyword budget spent twice, keyword stuffing, and URLs or support emails broken by translation. Use when the user wants to do ASO, research or validate app store keywords, pick an app name / subtitle / short description / keyword field, check store metadata character limits, localize a store listing for search, audit why an app is not ranking, prepare an App Store or Play submission, or runs /aso-craft.
In this repository31 other files it gives its agents.
- CLAUDE.mdCLAUDE.md
- ai-estimateSkill
- audit-reportSkill
- babysit-prsSkill
- blueprintSkill
- brag-docSkill
- business-briefSkill
- cagan-checkSkill
- code-craftSkill
- commit-reportSkill
- compassSkill
- cv-craftSkill
- dev-flowSkill
- grill-meSkill
- implementation-reviewSkill
- llm-wikiSkill
- parallel-worktreesSkill
- periscopeSkill
- portfolio-syncSkill
- pr-craftSkill
- problem-solvingSkill
- publish-skillSkill
- review-passSkill
- security-auditSkill
- semverSkill
- sentinelSkill
- seoSkill
- testing-philosophySkill
- to-prdSkill
- write-a-skillSkill
- wstg-security-testingSkill
The file
We split this skill into the rules it gives an agent
2 rules. About 0 are common, 2 are distinctive, and 0 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈2
Distinctive · estimate
This author's own choices. Worth a look.
0
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 92
Localize every locale in one pass: Never pause for per-language review unless asked.
- Distinctive: line 102
A 2xx is not verification: Read the field back per locale.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
aso-craft
ASO is three questions in order: what do people search, which surface indexes it, and did the listing actually land it. This skill answers all three with scripts, because all three are checkable and none survive being eyeballed across locales. One Markdown file per locale is the source of truth for both stores.
Quick start
# 1. RESEARCH — probe candidates against live store data (free, no key)
python3 scripts/keyword_probe.py "chord pad" "chord progression" --competitors
python3 scripts/keyword_probe.py --from listing/pt-BR.md --country br --lang pt_br
# 2. LINT — limits, coverage gaps, wasted budget, broken atoms
python3 scripts/check_listing.py listing/ --store both --atom '.sf2'Both scripts are stdlib-only and carry --selftest. The linter exits nonzero on FAIL,
so it works as a pre-submission gate. Field format: TEMPLATE.md.
Which surface indexes what
| Surface | App Store | Google Play |
| name / title | indexed, position-weighted | indexed, position-weighted |
| subtitle | indexed | does not exist |
| short description | does not exist | indexed |
| keyword field | indexed, hidden, 100 chars | does not exist |
| description | never indexed | indexed |
This is a strategy inversion, not a different constant. Apple indexes three
surfaces as one pool, so a phrase spent twice is budget burnt — put each concept in
exactly one place. Play indexes the description body, so concepts must appear there
in natural prose, and repeating across title and body is normal. What Play punishes is
a literal Keywords: a, b, c list, which is spam under its store listing policy and
buys nothing on Apple either.
The linter checks coverage against a ## Target keywords section, per store: a term on
no indexed surface cannot rank, and a term on three Apple surfaces was paid for twice.
Judging a keyword
keyword_probe.py measures three things off live results. None of them is volume —
Apple's autosuggest returns nothing now and Play has no free API, so demand is the
one thing this cannot see. Narrow the list here for free, then validate volume with a
real tool (AppFigures, Sensor Tower, AppTweak, Astro) before betting an app name.
- Intent — genre concentration of the top 20. Scattered genres mean searchers want
other categories, however much traffic the term has.
trackerreturns Health, Productivity and Lifestyle apps: high traffic, worthless to a calorie app. - Difficulty — median rating count of the top 10, an authority proxy. A new listing does not out-rank 100k-review incumbents. Low is winnable now, moderate is a bet on the next months, high and entrenched are for later.
- Density — share of top titles carrying the term. High means developers converge on it: evidence of demand and of a fight you lose without authority. Zero is ambiguous — a real gap and a dead term look identical from here.
Then assign: strongest term leads the name, second leads the subtitle (Apple) / short description (Play), the rest fill Apple's keyword field and appear naturally in Play's description. Keyword-led beats brand-led; leading with the brand is a vanity trade against installs, since nobody searches your brand until you are already known.
Research per market, never per translation
Germans do not search a translation of your English phrase, they search what Germans
type. Re-probe on each storefront with --country / --lang before localizing: a term
returning piano-tutor apps in Brazil is not the Portuguese word for your category,
whatever the dictionary says. With no data for a locale, translate the concept and
report that locale as unverified rather than researched.
Rules that survive every project
- Limits are hard — both stores reject the write, neither truncates. A source name over ~22 chars is a translation risk: de, fi, tr, hu, ta and ml blow limits English fits easily.
- Localize every locale in one pass. Never pause for per-language review unless asked; reviewing one language proves nothing about the other five. The linter is the review.
- Adapt keyword fields, never invent them. Same concepts per locale, in words locals search. No geo padding, no locale-invented extras.
- Never localize URLs, support emails, platform product names, file extensions, version numbers, or the brand as the author styles it.
- Keep out of name and subtitle: platform trademarks (Apple rejects them) and any price claim. Both are fine elsewhere — trademarks in Apple's keyword field, a FREE-vs-PRO breakdown in the description body.
- A 2xx is not verification. Read the field back per locale. On Play a successful mutate is scoped to an uncommitted edit and means nothing until commit.
Field semantics, locale codes, write models, asset specs, upload tooling and the honest limits of each proxy: REFERENCE.md.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

