Crates.io | daytona-client |
lib.rs | daytona-client |
version | 0.5.0 |
created_at | 2025-08-23 16:07:45.401851+00 |
updated_at | 2025-09-19 09:40:05.250266+00 |
description | Rust client for Daytona — secure sandboxes for AI code execution |
homepage | https://github.com/krzysztofwos/daytona-client |
repository | https://github.com/krzysztofwos/daytona-client |
max_upload_size | |
id | 1807645 |
size | 368,601 |
A Rust client library for the Daytona API, providing secure sandbox environments for code execution and development.
Version 0.5.0 — Complete volume and snapshot management with organization support.
These are server-side API bugs, not client library issues:
cwd
parameter exists but doesn't work correctlyAll other features are fully functional and tested.
Add this to your Cargo.toml
:
[dependencies]
daytona-client = "0.5"
use daytona_client::{DaytonaClient, CreateSandboxParams};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Create client from environment variables
let client = DaytonaClient::from_env()?;
// Create a sandbox
let sandbox = client.sandboxes()
.create(CreateSandboxParams {
class: Some("small".to_string()),
..Default::default()
})
.await?;
// Execute a command
let result = client.process()
.execute_command(&sandbox.id, "echo 'Hello from Daytona!'")
.await?;
println!("Output: {}", result.result);
// Clean up
client.sandboxes().delete(&sandbox.id).await?;
Ok(())
}
The client can be configured using environment variables:
DAYTONA_API_KEY
— Daytona API key (required)DAYTONA_BASE_URL
— API base URL (default: https://app.daytona.io/api
)DAYTONA_ORGANIZATION_ID
— Organization ID for multi-org accounts (optional)70+ integration tests covering all implemented features:
use daytona_client::{DaytonaClient, CreateSandboxParams};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = DaytonaClient::from_env()?;
// Create a sandbox
let sandbox = client.sandboxes()
.create(CreateSandboxParams {
class: Some("small".to_string()),
..Default::default()
})
.await?;
println!("Created sandbox: {}", sandbox.id);
// Execute a command
let result = client.process()
.execute_command(&sandbox.id, "echo 'Hello from Daytona!'")
.await?;
println!("Output: {}", result.result);
// Clean up
client.sandboxes().delete(&sandbox.id).await?;
Ok(())
}
// Upload a file
client.files()
.upload(&sandbox.id, "/app/main.py", b"print('Hello World!')")
.await?;
// Download a file
let content = client.files()
.download(&sandbox.id, "/app/main.py")
.await?;
// List directory contents
let entries = client.files()
.list(&sandbox.id, "/app")
.await?;
use daytona_client::GitCloneRequest;
// Clone a repository
let clone_request = GitCloneRequest {
url: "https://github.com/user/repo.git".to_string(),
path: "/workspace".to_string(),
branch: Some("main".to_string()),
depth: Some(1),
auth_token: None,
ssh_key: None,
};
client.git()
.clone(&sandbox.id, clone_request)
.await?;
// Check status
let status = client.git()
.status(&sandbox.id, "/workspace")
.await?;
println!("Current branch: {}", status.current_branch);
use daytona_client::SessionExecuteRequest;
// Create a persistent session
let session_id = "my-session";
client.process()
.create_session(&sandbox.id, session_id)
.await?;
// Execute commands in the session
let response = client.process()
.execute_session_command(&sandbox.id, session_id, SessionExecuteRequest {
command: "python -c 'x = 42; print(f\"x = {x}\")'".to_string(),
run_async: Some(false),
})
.await?;
println!("Session output: {:?}", response.output);
use daytona_client::{CreateWorkspaceParams, WorkspaceState};
// Create a workspace
let workspace = client.workspaces()
.create(CreateWorkspaceParams {
name: "my-project".to_string(),
description: Some("Development environment".to_string()),
class: Some("small".to_string()),
..Default::default()
})
.await?;
// Wait for it to start
let workspace = client.workspaces()
.wait_for_state(&workspace.id, WorkspaceState::Started, 120)
.await?;
println!("Workspace {} is ready!", workspace.id);
use daytona_client::{LspLanguage, SandboxLspExt};
// Initialize LSP for a sandbox
let lsp = sandbox.lsp(&client);
await lsp.start(LspLanguage::TypeScript, "/workspace/project").await?;
// Get code completions
let completions = lsp.get_completions(TextDocumentPosition {
text_document: TextDocumentIdentifier {
uri: "file:///workspace/project/src/main.ts".to_string(),
},
position: Position { line: 10, character: 15 },
}).await?;
// Get hover information
let hover = lsp.get_hover(position).await?;
// Get diagnostics
let diagnostics = lsp.get_diagnostics("file:///workspace/project/src/main.ts").await?;
// Get a public preview URL for a web application running on port 3000
let preview_url = client.sandboxes()
.get_preview_url(&sandbox.id, 3000)
.await?;
println!("Access the application at: {}", preview_url);
use daytona_client::VolumeState;
// Create a volume
let volume = client.volumes()
.create("my-data-volume".to_string())
.await?;
// Wait for volume to be ready
let volume = client.volumes()
.wait_for_state(&volume.id, VolumeState::Ready, 30)
.await?;
// Attach volume to a sandbox
let sandbox = client.sandboxes()
.create(CreateSandboxParams {
volumes: Some(vec![volume.id]),
..Default::default()
})
.await?;
// List all volumes
let volumes = client.volumes().list(false).await?;
println!("Found {} volumes", volumes.len());
// Delete volume
client.volumes().delete(&volume.id).await?;
use daytona_client::{CreateSnapshotRequest, SnapshotState};
// Create a snapshot
let snapshot_request = CreateSnapshotRequest {
name: "my-snapshot".to_string(),
image_name: Some("ubuntu:22.04".to_string()),
cpu: Some(2.0),
memory: Some(4),
disk: Some(20),
entrypoint: Some(vec!["/bin/bash".to_string()]),
..Default::default()
};
let snapshot = client.snapshots()
.create(snapshot_request)
.await?;
// List snapshots with pagination
let paginated = client.snapshots()
.list(Some(10), Some(1), None)
.await?;
println!("Total snapshots: {}", paginated.total);
// Activate a snapshot
client.snapshots().activate(&snapshot.id).await?;
// Get build logs for a snapshot
let logs = client.snapshots()
.get_build_logs(&snapshot.id, true)
.await?;
// Remove snapshot
client.snapshots().remove(&snapshot.id).await?;
use daytona_client::{CreateOrganizationRequest, UpdateOrganizationMemberAccess};
// Create an organization
let org = client.organizations()
.create(CreateOrganizationRequest {
name: "my-team".to_string(),
description: Some("My development team".to_string()),
})
.await?;
// Invite a member
client.organizations()
.invite_member(&org.id, "developer@example.com", "developer")
.await?;
// Update member role
client.organizations()
.update_member(
&org.id,
&member_id,
UpdateOrganizationMemberAccess {
role: "admin".to_string(),
}
)
.await?;
// Create API key for organization
let api_key = client.organizations()
.create_api_key(&org.id, "ci-deployment")
.await?;
println!("New API key: {}", api_key.key);
The client provides comprehensive error types:
use daytona_client::{DaytonaError, Result};
match client.sandboxes().create(params).await {
Ok(sandbox) => println!("Created: {}", sandbox.id),
Err(DaytonaError::QuotaExceeded(msg)) => {
eprintln!("Quota exceeded: {}", msg);
}
Err(DaytonaError::AuthenticationFailed(msg)) => {
eprintln!("Auth failed: {}", msg);
}
Err(e) => eprintln!("Error: {}", e),
}
Set the Daytona API key:
export DAYTONA_API_KEY="api-key"
Tests that create sandboxes are automatically run sequentially using the serial_test
crate to avoid exceeding Daytona's 30GB quota limit:
# Run all tests (resource-intensive tests run sequentially)
cargo test
# Run specific test suites
cargo test --test sandbox_integration
cargo test --test workspace_integration
cargo test --test process_integration
cargo test --test files_integration
cargo test --test git_integration
If tests fail or are interrupted, sandboxes may not be cleaned up. Use the provided utilities:
# Check current resource usage
cargo run --bin verify-cleanup
# Clean up test sandboxes only (safer)
cargo run --bin cleanup-test-sandboxes
# Force cleanup all resources (interactive)
cargo run --bin force-cleanup
Contributions are welcome. Please feel free to submit a Pull Request.
This project is licensed under either of:
at the option of the user.
This client is not officially affiliated with Daytona. For official SDKs, visit Daytona's documentation.