Skip to content
Launch offer: Mac Manager £9.99 first year

Shotlist guide

Shotlist user guide

What Shotlist does, what you need to run it, and the five steps from an Xcode project to screenshots in App Store Connect.

Shotlist user guide

Shotlist makes App Store screenshots a build step. You describe each screenshot as a scene in Swift. Shotlist builds your app, captures every scene on every device size, in every locale and appearance, in one run on simulators it manages itself. It then adds captions, draws the creative assets, checks everything against Apple’s rules and uploads the set to App Store Connect.

When you change the app, you run it again. Each run marks every screenshot as new, changed or unchanged against the last one, so you review only what moved.

This guide covers the command-line tool (shotlist), the Mac app and the in-app library (ShotlistKit). The CLI and the Mac app run the same engine and read the same project files, so you can switch between them freely.

What Shotlist does

Stage What happens Command
Set up Creates a Shotlist/ folder in your repo and a Screenshots.swift to start from. shotlist init
Check Confirms Xcode, simulator runtimes, disk space and iPhone Duo automation. shotlist doctor
Capture Builds the app once, then captures every scene on its own simulators. Waits on signals from inside your app rather than fixed delays. shotlist capture
Captions Shows which captions are written, drafted or missing, drafts translations, and records sign-off. shotlist captions
Compose Places captures on captioned canvases and draws the product page header and search results art. shotlist compose
Verify Checks sizes, transparency, counts, locales, captions and Apple’s content rules. shotlist verify
Publish Prints a plan of what would change in App Store Connect, then carries it out with --apply. shotlist publish

A few things set it apart from scripted screenshot tools:

  • Scenes are typed Swift. A scene is your app’s real root view or view controller, taken to one screen and filled with fixture data. There is no UI test target to maintain.
  • No sleeps. A scene is captured only when ShotlistKit reports that its preparation has finished, no request is in flight, no hold is open and two frames have passed with nothing new. The engine then captures until two consecutive frames match.
  • Repeatable output. Dates, time zone, hashing order, status bar and animations are pinned, so two runs of the same build give byte-identical files.
  • Every current size, including both displays of the iPhone Duo.
  • Any architecture. SwiftUI with @Observable, UIKit and the Composable Architecture (TCA) are all supported. TCA is never required.
  • Your simulators are left alone. Shotlist creates and uses its own, named Shotlist · <slot> · <runtime>.
  • It ends in App Store Connect, and never deletes a screenshot it didn’t upload unless you ask it to.

Requirements

You need Why
A Mac running macOS 26 or later The engine, the composer and the Mac app need it. The Mac app is for Apple silicon; the CLI is a universal binary, for Apple silicon and Intel.
Xcode 27 or later, selected with xcode-select Shotlist builds with xcodebuild and drives simulators with simctl. doctor fails on anything older.
iOS 27 simulator runtimes (Xcode › Settings › Components) Each slot needs a runtime that supports its device. With Xcode 27.1, the iPhone Duo runs on iOS 27.1 and every other device on iOS 27.0.
About 15 GB of free disk Each Shotlist simulator takes 2 to 6 GB. Each project’s build takes about 1 GB more.
An app that deploys to iOS 17 or later ShotlistKit, the library you add to your app, needs iOS 17.
An app that declares every locale you capture iOS falls back to another language for a locale the app doesn’t declare. See Setting up a project.
Someone at the Mac, screen unlocked, for the iPhone Duo’s inner display The Duo has to be unfolded through Device Hub, which can’t be reached while the screen is locked. Everything else runs unattended. See iPhone Duo.
A Shotlist subscription for capturing, composing and uploading Setting up, checking, verifying, captions and the read-only publish plan are free. See Subscription.
An App Store Connect team API key, to publish See App Store Connect.

The five steps

1. Install Shotlist and check the Mac

Download the Mac app, the CLI, or both from the Shotlist page, and activate your licence key. Then check the Mac:

shotlist doctor

See Installing Shotlist.

2. Set up the project and add ShotlistKit

In your app’s repo:

shotlist init --scenes-file MyApp/Screenshots.swift

Add the ShotlistKit package to your app and host the scenes in your app’s entry point: @Shot does it in one line, or host them yourself inside #if DEBUG. Release builds contain none of it. See Setting up a project.

3. Write scenes

A scene is your app’s real root, taken to one screen, showing fixture content:

SwiftUIScene("library") { context in
    RootView(router: Router(tab: .library), clock: .fixed(context.now))
        .modelContainer(try container(context))
}

List the scene ids in sequence in Shotlist/shotlist.json, in the order they should appear on the product page. See Writing scenes, Readiness and fixtures and Making runs identical.

4. Capture

shotlist capture

Raw captures land in Shotlist/Output/raw/<locale>/<slot>/NN-<scene>-<appearance>.png, with a manifest and a run log beside them. See Capturing.

5. Compose, verify and publish

shotlist captions status
shotlist compose
shotlist verify
shotlist publish
shotlist publish --apply

publish on its own prints the plan and changes nothing. --apply carries it out. See Captions and composing, Verifying output and App Store Connect.

Where things live

Everything Shotlist needs sits in your app’s repo as plain files, so a release’s screenshots can be reviewed in the same pull request as the code that changed them.

MyApp/                         the folder that holds your Xcode project
  MyApp.xcodeproj
  MyApp/Screenshots.swift      your scenes, in the app target, inside #if DEBUG
  Shotlist/
    shotlist.json              app, slots, locales, appearances, sequence
    Captions.xcstrings         a caption and subtitle per scene, per locale
    Fixtures/                  HTTP fixtures: shared/ and <locale>/
    Templates/                 your own templates and background images
    published.json             what Shotlist has put live in App Store Connect
    .gitignore                 leaves out Output/
    Output/                    not committed
      raw/<locale>/<slot>/NN-<scene>-<appearance>.png
      previous/raw/…           the last run's captures, for before and after
      composed/<locale>/<slot>-NN.png
      creative/<locale>/header.png, search.png, …
      manifest.json
      run.log
  .shotlist/                   builds and scratch files; ignores itself

The rest of this guide

Page Read it when
Installing Shotlist You’re installing the app or the CLI, or activating a licence.
Setting up a project You’re adding Shotlist to an app for the first time.
Writing scenes You’re deciding how to reach each screen.
Readiness and fixtures Your app loads data, images or anything asynchronous.
Making runs identical Screenshots change between runs when the app hasn’t.
Configuration You need the exact meaning of a shotlist.json key, or the slot sizes.
Capturing You want to know what a run does, or recover from a failure.
iPhone Duo You capture either Duo display.
Captions and composing You’re writing captions, translating them, or changing templates.
Verifying output You want to know what verify checks.
App Store Connect You’re uploading.
The Mac app You prefer a window to a terminal.
CI and automation You run Shotlist from a script, CI or an agent.
Subscription You want to know what’s free, what’s paid and how licences work.
Troubleshooting Something failed and the message names it.
FAQ You have a quick question.