mcpField
S
swift-valkey

swift-valkey

github.com/wendylabsincDevelopment6267 installsUpdated 5w ago
Repository

About swift-valkey

swift-valkey is a Valkey/Redis client library for Swift developers, with async/await support and connections to single servers or clusters. It covers common data structures as well as pub/sub, transactions, pipelining, and cluster routing.

Key features

  1. 01Swift async/await client
  2. 02Connects to single servers or clusters
  3. 03Supports strings, hashes, lists, and sets
  4. 04Pub/sub messaging
  5. 05Transactions and pipelined execution
  6. 06Routes cluster commands by key hash slots

Use cases

  1. 01Read and write Valkey or Redis data in Swift apps
  2. 02Access sharded data through cluster mode
  3. 03Send notifications with pub/sub
  4. 04Run batches of commands or transactions

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/wendylabsinc/claude-skills --skill swift-valkey

After installing, type/swift-valkeyin Claude Code to confirm it loaded.

Bundled filesreferences/valkey-patterns.md

Details

From the project README

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": "[email protected]"])

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

Comments

Markdown supported