
Swift Architecture
- 20 installs
- 9 repo stars
- Updated January 5, 2026
- pluginagentmarketplace/custom-plugin-swift
swift-architecture is a Claude Code skill for ai & agent building.
About
swift-architecture is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted development.
- swift-architecture
- AI & Agent Building
- AI-coding skill
Swift Architecture by the numbers
- 20 all-time installs (skills.sh)
- Ranked #10,442 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 4, 2026 (Skillselion catalog sync)
npx skills add https://github.com/pluginagentmarketplace/custom-plugin-swift --skill swift-architectureAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 20 |
|---|---|
| repo stars | ★ 9 |
| Last updated | January 5, 2026 |
| Repository | pluginagentmarketplace/custom-plugin-swift ↗ |
How do I helps with ai & agent building tasks.?
Helps with ai & agent building tasks.
Who is it for?
Best when you're working on ai & agent building and need structured help with swift architecture.
Skip if: Teams with no ai & agent building needs, or anyone wanting a generic chat assistant without this specific workflow.
When should I use this skill?
When you need to helps with ai & agent building tasks., or when swift-architecture is a claude code skill for ai & agent building.
What you get
Structured output aligned to swift-architecture: swift-architecture, AI & Agent Building.
Files
Swift Architecture Skill
Design patterns and architectural approaches for scalable, testable Swift applications.
Prerequisites
- Understanding of SOLID principles
- Familiarity with dependency injection
- Experience with protocol-oriented programming
Parameters
parameters:
architecture_pattern:
type: string
enum: [mvvm, mvc, tca, viper, clean]
default: mvvm
navigation_pattern:
type: string
enum: [coordinator, router, navigation_stack]
default: coordinator
di_approach:
type: string
enum: [manual, container, property_wrapper]
default: manualTopics Covered
Architecture Patterns
| Pattern | Complexity | Testability | Best For |
|---|---|---|---|
| MVC | Low | Low | Simple apps |
| MVVM | Medium | High | Most apps |
| Clean | High | Very High | Large teams |
| TCA | High | Very High | Complex state |
| VIPER | Very High | Very High | Enterprise |
Key Principles
| Principle | Description |
|---|---|
| Separation of Concerns | Each layer has one job |
| Dependency Inversion | Depend on abstractions |
| Single Source of Truth | One place for state |
| Unidirectional Data Flow | State → View → Action → State |
Layer Responsibilities
| Layer | Responsibility |
|---|---|
| View | UI rendering only |
| ViewModel | Presentation logic |
| UseCase | Business logic |
| Repository | Data access |
| Service | External integrations |
Code Examples
MVVM with Coordinator
// MARK: - Coordinator Protocol
protocol Coordinator: AnyObject {
var navigationController: UINavigationController { get }
var childCoordinators: [Coordinator] { get set }
func start()
}
extension Coordinator {
func addChild(_ coordinator: Coordinator) {
childCoordinators.append(coordinator)
}
func removeChild(_ coordinator: Coordinator) {
childCoordinators.removeAll { $0 === coordinator }
}
}
// MARK: - App Coordinator
final class AppCoordinator: Coordinator {
let navigationController: UINavigationController
var childCoordinators: [Coordinator] = []
private let dependencies: AppDependencies
init(navigationController: UINavigationController, dependencies: AppDependencies) {
self.navigationController = navigationController
self.dependencies = dependencies
}
func start() {
if dependencies.authService.isLoggedIn {
showMain()
} else {
showLogin()
}
}
private func showLogin() {
let coordinator = LoginCoordinator(
navigationController: navigationController,
dependencies: dependencies
)
coordinator.delegate = self
addChild(coordinator)
coordinator.start()
}
private func showMain() {
let coordinator = MainCoordinator(
navigationController: navigationController,
dependencies: dependencies
)
addChild(coordinator)
coordinator.start()
}
}
extension AppCoordinator: LoginCoordinatorDelegate {
func loginDidComplete(_ coordinator: LoginCoordinator) {
removeChild(coordinator)
showMain()
}
}
// MARK: - ViewModel
@MainActor
protocol ProductListViewModelProtocol: ObservableObject {
var products: [Product] { get }
var isLoading: Bool { get }
var error: Error? { get }
func loadProducts() async
func selectProduct(_ product: Product)
}
@MainActor
final class ProductListViewModel: ProductListViewModelProtocol {
@Published private(set) var products: [Product] = []
@Published private(set) var isLoading = false
@Published private(set) var error: Error?
private let getProductsUseCase: GetProductsUseCaseProtocol
private weak var coordinator: ProductCoordinator?
init(getProductsUseCase: GetProductsUseCaseProtocol, coordinator: ProductCoordinator) {
self.getProductsUseCase = getProductsUseCase
self.coordinator = coordinator
}
func loadProducts() async {
isLoading = true
error = nil
do {
products = try await getProductsUseCase.execute()
} catch {
self.error = error
}
isLoading = false
}
func selectProduct(_ product: Product) {
coordinator?.showProductDetail(product)
}
}Clean Architecture Layers
// MARK: - Domain Layer (Use Cases)
protocol GetProductsUseCaseProtocol {
func execute() async throws -> [Product]
}
final class GetProductsUseCase: GetProductsUseCaseProtocol {
private let repository: ProductRepositoryProtocol
init(repository: ProductRepositoryProtocol) {
self.repository = repository
}
func execute() async throws -> [Product] {
let products = try await repository.getProducts()
// Business logic: filter, sort, validate
return products.filter { $0.isAvailable }.sorted { $0.name < $1.name }
}
}
// MARK: - Data Layer (Repository)
protocol ProductRepositoryProtocol {
func getProducts() async throws -> [Product]
func getProduct(id: String) async throws -> Product
func saveProduct(_ product: Product) async throws
}
final class ProductRepository: ProductRepositoryProtocol {
private let remoteDataSource: ProductRemoteDataSourceProtocol
private let localDataSource: ProductLocalDataSourceProtocol
init(remoteDataSource: ProductRemoteDataSourceProtocol,
localDataSource: ProductLocalDataSourceProtocol) {
self.remoteDataSource = remoteDataSource
self.localDataSource = localDataSource
}
func getProducts() async throws -> [Product] {
// Try cache first
if let cached = try? await localDataSource.getProducts(), !cached.isEmpty {
// Refresh in background
Task {
if let remote = try? await remoteDataSource.fetchProducts() {
try? await localDataSource.saveProducts(remote)
}
}
return cached
}
// Fetch from remote
let products = try await remoteDataSource.fetchProducts()
try? await localDataSource.saveProducts(products)
return products
}
func getProduct(id: String) async throws -> Product {
try await remoteDataSource.fetchProduct(id: id)
}
func saveProduct(_ product: Product) async throws {
try await remoteDataSource.createProduct(product)
try await localDataSource.saveProduct(product)
}
}Dependency Injection Container
// MARK: - Dependencies Protocol
protocol HasAuthService {
var authService: AuthServiceProtocol { get }
}
protocol HasProductRepository {
var productRepository: ProductRepositoryProtocol { get }
}
typealias AppDependencies = HasAuthService & HasProductRepository
// MARK: - DI Container
final class DependencyContainer: AppDependencies {
// Singletons
lazy var authService: AuthServiceProtocol = AuthService()
// Factories
lazy var productRepository: ProductRepositoryProtocol = {
ProductRepository(
remoteDataSource: ProductRemoteDataSource(apiClient: apiClient),
localDataSource: ProductLocalDataSource(database: database)
)
}()
private lazy var apiClient: APIClientProtocol = APIClient()
private lazy var database: DatabaseProtocol = Database()
// Factory methods for ViewModels
func makeProductListViewModel(coordinator: ProductCoordinator) -> ProductListViewModel {
ProductListViewModel(
getProductsUseCase: GetProductsUseCase(repository: productRepository),
coordinator: coordinator
)
}
}
// MARK: - Property Wrapper Approach
@propertyWrapper
struct Injected<T> {
private let keyPath: KeyPath<DependencyContainer, T>
var wrappedValue: T {
DependencyContainer.shared[keyPath: keyPath]
}
init(_ keyPath: KeyPath<DependencyContainer, T>) {
self.keyPath = keyPath
}
}
// Usage
final class SomeService {
@Injected(\.authService) private var authService
}SwiftUI MVVM
// MARK: - View
struct ProductListView: View {
@StateObject private var viewModel: ProductListViewModel
init(viewModel: @autoclosure @escaping () -> ProductListViewModel) {
_viewModel = StateObject(wrappedValue: viewModel())
}
var body: some View {
Group {
if viewModel.isLoading {
ProgressView()
} else if let error = viewModel.error {
ErrorView(error: error) {
Task { await viewModel.loadProducts() }
}
} else {
productList
}
}
.navigationTitle("Products")
.task {
await viewModel.loadProducts()
}
}
private var productList: some View {
List(viewModel.products) { product in
ProductRow(product: product)
.onTapGesture {
viewModel.selectProduct(product)
}
}
}
}
// MARK: - SwiftUI Coordinator (Router)
@MainActor
final class Router: ObservableObject {
@Published var path = NavigationPath()
func push<T: Hashable>(_ value: T) {
path.append(value)
}
func pop() {
path.removeLast()
}
func popToRoot() {
path.removeLast(path.count)
}
}
struct ContentView: View {
@StateObject private var router = Router()
@StateObject private var dependencies = DependencyContainer()
var body: some View {
NavigationStack(path: $router.path) {
ProductListView(viewModel: dependencies.makeProductListViewModel(router: router))
.navigationDestination(for: Product.self) { product in
ProductDetailView(product: product)
}
}
.environmentObject(router)
}
}Troubleshooting
Common Issues
| Issue | Cause | Solution |
|---|---|---|
| Massive ViewModel | Too many responsibilities | Split into smaller VMs or use UseCases |
| Tight coupling | Direct dependencies | Use protocols and DI |
| Hard to test | Static/singleton dependencies | Inject dependencies |
| Memory leaks | Strong coordinator references | Use weak delegates |
| State sync issues | Multiple sources of truth | Single source + binding |
Debug Tips
// Check retain cycles
deinit {
print("\(Self.self) deinit")
}
// Trace view updates
var body: some View {
let _ = Self._printChanges()
// ...
}
// Validate architecture
// Run: swift package diagnose-api-breaking-changesValidation Rules
validation:
- rule: layer_separation
severity: error
check: Views should not import data layer
- rule: protocol_abstractions
severity: warning
check: Dependencies should be protocols
- rule: unidirectional_flow
severity: info
check: State changes flow in one directionUsage
Skill("swift-architecture")Related Skills
swift-fundamentals- Protocol-oriented designswift-swiftui- SwiftUI patternsswift-testing- Testing architecture
# Architecture Configuration
pattern: MVVM-C # MVVM with Coordinators
layers:
presentation:
- Views
- ViewModels
- Coordinators
domain:
- UseCases
- Entities
- Repositories (protocols)
data:
- Repositories (implementations)
- DataSources
- DTOs
dependency_injection: true
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "swift-architecture Configuration Schema",
"type": "object",
"properties": {
"skill": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"version": {
"type": "string",
"pattern": "^\\d+\\.\\d+\\.\\d+$"
},
"category": {
"type": "string",
"enum": [
"api",
"testing",
"devops",
"security",
"database",
"frontend",
"algorithms",
"machine-learning",
"cloud",
"containers",
"general"
]
}
},
"required": [
"name",
"version"
]
},
"settings": {
"type": "object",
"properties": {
"enabled": {
"type": "boolean",
"default": true
},
"log_level": {
"type": "string",
"enum": [
"debug",
"info",
"warn",
"error"
]
}
}
}
},
"required": [
"skill"
]
}import Foundation
import Combine
@MainActor
final class {{NAME}}ViewModel: ObservableObject {
// MARK: - Published Properties
@Published private(set) var state: ViewState = .idle
@Published private(set) var items: [Item] = []
// MARK: - Dependencies
private let useCase: {{NAME}}UseCaseProtocol
private var cancellables = Set<AnyCancellable>()
// MARK: - Init
init(useCase: {{NAME}}UseCaseProtocol) {
self.useCase = useCase
}
// MARK: - Actions
func load() async {
state = .loading
do {
items = try await useCase.execute()
state = .loaded
} catch {
state = .error(error.localizedDescription)
}
}
}
enum ViewState {
case idle
case loading
case loaded
case error(String)
}
Swift Architecture Guide
MVVM Pattern
// Model
struct User: Identifiable {
let id: UUID
let name: String
}
// ViewModel
@MainActor
class UserListViewModel: ObservableObject {
@Published var users: [User] = []
private let repository: UserRepository
init(repository: UserRepository) {
self.repository = repository
}
func loadUsers() async {
users = await repository.fetchAll()
}
}
// View
struct UserListView: View {
@StateObject var viewModel: UserListViewModel
var body: some View {
List(viewModel.users) { user in
Text(user.name)
}
.task {
await viewModel.loadUsers()
}
}
}Coordinator Pattern
protocol Coordinator {
var navigationController: UINavigationController { get }
func start()
}
class AppCoordinator: Coordinator {
let navigationController: UINavigationController
init(navigationController: UINavigationController) {
self.navigationController = navigationController
}
func start() {
let vc = HomeViewController()
vc.coordinator = self
navigationController.pushViewController(vc, animated: false)
}
func showDetail(for item: Item) {
let vc = DetailViewController(item: item)
navigationController.pushViewController(vc, animated: true)
}
}Dependency Injection
protocol Dependencies {
var userRepository: UserRepository { get }
var networkService: NetworkService { get }
}
class AppDependencies: Dependencies {
lazy var userRepository: UserRepository = UserRepositoryImpl(network: networkService)
lazy var networkService: NetworkService = URLSessionNetworkService()
}Swift Architecture Patterns
Design Patterns
Pattern 1: Input Validation
Always validate input before processing:
def validate_input(data):
if data is None:
raise ValueError("Data cannot be None")
if not isinstance(data, dict):
raise TypeError("Data must be a dictionary")
return TruePattern 2: Error Handling
Use consistent error handling:
try:
result = risky_operation()
except SpecificError as e:
logger.error(f"Operation failed: {e}")
handle_error(e)
except Exception as e:
logger.exception("Unexpected error")
raisePattern 3: Configuration Loading
Load and validate configuration:
import yaml
def load_config(config_path):
with open(config_path) as f:
config = yaml.safe_load(f)
validate_config(config)
return configAnti-Patterns to Avoid
❌ Don't: Swallow Exceptions
# BAD
try:
do_something()
except:
pass✅ Do: Handle Explicitly
# GOOD
try:
do_something()
except SpecificError as e:
logger.warning(f"Expected error: {e}")
return default_valueCategory-Specific Patterns: General
Recommended Approach
1. Start with the simplest implementation 2. Add complexity only when needed 3. Test each addition 4. Document decisions
Common Integration Points
- Configuration:
assets/config.yaml - Validation:
scripts/validate.py - Documentation:
references/GUIDE.md
---
Pattern library for swift-architecture skill
#!/usr/bin/env python3
"""
Validation script for swift-architecture skill.
Category: general
"""
import os
import sys
import yaml
import json
from pathlib import Path
def validate_config(config_path: str) -> dict:
"""
Validate skill configuration file.
Args:
config_path: Path to config.yaml
Returns:
dict: Validation result with 'valid' and 'errors' keys
"""
errors = []
if not os.path.exists(config_path):
return {"valid": False, "errors": ["Config file not found"]}
try:
with open(config_path, 'r') as f:
config = yaml.safe_load(f)
except yaml.YAMLError as e:
return {"valid": False, "errors": [f"YAML parse error: {e}"]}
# Validate required fields
if 'skill' not in config:
errors.append("Missing 'skill' section")
else:
if 'name' not in config['skill']:
errors.append("Missing skill.name")
if 'version' not in config['skill']:
errors.append("Missing skill.version")
# Validate settings
if 'settings' in config:
settings = config['settings']
if 'log_level' in settings:
valid_levels = ['debug', 'info', 'warn', 'error']
if settings['log_level'] not in valid_levels:
errors.append(f"Invalid log_level: {settings['log_level']}")
return {
"valid": len(errors) == 0,
"errors": errors,
"config": config if not errors else None
}
def validate_skill_structure(skill_path: str) -> dict:
"""
Validate skill directory structure.
Args:
skill_path: Path to skill directory
Returns:
dict: Structure validation result
"""
required_dirs = ['assets', 'scripts', 'references']
required_files = ['SKILL.md']
errors = []
# Check required files
for file in required_files:
if not os.path.exists(os.path.join(skill_path, file)):
errors.append(f"Missing required file: {file}")
# Check required directories
for dir in required_dirs:
dir_path = os.path.join(skill_path, dir)
if not os.path.isdir(dir_path):
errors.append(f"Missing required directory: {dir}/")
else:
# Check for real content (not just .gitkeep)
files = [f for f in os.listdir(dir_path) if f != '.gitkeep']
if not files:
errors.append(f"Directory {dir}/ has no real content")
return {
"valid": len(errors) == 0,
"errors": errors,
"skill_name": os.path.basename(skill_path)
}
def main():
"""Main validation entry point."""
skill_path = Path(__file__).parent.parent
print(f"Validating swift-architecture skill...")
print(f"Path: {skill_path}")
# Validate structure
structure_result = validate_skill_structure(str(skill_path))
print(f"\nStructure validation: {'PASS' if structure_result['valid'] else 'FAIL'}")
if structure_result['errors']:
for error in structure_result['errors']:
print(f" - {error}")
# Validate config
config_path = skill_path / 'assets' / 'config.yaml'
if config_path.exists():
config_result = validate_config(str(config_path))
print(f"\nConfig validation: {'PASS' if config_result['valid'] else 'FAIL'}")
if config_result['errors']:
for error in config_result['errors']:
print(f" - {error}")
else:
print("\nConfig validation: SKIPPED (no config.yaml)")
# Summary
all_valid = structure_result['valid']
print(f"\n==================================================")
print(f"Overall: {'VALID' if all_valid else 'INVALID'}")
return 0 if all_valid else 1
if __name__ == "__main__":
sys.exit(main())
Related skills
FAQ
What does swift-architecture do?
swift-architecture is a Claude Code skill for ai & agent building.
When should I use swift-architecture?
When you need to helps with ai & agent building tasks., or when swift-architecture is a claude code skill for ai & agent building.
What are the main capabilities?
swift-architecture; AI & Agent Building; AI-coding skill.