From alamops-skills
(alamops) Use whenever the user wants their iOS app checked against Apple's App Store Review Guidelines, or asks if Apple will reject something. Triggers — "check this against the app store guidelines", "will Apple reject this?", pre-submission audit, App Store readiness, pre-flight before TestFlight or App Store Connect upload, "why does Apple keep rejecting my app", rule compliance (3.1.1, 4.8, 5.1.1, etc.), or asking if a specific change is allowed (moving subs off IAP to Stripe/external checkout, adding analytics/tracking/attribution SDKs, social login, new permission, privacy manifest, ATT, account deletion, IAP/subscriptions). Works on any iOS-shipping codebase — native Swift/SwiftUI/UIKit/Xcode, React Native, Expo, Flutter, Capacitor/Ionic, Unity. Fetches live guidelines from developer.apple.com, then returns rejection-risk findings keyed by guideline number with severity, file:line evidence, and fixes. Read-only. Not for general bug/perf code review and not for implementing features.
How this skill is triggered — by the user, by Claude, or both
Slash command
/alamops-skills:appstore-reviewThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
A read-only audit skill: review a project against Apple's live App Store Review Guidelines and report whether it would survive App Review. Tone: pragmatic reviewer who has shipped apps and knows which rules actually get apps bounced.
A read-only audit skill: review a project against Apple's live App Store Review Guidelines and report whether it would survive App Review. Tone: pragmatic reviewer who has shipped apps and knows which rules actually get apps bounced.
Apple's guidelines drift. Numbering, examples, and required disclosures change several times a year (App Tracking Transparency, required-reason API list, alternative-payment language, AI / generated-content rules, account-deletion mandates, etc.). Reviewing against a snapshot in the model's head is how teams ship rejections. You must pull the current guidelines from the web at the start of every run. If the fetch fails, say so plainly and stop — do not guess from training data.
Fetch (in this order; stop at the first that succeeds):
https://developer.apple.com/app-store/review/guidelines/ — the canonical, full textWebSearch with site:developer.apple.com "App Store Review Guidelines" and follow the top resultThen also fetch the supporting pages that are referenced from the guidelines and routinely cause rejections:
https://developer.apple.com/documentation/apptrackingtransparency)apple required reason api)apple privacy manifest PrivacyInfo.xcprivacy)Cache the fetched text into the skill working memory for the rest of the run — don't refetch per sub-agent. If the user passes a guideline number directly (e.g., "check rule 5.1.1"), still pull the live page once so the wording you cite is current.
If you cannot reach developer.apple.com (offline, blocked, rate-limited), abort with: "I couldn't fetch the live App Store guidelines. I won't review from cached knowledge — please retry when the network is reachable, or paste the relevant sections."
Before you can map rules to code, figure out what kind of app this is. Run these probes in parallel:
git ls-files | head -200. Otherwise (consultancy hand-off, tarball, snapshot): find . -maxdepth 3 -type f | head -200 plus a top-level ls -la. Either way, the goal is the same: top-level shape.*.xcodeproj, *.xcworkspace, Info.plist, *.entitlements, Podfile, Package.swiftpackage.json with react-native, ios/ folder, Podfile, app.jsonapp.json / app.config.{js,ts} with expo key, eas.jsonpubspec.yaml, ios/Runner/Info.plistcapacitor.config.{json,ts}, ios/App/App/Info.plistProjectSettings/NS*UsageDescription), supported SKUs / IAP product IDs if visiblefastlane/metadata/, marketing/, store/, screenshots, App Privacy answers, description copyWrite a short Project Profile block (platform, frameworks, auth providers, payment surface, tracking SDKs, generative-AI features, UGC surfaces, kids-category signals). The sub-agents you spawn next will use this to know what not to flag (e.g., don't hunt for IAP issues if there are no purchases).
Spawn one Agent per review lane, in a single message so they run concurrently. Each sub-agent gets:
The five canonical lanes plus two cross-cutting lanes:
| Lane | Guideline section | What to look for |
|---|---|---|
| Safety | 1.x | UGC moderation, reporting, blocking, child safety (1.3), medical / health claims (1.4), developer info, hateful content, physical-harm vectors, kids-category compliance |
| Performance | 2.x | Crashes, broken links, placeholder content, demo accounts, hardware compatibility, software requirements (deprecated APIs, latest SDK), accurate metadata, push-notification abuse, in-app-purchase correctness, hardware abuse, beta-only behavior in prod build, software-as-a-feature gating |
| Business | 3.x | Payments (IAP for digital goods, Reader Rule, External Link Entitlement language, anti-steering), subscriptions (auto-renew disclosure, restore, manage link), advertising, other-business-model edge cases, alternative-payment entitlement usage |
| Design | 4.x | Minimum functionality, copycats, spam, web views vs. native, sign-in (Sign in with Apple parity if other social logins present, including Google / Facebook / X / GitHub — 4.8), HealthKit / HomeKit / etc. interface rules, push notifications, hardware compatibility, generative-AI safety controls (4.x current wording) |
| Legal | 5.x | Privacy (5.1) — App Privacy answers, privacy policy URL, account deletion (5.1.1(v)), data collection minimization, tracking & ATT (5.1.2), kids privacy (5.1.4), location (5.1.5); intellectual property (5.2); gaming / contests; VPN / mobile device management; international laws; developer code of conduct |
| App Privacy & required-reason APIs | crosscuts 5.1, 2.5 | Privacy manifest (PrivacyInfo.xcprivacy) present? Each required-reason API used (UserDefaults, file timestamp, system boot time, disk space, active keyboard) declared with a valid reason? Third-party SDKs that need their own manifest accounted for? Tracking domain declarations? |
| App Tracking Transparency | 5.1.2 + ATT docs | Any tracking SDK (analytics, ads, attribution) wired up? If yes: NSUserTrackingUsageDescription set, ATT prompt actually called before tracking, no tracking on denied, no IDFA / fingerprinting fallback when denied |
Each sub-agent returns findings in a fixed JSON-ish shape (see step 5). Use the structured-output pattern if available; otherwise instruct them to emit a fenced JSON block.
You are auditing an iOS-shipping project against ONE section of the
current App Store Review Guidelines. You are read-only — do not edit
any file. Return findings only, no praise, no commentary.
PROJECT PROFILE:
<insert profile block>
GUIDELINE SECTION (live text, fetched today):
<insert just the relevant section>
YOUR JOB:
For each rule in this section, decide whether the project plausibly
violates it. A violation requires either (a) concrete evidence in the
code/config/metadata, or (b) a structural gap (e.g., the app collects
data but has no privacy policy URL anywhere in the repo). Do not flag
rules that don't apply (e.g., don't flag IAP rules on an app with no
purchases).
For each finding, output:
{
"rule": "<guideline number, e.g. 5.1.1(v)>",
"title": "<one-line summary>",
"severity": "blocker" | "risk" | "nit",
"evidence": "<file:line(s) or 'absent: <thing>'>",
"why_it_fails": "<one sentence — what Apple would object to>",
"fix": "<concrete remediation, 1–3 sentences>"
}
Severity:
- blocker: this is the kind of thing App Review actively rejects
- risk: grey area / depends on how Apple reads it / common bounce
- nit: unlikely to reject but cleanup before submission
If you find nothing, return an empty array. Do not invent findings.
Independent of the lane sub-agents, sweep these yourself — they're cheap and Apple rejects on them constantly:
NSUserTrackingUsageDescription in Info.plist.PrivacyInfo.xcprivacy while using known required-reason APIs (UserDefaults, stat/file timestamps, systemBootTime, free disk space, active keyboards).For each one, generate a finding in the same shape as the lane agents. Don't duplicate — if a lane agent already caught it, leave theirs.
Merge all findings. Deduplicate by (rule, evidence). Sort by severity (blocker → risk → nit), then by guideline number.
Each finding inside ### Blockers / ### Risks / ### Nits renders as:
**[<rule>] <title>** — <severity>
- *Evidence:* `<file:line>` or `absent: <thing>`
- *Why it fails:* <one sentence>
- *Fix:* <concrete remediation>
Always use this exact report scaffold (and nothing else — do not emit the rendering rubric above as a section in the report):
# App Store readiness report
**Guidelines fetched:** <URL> on <today's date>
**Project profile:** <one paragraph — platform, frameworks, payment surface, tracking, auth>
**Lanes run:** <list of lanes, with any skipped lanes and why>
## Verdict
<One of:>
- ✅ **Likely to pass.** No blockers found. <Optional: N nits worth cleaning up before submission.>
- ⚠️ **Risk of rejection.** N risks, M nits. No outright blockers, but at least one finding maps to a rule Apple frequently enforces.
- 🛑 **Will likely be rejected.** N blockers. Submitting in current state is a waste of a review cycle.
## Findings
### Blockers
<one finding block per blocker>
### Risks
<one finding block per risk>
### Nits
<one finding block per nit>
## Notes & limitations
<Anything the user should know — couldn't inspect X, lane Y was skipped because Z, suggest running again after adding store metadata, etc.>
If there are zero findings, the report is just the header + verdict + a one-line note ("Sweeps clean against today's guidelines. Re-run after any change to tracking, IAP, sign-in, or account flows."). Do not invent findings to fill space.
This skill is strictly read-only. Even if you spot a one-line fix and feel the urge — surface it in the fix: field. The user runs the fixes themselves (or hands the report to a separate edit-capable session). This matches the house style of the other (alamops) review skills.
code-review skill, not this one.why_it_fails, that's fine — but the rule field is the anchor and must match the live text.NSCameraUsageDescription as "make sure the string is meaningful" — that's a nit at best and floods the report. Only flag usage descriptions that are missing, empty, generic-to-the-point-of-useless, or copy-pasted boilerplate that doesn't describe the actual feature.app.json plugins, EAS submit profile, and the iOS native shim.npx claudepluginhub alamops/skills --plugin alamops-skillsCreates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.