Claude Code Plugins

Community-maintained marketplace

Feedback

developing-with-swift

@czottmann/claude-code-stuff
2
0

Use when you work with Swift code or Xcode tooling - establishes style guidelines, teaches you vital Swift techniques, and how to use Xcode build tools

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

name developing-with-swift
description Use when you work with Swift code or Xcode tooling - establishes style guidelines, teaches you vital Swift techniques, and how to use Xcode build tools

Swift Styleguide

Indentation

2 spaces, no tabs.

Code comments & code documentation

If a comment contains documentation or explanation, it must use a triple slash (///), regardless of its position in the source code.

Use double slash comments (//) only for Xcode directive comments ("MARK:", "TODO:", etc.) and for temporarily disabling blocks of code. You must never use double slash (//) for documentation comments.

guard clauses

guard clauses must be written multi-line. If a clause combines multiple conditions, each condition must be on its own line.

Examples

// ❌ Bad
guard somethingCondition else { return }

// ✅ Good
guard somethingCondition else {
  return
}

// ❌ Bad
guard !somethingCondition1, let something else { return }

// ✅ Good
guard !somethingCondition1,
      let something
else {
  return
}

Any guard clause must be followed by a blank line.

if blocks

if clauses must be written multi-line. If a clause combines multiple conditions, each condition should be on its own line. If there is more than one condition, the opening bracket ({) should be on its own line.

Examples

// ❌ Bad
if !somethingCondition1, let something {
  return
}

// ✅ Good
if !somethingCondition1,
   let something
{
  return
}

switch/case

Every case block must be followed by a blank line.

Modern Swift

Write idiomatic SwiftUI code following Apple's latest architectural recommendations and best practices.

Core Philosophy

  • SwiftUI is the default UI paradigm for Apple platforms - embrace its declarative nature
  • Avoid legacy UIKit patterns and unnecessary abstractions
  • Focus on simplicity, clarity, and native data flow
  • Let SwiftUI handle the complexity - don't fight the framework

Architecture Guidelines

1. Embrace Native State Management

For simple use cases that don't contain a lot of logic and state, use SwiftUI's built-in property wrappers appropriately:

  • @State - Local, ephemeral view state
  • @Binding - Two-way data flow between views
  • @Observable - Shared state (iOS 17+)
  • @ObservableObject - Legacy shared state (pre-iOS 17)
  • @Environment - Dependency injection for app-wide concerns

For more complex use cases with lots of logic and interdependent states, use Composable Architecture. Before starting to write code, read the TCA documentation (see section "Read SDK/ package/ library/ framework documentation").

2. State Ownership Principles

  • Views own their local state unless sharing is required
  • State flows down, actions flow up
  • Keep state as close to where it's used as possible
  • Extract shared state only when multiple views need it

3. Modern Async Patterns

  • Use async/await as the default for asynchronous operations
  • Leverage .task modifier for lifecycle-aware async work
  • Avoid Combine unless absolutely necessary
  • Handle errors gracefully with try/catch

4. View Composition

  • Build UI with small, focused views
  • Extract reusable components naturally
  • Use view modifiers to encapsulate common styling
  • Prefer composition over inheritance

5. Code Organization

  • Organize by feature, not by type (avoid Views/, Models/, ViewModels/ folders)
  • Keep related code together in the same file when appropriate
  • Use extensions to organize large files
  • Follow Swift naming conventions consistently

Implementation Patterns

Simple State Example

struct CounterView: View {
  @State private var count = 0

  var body: some View {
    VStack {
      Text("Count: \(count)")
      Button("Increment") {
        count += 1
      }
    }
  }
}

Shared State with @Observable

@Observable
class UserSession {
  var isAuthenticated = false
  var currentUser: User?

  func signIn(user: User) {
    currentUser = user
    isAuthenticated = true
  }
}

struct MyApp: App {
  @State private var session = UserSession()

  var body: some Scene {
    WindowGroup {
      ContentView()
        .environment(session)
    }
  }
}

Async Data Loading

struct ProfileView: View {
  @State private var profile: Profile?
  @State private var isLoading = false
  @State private var error: Error?

  var body: some View {
    Group {
      if isLoading {
        ProgressView()
      } else if let profile {
        ProfileContent(profile: profile)
      } else if let error {
        ErrorView(error: error)
      }
    }
    .task {
      await loadProfile()
    }
  }

  private func loadProfile() async {
    isLoading = true
    defer { isLoading = false }

    do {
      profile = try await ProfileService.fetch()
    } catch {
      self.error = error
    }
  }
}

Best Practices

Do

  • Write self-contained views when possible
  • Use property wrappers as intended by Apple
  • Test logic in isolation, preview UI visually
  • Handle loading and error states explicitly
  • Keep views focused on presentation
  • Use Swift's type system for safety

Do not

  • Create ViewModels for every view
  • Move state out of views unnecessarily
  • Add abstraction layers without clear benefit
  • Use Combine for simple async operations
  • Fight SwiftUI's update mechanism
  • Overcomplicate simple features

Testing Strategy

  • Unit test business logic and data transformations
  • Use SwiftUI Previews for visual testing
  • Test @Observable classes independently
  • Keep tests simple and focused
  • Don't sacrifice code clarity for testability

Modern Swift Features

  • Use Swift Concurrency (async/await, actors)
  • Leverage Swift 6 data race safety when available, i.e. when the project is built with Swift 6 or later
  • Utilize property wrappers effectively
  • Embrace value types where appropriate
  • Use protocols for abstraction, not just for testing

Summary

Write SwiftUI code that looks and feels like SwiftUI. The framework has matured significantly - trust its patterns and tools. Focus on solving user problems rather than implementing architectural patterns from other platforms.

Building Xcode projects

Pipe xcodebuild output directly to xcsift to get clean, readable results for use by LLM:

xcodebuild [flags] 2>&1 | xcsift

Important: Always use 2>&1 to redirect STDERR to STDOUT. This ensures all compiler errors, warnings, and build output are captured, removing noise and providing clean, structured JSON output.