.agents/skills/apple-dev/SKILL.md
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,
npx skillsauth add roeybiran/dotfiles apple-devInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
xcode MCP if available, otherwise see below.foo?.bar).NSMenuItem.image is optional, so when assigning, don't do = NSImage("hello") ?? .init().async throws.@Suite attributeHashable and Equatable (e.g. test hashValue and ==, respectively), unless explicitly ordered so.==. 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.Task in tests to kick-off asynchronous actions:
Task to a let/var and never await the Task. Simply use a try await Task.sleep(for:) before the final assertion..sleep function should be extract to a shared constant.try!. Use try instead.as! and constructs such as guard let a = foo? as String else { Issue.record(); return } .Use try #require(x) instead.@Test func init(name:age:)``.systemUnderTest, [with optional condition/argument], should <expected result>. For example: @Test func processRequest, with AppElement throwing, should throw() { ... }.@Suite struct TableView Tests``).systemUnderTest part should retain its original casing (like camelCase, e.g. processRequest, should... or PROCESS_REQUEST, should...).displayName argument to @Test(_ displayName: String? = nil, _ traits: any TestTrait...).displayName argument to @Suite(_ displayName: String? = nil, _ traits: any SuiteTrait...).Package.swift exists in the project root (no xcodeproj/xcworkspace).*.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.
Run: swift build -q >/dev/null 2>&1 | grep ': error:'.
If the script ended with a zero exit code, the build succeeded.
Like "Build", but pass --build-tests too.
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.
RunningAppService as the scheme.xcodebuild: error: Scheme RunningAppService is not currently configured for the test action., stop, and ask for my attention and further steps.Builds the project, WITHOUT test targets.
./scripts/xcodebuild.sh build --scheme=SCHEME_NAME.Builds the project, WITH test targets.
./scripts/xcodebuild.sh build-tests --scheme=SCHEME_NAME.Run tests for the project.
only is provided as a parameter to this command:
./scripts/xcodebuild.sh run-tests --scheme=SCHEME_NAME --only='TEST_SPECIFIER' [--only="TEST_SPECIFIER2"...] and fix failing tests../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()../scripts/xcodebuild.sh run-tests --scheme=SCHEME_NAMEgrep, head or tail (etc.) to manipulate the scripts's output. The script is already designed to provide concise, context-efficient output.store.skipReceivedActions() unless explicitly told to.store.exhaustivity = .off unless explicitly told to.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:
@Observable classes with @MainActor.replacing("hello", with: "world") with strings rather than replacingOccurrences(of: "hello", with: "world").URL.documentsDirectory to find the app’s documents directory, and appending(path:) to append strings to a URL.Text(String(format: "%.2f", abs(myNumber))); always use Text(abs(change), format: .number.precision(.fractionLength(2))) instead..circle rather than Circle(), and .borderedProminent rather than BorderedProminentButtonStyle().DispatchQueue.main.async(). If behavior like this is needed, always use modern Swift concurrency.localizedStandardContains() as opposed to contains().try unless it is unrecoverable.foregroundStyle() instead of foregroundColor().clipShape(.rect(cornerRadius:)) instead of cornerRadius().Tab API instead of tabItem().ObservableObject; always prefer @Observable classes instead.onChange() modifier in its 1-parameter variant; either use the variant that accepts two parameters or accepts none.onTapGesture() unless you specifically need to know a tap’s location or the number of taps. All other usages should use Button.Task.sleep(nanoseconds:); always use Task.sleep(for:) instead.UIScreen.main.bounds to read the size of the available space.View structs instead.navigationDestination(for:) modifier to specify navigation, and always use NavigationStack instead of the old NavigationView.Button("Tap me", systemImage: "plus", action: myButtonAction).ImageRenderer to UIGraphicsImageRenderer.fontWeight() modifier unless there is good reason. If you want to make some text bold, always use bold() instead of fontWeight(.bold).GeometryReader if a newer alternative would work as well, such as containerRelativeFrame() or visualEffect().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)..scrollIndicators(.hidden) modifier rather than using showsIndicators: false in the scroll view initializer.AnyView unless it is absolutely required.development
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.
testing
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.
tools
GSAP animations for JARVIS HUD transitions and effects
tools
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.