# Rust Quickstart (Beta) > Source: `src/content/docs/actors/quickstart/rust.mdx` > Canonical URL: https://rivet.dev/docs/actors/quickstart/rust > Description: Build a Rivet Actor in Rust --- Rust support is in beta. The supported public Rust API is `rivetkit` and `rivetkit-client`; lower-level crates are internal implementation details and do not carry a stability guarantee. See the full API reference on [docs.rs/rivetkit](https://docs.rs/rivetkit), or the runnable [`hello-world-rust`](https://github.com/rivet-dev/rivet/tree/main/examples/hello-world-rust) example. ## Steps ### Add Rivet Add the `rivetkit` crate and its companions: ```sh cargo add rivetkit anyhow async-trait cargo add serde --features derive cargo add tokio --features full ``` ### Define Your Actor Put the actor in `src/lib.rs` so both your server and your client can share the same types. An actor is a type that implements `Actor`, plus one `Handles` implementation for each action. Persisted state lives in `type State`; ephemeral runtime state is just fields on your actor struct. ```rust src/lib.rs use std::{future::Future, pin::Pin, sync::Arc}; use async_trait::async_trait; use rivetkit::prelude::*; use serde::{Deserialize, Serialize}; type BoxFuture = Pin> + Send>>; pub struct Counter; #[derive(Default, Serialize, Deserialize)] pub struct CounterState { pub count: i64, } #[derive(Serialize, Deserialize)] pub struct Increment { pub amount: i64, } impl Action for Increment { type Output = i64; const NAME: &'static str = "increment"; } #[derive(Serialize, Deserialize)] pub struct NewCount { pub count: i64, } impl Event for NewCount { const NAME: &'static str = "newCount"; } #[async_trait] impl Actor for Counter { type State = CounterState; type Input = (); type Actions = (Increment,); type Events = (NewCount,); type Queue = (); type ConnParams = (); type ConnState = (); type Action = action::Raw; async fn create_state(_ctx: &Ctx, _input: Self::Input) -> Result { Ok(CounterState::default()) } async fn create(_ctx: &Ctx) -> Result { Ok(Self) } } impl Handles for Counter { type Future = BoxFuture; fn handle(self: Arc, ctx: Ctx, action: Increment) -> Self::Future { Box::pin(async move { let count = { let mut state = ctx.state_mut(); state.count += action.amount; state.count }; ctx.emit(NewCount { count })?; Ok(count) }) } } pub fn registry() -> Registry { let mut registry = Registry::new(); registry.register_actor::("counter"); registry } ``` ### Serve The Registry Your `src/main.rs` just starts the registry from the library: ```rust src/main.rs #[tokio::main] async fn main() -> anyhow::Result<()> { counter::registry().start().await } ``` Replace `counter` with your crate name (the package `name` in `Cargo.toml`, with dashes as underscores). ### Run The Server The Rust runtime connects to the Rivet Engine. Setting `RIVETKIT_ENGINE_AUTO_DOWNLOAD=1` lets the runtime download and cache a matching engine binary the first time you run, so there is nothing else to install: ```sh RIVETKIT_ENGINE_AUTO_DOWNLOAD=1 cargo run ``` Your server now connects to the Rivet Engine on `http://localhost:6420`. Clients connect directly to the engine on this port. Visit [http://localhost:6420](http://localhost:6420) in your browser (or point your AI agent at it) to open the Rivet developer tools and inspect your actors live. Already have an engine binary? Set `RIVET_ENGINE_BINARY_PATH=/path/to/rivet-engine` to point at it instead. If you are working inside the [Rivet monorepo](https://github.com/rivet-dev/rivet), a local `cargo build -p rivet-engine` is discovered automatically from `target/debug`. ### Connect To The Rivet Actor This code can run either in your frontend or within your backend: ### Rust Add a `src/bin/client.rs` that imports the same actor types from your library. There is no need to redefine the actor on the client. ```rust src/bin/client.rs use counter::{Counter, Increment, NewCount}; use rivetkit::{ client::{Client, ClientConfig}, prelude::*, TypedClientExt, }; #[tokio::main] async fn main() -> Result<()> { let client = Client::new(ClientConfig::new("http://localhost:6420").namespace("default")); let counter = client.get_or_create_typed_default::("counter", ["my-counter"])?; let count = counter.send(Increment { amount: 3 }).await?; println!("New count: {count}"); let connection = counter.connect(); connection .on::(|event| println!("Count changed: {}", event.count)) .await; connection.send(Increment { amount: 1 }).await?; Ok(()) } ``` With the server still running, start the client in another terminal: ```sh cargo run --bin client ``` See the [`hello-world-rust`](https://github.com/rivet-dev/rivet/tree/main/examples/hello-world-rust) example for a complete runnable counter. ### TypeScript A TypeScript client can call your Rust actor by name through the same engine. Actor and action names are resolved at runtime, so the client is untyped here: ```ts client.ts @nocheck import { createClient } from "rivetkit/client"; const client = createClient("http://localhost:6420"); const counter = client.counter.getOrCreate(["my-counter"]); const counterConnection = counter.connect(); counterConnection.on("newCount", (event) => { console.log("Event count:", event.count); }); const count = await counterConnection.increment(3); console.log("New count:", count); await counterConnection.increment(1); ``` See the [JavaScript client documentation](/docs/clients/javascript) for more information. ### React ```tsx Counter.tsx @nocheck import { createRivetKit } from "@rivetkit/react"; import { useState } from "react"; const { useActor } = createRivetKit("http://localhost:6420"); function Counter() { const [count, setCount] = useState(0); const counter = useActor({ name: "counter", key: ["my-counter"], }); const increment = async () => { await counter.connection?.increment(1); }; counter.useEvent("newCount", (event) => { setCount(event.count); }); return (

Count: {count}

); } ``` See the [React documentation](/docs/clients/react) for more information. ### Deploy ## Next Steps - [API Reference](https://docs.rs/rivetkit) — Full `rivetkit` crate documentation on docs.rs. - [Actions](/docs/actors/actions) — Define the RPC surface clients call on your actor. - [State](/docs/actors/state) — Persist and load actor state across sleeps and restarts. - [Events](/docs/actors/events) — Broadcast realtime updates to connected clients. _Source doc path: /docs/actors/quickstart/rust_