sail-rs 0.2.18

Official Rust SDK for Sail: create and drive sailboxes (sandboxed cloud VMs) with lifecycle, streaming exec, file transfer, and ingress.
Documentation

sail-rs

The official Rust SDK for Sail. Create and drive sailboxes, sandboxed cloud VMs, from Rust: lifecycle, streaming exec, file transfer, and ingress.

This crate is the canonical core that the Sail Python SDK, the TypeScript SDK, and the sail CLI are all built on, so the Rust API is the source of truth for behavior.

[dependencies]
sail-rs = "0.2"
# tokio must be a direct dependency to write #[tokio::main]:
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }

The crate is published as sail-rs and imported as sail:

use sail::Client;

Adding the crate does not install the sail CLI (a library crate cannot ship a companion binary). Install the CLI separately:

curl -fsSL https://cli.sailresearch.com/install.sh | sh

Quickstart

The client reads its API key from SAIL_API_KEY (falling back to the credential stored under ~/.sail), the same configuration the CLI uses.

use sail::exec::ExecOptions;
use sail::Client;

#[tokio::main]
async fn main() -> Result<(), sail::error::SailError> {
    let client = Client::from_env()?;

    // List the sailboxes in your org.
    let page = client.list_sailboxes(&Default::default()).await?;
    println!("{} sailboxes", page.items.len());

    // Bind a sailbox by id and run a command in it.
    let sb = client.sailbox("sb_...");
    let proc = sb.exec_shell("echo hello from the guest", ExecOptions::default()).await?;
    let result = proc.wait().await?;
    print!("{}", result.stdout);

    Ok(())
}

Runtime

Every method is async. The client is meant to be driven on a Tokio runtime:

  • Async hosts await the methods directly on their own runtime. Streaming operations (exec, read_stream, write_stream) spawn their background pump on the calling task's runtime, so call them from within one.
  • Synchronous code can drive any method with [sail::block_on], which runs it to completion on a shared internal runtime. Do not call block_on from inside an existing runtime; await the method instead.

[Client] is cheap to clone (it shares its connection pools and config behind an Arc), so clone it to share across tasks. Use one client per runtime.

Sail in other languages

  • Python: pip install sail (this crate compiled as a native extension).
  • TypeScript: npm install @sailresearch/sdk (this crate compiled as a napi-rs native addon for Node and Bun).
  • CLI: the sail command, built on this crate.

Documentation

Stability

The public API is everything documented here. Items hidden from this documentation (including the internal module) back the first-party bindings and are not part of the public API.

License

Licensed under the Apache License, Version 2.0.