Token导航 LogoToken导航TokenDH.com
开发敏感数据github未标认证来源可访问clear审计异常

rivetkit-client-swiftuiRivetkit 客户端 swiftui

Agent Skill

rivetkit-client-swiftui 用于记录任务执行中的错误、用户纠正、经验和能力缺口,适合在 Codex、Claude、Cursor、Gemini CLI 中希望让 Agent 持续沉淀问题、修正和最佳实践时使用。可结合来源仓库、安装命令和原始 README 继续核验具体用法。安装前建议确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写。

总安装

108,066

周安装

4,479

GitHub Stars

14

下载量

35,879
CodexClaudeCursorGemini CLI

安装说明

本站只整理中文说明和来源信息,不托管安装包,也不代用户安装。

GitHub

来源数

3

许可证

MIT

最后核验

2026-05-01

来源状态

来源可访问

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:rivetkit-client-swiftui(Rivetkit 客户端 swiftui)
来源仓库:https://github.com/rivet-dev/skills
仓库路径:skills/rivetkit-client-swiftui
安装命令:
npx skills add https://github.com/rivet-dev/skills --skill rivetkit-client-swiftui
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。不同来源提供的安装方式可能略有差异;本站展示可直接复制的安装命令,安装前请核对来源页面。

skills.shnpx skills
npx skills add https://github.com/rivet-dev/skills --skill rivetkit-client-swiftui

简介

SwiftUI 客户端库,用于通过反应式绑定和事件流连接到 Rivet Actors。

  • 提供@Actor
  • 用于获取或创建语义的属性包装器,具有连接生命周期管理,以及用于环境设置和事件订阅的视图修饰符
  • 支持类型化异步操作、即发即忘发送以及具有 0-5 个类型化参数的 AsyncStream 事件订阅
  • 包括连接状态跟踪、通过 ActorError 进行错误处理,以及对分层参与者寻址的复合键支持
  • 需要单个 .rivetKit(endpoint:)
  • 或 .rivetKit(客户端:)
  • 在应用程序根目录调用;从环境变量中读取可选配置(RIVET_NAMESPACE, RIVET_TOKEN, 铆钉_RUNNER)

SKILL.md

RivetKit SwiftUI Client

Use this skill when building SwiftUI apps that connect to Rivet Actors with RivetKitSwiftUI.

Version

RivetKit version: 2.2.0

Error Handling Policy

  • Prefer fail-fast behavior by default.
  • Avoid broad do/catch unless absolutely needed.
  • If a catch block is used, handle the error explicitly, at minimum by logging it.

Install

Add the Swift package dependency and import RivetKitSwiftUI:

// Package.swift
dependencies: [
    .package(url: "https://github.com/rivet-dev/rivetkit-swift", from: "2.0.0")
]

targets: [
    .target(
        name: "MyApp",
        dependencies: [
            .product(name: "RivetKitSwiftUI", package: "rivetkit-swift")
        ]
    )
]

RivetKitSwiftUI re-exports RivetKitClient and SwiftUI, so a single import covers both.

Minimal Client

import RivetKitSwiftUI
import SwiftUI

@main
struct HelloWorldApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
                .rivetKit(endpoint: "https://my-namespace:pk_...@api.rivet.dev")
        }
    }
}
import RivetKitSwiftUI
import SwiftUI

struct ContentView: View {
    @Actor("counter", key: ["my-counter"]) private var counter
    @State private var count = 0

    var body: some View {
        VStack(spacing: 16) {
            Text("\(count)")
                .font(.system(size: 64, weight: .bold, design: .rounded))

            Button("Increment") {
                counter.send("increment", 1)
            }
            .disabled(!counter.isConnected)
        }
        .task {
            count = (try? await counter.action("getCount")) ?? 0
        }
        .onActorEvent(counter, "newCount") { (newCount: Int) in
            count = newCount
        }
    }
}

Actor Options

The @Actor property wrapper always uses get-or-create semantics and accepts:

  • name (required)
  • key as String or [String] (required)
  • params (optional connection parameters)
  • createWithInput (optional creation input)
  • createInRegion (optional creation hint)
  • enabled (toggle connection lifecycle)
import RivetKitSwiftUI
import SwiftUI

struct ConnParams: Encodable {
    let authToken: String
}

struct ChatView: View {
    @Actor(
        "chatRoom",
        key: ["general"],
        params: ConnParams(authToken: "jwt-token"),
        enabled: true
    ) private var chat

    var body: some View {
        Text("Chat: \(chat.connStatus.rawValue)")
    }
}

Actions

import RivetKitSwiftUI
import SwiftUI

struct CounterView: View {
    @Actor("counter", key: ["my-counter"]) private var counter
    @State private var count = 0
    @State private var name = ""

    var body: some View {
        VStack {
            Text("Count: \(count)")
            Text("Name: \(name)")

            Button("Fetch") {
                Task {
                    count = try await counter.action("getCount")
                    name = try await counter.action("rename", "new-name")
                }
            }

            Button("Increment") {
                counter.send("increment", 1)
            }
        }
    }
}

Subscribing to Events

import RivetKitSwiftUI
import SwiftUI

struct GameView: View {
    @Actor("game", key: ["game-1"]) private var game
    @State private var count = 0
    @State private var isGameOver = false

    var body: some View {
        VStack {
            Text("Count: \(count)")
            if isGameOver {
                Text("Game Over!")
            }
        }
        .onActorEvent(game, "newCount") { (newCount: Int) in
            count = newCount
        }
        .onActorEvent(game, "gameOver") {
            isGameOver = true
        }
    }
}

Async Event Streams

import RivetKitSwiftUI
import SwiftUI

struct ChatView: View {
    @Actor("chatRoom", key: ["general"]) private var chat
    @State private var messages: [String] = []

    var body: some View {
        List(messages, id: \.self) { message in
            Text(message)
        }
        .task {
            for await message in chat.events("message", as: String.self) {
                messages.append(message)
            }
        }
    }
}

Connection Status

import RivetKitSwiftUI
import SwiftUI

struct StatusView: View {
    @Actor("counter", key: ["my-counter"]) private var counter
    @State private var count = 0

    var body: some View {
        VStack {
            Text("Status: \(counter.connStatus.rawValue)")

            if counter.connStatus == .connected {
                Text("Connected!")
                    .foregroundStyle(.green)
            }

            Button("Fetch via Handle") {
                Task {
                    if let handle = counter.handle {
                        count = try await handle.action("getCount", as: Int.self)
                    }
                }
            }
            .disabled(!counter.isConnected)
        }
    }
}

Error Handling

import RivetKitSwiftUI
import SwiftUI

struct UserView: View {
    @Actor("user", key: ["user-123"]) private var user
    @State private var errorMessage: String?
    @State private var username = ""

    var body: some View {
        VStack {
            TextField("Username", text: $username)

            Button("Update Username") {
                Task {
                    do {
                        let _: String = try await user.action("updateUsername", username)
                    } catch let error as ActorError {
                        errorMessage = "\(error.code): \(String(describing: error.metadata))"
                    }
                }
            }

            if let errorMessage {
                Text(errorMessage)
                    .foregroundStyle(.red)
            }
        }
        .onActorError(user) { error in
            errorMessage = "\(error.group).\(error.code): \(error.message)"
        }
    }
}

Concepts

Keys

Keys uniquely identify actor instances. Use compound keys (arrays) for hierarchical addressing:

import RivetKitSwiftUI
import SwiftUI

struct OrgChatView: View {
    @Actor("chatRoom", key: ["org-acme", "general"]) private var room

    var body: some View {
        Text("Room: \(room.connStatus.rawValue)")
    }
}

Don't build keys with string interpolation like "org:\(userId)" when userId contains user data. Use arrays instead to prevent key injection attacks.

Environment Configuration

Call .rivetKit(endpoint:) or .rivetKit(client:) once at the root of your view tree:

// With endpoint string (recommended for most apps)
@main
struct MyApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
                .rivetKit(endpoint: "https://my-namespace:pk_...@api.rivet.dev")
        }
    }
}

// With custom client (for advanced configuration)
@main
struct MyApp: App {
    private let client = RivetKitClient(
        config: try! ClientConfig(endpoint: "https://api.rivet.dev", token: "pk_...")
    )

    var body: some Scene {
        WindowGroup {
            ContentView()
                .rivetKit(client: client)
        }
    }
}

When using .rivetKit(endpoint:), the client is created once and cached per endpoint. When using .rivetKit(client:), store the client as a property on App (not inside body) since SwiftUI can call body multiple times.

Environment Variables

ClientConfig reads optional values from environment variables:

  • RIVET_NAMESPACE - Namespace (can also be in endpoint URL)
  • RIVET_TOKEN - Authentication token (can also be in endpoint URL)
  • RIVET_RUNNER - Runner name (defaults to "default")

The endpoint is always required. There is no default endpoint.

Endpoint Format

Endpoints support URL auth syntax:

https://namespace:token@api.rivet.dev

You can also pass the endpoint without auth and provide RIVET_NAMESPACE and RIVET_TOKEN separately. For serverless deployments, set the endpoint to your app's /api/rivet URL. See Endpoints for details.

API Reference

Property Wrapper

  • @Actor(name, key:, params:, createWithInput:, createInRegion:, enabled:) - SwiftUI property wrapper for actor connections

View Modifiers

  • .rivetKit(endpoint:) - Configure client with an endpoint URL (creates cached client)
  • .rivetKit(client:) - Configure client with a custom instance
  • .onActorEvent(actor, event) {...} - Subscribe to actor events (supports 0–5 typed args)
  • .onActorError(actor) {error in...} - Handle actor errors

ActorObservable

  • actor.action(name, args..., as:) - Async action call
  • actor.send(name, args...) - Fire-and-forget action
  • actor.events(name, as:) - AsyncStream of typed events
  • actor.connStatus - Current connection status
  • actor.isConnected - Whether connected
  • actor.handle - Underlying ActorHandle (optional)
  • actor.connection - Underlying ActorConnection (optional)
  • actor.error - Most recent error (optional)

Types

  • ActorConnStatus - Connection status enum (.idle, .connecting, .connected, .disconnected, .disposed)
  • ActorError - Typed actor errors with group, code, message, metadata

Need More Than the Client?

If you need more about Rivet Actors, registries, or server-side RivetKit, add the main skill:

npx skills add rivet-dev/skills

Then use the rivetkit skill for backend guidance.

适合场景

01

用户想查找某类 Agent Skill 时

02

需要根据任务场景推荐可安装能力包时

03

需要对比不同来源的安装命令和来源信息时

04

需要参考平台分布和安装热度时

能力概览

能力 1

按任务关键词查找相关 Skills

能力 2

展示可复制的安装命令

能力 3

保留来源站点、仓库和原始说明,方便继续核验

能力 4

补充不同宿主或平台的使用分布数据

能力 5

展示第三方安全扫描或审计结果

安装后应在对应宿主中按原始 README 的触发条件使用;具体调用方式请以来源页面和 README 为准。

平台分布

github-copilot

26.26%
按下载量换算9,422

Claude Code

20.95%
按下载量换算7,517

Gemini CLI

20%
按下载量换算7,176

Codex

14.39%
按下载量换算5,163

Cursor

7.81%
按下载量换算2,802

Antigravity

3.79%
按下载量换算1,360

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

未通过

权限和风险

敏感数据

该 Skill 可能接触密钥、Token、环境变量或敏感配置,应进入高风险复核队列,默认不自动发布。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。来源安全扫描存在 warning/failed 结果,不能写成本站确认安全。

来源信息

继续浏览同类 Skills