Documentation Index
Fetch the complete documentation index at: https://mintlify.com/brimblehq/rexec/llms.txt
Use this file to discover all available pages before exploring further.
Rust SDK
The official Rust SDK for Rexec provides a memory-safe, high-performance interface for Terminal as a Service.
Installation
Add to your Cargo.toml:
[dependencies]
rexec = "1.0"
tokio = { version = "1", features = ["full"] }
Quick Start
use rexec::{RexecClient, CreateContainerRequest};
#[tokio::main]
async fn main() -> Result<(), rexec::Error> {
let client = RexecClient::new(
"https://your-instance.com",
"your-api-token"
);
// Create a container
let container = client.containers()
.create(CreateContainerRequest::new("ubuntu:24.04")
.name("my-sandbox"))
.await?;
println!("Created container: {}", container.id);
// Connect to terminal
let mut term = client.terminal().connect(&container.id).await?;
term.write(b"echo 'Hello from Rexec!'\n").await?;
// Read output
if let Some(data) = term.read().await? {
println!("Output: {}", String::from_utf8_lossy(&data));
}
// Clean up
client.containers().delete(&container.id).await?;
Ok(())
}
Client Initialization
Basic Client
use rexec::RexecClient;
let client = RexecClient::new(
"https://your-instance.com",
"your-api-token"
);
With Custom Configuration
use rexec::{RexecClient, ClientConfig};
let client = RexecClient::with_config(
ClientConfig::new("https://your-instance.com", "your-token")
.timeout(60)
);
Container Operations
The Container service provides methods for managing sandboxed environments.
List Containers
let containers = client.containers().list().await?;
for c in containers {
println!("{}: {}", c.name, c.status);
}
Get Container
let container = client.containers().get("container-id").await?;
println!("Container {} is {}", container.name, container.status);
Create Container
The SDK uses the builder pattern for creating containers:
let container = client.containers()
.create(CreateContainerRequest::new("ubuntu:24.04")
.name("my-container")
.env("MY_VAR", "value")
.env("DEBUG", "true")
.label("project", "demo"))
.await?;
println!("Created: {}", container.id);
Start Container
client.containers().start("container-id").await?;
Stop Container
client.containers().stop("container-id").await?;
Delete Container
client.containers().delete("container-id").await?;
File Operations
Manage files and directories within containers.
List Files
let files = client.files().list("container-id", "/home").await?;
for f in files {
let icon = if f.is_dir { "📁" } else { "📄" };
println!("{} {} ({} bytes)", icon, f.name, f.size);
}
Download File
let content = client.files().download("container-id", "/etc/passwd").await?;
println!("{}", String::from_utf8_lossy(&content));
Create Directory
client.files().mkdir("container-id", "/home/mydir").await?;
Delete File
client.files().delete("container-id", "/home/file.txt").await?;
Terminal Operations
Connect to containers via WebSocket for real-time terminal access.
Connect to Terminal
let mut term = client.terminal().connect("container-id").await?;
// Or with custom size
let mut term = client.terminal()
.connect_with_size("container-id", 120, 40)
.await?;
Write to Terminal
// Write bytes
term.write(b"ls -la\n").await?;
// Write string (convenience method)
term.write_str("echo hello\n").await?;
Read from Terminal
// Single read
if let Some(data) = term.read().await? {
print!("{}", String::from_utf8_lossy(&data));
}
// Loop until connection closes
while let Some(data) = term.read().await? {
print!("{}", String::from_utf8_lossy(&data));
}
Resize Terminal
term.resize(150, 50).await?;
Close Terminal
Advanced Examples
Run a Script
use rexec::{RexecClient, Error};
async fn run_script(
client: &RexecClient,
container_id: &str,
script: &str,
) -> Result<String, Error> {
let mut term = client.terminal().connect(container_id).await?;
let mut output = String::new();
term.write_str(&format!("{}\nexit\n", script)).await?;
while let Some(data) = term.read().await? {
output.push_str(&String::from_utf8_lossy(&data));
}
Ok(output)
}
// Usage
let output = run_script(
&client,
&container.id,
"apt update && apt install -y curl"
).await?;
println!("{}", output);
Concurrent Operations
use futures::future::join_all;
use rexec::{RexecClient, Container, CreateContainerRequest};
async fn create_batch(
client: &RexecClient,
count: usize
) -> Vec<Container> {
let futures: Vec<_> = (0..count)
.map(|i| {
client.containers().create(
CreateContainerRequest::new("ubuntu:24.04")
.name(format!("worker-{}", i))
)
})
.collect();
join_all(futures)
.await
.into_iter()
.filter_map(Result::ok)
.collect()
}
// Create 5 containers in parallel
let containers = create_batch(&client, 5).await;
println!("Created {} containers", containers.len());
Real-time Log Streaming
async fn stream_logs(
client: &RexecClient,
container_id: &str,
command: &str,
) -> Result<(), rexec::Error> {
let mut term = client.terminal().connect(container_id).await?;
term.write_str(&format!("{}\n", command)).await?;
while let Some(data) = term.read().await? {
let output = String::from_utf8_lossy(&data);
print!("{}", output);
// Could also save to file, send to channel, etc.
// tokio::fs::write("logs.txt", &data).await?;
}
Ok(())
}
// Usage
stream_logs(&client, &container.id, "tail -f /var/log/app.log").await?;
Error Recovery
use rexec::{RexecClient, Error};
use std::time::Duration;
async fn create_container_with_retry(
client: &RexecClient,
max_retries: u32,
) -> Result<Container, Error> {
let mut attempts = 0;
loop {
match client.containers()
.create(CreateContainerRequest::new("ubuntu:24.04"))
.await
{
Ok(container) => return Ok(container),
Err(e) if attempts < max_retries => {
attempts += 1;
eprintln!("Attempt {} failed: {}", attempts, e);
tokio::time::sleep(Duration::from_secs(2)).await;
}
Err(e) => return Err(e),
}
}
}
Error Handling
use rexec::{RexecClient, Error};
match client.containers().get("invalid-id").await {
Ok(container) => println!("Found: {}", container.name),
Err(Error::Api { status_code, message }) => {
eprintln!("API Error {}: {}", status_code, message);
}
Err(Error::Connection(msg)) => {
eprintln!("Connection Error: {}", msg);
}
Err(e) => eprintln!("Error: {}", e),
}
Features
The SDK supports optional features:
[dependencies]
# Use rustls instead of native TLS
rexec = { version = "1.0", features = ["rustls"] }
# Default features (native TLS)
rexec = "1.0"
Available features:
default - Uses native TLS
rustls - Use rustls instead of native TLS
Type Safety
The SDK leverages Rust’s type system for compile-time safety:
// The compiler ensures you handle all error cases
let container = client.containers().get(id).await?;
// Builder pattern prevents invalid configurations
let request = CreateContainerRequest::new("ubuntu:24.04")
.name("valid-name") // Returns Self for chaining
.env("KEY", "value"); // Type-safe builder
Source Code
View the full source code on GitHub:
License
MIT License - see LICENSE for details.