sprites

Crates.iosprites
lib.rssprites
version0.1.0
created_at2026-01-13 00:55:04.13162+00
updated_at2026-01-13 00:55:04.13162+00
descriptionOfficial Rust SDK for Sprites - stateful sandbox environments from Fly.io
homepagehttps://sprites.dev
repositoryhttps://github.com/m-mohamed/sprites-rs
max_upload_size
id2039115
size206,342
m9d5m (m-mohamed)

documentation

https://docs.rs/sprites

README

sprites-rs

Crates.io Documentation License

Official Unofficial Rust SDK for Sprites - stateful sandbox environments from Fly.io.

Sprites are lightweight, persistent VMs powered by Firecracker. They hibernate when idle (no compute cost) and wake instantly when needed. Create checkpoints in ~300ms and restore to any previous state.

Installation

Add to your Cargo.toml:

[dependencies]
sprites = "0.1"
tokio = { version = "1", features = ["rt-multi-thread", "macros"] }

Quick Start

use sprites::SpritesClient;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Create a client with your API token
    let client = SpritesClient::new(std::env::var("SPRITES_TOKEN")?);

    // Create a sprite
    let sprite = client.create("my-sprite").await?;

    // Run commands
    let output = sprite.command("uname").arg("-a").output().await?;
    println!("{}", output.stdout_str());

    // Create a checkpoint
    let checkpoint = sprite.checkpoint("Initial state").await?;
    println!("Created checkpoint: {}", checkpoint.id);

    // Clean up
    sprite.destroy().await?;

    Ok(())
}

Features

Command Execution

The Command API mirrors std::process::Command:

let output = sprite
    .command("npm")
    .arg("install")
    .current_dir("/app")
    .env("NODE_ENV", "production")
    .output()
    .await?;

if output.success() {
    println!("stdout: {}", output.stdout_str());
} else {
    eprintln!("stderr: {}", output.stderr_str());
}

For long-running processes, use spawn() for streaming I/O:

let mut child = sprite.command("npm").arg("run").arg("dev").spawn().await?;

// Wait for completion
let status = child.wait().await?;
println!("Process exited with: {:?}", status);

Checkpoints

Create snapshots for instant rollback (~300ms):

// Checkpoint before risky operations
let checkpoint = sprite.checkpoint("Before migration").await?;

// Run migrations...
sprite.command("npm").arg("run").arg("migrate").output().await?;

// If something goes wrong, restore instantly
sprite.restore(&checkpoint.id).await?;

// List all checkpoints
let checkpoints = sprite.list_checkpoints().await?;
for cp in checkpoints {
    println!("{}: {:?}", cp.id, cp.comment);
}

Network Policies

Control egress with DNS-based filtering:

use sprites::{NetworkPolicy, NetworkPolicyRule, PolicyAction};

let policy = NetworkPolicy {
    rules: vec![
        NetworkPolicyRule {
            domain: "api.anthropic.com".into(),
            action: PolicyAction::Allow,
        },
        NetworkPolicyRule {
            domain: "*.npmjs.org".into(),
            action: PolicyAction::Allow,
        },
        NetworkPolicyRule {
            domain: "*".into(),
            action: PolicyAction::Deny,
        },
    ],
    include: vec![], // Optional policy bundles
};

sprite.set_policy(policy).await?;

Filesystem Access

Read and write files without executing commands:

let fs = sprite.filesystem();

// Read a file
let content = fs.read_file("/app/config.json").await?;

// Write a file
fs.write_file("/app/data.txt", b"Hello, Sprites!").await?;

// List directory
let entries = fs.read_dir("/app").await?;
for entry in entries {
    println!("{}: {} bytes", entry.name, entry.size);
}

Port Forwarding

Proxy local ports to your sprite:

// Forward local:8080 -> sprite:3000
let proxy = sprite.proxy_port(8080, 3000).await?;
println!("Proxy listening on {}", proxy.local_addr());

// Access your sprite's server at localhost:8080
// ...

proxy.close().await?;

Authentication

Get your API token from sprites.dev or exchange Fly.io credentials:

// Using Fly.io macaroon
let token = SpritesClient::create_token(
    std::env::var("FLY_API_TOKEN")?,
    "your-org-slug",
    None,
).await?;

let client = SpritesClient::new(token);

Configuration

Use the builder for advanced configuration:

use std::time::Duration;

let client = SpritesClient::builder(token)
    .base_url("https://api.sprites.dev")
    .timeout(Duration::from_secs(30))
    .build();

Examples

See the examples directory:

# Basic usage
cargo run --example basic

# Debug exec streaming
cargo run --example exec_debug

Related

Contributing

See CONTRIBUTING.md for development setup and guidelines.

License

Apache-2.0 - see LICENSE for details.

Commit count: 6

cargo fmt