A phone-only project aborted with 'no sevenInchScreenshots'. Play requires the 512 icon, the 1024x500 feature graphic and at least 2 screenshots (Play Console Help answer 9866151). play images uploads what exists and prints an info line for missing optional sets; play.tablets true makes missing tablet sets an error in shots render/check/gallery, validate and play images. Pitfall 19.
- aso competitors: top apps per keyword from the iTunes Search API (name, developer,
rating count, release / update dates, localized genre), coverage gaps (words of 2+
developers), new entrants vs the last snapshot (.storebound/aso/competitors/)
- aso suggest: candidates from own text, competitor names, localized category names and
Apple Ads keyword suggestions (POST /v1/suggestions/keywords/query, relative 0-100
popularity, only with credentials); 100-byte keyword field per locale as a diff,
--write marks it a draft that check --aso and aso audit report
- aso audit: check --aso, free keyword room, rank trend arrows, gaps, Play short
description / density, App Store conversion, PPO / Play experiment ideas, next 3 actions
- MCP: read-only aso_competitors, aso_suggest, aso_audit; desktop ASO card (visx rank chart)
- docs: README, aso-basics, store-pitfalls (Search API order, no Play search API), CHANGELOG;
demo-app listing files; tests on recorded Search API and mocked Ads answers
Web capture runs frames in parallel browser contexts (default from the CPU count, lower for GPU-heavy capture),
logs n/total + ETA and goto / waitFor / eval / delay / screenshot per frame, writes .storebound/capture-report.json
with the slowest frames and steps. shots.capture.session 'per-language' boots the app once per language and device
and switches shots via pushState / popstate (navigate 'spa') or goto (navigate 'reload'), falling back to a fresh
page when a precondition fails. .storebound/capture-cache.json skips frames with unchanged inputs; --only-missing,
--force. shots render renders with --concurrency pages and async ffmpeg.
Conflict in cli/lib/config.ts (play section): kept play.build from main and the new targetAges, accountType, accountCreated and billingPrograms. Adapters and API tables regenerated (unchanged).
Conflicts resolved for both sides:
- cli/lib/plist.ts, cli/lib/zip.ts: one implementation each. plist reads XML (text or
bytes, attributes tolerated) and binary plists; ads scan now reads bytes, so a binary
Info.plist works too. zip gains unzip() for the Play report exports on top of
zipEntries / zipRead.
- apple upload waits with testflight wait's loop (waitForBuild) instead of its own copy;
BUILD_DONE removed.
- config, credentials (profiles, keystore, ASC_VENDOR_NUMBER, now also a profile key),
command table, MCP tools, credentials template, README, CHANGELOG: union.
- MCP: --write stays forbidden; the three pull tools are the listed local-file exception
(LOCAL_WRITE_TOOLS), so scan --write remains unreachable.
- Adapters and API coverage tables regenerated.
Play rules verified against the live Policy Center / Play Console Help pages
(checked 2026-10-11, cited in cli/lib/scan/play-rules.ts): restricted
permissions and their declarations (background location, photo / video, All
files access, AccessibilityService, REQUEST_INSTALL_PACKAGES, Health Connect,
full-screen intent, VpnService), prominent disclosure and the in-app privacy
policy, Data safety vs SDK disclosures, Families (certified ad SDKs, AD_ID,
location), AD_ID on targetSdk 33+, 16 KB page sizes (Unity, React Native, NDK,
AGP, prebuilt .so), testing for new personal accounts, Play metadata, ads at
launch, payments outside Play Billing, impersonation. Detection reads manifest
components, accessibility configs, strings.xml, native toolchain versions and a
local build's merged manifest. New fixtures and tests; README table per store.
- apple testflight wait --build N (progress, timeout, exit 0/1/7) and expire --keep N | --older-than D (dry run, asks)
- apple iap-submit: IAP / subscription / group versions into a review submission; first of a type only with the app
version (--with-version), --no-submit keeps the draft; read-only MCP plan
- apple listing pull, play listing pull (diff, --write), catalog pull (config proposal, never rewritten)
- whats-new --languages / check / apply: one file per language, agent or hook translation, per-store limits
- apple offer-codes, win-back, promoted, preorder; Play pre-registration as a guide (no API)
- apple cpp and apple events: list, create, upload, submit (asks)
- reports: Apple sales / finance, Play earnings / sales into .storebound/reports with summary and CSV
- triage: TestFlight crash / feedback and Play error reports grouped by signature, device, OS
- aso rank: iTunes Search API ranks and competitors, rate limited
- ads scan: AdAttributionKit / SKAdNetwork Info.plist and source checks
- tests against recorded, sanitized answers; skills, README, CHANGELOG
apple signing status|ensure: bundle id capabilities, a distribution certificate from a key made locally (kept in .storebound/signing, never printed), App Store profiles installed for Xcode; Developer ID 403 explained.
apple build / apple upload: xcodebuild archive + export with a generated ExportOptions.plist, next build number, App Store Connect API build upload (or altool), processing wait. Native, Capacitor, React Native, Flutter, Unity projects.
play build / play upload: Gradle bundleRelease with the upload key passed through the environment, next versionCode read back from the AAB, testing tracks only.
originality: offline Guideline 4.3 check (name, listing text, icon and screenshot perceptual hashes, project structure).
New skill build-and-sign; zero new dependencies.
- specs/: Apple's App Store Connect OpenAPI 4.5.1 and the Google discovery docs for androidpublisher v3 and
playdeveloperreporting v1beta1, pinned with URL, date and SHA-256 (specs/SOURCES.json)
- tools/gen-api.ts: one row per operation (cli/api/apple.gen.ts 1303, cli/api/play.gen.ts 170), a scan of which
operations the commands already call (cli/api/wrapped.gen.ts) and docs/api-coverage.md; CI checks freshness
- cli/api/client.ts + types.ts: generic URL / parameter building, retries with Retry-After, pagination, types derived
from the rows; auth reuses ascJwt and the Play service account
- cli/api/gate.ts: GET runs, writes dry unless --yes in a TTY, owner-only operations need the id typed, nothing
written under MCP or serve; MCP gets the read-only api_get
- storebound api list | coverage | apple|play <op|METHOD path>; skill store-api, README, CHANGELOG, tests
- storebound.workspace.json: app folders (globs), studios with accounts by credential profile, ignore list, the
desktop's pairing overrides; ws init | list | status | check | validate | run | apps import | desktop export/import
- credential profiles in ~/.storebound/credentials/<profile>.json or env, --account <profile> on any command
- release status / release plan <version>, table or --json; MCP workspace_list, workspace_status, release_status,
release_plan (read-only)
- pairing rules (cli/lib/identity.ts), release lanes (cli/lib/train.ts) and the per-app status read
(cli/lib/app-status.ts) shared with the desktop instead of copied
- tests with sanitized fixtures, README, skills, CHANGELOG
Detects the stack (native iOS / Android, React Native, Expo, Capacitor, Cordova,
Flutter, Unity, Godot) and the SDKs from a maintained table with versions,
file:line and each vendor's disclosure page, then reports App Store and Google
Play rejection risks with guideline, evidence, fix, severity and skill: 2.1(a)
demo account and placeholder text, 5.1.1(v) account deletion, 4.8 login
services, 3.1.1 restore and outside payments, 3.1.2 subscription info, 5.1.2(i)
ATT, purpose strings, privacy link, privacy manifest, 2.3.10, 2.3.7, 2.3.8, 4.2
web wrappers, 2.5.1, 2.5.5, ATS, export compliance, 1.3 kids ads, review
prompts, privacy labels vs SDKs; Play target SDK 36, delete-account URL, App
access, foreground services, exact alarms, QUERY_ALL_PACKAGES, SMS / call log,
com.example package name.
Proposes Data safety / App Privacy / ATT / privacy manifest answers (detected
file:line or ask owner) as a diff against the config; --write adds only the
detected ones. scan.ignore records owner-accepted findings. MCP tool scan
(read-only), validate includes open findings, desktop Checks tab shows them.
Fixtures for iOS, Android, Capacitor, Unity, Flutter, clean and teaser.
storebound import fastlane [--dir] [--out] [--profile] [--dry] (MCP import_fastlane, dry run by default) reads
Appfile / Deliverfile plain option lines, deliver and supply metadata and screenshots, and writes
storebound.config.ts, store/appstore.md, store/listing.md, the Play icon and feature graphics, and frames with a
folder capture source. App Store and Play language codes are paired (cli/lib/store-locales.ts). Existing files are
never overwritten (.imported copies with a diff hint); keys, team ids, the review contact and demo account are only
named in the report. Fixture tests/fixtures/fastlane-sample, skill migrate-from-fastlane, README and CHANGELOG.
apple ppo status | create --variant b[,c] | upload --variant b | start | stop: v2 experiments (platform IOS, traffic
proportion), one treatment per shots variant (max 3), a treatment localization per App Store locale, and the variant
renders synced into the treatment screenshot sets (shared MD5-idempotent set sync with apple screenshots, which no
longer creates sets on --dry). start / stop ask first and are not MCP tools; MCP: apple_ppo_status, apple_ppo_create,
apple_ppo_upload. Play experiments stay console-only (documented).
apple.iphoneMedium (off by default): iphone-medium size key, 1206 x 2622 (1179 x 2556 accepted), uploaded as
APP_IPHONE_61; rendered, checked, required and uploaded only when enabled. Apple's scaling rule documented in the config
and the store-screenshots skill.
App Store Connect Analytics Reports API (ONGOING request, Discovery and Engagement + Downloads Standard reports,
daily instances, md5-checked gzip segments, newest processing per day) and the Play statistics exports in the
pubsite_prod_rev_ Cloud Storage bucket (UTF-16 CSV, store listing visitors / acquisitions, daily user installs;
play.reportsBucket). Snapshots in .storebound/analytics/<date>.json; compare lines them up with the git history of the
store files (7 days before vs after each change). MCP: analytics_snapshot, analytics_compare, analytics_setup.
export reads the current App Store manual (and with --with-automatic the equalized) prices and the Play purchase
option regional prices into one CSV. import parses and checks the sheet, prints a diff table (change %), and after a
confirmation writes one App Store price schedule per changed product (base territory + every manual price, future-dated
changes via start_date, price point ids looked up per territory) and the Play regional configs (CSV over current,
convertRegionPrices for regions without a price, --reconvert). MCP: prices_diff (read-only), prices_export; applying
stays a terminal command. store-iap-setup skill: price sheet section.
App Store customerReviews / customerReviewResponses and Google Play reviews.list / reviews.reply. draft writes one
Markdown file per unanswered review to .storebound/replies (front matter approved: false, never overwritten); send
only sends approved, unsent drafts that pass the checks (Play 350 characters, no incentives or rating requests,
personal data / link / tone warnings) after a confirmation, and marks them sent. MCP: reviews_list, reviews_draft;
send is never exposed.
Play Developer Reporting API v1beta1 (crashRateMetricSet / anrRateMetricSet DAILY queries in America/Los_Angeles,
user-perceived 28-day rates, worst device models, errorIssues:search) and App Store Connect perfPowerMetrics,
diagnostic signatures and TestFlight crash submissions. Thresholds 1.09 % crash / 0.47 % ANR / 8 % per device
(developer.android.com/topic/performance/vitals): over = blocker, from 80 % = warn, in validate too (--no-health).
Weekly Markdown report with week-over-week change in .storebound/health/. MCP: health (read-only), health_report.
Beta groups from apple.testflight.groups (created when missing, never changed), testers from a CSV in .storebound/
(masked in logs, confirmation before Apple emails invitations, --remove / --invite), What to Test per locale from the
App Store listing (whatToTest or whatsNew), Test Information and Beta App Review details, builds by exact number to
groups, Beta App Review submission behind --submit-review and a confirmation. Pure planners in cli/lib/testflight.ts,
shared CSV / table / JSON:API helpers. MCP: apple_testflight_status, _groups, _what_to_test, _info, _distribute
(internal groups only). Skill testflight.
- storebound mcp: stdio MCP server (spec 2025-11-25, tools only), one tool per command, write tools
dry_run by default, readOnly/destructive/idempotent/openWorld annotations; submit, release,
rollout, cancel and delete are not exposed. Own JSON-RPC subset, no SDK, zero runtime deps.
- storebound install --agent claude|codex|cursor|copilot|windsurf|gemini|opencode: copies the skills
and adds the storebound MCP entry (.mcp.json, .codex/config.toml, .cursor/mcp.json, .vscode/mcp.json,
Windsurf mcp_config.json, .gemini/settings.json, opencode.json). Idempotent, keeps other entries, --dry.