Shotkit
End-to-end App Store screenshot pipeline for indie iOS developers. From raw Simulator capture to upload-ready assets, with native App Store Connect integration.
This skill is fully automated. When triggered, the agent handles the entire pipeline — booting simulators, capturing screenshots, compositing with trending styles, and uploading to App Store Connect — without requiring manual interaction.
What This Skill Does
Stage 1 — Auto-Capture (optional): Boots Xcode Simulator devices, launches the app via bundle ID, navigates screens via deep links, sets a clean status bar (9:41, full battery), and captures raw UI screenshots — all without user interaction.
Stage 2 — Generate Copy: Produces locale-aware headlines (max 30 chars) + sublines (max 60 chars) for each screenshot frame. If no copy.json is provided, the agent generates one based on the app's features and target audience.
Stage 3 — Composite: Renders styled screenshot images using Pillow — background, device UI area, app screenshot, and text overlay — with 5 template styles.
Stage 4 — Organize & Validate: Outputs an ASC-ready folder structure ({locale}/{device}/), validates dimensions against App Store requirements, and generates an upload checklist.
Stage 5 — Upload (optional): Uploads screenshots directly to App Store Connect via native API integration. Supports uploading new screenshots and replacing existing ones.
Workflow
Step 1 — Collect Inputs
Ask the developer for the following (or infer from context if already provided):
Required:
- App name
- Core features to highlight (3–8 bullet points)
- Target audience (one sentence)
- Primary language (default: English)
- Additional locales (optional, e.g. Italian, German, Japanese)
Screenshot source (choose one):
- A) Automated capture from Simulator → ask for app Bundle ID and deep link URLs per screen
- B) Existing screenshots folder → ask for path to folder of PNG/JPG files
- C) No UI screenshots yet → generate placeholder-based composites with colored UI mockups
If the developer chooses option A, also ask:
- Deep link URL scheme (e.g.
myapp://) and paths for each screen to capture - Which Simulator devices to boot (default: iPhone 16 Pro Max)
- If no deep links are available, the agent will capture the app's launch screen only
Template style (choose one, or generate previews for all):
minimal— white/light background, small device frame, centered text, clean typographybold— full-bleed gradient background, large text, high contrast, punchydark— dark/black background, device glow effect, premium feeleditorial— magazine-style layout, split composition, text beside deviceflat— no device frame, full-bleed app UI with text overlay bar at bottom
Device targets (default: iPhone 6.9" + iPad 13"):
- iPhone 6.9" — 1320 × 2868 px (mandatory as of 2025)
- iPhone 6.7" — 1290 × 2796 px (legacy, still widely used)
- iPhone 6.5" — 1242 × 2688 px
- iPad 13" — 2064 × 2752 px (mandatory if app supports iPad)
- iPad 12.9" — 2048 × 2732 px
Read
references/device_specs.mdfor the full device dimensions table.
Step 2 — Install Dependencies and Run Doctor
Run the dependency installer:
shotkit install-deps
By default this creates an isolated virtualenv at ~/.shotkit/venv and installs Pillow, PyJWT, and cryptography there. The shotkit CLI auto-detects the venv, so the user's system Python is left untouched. Set SHOTKIT_LEGACY_INSTALL=1 before running to fall back to installing into system Python.
Then run the environment check:
shotkit doctor
shotkit doctor verifies Python, the required packages, xcrun, whether a Simulator is booted, and (if present) the .shotkit.json config plus the .p8 private key path. It exits non-zero only when a required check fails; missing optional pieces (booted simulator, ASC config) are surfaced but don't fail the run.
Step 3 — Capture Screenshots (Automated)
Option A — Fully automated capture with deep links:
bash skills/shotkit/scripts/auto_capture.sh \
--bundle-id com.yourapp.bundleid \
--devices "iPhone 16 Pro Max,iPad Pro 13-inch (M4)" \
--screens "home,detail,settings,profile,onboarding" \
--deeplinks "myapp://home,myapp://detail/1,myapp://settings,myapp://profile,myapp://onboarding" \
--output ./raw-captures
Option A (with config file):
Create a capture_config.json:
{
"bundle_id": "com.yourapp.bundleid",
"devices": ["iPhone 16 Pro Max", "iPad Pro 13-inch (M4)"],
"screens": [
{"name": "home", "deeplink": "myapp://home"},
{"name": "detail", "deeplink": "myapp://detail/1"},
{"name": "settings", "deeplink": "myapp://settings"},
{"name": "profile", "deeplink": "myapp://profile"},
{"name": "onboarding", "deeplink": "myapp://onboarding"}
]
}
Then run:
bash skills/shotkit/scripts/auto_capture.sh --config capture_config.json --output ./raw-captures
The auto-capture script will:
- Boot each Simulator device automatically
- Set a clean status bar (9:41, full battery, full signal)
- Launch the app
- Navigate to each screen via deep link
- Wait for the screen to settle, then capture
- Save organized by device subfolder
- Shut down each device when done
Option B — Interactive capture (fallback):
bash skills/shotkit/scripts/capture_simulator.sh com.yourapp.bundleid ./raw-captures
This is the legacy interactive mode where the developer navigates manually and presses ENTER to capture.
Option C — Existing screenshots:
Skip this step. Point --captures at the existing folder in Step 4.
Step 4 — Generate Copy (if needed)
If the developer has not provided a copy.json, generate one based on the app's features and target audience. Follow the format in references/copy_example.json:
{
"en-US": {
"screenshots": [
{"headline": "Max 30 chars", "subline": "Max 60 chars for the subline text", "scene": "Screen name"}
]
}
}
Rules:
- Headlines: max 30 characters, action-oriented
- Sublines: max 60 characters, benefit-focused
- Adapt tone per locale (formal for de/ja, casual for en-US)
- One entry per screenshot, matched by index to the capture files
- Add
"review": trueon any entry that makes a subjective, superlative, or legal-sensitive claim ("best", "fastest", "certified", pricing, medical, financial).generateprints these on stderr and includes them in the run report so they can't ship unnoticed.
When generate runs, it also warns on stderr for any headline or subline that overflows the 30- / 60-character budget in a given locale (translations often blow past English lengths); these overflow warnings are recorded in the run report.
Save as copy.json in the project root or a path the developer specifies.
Step 5 — Composite Screenshots
Run the compositing engine:
python3 skills/shotkit/scripts/generate_screenshots.py \
--app-name "YourApp" \
--captures ./raw-captures \
--copy ./copy.json \
--template bold \
--devices iphone-6.9 ipad-13 \
--locales en-US it \
--output ./screenshots-output
This will:
- Load raw captures from the captures directory
- Load copy data for each locale
- Render each screenshot through the chosen template
- Resize and position the UI within the device-specific canvas
- Add text overlays (headline + subline)
- Save as PNG in the ASC-ready folder structure:
{output}/{locale}/{device}/01_screen.png
Available templates: minimal, bold, dark, editorial, flat, trending
Read
references/template_guide.mdfor detailed template descriptions and customization.
Trending template (recommended):
shotkit generate --app-name "YourApp" --captures ./raw --template trending --icon ./icon.png
shotkit generate --app-name "YourApp" --captures ./raw --template trending --palette aurora
shotkit generate --app-name "YourApp" --captures ./raw --template trending --brand-color "#1E90FF"
The trending template uses curated color palettes and layouts based on top-charting App Store apps. It can also auto-extract brand colors from your app icon. Run shotkit palettes to see all available palettes.
Step 6 — Validate Output
shotkit validate --dir ./screenshots-output
Or emit a machine-readable report:
shotkit validate --dir ./screenshots-output --json # to stdout
shotkit validate --dir ./screenshots-output --report ./run.json # to a file
Checks:
- Recognised device folder keys (see
references/device_specs.md) - Portrait or landscape dimensions match the current Apple spec (marked by
spec_versionin the report) - Files are readable, and PNG/JPEG magic bytes match the extension
- No PNG carries an alpha channel (App Store Connect rejects those on upload)
- No empty per-device folders, and no folder over the 10-image limit
- Generates a pass/fail summary; magic-byte and alpha-channel checks are warnings in v2.2 and are scheduled to become errors in v2.3.
Step 7 — App Store Connect Integration
First-time setup:
shotkit init
This connects to App Store Connect, verifies credentials, and saves config to .shotkit.json.
Download existing screenshots (backup):
shotkit download --output ./backup
Upload new screenshots:
shotkit upload --dir ./screenshots-output
Replace existing screenshots:
shotkit update --dir ./screenshots-output
The upload command validates screenshots automatically before uploading.
Read
references/app_store_connect.mdfor full ASC integration details.
Full Pipeline (One Command)
shotkit screenshots \
--bundle-id com.yourapp.id \
--app-name "YourApp" \
--template trending \
--icon ./icon.png \
--deeplinks "myapp://home,myapp://detail,myapp://settings" \
--screens "home,detail,settings" \
--devices iphone-6.9 \
--locales en-US \
--report ./run.json
This runs capture + generate + validate in sequence. Pass --report FILE to write a JSON summary at the end — same schema as shotkit validate --json, useful for CI or for stashing an audit trail per release.
Automation Best Practices
Deep Link Setup
For fully automated capture, the app must support URL schemes or Universal Links. Common patterns:
myapp://home— main screenmyapp://feature/detail?id=1— specific contentmyapp://settings— settings screenmyapp://onboarding— onboarding flow
Add URL schemes in Xcode: Target → Info → URL Types.
Demo Data
For best results, ensure the app has realistic demo data loaded before capture. Options:
- Use a debug build with seeded data
- Set up a launch argument (e.g.
--demo-mode) that loads sample content - Use
xcrun simctlto push notifications or set defaults before capture
Multi-Device Workflow
The automated capture handles multiple devices sequentially — it boots each device, captures all screens, then shuts it down before moving to the next. This keeps resource usage low.
Status Bar
The auto-capture script automatically sets the status bar to the Apple-standard "marketing" look: 9:41 AM, full battery, full signal, no carrier name. Use --no-clean-status to skip this.