Agent skill
rivetkit-client-javascript
RivetKit JavaScript client guidance. Use for browser, Node.js, or Bun clients that connect to Rivet Actors with rivetkit/client, create clients, call actions, or manage connections.
Install this agent skill to your Project
npx add-skill https://github.com/rivet-dev/skills/tree/main/rivetkit-client-javascript
SKILL.md
RivetKit JavaScript Client
Use this skill when building JavaScript clients (browser, Node.js, or Bun) that connect to Rivet Actors with rivetkit/client.
First Steps
- Install the client (latest: 2.2.0)
bash
npm install rivetkit@2.2.0 - Create a client with
createClient()and call actor actions.
Error Handling Policy
- Prefer fail-fast behavior by default.
- Avoid
try/catchunless absolutely needed. - If a
catchis used, handle the error explicitly, at minimum by logging it.
Getting Started
See the backend quickstart guide for getting started.
Minimal Client
import { createClient } from "rivetkit/client";
import type { registry } from "./index";
const client = createClient<typeof registry>({
endpoint: "https://my-namespace:pk_...@api.rivet.dev",
});
const counter = client.counter.getOrCreate(["my-counter"]);
const count = await counter.increment(1);
import { actor, setup } from "rivetkit";
export const counter = actor({
state: { count: 0 },
actions: {
increment: (c, x: number) => {
c.state.count += x;
return c.state.count;
},
},
});
export const registry = setup({
use: { counter },
});
registry.start();
Stateless vs Stateful
import { createClient } from "rivetkit/client";
const client = createClient();
const handle = client.counter.getOrCreate(["my-counter"]);
// Stateless: each call is independent
await handle.increment(1);
// Stateful: keep a connection open for realtime events
const conn = handle.connect();
conn.on("count", (value) => console.log(value));
await conn.increment(1);
Getting Actors
import { createClient } from "rivetkit/client";
const client = createClient();
const room = client.chatRoom.getOrCreate(["room-42"]);
const existing = client.chatRoom.get(["room-42"]);
const created = await client.game.create(["game-1"], {
input: { mode: "ranked" },
});
const byId = client.chatRoom.getForId("actor-id");
const resolvedId = await room.resolve();
Connection Parameters
import { createClient } from "rivetkit/client";
const client = createClient();
const chat = client.chatRoom.getOrCreate(["general"], {
params: { authToken: "jwt-token-here" },
});
const conn = chat.connect();
import { createClient } from "rivetkit/client";
async function getAuthToken(): Promise<string> {
return "jwt-token-here";
}
const client = createClient();
const chat = client.chatRoom.getOrCreate(["general"], {
getParams: async () => ({
authToken: await getAuthToken(),
}),
});
const conn = chat.connect();
Use params for static connection parameters. Use getParams when the value can change between connection attempts, such as refreshing a JWT before each .connect() or reconnect.
Subscribing to Events
import { createClient } from "rivetkit/client";
const client = createClient();
const conn = client.chatRoom.getOrCreate(["general"]).connect();
conn.on("message", (msg) => console.log(msg));
conn.once("gameOver", () => console.log("done"));
Connection Lifecycle
import { createClient } from "rivetkit/client";
const client = createClient();
const conn = client.chatRoom.getOrCreate(["general"]).connect();
conn.onOpen(() => console.log("connected"));
conn.onClose(() => console.log("disconnected"));
conn.onError((err) => console.error("error:", err));
conn.onStatusChange((status) => console.log("status:", status));
await conn.dispose();
Low-Level HTTP & WebSocket
For actors that implement onRequest or onWebSocket, call them directly:
import { createClient } from "rivetkit/client";
const client = createClient();
const handle = client.chatRoom.getOrCreate(["general"]);
const response = await handle.fetch("history");
const history = await response.json();
const ws = await handle.webSocket("stream");
ws.addEventListener("message", (event) => {
console.log("message:", event.data);
});
ws.send("hello");
Calling from Backend
import { Hono } from "hono";
import { createClient } from "rivetkit/client";
const app = new Hono();
const client = createClient();
app.post("/increment/:name", async (c) => {
const counterHandle = client.counter.getOrCreate([c.req.param("name")]);
const newCount = await counterHandle.increment(1);
return c.json({ count: newCount });
});
Error Handling
import { ActorError } from "rivetkit/client";
import { createClient } from "rivetkit/client";
const client = createClient();
try {
await client.user.getOrCreate(["user-123"]).updateUsername("ab");
} catch (error) {
if (error instanceof ActorError) {
console.log(error.code, error.metadata);
}
}
Concepts
Keys
Keys uniquely identify actor instances. Use compound keys (arrays) for hierarchical addressing:
import { createClient } from "rivetkit/client";
import type { registry } from "./index";
const client = createClient<typeof registry>("http://localhost:6420");
// Compound key: [org, room]
client.chatRoom.getOrCreate(["org-acme", "general"]);
import { actor, setup } from "rivetkit";
export const chatRoom = actor({
state: { messages: [] as string[] },
actions: {
getRoomInfo: (c) => ({ org: c.key[0], room: c.key[1] }),
},
});
export const registry = setup({
use: { chatRoom },
});
registry.start();
Don't build keys with string interpolation like "org:${userId}" when userId contains user data. Use arrays instead to prevent key injection attacks.
Environment Variables
createClient() automatically reads:
RIVET_ENDPOINT(endpoint)RIVET_NAMESPACERIVET_TOKENRIVET_RUNNER
Defaults to http://localhost:6420 when unset. RivetKit runs on port 6420 by default.
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, use your app's /api/rivet URL. See Endpoints for details.
API Reference
Package: rivetkit
See the RivetKit client overview.
createClient- Create a clientcreateEngineDriver- Engine driverDriverConfig- Driver configurationClient- Client type
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.
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
multiplayer-game
Pragmatic patterns for building multiplayer games: matchmaking, tick loops, realtime state, interest management, and validation.
rivetkit-client-swift
RivetKit Swift client guidance. Use for Swift clients that connect to Rivet Actors with RivetKitClient, create actor handles, call actions, or manage connections.
rivetkit-client-react
RivetKit React client guidance. Use for React apps that connect to Rivet Actors with @rivetkit/react, create hooks with createRivetKit, or manage realtime state with useActor.
rivetkit-client-swiftui
RivetKit SwiftUI client guidance. Use for SwiftUI apps that connect to Rivet Actors with RivetKitSwiftUI, @Actor, rivetKit view modifiers, and SwiftUI bindings.
sandbox-agent
Deploy, configure, and integrate Sandbox Agent - a universal API for orchestrating AI coding agents (Claude Code, Codex, OpenCode, Amp) in sandboxed environments. Use when setting up sandbox-agent server locally or in cloud sandboxes (E2B, Daytona, Docker), creating and managing agent sessions via SDK or API, streaming agent events and handling human-in-the-loop interactions, building chat UIs for coding agents, or understanding the universal schema for agent responses.
rivetkit
RivetKit backend and Rivet Actor runtime guidance. Use for building, modifying, debugging, or testing Rivet Actors, registries, serverless/runner modes, deployment, or actor-based workflows.
Didn't find tool you were looking for?