Skip to content
Developer Preview

Rust SDK

The Rust SDK is the muse-code-sdk crate on crates.io: an async client for driving Muse Code over the Muse Session Protocol from your own Tokio runtime. It covers the same journey as the TypeScript and Python SDKs. You spawn a muse serve host or attach to a transport you already run, open and resume sessions, stream a turn’s items as they arrive, and answer approval requests with a handler you register. The generated wire types are in muse_code_sdk::msp.

  • Install Muse Code. curl https://dev.meta.ai/install.sh | bash installs a checksum-verified muse launcher in ~/.local/bin, adds it to your PATH, and keeps it up to date; the user manual has the details. Run muse --version to see which release you have. Because muse updates itself, it can move ahead of a pinned crate. If that release changed the protocol, the connection reports fingerprint_warning and stays open, but calls whose shape changed can fail. Move your pin to the version muse --version prints.
  • Log in once. Run muse and log in, or point your program’s HOME at a profile that already has credentials. A host with no provider credentials fails every turn.
  • Rust 1.97 or newer, and a Tokio runtime. The crate never starts a runtime of its own; you drive it from yours.

The crate does not bundle a host. It runs the muse on your PATH, or the binary you name in SpawnOptions::muse_bin. With neither, it fails before spawning anything with a “no muse host found” error that points at the compatibility page.

Every Muse Code release ships the crate at the same version: muse-code-sdk X.Y.Z pairs with Muse Code X.Y.Z. Use the version muse --version prints and pin it exactly:

Terminal window
cargo add muse-code-sdk@=X.Y.Z
cargo add tokio --features macros,rt

The second line is for the examples on this page. They run on tokio, which the crate uses but does not re-export, under #[tokio::main(flavor = "current_thread")]; a plain #[tokio::main] also needs the rt-multi-thread feature. The first writes an exact requirement into your manifest:

[dependencies]
muse-code-sdk = "=X.Y.Z"

The = matters. Cargo treats every later 1.x release as compatible, but a Muse Code minor release can change the protocol, so an unpinned requirement can pick up a crate built for a newer host than the one you run.

use muse_code_sdk::client::{MuseClient, StartSessionOptions};
use muse_code_sdk::msp::{TurnInputPart, TurnInputPartType};
use muse_code_sdk::session::SendUserTurnOptions;
use muse_code_sdk::spawn::SpawnOptions;
use muse_code_sdk::turn::TurnOutcome;
#[tokio::main(flavor = "current_thread")]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let connection = MuseClient::spawn(SpawnOptions::default()).await?;
let client = connection.client;
let session = client.start_session(StartSessionOptions::default()).await?;
let turn = session
.send_user_turn(SendUserTurnOptions {
input: vec![text_part("Summarize this repository.")],
..SendUserTurnOptions::default()
})
.await?;
let mut items = turn.items();
while let Some(item) = items.recv().await? {
println!("{:?}", item.kind);
}
match turn.completed().await? {
TurnOutcome::Completed { params, .. } => println!("turn ended as {:?}", params.terminal),
TurnOutcome::Unqueued(params) => println!("turn {} was unqueued", params.turn_id),
_ => println!("turn ended"),
}
client.close().await;
Ok(())
}
fn text_part(text: impl Into<String>) -> TurnInputPart {
TurnInputPart {
part_type: TurnInputPartType::Text,
text: Some(text.into()),
media_type: None,
base64_data: None,
width: None,
height: None,
selector: None,
arguments: None,
upload_id: None,
source: None,
}
}

MuseClient::spawn and MuseClient::attach both complete the handshake before they return. A host serving a schema fingerprint the crate was not built against sets connection.fingerprint_warning, and the connection stays open, but calls whose shape changed can fail. Move your pin to the version muse --version prints.

Open protocol enums are #[non_exhaustive], and so are the SDK’s own public enums (its errors, outcomes and states). A match on one needs a catch-all _ arm, so when you move your pin to a newer crate that adds a value, your build still compiles.

  • API reference. rustdoc builds it for every published version. Find muse-code-sdk on crates.io and follow the crate page’s Documentation link.
  • Examples. The crate’s examples directory holds a fuller quickstart and recipes for approvals, retries and cancellation. They ship inside the package.
  • Source. The crate is published from the rust folder of the public SDK repository, which every release refreshes.
  • The protocol. MSP concepts and the wire protocol reference apply unchanged: the crate speaks the same protocol as the other SDKs.