🎯

swift-nio

🎯Skill

from joannis/claude-skills

VibeIndex|
What it does

Provides expert guidance on SwiftNIO networking, helping developers build performant, safe network applications with event-driven patterns and Swift Concurrency best practices.

πŸ“¦

Part of

joannis/claude-skills(11 items)

swift-nio

Installation

πŸ“‹ No install commands found in docs. Showing default command. Check GitHub for actual instructions.
Quick InstallInstall with npx
npx skills add joannis/claude-skills --skill swift-nio
1Installs
-
AddedFeb 4, 2026

Skill Details

SKILL.md

'Expert guidance on SwiftNIO best practices, patterns, and implementation. Use when developers mention: (1) SwiftNIO, NIO, ByteBuffer, Channel, ChannelPipeline, ChannelHandler, EventLoop, NIOAsyncChannel, or NIOFileSystem, (2) EventLoopFuture, ServerBootstrap, or DatagramBootstrap, (3) TCP/UDP server or client implementation, (4) ByteToMessageDecoder or wire protocol codecs, (5) binary protocol parsing or serialization, (6) blocking the event loop issues.'

Overview

# Swift NIO

Overview

This skill provides expert guidance on SwiftNIO, Apple's event-driven network application framework. Use this skill to help developers write safe, performant networking code, build protocol implementations, and properly integrate with Swift Concurrency.

Agent Behavior Contract (Follow These Rules)

  1. Analyze the project's Package.swift to determine which SwiftNIO packages are used.
  2. Before proposing fixes, identify if Swift Concurrency can be used instead of EventLoopFuture chains.
  3. Never recommend blocking the EventLoop - this is the most critical rule in SwiftNIO development.
  4. Prefer NIOAsyncChannel and structured concurrency over legacy ChannelHandler patterns for new code.
  5. Use EventLoopFuture/EventLoopPromise only for low-level protocol implementations.
  6. When working with ByteBuffer, always consider memory ownership and avoid unnecessary copies.

Quick Decision Tree

When a developer needs SwiftNIO guidance, follow this decision tree:

  1. Building a TCP/UDP server or client?

- Read references/Channels.md for Channel concepts and NIOAsyncChannel

- Use ServerBootstrap for TCP servers, DatagramBootstrap for UDP

  1. Understanding EventLoops?

- Read references/EventLoops.md for event loop concepts

- Critical: Never block the EventLoop!

  1. Working with binary data?

- Read references/ByteBuffer.md for buffer operations

- Prefer slice views over copies when possible

  1. Implementing a binary protocol?

- Read references/ByteToMessageCodecs.md for codec patterns

- Use ByteToMessageDecoder and MessageToByteEncoder

  1. Migrating from EventLoopFuture to async/await?

- Use .get() to bridge futures to async

- Use NIOAsyncChannel for channel-based async code

Triage-First Playbook (Common Issues -> Solutions)

  • "Blocking the EventLoop"

- Offload CPU-intensive work to a dispatch queue or use NIOThreadPool

- Never perform synchronous I/O on an EventLoop

- See references/EventLoops.md

  • Type mismatch crash in ChannelPipeline

- Ensure InboundOut of handler N matches InboundIn of handler N+1

- Ensure OutboundOut of handler N matches OutboundIn of handler N-1

- See references/Channels.md

  • Implementing binary protocol serialization

- Use ByteToMessageDecoder for parsing bytes into messages

- Use MessageToByteEncoder for serializing messages to bytes

- Use readLengthPrefixedSlice and writeLengthPrefixed helpers

- See references/ByteToMessageCodecs.md

  • Memory issues with ByteBuffer

- Use readSlice instead of readBytes when possible

- Remember ByteBuffer uses copy-on-write semantics

- See references/ByteBuffer.md

  • Deadlock when waiting for EventLoopFuture

- Never .wait() on a future from within the same EventLoop

- Use .get() from async contexts or chain with .flatMap

Core Patterns Reference

Creating a TCP Server (Modern Approach)

```swift

let server = try await ServerBootstrap(group: MultiThreadedEventLoopGroup.singleton)

.bind(host: "0.0.0.0", port: 8080) { channel in

channel.eventLoop.makeCompletedFuture {

try NIOAsyncChannel(

wrappingChannelSynchronously: channel,

configuration: .init(

inboundType: ByteBuffer.self,

outboundType: ByteBuffer.self

)

)

}

}

try await withThrowingDiscardingTaskGroup { group in

try await server.executeThenClose { clients in

for try await client in clients {

group.addTask {

try await handleClient(client)

}

}

}

}

```

EventLoopGroup Best Practice

```swift

// Preferred: Use the singleton

let group = MultiThreadedEventLoopGroup.singleton

// Get any EventLoop from the group

let eventLoop = group.any()

```

Bridging EventLoopFuture to async/await

```swift

// From EventLoopFuture to async

let result = try await someFuture.get()

// From async to EventLoopFuture

let future = eventLoop.makeFutureWithTask {

try await someAsyncOperation()

}

```

ByteBuffer Operations

```swift

var buffer = ByteBufferAllocator().buffer(capacity: 1024)

// Writing

buffer.writeString("Hello")

buffer.writeInteger(UInt32(42))

// Reading

let string = buffer.readString(length: 5)

let number = buffer.readInteger(as: UInt32.self)

```

Reference Files

Load these files as needed for specific topics:

  • EventLoops.md - EventLoop concepts, nonblocking I/O, why blocking is bad
  • Channels.md - Channel anatomy, ChannelPipeline, ChannelHandlers, NIOAsyncChannel
  • ByteToMessageCodecs.md - ByteToMessageDecoder, MessageToByteEncoder for binary protocol (de)serialization
  • patterns.md - Advanced integration patterns: ServerChildChannel abstraction, state machines, noncopyable ResponseWriter, graceful shutdown, ByteBuffer patterns

Best Practices Summary

  1. Never block the EventLoop - Offload heavy work to thread pools
  2. Use structured concurrency - Prefer NIOAsyncChannel over legacy handlers
  3. Use the singleton EventLoopGroup - MultiThreadedEventLoopGroup.singleton
  4. Handle errors in task groups - Throwing from a client task closes the server
  5. Mind the types in pipelines - Type mismatches crash at runtime
  6. Use ByteBuffer efficiently - Prefer slices over copies

Use ByteBuffer for Binary Protocol Handling

When parsing or serializing binary data (especially for network protocols), use SwiftNIO's ByteBuffer instead of Foundation's Data. ByteBuffer provides:

  • Efficient read/write operations with built-in endianness handling
  • Zero-copy slicing with reader/writer index tracking
  • Integration with NIO ecosystem

When converting between ByteBuffer and Data, use NIOFoundationCompat:

```swift

import NIOFoundationCompat

// ByteBuffer to Data

let data = Data(buffer: byteBuffer)

// Data to ByteBuffer - use writeData for better performance

var buffer = ByteBuffer()

buffer.writeData(data) // Faster than writeBytes(data)

```

Bad - Using Data with manual byte manipulation:

```swift

var buffer = Data()

var messageLength: UInt32?

for try await message in inbound {

buffer.append(message)

if messageLength == nil && buffer.count >= 4 {

messageLength = UInt32(buffer[0]) << 24

| UInt32(buffer[1]) << 16

| UInt32(buffer[2]) << 8

| UInt32(buffer[3])

buffer = Data(buffer.dropFirst(4)) // Copies data!

}

}

```

Good - Using ByteBuffer:

```swift

var buffer = ByteBuffer()

for try await message in inbound {

buffer.writeBytes(message)

if buffer.readableBytes >= 4 {

let readerIndex = buffer.readerIndex

guard let messageLength = buffer.readInteger(endianness: .big, as: UInt32.self) else {

continue

}

if buffer.readableBytes >= messageLength {

guard let bytes = buffer.readBytes(length: Int(messageLength)) else { continue }

// Process bytes...

} else {

// Not enough data yet, reset reader index

buffer.moveReaderIndex(to: readerIndex)

}

}

}

```

Binary Data Types Comparison

There are several "bag of bytes" data structures in Swift:

| Type | Source | Platform | Notes |

|------|--------|----------|-------|

| Array | stdlib | All | Safe, growable, good for Embedded Swift |

| InlineArray | stdlib (6.1+) | All | Fixed-size, stack-allocated, no heap allocation |

| Data | Foundation | All (large binary) | Not always contiguous on Apple platforms |

| ByteBuffer | SwiftNIO | All (requires NIO) | Best for network protocols, not Embedded |

| Span | stdlib (6.2+) | All | Zero-copy view, requires Swift 6.2+ |

| UnsafeBufferPointer | stdlib | All | Unsafe, manual memory management |

Recommendations:

  • For iOS/macOS-only projects: Data is fine due to framework integration
  • For SwiftNIO-based projects: ByteBuffer is required for I/O operations
  • For Embedded Swift: [UInt8] and InlineArray
  • For cross-platform APIs: Span (Swift 6.2+) allows any backing type

NIO Channel Pattern with executeThenClose

Use executeThenClose to get inbound/outbound streams from NIOAsyncChannel:

```swift

return try await channel.executeThenClose { inbound, outbound in

let socket = Client(inbound: inbound, outbound: outbound, channel: channel.channel)

return try await perform(client)

}

```

Public API with Internal NIO Types

When exposing async sequences that wrap NIO types:

  1. Create a custom AsyncSequence wrapper struct with internal NIO stream
  2. The wrapper's AsyncIterator transforms NIO types to public types
  3. This avoids exposing internal NIO imports in public API

SwiftNIO UDP Notes

  • Use DatagramBootstrap for UDP sockets
  • Messages use AddressedEnvelope containing remote address and data
  • Multicast requires casting channel to MulticastChannel protocol
  • Socket options use SocketOptionValue (Int32) type
  • so_reuseport is only available on Linux

More from this repository10

🎯
valkey🎯Skill

Provides Swift developers with a comprehensive Valkey/Redis client library for async key-value operations, cluster support, and advanced data structure management.

🎯
hummingbird🎯Skill

I apologize, but I cannot generate a description without seeing the actual code or details about the "hummingbird" skill. Could you provide more context or share the code/repository details so I ca...

🎯
swift-library-design🎯Skill

Helps developers design Swift libraries with best practices, architectural guidance, and code generation recommendations.

🎯
swift-concurrency🎯Skill

Provides expert guidance on Swift Concurrency, helping developers implement safe async/await patterns, resolve thread safety issues, and navigate structured concurrency challenges.

🎯
postgres🎯Skill

Enables Swift developers to interact with PostgreSQL databases using async/await, type-safe queries, connection pooling, and prepared statements via the postgres-nio library.

🎯
database-driver-design🎯Skill

Designs robust Swift database client libraries with safe, type-safe protocols, connection management, and NIO integration for high-performance data access.

🎯
wendy-contributing🎯Skill

Contributes code to a project by generating and suggesting improvements based on the current codebase and context.

🎯
wendy🎯Skill

I apologize, but I cannot generate a description without seeing the actual code or context for the "wendy" skill. Could you provide more details about what the skill does, or share the relevant cod...

🎯
linear🎯Skill

Manages Linear issue tracking via CLI, enabling listing, viewing, updating, and linking issues across different states and teams.

🎯
swift🎯Skill

Provides expert Swift development guidance, covering best practices, testing, logging, OpenTelemetry, platform-specific patterns, and memory-safe API design.