rorshopping/shipside

Ship iOS apps to App Store Connect from the command line - your key, your machine, the last mile automated.

Python

0

5 commits

updated Oct 1, 2026

See the code

See what people are saying

SourceMessageScoreDate

I turned my iOS submission pipeline into a product: Shipside — ship apps to App Store Connect from the CLI (r/SideProject)

Last month I submitted five iOS apps to App Review in a single day. The trick: everything after the build is API-driven. I've now packaged that pipeline as **Shipside** — a CLI that ships iOS apps to App Store Connect from the terminal. What it does: - `shipside state` — full ASC status report…

0

Oct 1, 2026

README

Shipside

Ship iOS apps to App Store Connect from the command line — metadata, screenshots, and the actual submission, driven by the ASC REST API with your own key, on your own machine.

Not a build tool. Shipside picks up where the archive ends: it creates the version, pushes the listing, uploads screenshots, wires the age rating and review contact, attaches the build, opens the review submission — and submits. Then it tells you exactly what Apple's API refused to do and how to fix it in two clicks.

pipx install git+https://github.com/rorshopping/shipside
# or: uv tool install git+https://github.com/rorshopping/shipside

cd your-app            # folder with your project
shipside init          # 10 questions -> shipside.toml (your ASC key id/issuer/.p8 path)
shipside state         # what does ASC actually say right now?
shipside plan          # dry-run the submission: every blocker, nothing written
shipside screenshots ./shots-67
shipside metadata      # fastlane-deliver-compatible metadata/<locale>/*.txt
shipside submit --yes  # fixes the fixables, submits for review

Why

In one day — 2026-09-30 — this pipeline shipped five apps to App Review end-to-end: Adhera, Pushup Alarm, REM Sleep Alarm, InCase and RenewalRadar. That day hit every wall App Store Connect has: the 405 version-creation deadlock, an INVALID_BINARY mid-flight, the age-rating questionnaire, the 640×920 subscription screenshot trap. The full story and every playbook are in this repo and encoded in the CLI: when an API call fails in a known way, Shipside prints the exact recovery steps instead of a stack trace.

What it does

CommandWhat happensWrites?
shipside initConfig wizard: bundle id, team key id/issuer/.p8 path, review contact → shipside.tomllocal file
shipside doctorSigns a JWT, checks team + app accessno
shipside stateFull report: versions, builds, screenshots, IAPs, review submissions + next actionno
shipside planThe submission dry-run: every step marked ok / fix / blockedno
shipside metadataPushes listing text (deliver-compatible folders) into the editable version, with Apple's char limits enforcedyes
shipside screenshotsUploads PNGs (1320×2868 / 1290×2796) into the 6.7" set — including the APP_IPHONE_69-is-not-an-enum trapyes
shipside submit --yesCreates the version if needed, sets age rating + review details + content rights, attaches the newest VALID build, opens the review submission, submitsirreversible
shipside trial / license14-day free trial, then license activationlocal

Hard-won defaults

  • Retry with a spine: 429/5xx back off with Retry-After respect; a 409 on a retried write means the first write landed — treated as success.
  • Version creation: two API routes are tried; on the 405 deadlock you get the exact web click-path, not silence.
  • Age rating is scriptable: the questionnaire PATCH is iterated field-by-field until Apple accepts it (this surprises people; it shouldn't).
  • whatsNew is locked on first versions: detected, never fatal, playbook printed.
  • INVALID_BINARY: the build is the only thing that dies — Shipside re-attaches the next VALID build instead of recreating your version.
  • Your secrets stay yours: the .p8 is referenced by path, never copied, never uploaded. Shipside's own servers never see your ASC credentials.

License

14-day free trial with every feature, no card. Then $19/month or $149/year per developer — launch code SHIPDAY takes 40% off your first year. Activate with the email you bought with:

shipside trial --email you@example.com
shipside license activate --email you@example.com

The license check is online with a 14-day offline grace window — airport-friendly.

Requirements

  • Python 3.9+ (macOS, Linux, Windows — the ASC API is plain REST over HTTPS)
  • An App Store Connect API key (App Manager role or higher): Users and Access → Integrations
  • Builds are still your job (Xcode / altool / Transporter) — Shipside takes it from there and prints the exact altool command when no VALID build exists.

Status

v0.1, dogfooded in anger. See docs/PLAYBOOKS.md for the failure catalog and docs/LAUNCH_STORY.md for the day this was battle-tested.

MIT licensed. Not affiliated with Apple. App Store Connect is a trademark of Apple Inc.

rorshopping/shipside

Ship iOS apps to App Store Connect from the command line - your key, your machine, the last mile automated.

Python

0

5 commits

updated Oct 1, 2026

See the code

See what people are saying

SourceMessageScoreDate

I turned my iOS submission pipeline into a product: Shipside — ship apps to App Store Connect from the CLI (r/SideProject)

Last month I submitted five iOS apps to App Review in a single day. The trick: everything after the build is API-driven. I've now packaged that pipeline as **Shipside** — a CLI that ships iOS apps to App Store Connect from the terminal. What it does: - `shipside state` — full ASC status report…

0

Oct 1, 2026

README

Shipside

Ship iOS apps to App Store Connect from the command line — metadata, screenshots, and the actual submission, driven by the ASC REST API with your own key, on your own machine.

Not a build tool. Shipside picks up where the archive ends: it creates the version, pushes the listing, uploads screenshots, wires the age rating and review contact, attaches the build, opens the review submission — and submits. Then it tells you exactly what Apple's API refused to do and how to fix it in two clicks.

pipx install git+https://github.com/rorshopping/shipside
# or: uv tool install git+https://github.com/rorshopping/shipside

cd your-app            # folder with your project
shipside init          # 10 questions -> shipside.toml (your ASC key id/issuer/.p8 path)
shipside state         # what does ASC actually say right now?
shipside plan          # dry-run the submission: every blocker, nothing written
shipside screenshots ./shots-67
shipside metadata      # fastlane-deliver-compatible metadata/<locale>/*.txt
shipside submit --yes  # fixes the fixables, submits for review

Why

In one day — 2026-09-30 — this pipeline shipped five apps to App Review end-to-end: Adhera, Pushup Alarm, REM Sleep Alarm, InCase and RenewalRadar. That day hit every wall App Store Connect has: the 405 version-creation deadlock, an INVALID_BINARY mid-flight, the age-rating questionnaire, the 640×920 subscription screenshot trap. The full story and every playbook are in this repo and encoded in the CLI: when an API call fails in a known way, Shipside prints the exact recovery steps instead of a stack trace.

What it does

CommandWhat happensWrites?
shipside initConfig wizard: bundle id, team key id/issuer/.p8 path, review contact → shipside.tomllocal file
shipside doctorSigns a JWT, checks team + app accessno
shipside stateFull report: versions, builds, screenshots, IAPs, review submissions + next actionno
shipside planThe submission dry-run: every step marked ok / fix / blockedno
shipside metadataPushes listing text (deliver-compatible folders) into the editable version, with Apple's char limits enforcedyes
shipside screenshotsUploads PNGs (1320×2868 / 1290×2796) into the 6.7" set — including the APP_IPHONE_69-is-not-an-enum trapyes
shipside submit --yesCreates the version if needed, sets age rating + review details + content rights, attaches the newest VALID build, opens the review submission, submitsirreversible
shipside trial / license14-day free trial, then license activationlocal

Hard-won defaults

  • Retry with a spine: 429/5xx back off with Retry-After respect; a 409 on a retried write means the first write landed — treated as success.
  • Version creation: two API routes are tried; on the 405 deadlock you get the exact web click-path, not silence.
  • Age rating is scriptable: the questionnaire PATCH is iterated field-by-field until Apple accepts it (this surprises people; it shouldn't).
  • whatsNew is locked on first versions: detected, never fatal, playbook printed.
  • INVALID_BINARY: the build is the only thing that dies — Shipside re-attaches the next VALID build instead of recreating your version.
  • Your secrets stay yours: the .p8 is referenced by path, never copied, never uploaded. Shipside's own servers never see your ASC credentials.

License

14-day free trial with every feature, no card. Then $19/month or $149/year per developer — launch code SHIPDAY takes 40% off your first year. Activate with the email you bought with:

shipside trial --email you@example.com
shipside license activate --email you@example.com

The license check is online with a 14-day offline grace window — airport-friendly.

Requirements

  • Python 3.9+ (macOS, Linux, Windows — the ASC API is plain REST over HTTPS)
  • An App Store Connect API key (App Manager role or higher): Users and Access → Integrations
  • Builds are still your job (Xcode / altool / Transporter) — Shipside takes it from there and prints the exact altool command when no VALID build exists.

Status

v0.1, dogfooded in anger. See docs/PLAYBOOKS.md for the failure catalog and docs/LAUNCH_STORY.md for the day this was battle-tested.

MIT licensed. Not affiliated with Apple. App Store Connect is a trademark of Apple Inc.

Languages

Python

86.9%

HTML

13.1%