rshankras/networking-layer
Generates a protocol-based networking layer with async/await, error handling, and swappable implementations. Use when user wants to add API client, networking, or HTTP layer.
npx skills add https://github.com/rshankras/claude-code-apple-skills --skill networking-layer
Generate a modern, protocol-based networking layer using Swift's async/await concurrency, with proper error handling and easy testability.
Use this skill when the user:
Search for existing networking:
Glob: **/*API*.swift, **/*Network*.swift, **/*Client*.swift
Grep: "URLSession" or "HTTPURLResponse"
If found, ask user:
Ask user via AskUserQuestion:
Generate these files:
APIClient.swift - Protocol and implementationAPIEndpoint.swift - Endpoint definition protocolNetworkError.swift - Typed errorsAPIConfiguration.swift - Base URL and auth configBased on configuration:
RetryPolicy.swift - If retry logic selectedNetworkLogger.swift - If logging selectedCheck project structure:
Sources/ exists → Sources/Networking/App/ exists → App/Networking/Networking/Reference: Apple's Swift Concurrency Updates
Use @concurrent to offload heavy processing:
@concurrent
static func parseResponse<T: Decodable>(_ data: Data) async throws -> T {
try JSONDecoder().decode(T.self, from: data)
}
Keep UI-related code on MainActor:
@Observable
@MainActor
final class NetworkViewModel {
var items: [Item] = []
func fetch() async {
items = try await apiClient.fetch(ItemsEndpoint())
}
}
After generation, provide:
Sources/Networking/
├── APIClient.swift # Protocol + URLSession implementation
├── APIEndpoint.swift # Endpoint protocol
├── NetworkError.swift # Error types
├── APIConfiguration.swift # Config (base URL, auth)
└── Endpoints/ # Example endpoints
└── ExampleEndpoint.swift
Define an Endpoint:
struct UsersEndpoint: APIEndpoint {
typealias Response = [User]
var path: String { "/users" }
var method: HTTPMethod { .get }
}
Make a Request:
let client = URLSessionAPIClient(configuration: .production)
let users = try await client.request(UsersEndpoint())
With SwiftUI:
struct UsersView: View {
@State private var users: [User] = []
@Environment(\.apiClient) private var apiClient
var body: some View {
List(users) { user in
Text(user.name)
}
.task {
users = try await apiClient.request(UsersEndpoint())
}
}
}
Use MockAPIClient for tests:
let mockClient = MockAPIClient()
mockClient.mockResponse(for: UsersEndpoint.self, response: [User.mock])
let viewModel = UsersViewModel(apiClient: mockClient)
await viewModel.fetch()
XCTAssertEqual(viewModel.users.count, 1)
Take rshankras/networking-layer from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.