apple-dev
Apple development guidelines for Swift packages (SPM), Xcode projects, Swift Testing framework, and The Composable Architecture (TCA). Load this skill whenever working in an Xcode project (xcodeproj/xcworkspace), a Swift package (Package.swift), writing or fixing Swift tests (Swift Testing, @Test, @Suite,
Best use case
apple-dev is best used when you need a repeatable AI agent workflow instead of a one-off prompt.
Apple development guidelines for Swift packages (SPM), Xcode projects, Swift Testing framework, and The Composable Architecture (TCA). Load this skill whenever working in an Xcode project (xcodeproj/xcworkspace), a Swift package (Package.swift), writing or fixing Swift tests (Swift Testing, @Test, @Suite,
Teams using apple-dev should expect a more consistent output, faster repeated execution, less prompt rewriting.
When to use this skill
- You want a reusable workflow that can be run more than once with consistent structure.
When not to use this skill
- You only need a quick one-off answer and do not need a reusable workflow.
- You cannot install or maintain the underlying files, dependencies, or repository context.
Installation
Claude Code / Cursor / Codex
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/apple-dev/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How apple-dev Compares
| Feature / Agent | apple-dev | Standard Approach |
|---|---|---|
| Platform Support | Not specified | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/A |
Frequently Asked Questions
What does this skill do?
Apple development guidelines for Swift packages (SPM), Xcode projects, Swift Testing framework, and The Composable Architecture (TCA). Load this skill whenever working in an Xcode project (xcodeproj/xcworkspace), a Swift package (Package.swift), writing or fixing Swift tests (Swift Testing, @Test, @Suite,
Where can I find the source code?
You can find the source code on GitHub using the link provided at the top of the page.
Related Guides
SKILL.md Source
## Coding Guidelines
- Use red/green TDD.
- Use the `xcode` MCP if available, otherwise see below.
- Don't be over-defensive:
- Embrance optional chaining (`foo?.bar`).
- Don't provide for fallbacks for properties that are optional. For example: `NSMenuItem.image` is optional, so when assigning, don't do `= NSImage("hello") ?? .init()`.
## Testing Guidelines
- Use the Swift Testing framework exclusively (not XCTest).
- Every test must be `async throws`.
- All test suites must be marked with the `@Suite` attribute
- Never test standard protocols such as `Hashable` and `Equatable` (e.g. test `hashValue` and `==`, respectively), unless explicitly ordered so.
- When assertion equatable types, never assert properties individually. Simply use `==`. For example, if you're comparing two `Person` struct, don't `personA.name == personB.name` and then `personA.age == personB.age`. Simply do `personA == personB`.
- When using `Task` in tests to kick-off asynchronous actions:
- Never assign the `Task` to a let/var and never `await` the `Task`. Simply use a `try await Task.sleep(for:)` before the final assertion.
- The argument for the `.sleep` function should be extract to a shared constant.
- Avoid `try!`. Use `try` instead.
- Avoid `as!` and constructs such as `guard let a = foo? as String else { Issue.record(); return }` .Use `try #require(x)` instead.
- When testing initializers, use the full declaration in the test's name, e.g. `@Test func `init(name:age:)``.
### Naming Suites and Tests
- Every test function should have a nice, human-readable name, using Swift 6.2's raw identifier syntax, and in the following scheme: Use the naming scheme ``systemUnderTest, [with optional condition/argument], should <expected result>``. For example: `@Test func `processRequest, with AppElement throwing, should throw`() { ... }`.
- Every test suite should have a nice, human-readable name, using Swift 6.2's' raw identifier syntax (e.g. `@Suite struct `TableView Tests``).
- For both test suite and functions, the `systemUnderTest` part should retain its original casing (like camelCase, e.g. `processRequest, should...` or `PROCESS_REQUEST, should...`).
- Never provide the `displayName` argument to `@Test(_ displayName: String? = nil, _ traits: any TestTrait...)`.
- Never provide the `displayName` argument to `@Suite(_ displayName: String? = nil, _ traits: any SuiteTrait...)`.
### See Also
- See [implementing-parameterized-tests.md](references/implementing-parameterized-tests.md) for implementing parameterized tests.
- See [migrating-a-test-from-xctest.md](references/migrating-a-test-from-xctest.md) for migrating from the old XCTest framework.
---
## Project Type Detection
- **Swift Package** — `Package.swift` exists in the project root (no `xcodeproj`/`xcworkspace`).
- **Xcode Project** — `*.xcodeproj` or `*.xcworkspace` file exists in the project root.
Both types may coexist (e.g., a workspace containing local packages). Apply the appropriate
build/test section below based on what you're working in.
---
## Swift Package (SPM)
### Build
Run: `swift build -q >/dev/null 2>&1 | grep ': error:'`.
If the script ended with a zero exit code, the build succeeded.
### Build for Testing
Like "Build", but pass `--build-tests` too.
### Test
Run: `swift test -q >/dev/null 2>&1 | grep -E ' failed | recorded an issue '`.
If the script ended with a zero exit code, testing succeeded. Otherwise, fix any failing tests.
---
## Xcode Project
- Scheme name is this project's name, unless specified otherwise by a parameter to this command.
- If the prompt revolves around a code change inside a specific scheme, (like a LOCAL package dependency, or target) contained in the project, build and test just the scheme to save build times and keep the focus on the problem your were tasked with. FOR EXAMPLE: if I ask to "fix build errors" in a file called "RunningAppService.swift" that is a part of a local package named "RunningAppService", use `RunningAppService` as the scheme.
- If the above command fails with e.g. `xcodebuild: error: Scheme RunningAppService is not currently configured for the test action.`, stop, and ask for my attention and further steps.
### Build
Builds the project, WITHOUT test targets.
- Run `./scripts/xcodebuild.sh build --scheme=SCHEME_NAME`.
- Fix any errors, don't address warnings unless told otherwise.
### Build for Testing
Builds the project, WITH test targets.
- Run `./scripts/xcodebuild.sh build-tests --scheme=SCHEME_NAME`.
- Fix any errors, don't address warnings unless told otherwise.
### Test
Run tests for the project.
- If `only` is provided as a parameter to this command:
- Wrap the specifier in single quotes.
- Multiple test may be provided.
- Run `./scripts/xcodebuild.sh run-tests --scheme=SCHEME_NAME --only='TEST_SPECIFIER' [--only="TEST_SPECIFIER2"...]` and fix failing tests.
- If the test isn't found, run `./scripts/xcodebuild.sh list-tests` and find the correct test identifier. Then, pass the test identifier AS-IS, including backticks and parentheses (this is valid Swift 6.2 syntax). For example: ``MyApp Tests`/`Feature Tests`/`function Tests()``.
- If the specific test to run hasn't been provided, require it.
- Otherwise, run `./scripts/xcodebuild.sh run-tests --scheme=SCHEME_NAME`
- Fix failing tests.
- For each run of this command, run the script ONCE. Running the tests takes time.
- Generate a list of TODOs, where each TODO represents a failing test.
- Save to context each test's output, for reference, saving you from running the tests repeatedly.
- Fix all tests, and only THEN run the script again.
- DON'T RUN TESTS IN BETWEEN TODOs. ONLY AFTER YOU CONSIDER ALL TODOs TO BE DONE.
- DO NOT USE `grep`, `head` or `tail` (etc.) to manipulate the scripts's output. The script is already designed to provide concise, context-efficient output.
- If the build is failing, fix build errors, then run the tests.
---
## The Composable Architecture (TCA)
- Use the testing tools provided by the library to test features.
- **Never** use `store.skipReceivedActions()` unless explicitly told to.
- **Never** use `store.exhaustivity = .off` unless explicitly told to.
- When overriding dependencies in tests, pay extra attention to the dependency endpoints' signatures and how they should be overridden - simply look in the call sites in the production code. For example, if you're overriding a `var fetch: (_ id: String) -> Bool` endpoint, then obviously the override would be `.fetch = { _ in false }`. Otherwise, compilation will break and the compiler will emit cryptic messages that won't help you here.
---
The following are additions from [twostraws/SwiftAgents](https://github.com/twostraws/SwiftAgents):
## Swift instructions
- Always mark `@Observable` classes with `@MainActor`.
- Assume strict Swift concurrency rules are being applied.
- Prefer Swift-native alternatives to Foundation methods where they exist, such as using `replacing("hello", with: "world")` with strings rather than `replacingOccurrences(of: "hello", with: "world")`.
- Prefer modern Foundation API, for example `URL.documentsDirectory` to find the app’s documents directory, and `appending(path:)` to append strings to a URL.
- Never use C-style number formatting such as `Text(String(format: "%.2f", abs(myNumber)))`; always use `Text(abs(change), format: .number.precision(.fractionLength(2)))` instead.
- Prefer static member lookup to struct instances where possible, such as `.circle` rather than `Circle()`, and `.borderedProminent` rather than `BorderedProminentButtonStyle()`.
- Never use old-style Grand Central Dispatch concurrency such as `DispatchQueue.main.async()`. If behavior like this is needed, always use modern Swift concurrency.
- Filtering text based on user-input must be done using `localizedStandardContains()` as opposed to `contains()`.
- Avoid force unwraps and force `try` unless it is unrecoverable.
## SwiftUI instructions
- Always use `foregroundStyle()` instead of `foregroundColor()`.
- Always use `clipShape(.rect(cornerRadius:))` instead of `cornerRadius()`.
- Always use the `Tab` API instead of `tabItem()`.
- Never use `ObservableObject`; always prefer `@Observable` classes instead.
- Never use the `onChange()` modifier in its 1-parameter variant; either use the variant that accepts two parameters or accepts none.
- Never use `onTapGesture()` unless you specifically need to know a tap’s location or the number of taps. All other usages should use `Button`.
- Never use `Task.sleep(nanoseconds:)`; always use `Task.sleep(for:)` instead.
- Never use `UIScreen.main.bounds` to read the size of the available space.
- Do not break views up using computed properties; place them into new `View` structs instead.
- Do not force specific font sizes; prefer using Dynamic Type instead.
- Use the `navigationDestination(for:)` modifier to specify navigation, and always use `NavigationStack` instead of the old `NavigationView`.
- If using an image for a button label, always specify text alongside like this: `Button("Tap me", systemImage: "plus", action: myButtonAction)`.
- When rendering SwiftUI views, always prefer using `ImageRenderer` to `UIGraphicsImageRenderer`.
- Don’t apply the `fontWeight()` modifier unless there is good reason. If you want to make some text bold, always use `bold()` instead of `fontWeight(.bold)`.
- Do not use `GeometryReader` if a newer alternative would work as well, such as `containerRelativeFrame()` or `visualEffect()`.
- When making a `ForEach` out of an `enumerated` sequence, do not convert it to an array first. So, prefer `ForEach(x.enumerated(), id: \.element.id)` instead of `ForEach(Array(x.enumerated()), id: \.element.id)`.
- When hiding scroll view indicators, use the `.scrollIndicators(.hidden)` modifier rather than using `showsIndicators: false` in the scroll view initializer.
- Place view logic into view models or similar, so it can be tested.
- Avoid `AnyView` unless it is absolutely required.
- Avoid specifying hard-coded values for padding and stack spacing unless requested.
- Avoid using UIKit colors in SwiftUI code.Related Skills
sparkle
Integrate, migrate, secure, publish, and troubleshoot Sparkle in macOS apps. Use when working on Sparkle dependency setup (SPM/Carthage/manual), updater wiring (SPUStandardUpdaterController or programmatic setup), Info.plist update keys (SUFeedURL and SUPublicEDKey), appcast/signing workflows, sandboxed updater behavior, or update-check debugging.
note
Update AGENTS.md instructions from user notes. Use when a user asks to add, revise, remove, or reorganize project operating instructions in AGENTS.md. Default to the current project's AGENTS.md, and only target global AGENTS.md when the user explicitly asks for global scope.
gsap
GSAP animations for JARVIS HUD transitions and effects
create-macos-app
Blueprint for setting up a new macOS Xcode project the right way. Use this skill whenever the user asks to create a macOS app, set up a new macOS Xcode project, or bootstrap a macOS application. Covers project creation, scheme configuration, code-level bootstrapping, menu bar setup, build configurations, and linting tooling.
apple-appstore-reviewer
Serves as a reviewer of the codebase with instructions on looking for Apple App Store optimizations or rejection reasons.
apple-hig-expert
Expert guidance on Apple Human Interface Guidelines (HIG). Covers iOS, macOS, and visionOS with 2026 Liquid Glass aesthetics and accessibility-first design.
pear-apple
iCloud Calendar, Reminders & Contacts via Pear. Manage events, reminders, contacts, daily briefings, and AI scheduling. 27 tools for Apple iCloud via CalDAV/CardDAV.
apple-photos-cleaner
Analyze, clean up, and organize Apple Photos libraries. Find and report junk photos (screenshots, low-quality, burst leftovers, duplicates), analyze storage usage, generate photo timeline recaps, plan smart exports, analyze Live Photos, check iCloud sync, audit shared libraries, detect similar photos, curate seasonal highlights, and score face quality. All analysis operations are READ-ONLY on the database (safe). macOS only. Requires Python 3.9+ (stdlib only) and access to the Apple Photos SQLite database. Trigger on: Photos cleanup, photo storage, duplicate photos, junk photos, screenshot cleanup, Photos analysis, photo timeline, photo export, Photos library stats, burst cleanup, storage hogs, photo organization, Live Photos, iCloud sync, shared library, similar photos, seasonal highlights, face quality, portraits.
apple-music-dj
Ultimate personalization engine for Apple Music. Analyzes listening history, Apple Music Replay stats, library data, and taste patterns to create intelligent playlists directly in the user's Apple Music library via the MusicKit API. Supports deep cuts discovery, mood/activity playlists, trend scouting, constellation discovery ("surprise me"), playlist refresh/evolution, automated weekly curation via cron, taste DNA cards, compatibility scoring, listening insights, catalog gap analysis, album deep dives, artist rabbit holes, daily song drops, concert prep, and personalized new release radar. Use this skill whenever the user mentions Apple Music, playlists, music recommendations, listening habits, music taste, "what should I listen to", discovering new music, mood playlists, workout playlists, deep cuts, hidden gems, trending music, "surprise me", refreshing a playlist, or anything related to curating their music experience. Also trigger on: "DJ", "mix", "playlist for", "music for", "songs like", "similar to", "what's hot", "new releases for me", "taste DNA", "taste card", "compatibility", "how compatible", "year in review", "listening stats", "what have I missed", "album deep dive", "rabbit hole", "concert prep", "seeing [artist] live", "daily song", "what should I listen to right now", or OpenClaw in the context of music.
apple-books
Read your Apple Books library, highlights, notes, and reading progress directly from the local SQLite databases on macOS.
apple-developer-toolkit
All-in-one Apple developer skill with three integrated tools shipped as a single unified binary. (1) Documentation search across Apple frameworks, symbols, and 1,267 WWDC sessions from 2014-2025. No credentials needed. (2) App Store Connect CLI with 120+ commands covering builds (find/wait/upload), TestFlight, pre-submission validate, submissions, signing, subscriptions (family-sharable), IAP, analytics, Xcode Cloud, metadata workflows, release pipeline dashboard, insights, win-back offers, promoted purchases, product pages, nominations, accessibility declarations, pre-orders, pricing filters, localizations update, diff, webhooks with local receiver, workflow automation, and more. Requires App Store Connect API key. (3) Multi-platform app builder (iOS/watchOS/tvOS/iPad/macOS/visionOS) that generates complete Swift/SwiftUI apps from natural language with auto-fix, simulator launch, interactive chat mode, and open-in-Xcode. Requires an LLM API key and Xcode. Includes 38 iOS development rules and 12 SwiftUI best practice guides for Liquid Glass, navigation, state management, and modern APIs. All three tools ship as one binary (appledev). USE WHEN: Apple API docs, App Store Connect management, WWDC lookup, or building iOS/watchOS/tvOS/macOS/visionOS apps from scratch. DON'T USE WHEN: non-Apple platforms or general coding.
apple-media
Control Apple TV, HomePod, and AirPlay devices via pyatv (scan, stream, playback, volume, navigation).