storebound logo storebound

Open source · CLI · desktop app · for apps and games

From an empty folder to Submit for review.

On Google Play and the App Store. Your AI agent does all of it with storebound: builds, uploads, store text, screenshots in every language and size, in-app products and prices, the compliance forms, even the consoles without an API. You only press Submit.

npx storebound init

Needs Node 20+ (or Bun (opens in a new tab) 1.1+: bunx storebound init). No account, no sign-up, no telemetry.

The teaser: the demo game from an empty folder to both stores, then the desktop app. Real output and real app frames; has music.
  • MIT licensed
  • Zero runtime dependencies
  • No telemetry
  • --dry on every write
  • 25 Agent Skills + MCP server

Works with Claude Code · Codex · Cursor · Gemini CLI · Copilot · Windsurf · OpenCode · or just the CLI

1 · The whole job

You ask once. Your agent does the rest.

“Get my app ready for both stores.” storebound plans every step on both stores in fix order, and your agent works through it: API first, its own browser for the consoles without an API, a dry run before every write, a read-back after.

$ storebound release plan 1.0.0
[release] Example App: validate (read-only, both stores)
Example App 1.0.0
 both stores (fix first):
   1. CONFIG  App Review needs a demo account (sign-in required) · add reviewDemoAccount to .storebound/credentials.json · review-access skill
             -> storebound check
   2. CONFIG  missing file: store/icon/icon.png
             -> storebound check
   3. CONFIG  missing file: store/icon/foreground.png
             -> storebound check
   4. CONFIG  missing file: store/icon/background.png
             -> storebound check
 App Store: not on the store
   5. STORE   1.0.0 is not on App Store yet: upload a build (Xcode / Transporter), then create the version with its texts
             -> storebound apple next-build; storebound apple listing --version 1.0.0 --build <N> --dry
   6. BLOCKER no App Store version being prepared
             -> storebound apple listing --version x.y.z
   7. BLOCKER no build attached to the version
… 19 more steps on both stores, each with the command that fixes it
Real output, full text
  • Builds and uploadsSigning, the next free build number, AAB and IPA to the right track, TestFlight groups.
  • Store text in every languageListings for both stores within every limit, translated drafts, What's new from git.
  • Screenshots and previewsEvery store size, every language, from your real app, checked against both stores' specs.
  • In-app products and pricesProducts and subscriptions on both stores from one list, priced in 175 countries.
  • The compliance formsData safety, App Privacy, age rating, export compliance, answered from your config and code. What only you know, it asks once.
  • Even consoles without an APIA console plan gives the agent the steps, the answers and the buttons it must never press.

Real output from the demo projects

Store screenshots, every size, every language

One command rendered 200 store-ready images: 6 device sizes plus the Play feature graphic, 4 languages, an A/B variant. Then checked them against both stores' specs: 0 errors.

$ storebound shots render --variants

  • EN
  • JA
  • AR
  • TR
  • EN
  • JA
  • AR
  • TR
  • EN
  • JA
  • AR
  • TR
  • EN
  • JA
  • AR
  • TR

200 images · iPhone 6.9" and 6.5", iPad 13", Play phone, 7" and 10" tablet, feature graphic

By hand 200 exports from a design tool, each dropped into the right slot in two consoles.

Real output · examples/demo-game and demo-app · offline commands and dry runs, nothing sent to a store

Store art, every size, every language

Store screenshots rendered by storebound: four scenes of the demo game in English plus the hero scene in Turkish, Japanese and Arabic
The demo game “Prism Puddle”: four scenes in English, the hero scene in Turkish, Japanese and Arabic (right to left). Rendered by shots render, checked by shots check.

The consoles, too

$ storebound console plan play-content-rating
Play Console: Content rating (IARC)
Owner batch (everything the owner does, in ONE message, in the order the agent needs it):
  1. [before the run] Answer 17 question(s) in ONE batch (askOwner), then write the answers into storebound.config.ts and rerun the plan: Category; V…
  2. [before the run] Tick the IARC Terms of Use box  @ Play Console > the app > Policy and programs > App content > Content ratings > "Start questio…
  3. [after the run] Press Send changes for review once every App content card and store setting is done  @ Publishing overview (left menu): "Submit…
start: https://play.google.com/console
  then: Pick the developer account if asked (set play.developerId for a deep link)
  then: the app (com.example.prismpuddle) in the app list
  then: Policy and programs > App content
  then: Content rating > Start (or Manage)
Steps:
  2. Page 1: type the email address and pick the category (material radio: JS click on the inner [role=radio]). The IARC Terms of Use checkbox is an…
  9. Summary: read the ratings per authority, then press its Save yourself (a declaration save, "Save", not "Submit"; verified 2026-10-13: it stores…
Never press: "IARC Terms of Use box", "Send changes for review", "Publish", "Submit", "Create", "Create app", "Send", "Release", "Definitions and Examples", "?", "More information", "Submit N changes for review", "Restart review"
Final button (the owner's): Send changes for review
… the answer sheet, the in-page helper and how to verify
Real output, full text

Some store pages have no API: creating the app records, Play's App content cards and content rating, App Privacy labels. storebound console plan hands your agent the start URL, every step, the answer sheet from your config and the buttons it must never press. The agent drives the page and stops before the final button.

YOU
  • App Store: Submit for Review · Play: Send changes for review
  • Releasing an approved version, completing a rollout
  • App Privacy Publish, agreements, banking and tax
  • The answers only you can know, asked once, in one batch

Every step, what is API, what the agent drives and what stays yours: the journey (opens in a new tab).

2 · No avoidable rejections

You won't get rejected for the avoidable things.

storebound scan reads your project offline and read-only: Xcode and Gradle files, Info.plist, manifests, entitlements, lockfiles and engine settings, plus your config and listings. It works out the stack and the SDKs, then reports every rejection risk it can prove, each with the guideline, the evidence as file:line, the fix, a severity and the skill to open.

$ storebound scan
Rejection risks: 2 blocker, 3 high, 0 medium, 0 low
  1. BLOCKER 2.1(a) · App Store · Sign-in is required but there is no demo account for App Review
       at storebound.config.ts:12  reviewAccess: { signInRequired: true, instructions: 'Sign in with the demo account.' },
       at storebound.config.ts:11  accounts: { enabled: true },
       at Podfile.lock:3  Google Sign-In: GoogleSignIn 7.1.0
       fix: Create a demo account that sees every feature (not a sign-up the reviewer must do), put it in .storebound/credentials.json as reviewDemoAccount (never in the repo), then `storebound apple review-details`.
       skill: review-access · https://developer.apple.com/app-store/review/guidelines/
  2. BLOCKER 5.1.1(v) · App Store · Accounts can be created but no in-app account deletion was found
       at storebound.config.ts:11  accounts: { enabled: true },
       at Planner/LoginView.swift:11  Button("Create account") { Task { try await AccountApi.signUp() } }
       at Planner/LoginView.swift:17  static func signUp() async throws {
       fix: Add "Delete account" in the app (it deletes the account and its data, not only signs out; with Sign in with Apple also revoke the token), then set accounts.inApp to where it starts, e.g. "Settings > Account > Delete account".
… 3 more findings (4.8, 3.1.1, 5.1.2(i)), then the Data safety / App Privacy proposal
Real output, full text

What it proves, on both stores

  • 2.1(a)App access

    A sign-in with no demo account for the reviewer.

  • 5.1.1(v)Account deletion

    Sign-up or social login without an in-app deletion path or a deletion URL.

  • 4.8

    Google or Facebook login without Sign in with Apple or another equivalent option.

  • 3.1.1, 3.1.2Payments

    No Restore Purchases path, card SDKs next to in-app products, missing subscription terms.

  • 5.1.2Data safety

    Tracking SDKs without ATT; SDK data types missing from App Privacy or Data safety.

  • 5.1.1, ITMS-91053

    Permissions without purpose strings; a missing or incomplete privacy manifest.

  • Restricted permissions

    Background location, photos, all files, accessibility, exact alarms, foreground services, and the Console declaration each one needs.

  • 1.3Families

    Ad or analytics SDKs in a Kids Category or child-directed app.

  • Target API, 16 KB pages

    targetSdk below 36; Unity, React Native, NDK or AGP versions without 16 KB page support.

  • 2.3.7, 2.3.10Metadata

    Other apps' names, "best / #1", keyword lists, other stores in App Store text, placeholder text.

  • 2.2

    "Beta", "demo" or "test" wording in the app name and the listing.

  • 4.3Repetitive content

    scan --originality --against <folders> adds the near-duplicate check against your other apps.

  • 4.8 App Store guideline
  • Families Google Play policy

Below the risks comes a proposal for Data safety, App Privacy, ATT and the privacy manifest from the detected SDKs, each answer marked detected or ask owner. Nothing is written unless you run scan --write. validate includes the open findings, and the desktop app shows them on its Checks tab.

3 · The desktop app

Every app on both stores, in one window.

Releases, charts, catalog and prices side by side, crash health, reviews, TestFlight and the rejection checks, for every app and game you ship. Send for review from there too: a dry run first, then a confirm. Same storebound underneath, with the CLI's version number, store accounts and app folders: npx storebound desktop installs it and opens your app folder.

storebound desktop, Releases › Send for review: the dry run of the submission with the build picked by number, then a confirm. You press the button.
Releases › Send for review: the dry run of the submission with the build picked by number, then a confirm. You press the button.

Download storebound desktop

macOS, Windows and Linux. Looking up the latest release…

Checksums and signatures
  1. Checksum: shasum -a 256 <file> (macOS, Linux) or Get-FileHash <file> (Windows) must print the SHA-256 above.
  2. Signature: every file has a .sig next to it (the app's update key, minisign). With minisign (opens in a new tab): base64 -d <file>.sig > f.minisig && minisign -Vm <file> -x f.minisig -P <key>, with the public key RWQqOO/ZeIr3RBmolt/fx108m89QNEUndRTFrucjx0CBMoeFb7/xhrvW
  3. Or let the CLI do both: npx storebound desktop downloads the app for your system, checks its size, SHA-256 and signature, installs it for your user (no admin rights; it asks first) and opens it on the current app folder. --download only saves the checked installer to ~/Downloads.

One product, one version: the app and the npm package storebound (CLI, MCP server, agent skills) are released together with the same number, and the app runs its own copy of that CLI. They share the store accounts (~/.storebound/credentials) and the list of app folders. The app also updates itself from this site: each update is signed, and the app checks the signature before it replaces anything. It asks before installing.

4 · Works with your AI

Your AI coding agent drives it. Safely.

Skills, an MCP server and the CLI: the same tools for every agent. The skills are plain Markdown and the CLI is a normal command, so nothing requires a particular tool, or any agent at all.

  • Claude Code
  • OpenAI Codex
  • Cursor
  • GitHub Copilot
  • Gemini CLI
  • Windsurf
  • OpenCode
  • anything that reads AGENTS.md

Connect your tool

Claude Code

/plugin marketplace add https://git.crt.fyi/CRT/storebound.git
/plugin install storebound@crtkafa

Skills, MCP server and storebound on PATH. Or per project: npx storebound install --agent claude

OpenAI Codex

npx storebound install --agent codex

Skills in .agents/skills, MCP in .codex/config.toml (Codex reads it for trusted projects). The repo is also a Codex plugin, skills only.

Gemini CLI

gemini extensions install https://git.crt.fyi/CRT/storebound.git

Skills, MCP server and GEMINI.md. Or npx storebound install --agent gemini

Cursor

npx storebound install --agent cursor

Skills in .agents/skills and .cursor/mcp.json. The repo's .cursor/rules/storebound.mdc is an agent-requested rule you can copy.

VS Code / GitHub Copilot

npx storebound install --agent copilot

Skills in .github/skills and .vscode/mcp.json.

Windsurf (Devin Desktop)

npx storebound install --agent windsurf

Skills in .agents/skills, MCP in your global mcp_config.json.

OpenCode

npx storebound install --agent opencode

Skills in .opencode/skills and opencode.json.

Anything that reads AGENTS.md

Copy or link AGENTS.md (rules and skill index) into your project and use the CLI. For an MCP client install does not know: command npx (or bunx) with args ["storebound", "mcp"].

install takes several agents at once (--agent codex,cursor), --dry to preview, and only touches its own storebound entry and skill folders. Re-running it is safe.

Every write is a dry run first

$ storebound play products --dry
[play] 1/2 com.example.app.no_ads: would create · 174 regions · 2 listings (dry)
[play] 2/2 com.example.app.gems_100: would create · 174 regions · 2 listings (dry)
dry run: play products: 2 change(s); nothing written
item                      action  detail
------------------------  ------  ---------------------------------
com.example.app.no_ads    create  174 regions, 2 listings, USD 2.99
com.example.app.gems_100  create  174 regions, 2 listings, USD 0.99
[play] not on Google Play: com.example.app.no_ads, com.example.app.gems_100. If you created them in the last minutes, the store's list can lag a minute after creating; re-run before acting on this plan
[play] products checked (dry run, nothing written)
Real output, full text
  • Dry run everywhere

    Every write command takes --dry; every MCP write tool has dry_run, default true.

  • The owner's buttons stay yours

    Submitting, releasing, completing a rollout, canceling a submission, deleting and creating offer codes are not MCP tools; the terminal commands ask first.

  • Credentials stay local

    Store accounts once per machine in ~/.storebound/credentials (files only you can read, shared by the CLI and the desktop app), the rest in the project's gitignored .storebound/. Official store APIs only, with keys you create and can revoke, never your password.

  • Idempotent writes

    Re-running converges (MD5 checks for screenshots and previews, one Play edit per language), so a failed upload is fixed by running it again.

  • Personal data stays local

    Tester lists, the App Review demo account, reply drafts and reports live in .storebound/, masked in every log line.

  • Careful with your devices

    storebound shuts down only a simulator it booted itself, and never boots, wipes or reboots an Android emulator or device.

What a session with your agent looks like
example · tidy-lists
you: Add a yearly Pro plan with a 1-week free trial and a monthly plan, on both stores.agent: Adding both to subscriptions in storebound.config.ts (USD 29.99 / 3.99, Turkey set by hand). Dry runs first.$ bunx storebound check
09:41:02 [check] config ok: storebound.config.ts
09:41:02 [check] subscriptions: 2 in 1 group(s)
09:41:02 [check] all good
$ bunx storebound apple subscriptions --dry
09:41:05 [apple] reading subscription groups, subscriptions, ...
09:41:07 [apple] 1/9 create subscription group "Tidy Pro"
09:41:07 [apple] 3/9 create pro_yearly (ONE_YEAR, level 1)
09:41:07 [apple] 6/9 pro_yearly: introductory offer FREE_TRIAL P1W
09:41:07 [apple] subscriptions planned (dry run, nothing written; ...) (5s)
$ bunx storebound play subscriptions --dry
09:41:10 [play] 1/2 pro_yearly: create, base plan yearly (P1Y) in 173 regions · intro offer intro (free)
09:41:10 [play] 2/2 pro_monthly: create, base plan monthly (P1M) in 173 regions
09:41:10 [play] subscriptions planned (dry run, nothing written) (3s)
agent: Plan matches the config. Create them on both stores?you: yes$ bunx storebound apple subscriptions && bunx storebound play subscriptions
09:42:31 [apple] group "Tidy Pro" created
09:42:33 [apple] 1/2 pro_yearly: created
09:42:52 [apple] subscriptions done (first ones are submitted with an app version: ...) (21s)
09:43:04 [play] pro_yearly: base plan yearly activated
09:43:05 [play] pro_yearly: offer intro created and activated
09:43:07 [play] subscriptions done (25s)
$ bunx storebound validate
 1. BLOCKER [apple] pro_yearly: no review screenshot
      fix: subscriptions[].reviewScreenshot, then storebound apple subscriptions
 2. warn    [apple] description without a Terms of Use link: tr (3.1.2; ...)
09:43:20 [validate] 1 blocker(s)
agent: Left for you: a paywall screenshot for the reviewer (I'll upload it), the Terms link in the Turkish description, and in App Store Connect, adding the first subscriptions to the version's submission (no API; I'll walk you through it).Submit for review · your click
Example session: the user asks for two subscriptions, the agent runs storebound dry runs, the user confirms, storebound creates them on both stores, and validate lists what is left.

5 · Install and start

Five steps, from an empty folder to your Submit click.

storebound lives in your app's repo. Describe the app once, add your keys, then ask your agent or run the commands yourself.

  1. Start in your app repo

    Pick a profile. Adds config and store files, never overwrites.

    Terminal
    $ npx storebound init --profile app
    $ npx storebound desktop          # optional: installs the app once, opens this folder
    Profiles appsubscription-appgame
    • storebound.config.tsids, languages, products, Data safety
    • store/listing text, questionnaire answers, screenshot captions
    • .storebound/this app's upload key and review contact, gitignored

    storebound is installed once per machine; each project has its storebound.config.ts and .storebound/. Needs Node 20+ (or Bun (opens in a new tab) 1.1+ with bunx), plus ffmpeg for icons, screenshots and video.

  2. Describe the app once

    One config for both stores, checked offline.

    storebound.config.ts
    const config: ShipConfig = {
      app: { name: 'My App', profile: 'app' },
      languages: [
        { id: 'en', play: 'en-US', apple: 'en-US' },
        { id: 'tr', play: 'tr-TR', apple: 'tr' },
      ],
      play:  { packageName: 'com.example.app' },
      apple: { bundleId: 'com.example.app' },
    };
    Terminal
    $ npx storebound check

    Store text lives next to it in store/listing.md and store/appstore.md, one section per language.

  3. Add your store keys

    Official API keys you create and can revoke.

    ~/.storebound/credentials/default.jsononce per machine
    {
      "PLAY_SERVICE_ACCOUNT": "/keys/play.json",
      "ASC_KEY_ID": "KEY_ID",
      "ASC_ISSUER_ID": "ISSUER_ID",
      "ASC_P8": "/keys/AuthKey_KEY_ID.p8"
    }

    A Play service account and an App Store Connect API key, once for every project on this machine (the desktop app's Accounts screen writes the same file; keys already in a project: npx storebound accounts import). Env vars work too. Never your password, never committed.

  4. Connect your agent, ask in plain words

    It runs dry runs first and walks you through console-only forms.

    Terminal
    $ npx storebound install --agent claude

    Or codex, cursor, copilot, gemini, windsurf, opencode (per tool). No agent? Every step is a CLI command too.

    • Set up my in-app products on both stores
    • Make store screenshots in 14 languages
    • What still blocks my submission?
  5. Zero blockers, then you submit

    A read-only check of both stores, in fix order.

    Terminal
    $ npx storebound validate
    1. Blockers, per store, in fix orderbuild, encryption, metadata, screenshots, review details, prices, products
    2. Fix, run again, until zeroread-only, so it is safe to run as often as you like
    3. You press Submit for reviewand Send changes for review on Play. Never the agent.

Built for

  • Indie developers

    One app or a handful: the store chores without a week of console tabs.

  • Studios shipping many titles

    One config per title, the same checks and store art pipeline every time.

  • Agencies

    Reviewable config in the client's repo. Their keys, their Submit.

FAQ

Questions, answered.

The short version. The docs have the long one, with every command and what each store allows through its API.

Do I need an AI agent?

No. Every step is a CLI command too (npx storebound --help), and the skills are Markdown checklists you can read yourself for the console-only forms. The agent integrations are optional.

Will it press Submit for me?

No, never. Submitting, releasing, completing a rollout and deleting are not MCP tools, and the terminal commands for them ask first. storebound gets you to zero blockers; you press Submit for review on the App Store and Send changes for review on Play.

Is it only for games?

No. --profile app (the default) and --profile subscription-app bring templates for utility and subscription apps: accounts, account deletion, demo accounts for review, subscriptions on both stores and a calm screenshot style. --profile game is for free-to-play games with ads and in-app purchases.

Where do my keys go? Is my store account safe?

In environment variables or .storebound/credentials.json, which init gitignores. storebound uses the official store APIs with keys you create and can revoke, never your password. Use an App Store Connect key with the App Manager role and a Play service account limited to your app. Every write is a dry run until you say yes.

My app is Unity, Godot, Flutter, React Native or native.

Fine. The store commands work on build numbers and listing files, not engines. Screenshots and clips come from a web build, the iOS Simulator, an Android emulator or device, or a folder of your own frames.

Does it cost anything? Any telemetry?

It is free and open source under the MIT license. No account, no sign-up, no telemetry: it only talks to the Google Play and App Store Connect APIs with your keys. You still need your own Play Console and Apple Developer accounts.

Can I use it for many apps?

Yes. Each app or game gets its own config in its own repo, so the same checks and store art pipeline run for every title. If you ship many similar apps, storebound originality --against <folders> compares one against the others offline (listing text, name, icon and screenshot perceptual hashes, project structure) for Apple's spam guideline (4.3) and Play's repetitive content policy, and exits with 1 on a near-duplicate. storebound scan --originality runs the same check as part of the scan, and the portfolio-originality skill walks your agent through the fixes.

Does it run on Windows or Linux?

It runs on Node 20+ (npx storebound) and on Bun 1.1+ (bunx storebound). The store commands are API calls. Capturing from the iOS Simulator needs a Mac with Xcode; a web build, an Android emulator or a folder of frames works anywhere. Icons, screenshots and video also need ffmpeg.