axiom-networking-legacy

This skill should be used when working with NWConnection patterns for iOS 12-25, supporting apps that can't use async/await yet, or maintaining backward compatibility with completion handler networking.

25 stars

Best use case

axiom-networking-legacy is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

This skill should be used when working with NWConnection patterns for iOS 12-25, supporting apps that can't use async/await yet, or maintaining backward compatibility with completion handler networking.

Teams using axiom-networking-legacy should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/axiom-networking-legacy/SKILL.md --create-dirs "https://raw.githubusercontent.com/ComeOnOliver/skillshub/main/skills/CharlesWiltgen/Axiom/axiom-networking-legacy/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/axiom-networking-legacy/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How axiom-networking-legacy Compares

Feature / Agentaxiom-networking-legacyStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

This skill should be used when working with NWConnection patterns for iOS 12-25, supporting apps that can't use async/await yet, or maintaining backward compatibility with completion handler networking.

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

SKILL.md Source

# Legacy iOS 12-25 NWConnection Patterns

These patterns use NWConnection with completion handlers for apps supporting iOS 12-25. If your app targets iOS 26+, use NetworkConnection with async/await instead (see axiom-network-framework-ref skill).

## Pattern 2a: NWConnection with TLS (iOS 12-25)

**Use when** Supporting iOS 12-25, need TLS encryption, can't use async/await yet

**Time cost** 10-15 minutes

### GOOD: NWConnection with Completion Handlers

```swift
import Network

// Create connection with TLS
let connection = NWConnection(
    host: NWEndpoint.Host("mail.example.com"),
    port: NWEndpoint.Port(integerLiteral: 993),
    using: .tls // TCP inferred
)

// Handle connection state changes
connection.stateUpdateHandler = { [weak self] state in
    switch state {
    case .ready:
        print("Connection established")
        self?.sendInitialData()
    case .waiting(let error):
        print("Waiting for network: \(error)")
        // Show "Waiting..." UI, don't fail immediately
    case .failed(let error):
        print("Connection failed: \(error)")
    case .cancelled:
        print("Connection cancelled")
    default:
        break
    }
}

// Start connection
connection.start(queue: .main)

// Send data with pacing
func sendData() {
    let data = Data("Hello, world!".utf8)
    connection.send(content: data, completion: .contentProcessed { [weak self] error in
        if let error = error {
            print("Send error: \(error)")
            return
        }
        // contentProcessed callback = network stack consumed data
        // This is when you should send next chunk (pacing)
        self?.sendNextChunk()
    })
}

// Receive exact byte count
func receiveData() {
    connection.receive(minimumIncompleteLength: 10, maximumLength: 10) { [weak self] (data, context, isComplete, error) in
        if let error = error {
            print("Receive error: \(error)")
            return
        }

        if let data = data {
            print("Received \(data.count) bytes")
            // Process data...
            self?.receiveData() // Continue receiving
        }
    }
}
```

### Key differences from NetworkConnection
- Must use `[weak self]` in all completion handlers to prevent retain cycles
- stateUpdateHandler receives state, not async sequence
- send/receive use completion callbacks, not async/await

### When to use
- Supporting iOS 12-15 (70% of devices as of 2024)
- Codebases not yet using async/await
- Libraries needing backward compatibility

### Migration to NetworkConnection (iOS 26+)
- stateUpdateHandler -> connection.states async sequence
- Completion handlers -> try await calls
- [weak self] -> No longer needed (async/await handles cancellation)

## Pattern 2b: NWConnection UDP Batch (iOS 12-25)

**Use when** Supporting iOS 12-25, sending multiple UDP datagrams efficiently, need ~30% CPU reduction

**Time cost** 10-15 minutes

**Background** Traditional UDP sockets send one datagram per syscall. If you're sending 100 small packets, that's 100 context switches. Batching reduces this to ~1 syscall.

### BAD: Individual UDP Sends (High CPU)
```swift
// WRONG — 100 context switches for 100 packets
for frame in videoFrames {
    sendto(socket, frame.bytes, frame.count, 0, &addr, addrlen)
    // Each send = context switch to kernel
}
```

### GOOD: Batched UDP Sends (30% Lower CPU)

```swift
import Network

// UDP connection
let connection = NWConnection(
    host: NWEndpoint.Host("stream-server.example.com"),
    port: NWEndpoint.Port(integerLiteral: 9000),
    using: .udp
)

connection.stateUpdateHandler = { state in
    if case .ready = state {
        print("Ready to send UDP")
    }
}

connection.start(queue: .main)

// Batch sending for efficiency
func sendVideoFrames(_ frames: [Data]) {
    connection.batch {
        for frame in frames {
            connection.send(content: frame, completion: .contentProcessed { error in
                if let error = error {
                    print("Send error: \(error)")
                }
            })
        }
    }
    // All sends batched into ~1 syscall
    // 30% lower CPU usage vs individual sends
}

// Receive UDP datagrams
func receiveFrames() {
    connection.receive(minimumIncompleteLength: 1, maximumLength: 65536) { [weak self] (data, context, isComplete, error) in
        if let error = error {
            print("Receive error: \(error)")
            return
        }

        if let data = data {
            // Process video frame
            self?.displayFrame(data)
            self?.receiveFrames() // Continue receiving
        }
    }
}
```

### Performance characteristics
- **Without batch** 100 datagrams = 100 syscalls = 100 context switches
- **With batch** 100 datagrams = ~1 syscall = 1 context switch
- **Result** ~30% lower CPU usage (measured with Instruments)

### When to use
- Real-time video/audio streaming
- Gaming with frequent updates (player position)
- High-frequency sensor data (IoT)

**WWDC 2018 demo** Live video streaming showed 30% lower CPU on receiver with user-space networking + batching

## Pattern 2c: NWListener (iOS 12-25)

**Use when** Need to accept incoming connections, building servers or peer-to-peer apps, supporting iOS 12-25

**Time cost** 20-25 minutes

### BAD: Manual Socket Listening
```swift
// WRONG — Manual socket management
let sock = socket(AF_INET, SOCK_STREAM, 0)
bind(sock, &addr, addrlen)
listen(sock, 5)
while true {
    let client = accept(sock, nil, nil) // Blocks thread
    // Handle client...
}
```

### GOOD: NWListener with Automatic Connection Handling

```swift
import Network

// Create listener with default parameters
let listener = try NWListener(using: .tcp, on: 1029)

// Advertise Bonjour service
listener.service = NWListener.Service(name: "MyApp", type: "_myservice._tcp")

// Handle service registration updates
listener.serviceRegistrationUpdateHandler = { update in
    switch update {
    case .add(let endpoint):
        if case .service(let name, let type, let domain, _) = endpoint {
            print("Advertising as: \(name).\(type)\(domain)")
        }
    default:
        break
    }
}

// Handle incoming connections
listener.newConnectionHandler = { [weak self] newConnection in
    print("New connection from: \(newConnection.endpoint)")

    // Configure connection
    newConnection.stateUpdateHandler = { state in
        switch state {
        case .ready:
            print("Client connected")
            self?.handleClient(newConnection)
        case .failed(let error):
            print("Client connection failed: \(error)")
        default:
            break
        }
    }

    // Start handling this connection
    newConnection.start(queue: .main)
}

// Handle listener state
listener.stateUpdateHandler = { state in
    switch state {
    case .ready:
        print("Listener ready on port \(listener.port ?? 0)")
    case .failed(let error):
        print("Listener failed: \(error)")
    default:
        break
    }
}

// Start listening
listener.start(queue: .main)

// Handle client data
func handleClient(_ connection: NWConnection) {
    connection.receive(minimumIncompleteLength: 1, maximumLength: 65536) { [weak self] (data, context, isComplete, error) in
        if let error = error {
            print("Receive error: \(error)")
            return
        }

        if let data = data {
            print("Received \(data.count) bytes")

            // Echo back
            connection.send(content: data, completion: .contentProcessed { error in
                if let error = error {
                    print("Send error: \(error)")
                }
            })

            self?.handleClient(connection) // Continue receiving
        }
    }
}
```

### When to use
- Peer-to-peer apps (file sharing, messaging)
- Local network services
- Development/testing servers

### Bonjour advertising
- Automatic service discovery on local network
- No hardcoded IPs needed
- Works with NWBrowser for discovery

### Security considerations
- Use TLS parameters for encryption: `NWListener(using: .tls, on: port)`
- Validate client connections before processing data
- Set connection limits to prevent DoS

## Pattern 2d: Network Discovery (iOS 12-25)

**Use when** Discovering services on local network (Bonjour), building peer-to-peer apps, supporting iOS 12-25

**Time cost** 25-30 minutes

### BAD: Hardcoded IP Addresses
```swift
// WRONG — Brittle, requires manual configuration
let connection = NWConnection(host: "192.168.1.100", port: 9000, using: .tcp)
// What if IP changes? What if multiple devices?
```

### GOOD: NWBrowser for Service Discovery

```swift
import Network

// Browse for services on local network
let browser = NWBrowser(for: .bonjour(type: "_myservice._tcp", domain: nil), using: .tcp)

// Handle discovered services
browser.browseResultsChangedHandler = { results, changes in
    for result in results {
        switch result.endpoint {
        case .service(let name, let type, let domain, _):
            print("Found service: \(name).\(type)\(domain)")
            // Connect to this service
            self.connectToService(result.endpoint)
        default:
            break
        }
    }
}

// Handle browser state
browser.stateUpdateHandler = { state in
    switch state {
    case .ready:
        print("Browser ready")
    case .failed(let error):
        print("Browser failed: \(error)")
    default:
        break
    }
}

// Start browsing
browser.start(queue: .main)

// Connect to discovered service
func connectToService(_ endpoint: NWEndpoint) {
    let connection = NWConnection(to: endpoint, using: .tcp)

    connection.stateUpdateHandler = { state in
        if case .ready = state {
            print("Connected to service")
        }
    }

    connection.start(queue: .main)
}
```

### When to use
- Peer-to-peer discovery (AirDrop-like features)
- Local network printers, media servers
- Development/testing (find test servers automatically)

### Performance characteristics
- mDNS-based (multicast DNS, no central server)
- Near-instant discovery on same subnet
- Automatic updates when services appear/disappear

### iOS 26+ alternative
- Use NetworkBrowser with Wi-Fi Aware for peer-to-peer without infrastructure
- See Pattern 1d in axiom-network-framework-ref skill

## Resources

**Skills**: axiom-networking, axiom-network-framework-ref, axiom-networking-migration

Related Skills

legacy-circuit-mockups

25
from ComeOnOliver/skillshub

Generate breadboard circuit mockups and visual diagrams using HTML5 Canvas drawing techniques. Use when asked to create circuit layouts, visualize electronic component placements, draw breadboard diagrams, mockup 6502 builds, generate retro computer schematics, or design vintage electronics projects. Supports 555 timers, W65C02S microprocessors, 28C256 EEPROMs, W65C22 VIA chips, 7400-series logic gates, LEDs, resistors, capacitors, switches, buttons, crystals, and wires.

legacy-modernizer

25
from ComeOnOliver/skillshub

Refactor legacy codebases, migrate outdated frameworks, and implement gradual modernization. Handles technical debt, dependency updates, and backward compatibility. Use PROACTIVELY for legacy system updates, framework migrations, or technical debt reduction.

hybrid-cloud-networking

25
from ComeOnOliver/skillshub

Configure secure, high-performance connectivity between on-premises infrastructure and cloud platforms using VPN and dedicated connections. Use when building hybrid cloud architectures, connecting data centers to cloud, or implementing secure cross-premises networking.

framework-migration-legacy-modernize

25
from ComeOnOliver/skillshub

Orchestrate a comprehensive legacy system modernization using the strangler fig pattern, enabling gradual replacement of outdated components while maintaining continuous business operations through ex

axiom-audit

25
from ComeOnOliver/skillshub

Audit Axiom logs to identify and prioritize errors and warnings, research probable causes, and flag log smells. Use when user asks to check Axiom logs, analyze production errors, investigate log issues, or audit logging patterns.

vibecoder-guide-legacy

25
from ComeOnOliver/skillshub

Guides VibeCoder (non-technical users) through natural language development (legacy). Use when user mentions どうすればいい, 次は何, 使い方, 困った, help, what should I do. Do NOT load for: 技術者向け作業, 直接的な実装指示, レビュー.

p2p-networking

25
from ComeOnOliver/skillshub

Peer-to-peer networking patterns using commonware for building decentralized Guts network

Axiom — Serverless Log Analytics

25
from ComeOnOliver/skillshub

## Overview

Azure Networking Skill

25
from ComeOnOliver/skillshub

This skill provides expert guidance for Azure Networking. Covers troubleshooting, best practices, decision making, architecture & design patterns, security, and integrations & coding patterns. It combines local quick-reference content with remote documentation fetching capabilities.

ios-networking

25
from ComeOnOliver/skillshub

Standards for URLSession, Alamofire, and API communication. Use when implementing URLSession networking, Alamofire, or API clients in iOS. (triggers: **/*Service.swift, **/*API.swift, **/*Client.swift, URLSession, Alamofire, Moya, URLRequest, URLComponents, Codable)

flutter-retrofit-networking

25
from ComeOnOliver/skillshub

HTTP networking standards using Dio and Retrofit with Auth interceptors. Use when integrating Dio, Retrofit, or API auth interceptors in Flutter. (triggers: **/data_sources/**, **/api/**, Retrofit, Dio, RestClient, GET, POST, Interceptor, refreshing)

android-networking

25
from ComeOnOliver/skillshub

Standards for Retrofit, OkHttp, and API Communication. Use when integrating Retrofit, OkHttp, or API clients in Android apps. (triggers: **/*Api.kt, **/*Service.kt, **/*Client.kt, Retrofit, OkHttpClient, @GET, @POST)