Developing iOS Apps
daymade/claude-code-skills
Builds and ships iOS/macOS apps with XcodeGen, SwiftUI and SPM: Xcode build fixes, device deployment, Apple Developer signing/notarization, CI/CD pipelines.
A skill your agent uses when the user wants to automate capture of marketing screenshots for a SwiftUI iOS app across multiple locales, devices, or appearances.
$ npx skills add ParthJadhav/ios-marketing-capture --skill ios-marketing-capture -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install ParthJadhav/ios-marketing-capture ios-marketing-capture --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
Claude Code skills documentation · loads skills from .claude/skills/
Install the "ios-marketing-capture" agent skill from https://github.com/ParthJadhav/ios-marketing-capture/tree/main into .claude/skills/ios-marketing-capture/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "ios-marketing-capture", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add ParthJadhav/ios-marketing-capture --skill ios-marketing-capture -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install ParthJadhav/ios-marketing-capture ios-marketing-capture --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "ios-marketing-capture" agent skill from https://github.com/ParthJadhav/ios-marketing-capture/tree/main into .agents/skills/ios-marketing-capture/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "ios-marketing-capture", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add ParthJadhav/ios-marketing-capture --skill ios-marketing-capture -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install ParthJadhav/ios-marketing-capture ios-marketing-capture --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "ios-marketing-capture" agent skill from https://github.com/ParthJadhav/ios-marketing-capture/tree/main into .cursor/skills/ios-marketing-capture/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "ios-marketing-capture", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add ParthJadhav/ios-marketing-capture --skill ios-marketing-capture -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install ParthJadhav/ios-marketing-capture ios-marketing-capture --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "ios-marketing-capture" agent skill from https://github.com/ParthJadhav/ios-marketing-capture/tree/main into .gemini/skills/ios-marketing-capture/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "ios-marketing-capture", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install ParthJadhav/ios-marketing-capture ios-marketing-captureInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add ParthJadhav/ios-marketing-capture --skill ios-marketing-capture -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "ios-marketing-capture" agent skill from https://github.com/ParthJadhav/ios-marketing-capture/tree/main into .github/skills/ios-marketing-capture/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "ios-marketing-capture", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add ParthJadhav/ios-marketing-capture --skill ios-marketing-capture -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install ParthJadhav/ios-marketing-capture ios-marketing-capture --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "ios-marketing-capture" agent skill from https://github.com/ParthJadhav/ios-marketing-capture/tree/main into .opencode/skills/ios-marketing-capture/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "ios-marketing-capture", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
ios-marketing-captureA skill your agent uses when the user wants to automate capture of marketing screenshots for a SwiftUI iOS app across multiple locales, devices, or appearances.
iOS Marketing Capture is an agent skill from ParthJadhav/ios-marketing-capture. Use when the user wants to automate capture of marketing screenshots for a SwiftUI iOS app across multiple locales, devices, or appearances. Covers full-screen shots, isolated element renders (carousel cards, widgets), and reproducible output naming. Triggers on marketing screenshots, locale screenshots, widget renders, App Store assets, fastlane-alternative, simctl screenshots.
Its SKILL.md is about 6.1k tokens, which your agent loads only when the skill is triggered. The skill folder holds 13 other files (for example `.github/FUNDING.yml`, `.github/ISSUE_TEMPLATE/bug_report.yml` and `.github/ISSUE_TEMPLATE/config.yml`).
It sits in Mobile, covering iOS development and App store release. It works with iOS, SwiftUI and Xcode. The repository describes itself as: Automate Multi-Locale asset creation for your iOS app. The licence is MIT.
12 steps, taken from the step headings in SKILL.md.
Read from SKILL.md and the folder at commit 5d78311. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
Shell commands in SKILL.md call:
xcodebuildpython3xcrunFrom the folder's file list and the shell code blocks in SKILL.md.
No URLs in SKILL.md.
From URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
iOS Marketing Capture loads about 6.1k tokens when it runs. Until then it costs about 101 tokens; SKILL.md has 2,326 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from ParthJadhav/ios-marketing-capture at commit 5d78311, republished under its MIT licence (© ParthJadhav). 2,326 words, ~6,074 tokens.
.claude/skills/ios-marketing-capture/SKILL.md (or your agent's skills folder). This skill also uses 10 other files; get the full folder from GitHub.Automate reproducible marketing screenshot capture for a SwiftUI iOS app across multiple locales, with two parallel output streams:
This skill is the capture step. If the user also wants Apple-style marketing pages composited around the shots (device mockups, headlines, gradients), combine with the app-store-screenshots skill as a post-processing step.
In-app capture mode, not XCUITest. This is a hard decision that trades off against Fastlane snapshot / XCUITest conventions, and it wins for almost every real project.
Why in-app over XCUITest:
xcodebuild test. The whole flow is xcodebuild build once, then simctl launch per locale. No test-bundle overhead.UIWindow.drawHierarchy directly. XCUITest can only tap and read accessibility elements.ImageRenderer on widget views or isolated components must run inside the app process — there's no XCUITest equivalent.How it works:
MarketingCapture.swift file lives in the main app target-MarketingCapture 1, the app seeds data, then a coordinator walks a list of CaptureSteps — each step navigates, waits for settle, snapshots, and cleans upDocuments/marketing/<locale>/ directory-AppleLanguages (xx) -AppleLocale xx, pulling files out via simctl get_app_containerWork through these steps in order. Do not skip ahead.
Ask the user these questions one at a time (do not batch them — each answer can invalidate later questions):
Localizable.xcstrings, (b) an App Store subset I'll specify, or (c) let me give you an explicit list." If (a), grep the .xcstrings file for locale codes:python3 -c "import json; d=json.load(open('<path>/Localizable.xcstrings')); langs=set(); [langs.update(v.get('localizations',{}).keys()) for v in d['strings'].values()]; print(sorted(langs))"xcrun simctl list devices available.Before writing any code, explore the codebase enough to answer:
PBXFileSystemSynchronizedRootGroup)? If yes, new files auto-include in their target — no pbxproj edits needed. Check with grep -c PBXFileSystemSynchronized <proj>.xcodeproj/project.pbxproj.TabView(selection:) — most common. You need: the @State selectedTab binding, tab indices, and which tabs have nested NavigationStack.NavigationStack (single stack with a router) — you need: the path binding or router object, plus the set of NavigationLink(value:) / .navigationDestination types.NavigationSplitView — you need: the sidebar selection binding, detail column's navigation state.navigate(to:) method or equivalent.onOpenURL handler and the enum/switch that maps URLs to navigation state.ModelContext. If no seeder exists, see "Creating a demo data seeder" below.cloudKitDatabase: .automatic)? If yes, flag as a known gotcha.static var priming mechanism (see "Priming view state" below).Before writing code, summarize your plan in this structure. Get explicit approval before proceeding:
Use the templates in templates/ as starting points. They are reference patterns, not copy-paste scaffolding — every project has different navigation, models, and views. The templates show the building blocks; you compose them for the target app.
Key files to produce:
<AppName>/Debug/MarketingCapture.swift — the whole capture system, DEBUG-only. Contains:MarketingCapture enum (launch arg parsing, output helpers, window snapshot, priming vars)MarketingCaptureCoordinator class (walks [CaptureStep] and snapshots each)MarketingElementHarness enum (ImageRenderer renders of cards, widgets, charts)<AppName>/ContentView.swift (or wherever the root view lives) — DEBUG hook that seeds data and runs the coordinator..onAppear hooks and .onReceive dismiss listeners.scripts/capture-marketing.sh — build + install + per-locale loop..gitignore — add marketing/.Do not hand the script to the user and wait. Run it yourself against a simulator and verify at least one locale before declaring done. Read the output PNGs with the Read tool to visually verify each screen shows what you expect. Common runtime issues are listed in "Known Gotchas" below.
When you find an issue, fix it, rerun the whole script (not just the failing locale — fixes can regress earlier locales), and re-verify visually.
The coordinator drives capture by walking a list of CaptureStep values. Each step is self-contained: it knows how to navigate to its screen, how long to wait, and how to clean up afterward.
struct CaptureStep {
let name: String // output filename, e.g. "01-home"
let navigate: @MainActor () -> Void // put the app in the right state
let settle: Duration // wait for animations/loads
let cleanup: (@MainActor () -> Void)? // tear down before next step
}The coordinator is a simple loop:
for step in steps {
step.navigate()
try? await Task.sleep(for: step.settle)
if let image = MarketingCapture.snapshotKeyWindow() {
MarketingCapture.writePNG(image, name: step.name)
}
step.cleanup?()
try? await Task.sleep(for: .milliseconds(400)) // cleanup animation
}TabView app (most common):
// Simple tab switch — just set the index
CaptureStep(name: "01-home", navigate: { setTab(0) }, settle: .milliseconds(1800), cleanup: nil)
// Tab + presented sheet
CaptureStep(
name: "05-timer-setup",
navigate: {
setTab(3)
pendingBrewRecipe = someRecipe
},
settle: .milliseconds(2000),
cleanup: {
NotificationCenter.default.post(name: MarketingCapture.dismissSheetNotification, object: nil)
pendingBrewRecipe = nil
}
)NavigationStack + router app:
// Push a route onto the stack
CaptureStep(
name: "02-detail",
navigate: { router.push(.itemDetail(item)) },
settle: .milliseconds(1800),
cleanup: { router.popToRoot() }
)NavigationSplitView app:
// Select sidebar item, then detail
CaptureStep(
name: "03-detail",
navigate: {
sidebarSelection = .recipes
detailSelection = recipes.first
},
settle: .milliseconds(1800),
cleanup: { detailSelection = nil }
)Capture any screen that needs a "clean" navigation state BEFORE screens that push onto the same stack. Nested NavigationPath / @State inside child views can't be popped from the coordinator. So:
Good: Shelf (clean list) → Coffee Detail (pushes onto shelf's stack)
Bad: Coffee Detail → Shelf (stack still has detail pushed)If two screens share a NavigationStack, capture the root-level view first.
Some screens need to be captured in a specific non-default state — a timer mid-countdown, a chart with particular values, a form half-filled. The pattern:
Add a static var to MarketingCapture for each priming value:
/// Set by the coordinator before presenting the timer view.
/// The view reads this in .onAppear to jump to a specific elapsed time.
static var pendingElapsedSeconds: Int?
/// Set to true to show the assessment overlay on the timer.
static var pendingShowAssessment: Bool = falseIn the target view, add a DEBUG-gated .onAppear that reads the priming value:
.onAppear {
#if DEBUG
if MarketingCapture.isActive, let elapsed = MarketingCapture.pendingElapsedSeconds {
phase = .active
timerVM.elapsedTime = TimeInterval(elapsed)
timerVM.start()
DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) { timerVM.pause() }
}
#endif
}In the coordinator, set the var before navigating:
CaptureStep(
name: "06-timer-midway",
navigate: {
MarketingCapture.pendingElapsedSeconds = 75
openTimerSheet(someRecipe)
},
settle: .milliseconds(2400),
cleanup: {
MarketingCapture.pendingElapsedSeconds = nil
NotificationCenter.default.post(name: MarketingCapture.dismissSheetNotification, object: nil)
}
)If the app has no existing demo data mechanism, create one. Place it in <AppName>/Debug/DemoDataSeeder.swift, wrapped in #if DEBUG.
Guidelines:
ModelContext. If Core Data, use the managed object context. If a REST backend, seed via the local cache/store layer.Minimal shape:
#if DEBUG
enum DemoDataSeeder {
static func seedIfEmpty(in context: ModelContext) {
let existing = (try? context.fetchCount(FetchDescriptor<Item>())) ?? 0
guard existing == 0 else { return }
// Items with varied states
let items = [
Item(name: "...", status: .active, ...),
Item(name: "...", status: .lowStock, ...),
// ...enough to fill every screen
]
items.forEach { context.insert($0) }
try? context.save()
}
}
#endifElements are rendered via ImageRenderer at 3x scale with transparency outside rounded corners.
@MainActor
static func renderCards(items: [Item], theme: AppTheme) {
let cardWidth: CGFloat = 380
for item in items {
let card = ItemCard(item: item, theme: theme)
.padding(.horizontal, 16)
.padding(.vertical, 12)
.frame(width: cardWidth)
.background(theme.background)
.clipShape(RoundedRectangle(cornerRadius: 20, style: .continuous))
let renderer = ImageRenderer(content: card)
renderer.scale = 3
renderer.isOpaque = false
renderer.proposedSize = .init(width: cardWidth, height: nil)
guard let image = renderer.uiImage else { continue }
MarketingCapture.writePNG(image, name: "card-\(slugify(item.name))", subfolder: "elements")
}
}Widget views require special handling because they normally run inside WidgetKit's process and rely on system-provided padding and backgrounds.
@MainActor
static func renderWidget(
name: String,
size: CGSize,
cornerRadius: CGFloat? = nil,
@ViewBuilder content: () -> some View
) {
let isAccessory = size.height <= 80
let radius = cornerRadius ?? (isAccessory ? 8 : 22)
let contentPadding: CGFloat = isAccessory ? 0 : 16
let view = content()
.padding(contentPadding)
.frame(width: size.width, height: size.height)
.background(theme.background)
.clipShape(RoundedRectangle(cornerRadius: radius, style: .continuous))
.environment(\.colorScheme, .light)
let renderer = ImageRenderer(content: view)
renderer.scale = 3
renderer.isOpaque = false
renderer.proposedSize = .init(width: size.width, height: size.height)
guard let image = renderer.uiImage else { return }
MarketingCapture.writePNG(image, name: name, subfolder: "elements")
}
// Standard iPhone widget sizes (points, iPhone 14-17 size class)
enum WidgetSize {
static let small = CGSize(width: 170, height: 170)
static let medium = CGSize(width: 364, height: 170)
static let large = CGSize(width: 364, height: 382)
static let accessoryCircular = CGSize(width: 76, height: 76)
static let accessoryRectangular = CGSize(width: 172, height: 76)
static let accessoryInline = CGSize(width: 257, height: 26)
}
// Usage:
renderWidget(name: "widget-pulse-small", size: WidgetSize.small) {
PulseSmallView(entry: PulseEntry(
date: Date(),
count: 2,
streak: 5,
lastItemName: "Morning Routine"
))
}Any SwiftUI view can be rendered as an element. Wrap it the same way — explicit size, background, corner clip:
@MainActor
static func renderChart() {
let chart = MyChartView(values: ChartData.sample)
.frame(width: 420, height: 420)
.background(theme.background)
.clipShape(RoundedRectangle(cornerRadius: 32, style: .continuous))
let renderer = ImageRenderer(content: chart)
renderer.scale = 3
renderer.isOpaque = false
renderer.proposedSize = .init(width: 420, height: 420)
guard let image = renderer.uiImage else { return }
MarketingCapture.writePNG(image, name: "chart-overview", subfolder: "elements")
}These are all real bugs that bit a real project. Treat this list as load-bearing.
ActivityKit Live Activities outlive process termination. If your app starts a Live Activity during capture (e.g. via a timer's start()), then the next locale's relaunch will inherit it. Combined with a fresh seed that deletes the models the stale LA references, you get SwiftData persisted-property assertions.
Fix: call <ActivityManager>.shared.endImmediately() at the very start of the marketing capture block, before touching data. Also call timerVM.stop() (or whatever properly ends the LA) in the view's onDisappear when in capture mode.
Seeding SwiftData + CloudKit per locale causes sync churn and crashes. The SwiftData store persists across relaunches — the data is locale-agnostic demo content, so seed once on the first run and skip subsequent runs:
contentVM.fetchItems()
if contentVM.allItems.isEmpty {
DemoDataSeeder.seedIfEmpty(in: modelContext)
contentVM.fetchItems()
}If the root view's onAppear calls someVM.setup(modelContext:) before the marketing seed runs, the VM holds a snapshot of the empty store. After seeding, call someVM.refresh() (or its equivalent fetch method) for every VM whose data you need.
If a parent view presents a .fullScreenCover(item: $request) and request is driven by an internal @State, then setting the trigger binding (e.g. pendingItem = nil) does nothing to the cover. The cover stays up, and your next screenshot captures it instead of the screen you navigated to.
Fix: broadcast a dismiss signal via NotificationCenter, and have the presented view listen:
// MarketingCapture.swift
static let dismissSheetNotification = Notification.Name("MarketingCapture.dismissSheet")
// In presented view body
.onReceive(NotificationCenter.default.publisher(for: MarketingCapture.dismissSheetNotification)) { _ in
dismiss()
}Then in the step's cleanup, post the notification and allow at least 900ms for the cover animation to complete before the next step begins.
If a child view holds @State private var navigationPath = NavigationPath() and a deep link pushes onto it, the coordinator can't reach in to pop. Solution: reorder your capture sequence so screens that push onto a stack come AFTER screens that need a clean stack. Example: capture Shelf first, then push into Coffee Detail — don't do it the other way around.
If the user's widget views are only in the widget extension target, you can't reference them from MarketingCapture.swift in the main app target. You need to either:
PBXFileSystemSynchronizedBuildFileExceptionSet.membershipExceptions. CRITICAL GOTCHA: membershipExceptions is an INCLUSION list, not an exclusion list. Files listed there ARE members of the target, not excluded from it. Read this twice before editing.You'll also need to exclude <App>WidgetBundle.swift from the main app target (it has @main and conflicts with the app's @main).
ImageRenderer + ProgressView(value:total:) = prohibited symbolWithout an explicit style, ProgressView determinate renders as a red circle-with-slash when composited through ImageRenderer. Fix: .progressViewStyle(.linear) on the ProgressView. It's a no-op in normal rendering and fixes the render glitch.
.containerBackground(for: .widget) is a no-op outside widget contextWhen you render a widget view via ImageRenderer in the app, its .containerBackground does nothing — the widget's background is transparent, and pixels outside the content are bare. You must wrap the widget render with an explicit background color + rounded rect clip:
content()
.padding(16) // widget container normally provides this
.frame(width: size.width, height: size.height)
.background(theme.background)
.clipShape(RoundedRectangle(cornerRadius: 22, style: .continuous))Home-screen widget corner radius on iPhone: ~22pt. Lock-screen accessory radius: ~8pt.
If the user asks for a "6.5" iPhone" (legacy App Store size), note that iOS 26+ simulators don't include iPhone 8 Plus / iPhone 11 Pro Max. Options: (a) install an older iOS runtime via Xcode > Settings > Platforms, or (b) fall back to a modern 6.1" like iPhone 17 for iOS 26 design features.
Pass -AppleLanguages (xx) -AppleLocale xx at every simctl launch. The parens around the language code are mandatory (it's a plist array literal). Use Locale.current.language.languageCode?.identifier for folder naming — it's more robust than Locale.current.identifier which may include region suffixes like en_US.
ImageRenderer captures a single frame — it doesn't wait for animations. If your component has an .onAppear animation (chart drawing, number counting up), the render may capture the initial state. Either disable the animation in capture mode or add an explicit delay before rendering:
try? await Task.sleep(for: .milliseconds(500)) // let onAppear animations finish
let renderer = ImageRenderer(content: view)marketing/
<locale>/ e.g. en, de, es, fr, ja
01-home.png
02-<screen>.png
...
NN-<screen>.png
elements/
card-<name>.png
widget-<family>-<size>.png
chart-<name>.pngPut marketing/ in .gitignore. These are outputs, not source.
Before declaring the capture pipeline done, verify:
en/settings.png and de/settings.png are byte-identical, locale switching didn't take effect)templates/MarketingCapture.swift.template — skeleton of the capture file with step-based coordinator. Reference the body of this skill for the patterns to apply.templates/capture-marketing.sh.template — skeleton of the shell script. Replace the bundle ID, scheme name, and simulator name for each project.© ParthJadhav, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
SKILL.md and 10 other files in the repository root of ParthJadhav/ios-marketing-capture.
Open the folder on GitHubat commit 5d78311
iOS Marketing Capture next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| iOS Marketing Capture this skillParthJadhav/ios-marketing-capture | 262 | — | ~6.1k | Automated safety check: Pass | MIT | |
| Developing iOS Appsdaymade/claude-code-skills | 1.4k | — | ~3.2k | Automated safety check: Pass | MIT | |
| iOS DevelopmentCoWork-OS/CoWork-OS | 477 | — | ~452 | Automated safety check: Pass | MIT | |
| Update Swiftui APIsAvdLee/SwiftUI-Agent-Skill | 3.7k | — | ~1.2k | Automated safety check: Pass | MIT | |
| OdevioOdevio/Odevio-CLI | 423 | — | ~7.6k | Automated safety check: Pass | MIT | |
| iOS App Store SubmitZestfulPulse/ios-app-store-submit | 142 | — | ~4.7k | Automated safety check: Pass | MIT |
daymade/claude-code-skills
Builds and ships iOS/macOS apps with XcodeGen, SwiftUI and SPM: Xcode build fixes, device deployment, Apple Developer signing/notarization, CI/CD pipelines.
CoWork-OS/CoWork-OS
iOS/Swift development: SwiftUI, UIKit, Core Data, Xcode builds, simulator management, code signing, and App Store submission.
AvdLee/SwiftUI-Agent-Skill
Scan Apple's SwiftUI documentation for deprecated APIs and update the SwiftUI Expert Skill with modern replacements.
Odevio/Odevio-CLI
Take a Flutter project to an iPhone or the App Store with Odevio - build, sign and publish iOS apps from Windows, Linux or macOS with no Mac and no Xcode.
ZestfulPulse/ios-app-store-submit
Build, sign, and submit a Flutter/iOS app to the App Store Connect — covers Xcode archive/export, code signing (including headless-Mac keychain workarounds), the asc CLI for App Store Connect…
Wholiver/swiftui-design-skill
Guides the agent to design distinctive SwiftUI interfaces for iOS and macOS, with six anti-generic rules, a design direction workflow and a five-dimension review.
Categories
A skill your agent uses when the user wants to automate capture of marketing screenshots for a SwiftUI iOS app across multiple locales, devices, or appearances. iOS Marketing Capture is an agent skill from ParthJadhav/ios-marketing-capture. Use when the user wants to automate capture of marketing screenshots for a SwiftUI iOS app across multiple locales, devices, or appearances.
iOS Marketing Capture fits situations like: the user wants to automate capture of marketing screenshots for a SwiftUI iOS app across multiple locales; marketing screenshots; locale screenshots; app Store assets.
Run `npx skills add ParthJadhav/ios-marketing-capture --skill ios-marketing-capture -a claude-code`. Or copy the skill folder (the ParthJadhav/ios-marketing-capture repository) into .claude/skills/ios-marketing-capture in your project. Claude Code loads it when a task matches its description.
Run `npx skills add ParthJadhav/ios-marketing-capture --skill ios-marketing-capture -a codex`. Or copy the skill folder (the ParthJadhav/ios-marketing-capture repository) into .agents/skills/ios-marketing-capture in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add ParthJadhav/ios-marketing-capture --skill ios-marketing-capture -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/ios-marketing-capture, .gemini/skills/ios-marketing-capture, .github/skills/ios-marketing-capture and .opencode/skills/ios-marketing-capture in your project.
Going by SKILL.md and its folder, iOS Marketing Capture needs the command-line tools its instructions call (xcodebuild, python3 and xcrun). Our summary lists: Python 3; A Bash shell.
SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
iOS Marketing Capture is published under the MIT licence (from the LICENSE file in the skill folder). It allows redistribution, so the full SKILL.md is shown on this page.
About 6.1k tokens (SKILL.md is roughly 24k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with iOS Marketing Capture: Developing iOS Apps (daymade/claude-code-skills, 1.4k stars), iOS Development (CoWork-OS/CoWork-OS, 477 stars), Update Swiftui APIs (AvdLee/SwiftUI-Agent-Skill, 3.7k stars) and Odevio (Odevio/Odevio-CLI, 423 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
ParthJadhav (a GitHub user) maintains it in ParthJadhav/ios-marketing-capture, which has 262 GitHub stars. The repository was last updated on September 5, 2026.
Source: ParthJadhav/ios-marketing-capture on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.