swift-valkey

Expert guidance on using Valkey and Redis with Swift. Use when developers mention: (1) Valkey or Redis in Swift, (2) valkey-swift library, (3) RESP protocol or RESP3, (4) Redis cluster routing or hash slots, (5) pub/sub or subscriptions, (6) Redis transactions or MULTI/EXEC, (7) caching with Redis.

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "swift-valkey" with this command: npx skills add joannis/claude-skills/joannis-claude-skills-swift-valkey

Valkey / Redis

Valkey is an open-source, high-performance key-value store (fork of Redis). The valkey-swift library provides a Swift client with full async/await support, cluster routing, and pub/sub.

Quick Start

Installation

Add to Package.swift:

dependencies: [
    .package(url: "https://github.com/valkey-io/valkey-swift.git", from: "1.0.0")
]

Basic Usage

import Valkey

// Connect to single server
let client = try await ValkeyClient.connect(to: .init(host: "localhost", port: 6379))

// Basic operations
try await client.set("key", "value")
let value = try await client.get("key") // Optional<String>

// With expiration
try await client.set("session", sessionData, expiration: .seconds(3600))

// Delete
try await client.del("key")

Cluster Mode

// Connect to cluster
let client = try await ValkeyClient.connect(
    to: .cluster([
        .init(host: "node1.redis.local", port: 6379),
        .init(host: "node2.redis.local", port: 6379),
        .init(host: "node3.redis.local", port: 6379)
    ])
)

// Commands automatically route to correct shard
try await client.set("user:123", userData)

Commands

Strings

// SET with options
try await client.set("key", "value", condition: .nx)  // Only if not exists
try await client.set("key", "value", condition: .xx)  // Only if exists
try await client.set("key", "value", expiration: .milliseconds(5000))

// GET
let value = try await client.get("key")

// INCR/DECR
let newValue = try await client.incr("counter")
let decreased = try await client.decr("counter")
try await client.incrBy("counter", 10)

Hashes

try await client.hset("user:123", field: "name", value: "Alice")
try await client.hset("user:123", fields: ["name": "Alice", "email": "alice@example.com"])

let name = try await client.hget("user:123", field: "name")
let user = try await client.hgetall("user:123") // [String: String]

Lists

try await client.lpush("queue", "item1", "item2")
try await client.rpush("queue", "item3")

let item = try await client.lpop("queue")
let items = try await client.lrange("queue", start: 0, stop: -1)

Sets

try await client.sadd("tags", "swift", "redis", "backend")
let isMember = try await client.sismember("tags", "swift")
let members = try await client.smembers("tags")

Sorted Sets

try await client.zadd("leaderboard", score: 100, member: "player1")
try await client.zadd("leaderboard", members: [("player2", 200), ("player3", 150)])

let top10 = try await client.zrange("leaderboard", start: 0, stop: 9, withScores: true)
let rank = try await client.zrank("leaderboard", member: "player1")

Pub/Sub

// Subscribe to channels
let subscription = try await client.subscribe(to: ["notifications", "updates"])

// Process messages
for try await message in subscription {
    switch message {
    case .message(let channel, let payload):
        print("Received on \(channel): \(payload)")
    case .subscribe(let channel, let count):
        print("Subscribed to \(channel)")
    }
}

// Publish
try await client.publish("notifications", message: "Hello subscribers!")

// Pattern subscribe
let patternSub = try await client.psubscribe(to: ["user:*", "event:*"])

Transactions

// MULTI/EXEC transaction
let results = try await client.transaction(
    SET("key1", "value1"),
    SET("key2", "value2"),
    GET("key1")
)
// Results is tuple: (Result<String?, Error>, Result<String?, Error>, Result<String?, Error>)

Pipelining

// Execute multiple commands in single round-trip
let (setResult, getResult, incrResult) = try await client.execute(
    SET("key", "value"),
    GET("key"),
    INCR("counter")
)

Cluster Routing

Commands are automatically routed to the correct shard based on key hash slots:

// Keys with same hash tag go to same shard
try await client.set("{user:123}:profile", profileData)
try await client.set("{user:123}:settings", settingsData)
// Both keys route to same shard due to {user:123} hash tag

Connection Configuration

let config = ValkeyClient.Configuration(
    endpoints: .single(.init(host: "localhost", port: 6379)),
    password: "secret",
    database: 0,
    connectionTimeout: .seconds(5),
    commandTimeout: .seconds(30),
    tls: .require(.makeClientConfiguration())
)

let client = try await ValkeyClient.connect(configuration: config)

Error Handling

do {
    let value = try await client.get("key")
} catch let error as ValkeyClientError {
    switch error {
    case .connectionClosed:
        // Reconnect logic
    case .timeout:
        // Retry logic
    case .serverError(let message):
        print("Server error: \(message)")
    }
}

Reference Files

Load these files as needed for specific topics:

  • references/valkey-patterns.md - Command protocol pattern, RESP encoding/decoding, cluster routing with hash slots, subscription management, transaction patterns, connection pool integration, module extensions

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

swift-nio

No summary provided by upstream source.

Repository SourceNeeds Review
General

hummingbird

No summary provided by upstream source.

Repository SourceNeeds Review
General

database-driver-design

No summary provided by upstream source.

Repository SourceNeeds Review
General

swift-concurrency

No summary provided by upstream source.

Repository SourceNeeds Review