# Daytona Documentation v0.0.0-dev
# Generated on: 2026-03-19
Daytona API keys authenticate requests to the [Daytona API](https://www.daytona.io/docs/en/tools/api.md). They are used by the Daytona [SDKs](https://www.daytona.io/docs/en/getting-started.md#sdks) and [CLI](https://www.daytona.io/docs/en/getting-started.md#cli) to access and manage resources in your organization.
## Create an API key
Daytona provides options to create API keys in [Daytona Dashboard ↗](https://app.daytona.io/dashboard/keys) or programmatically using the [API](https://www.daytona.io/docs/en/tools/api.md#daytona/tag/api-keys).
1. Navigate to [Daytona Dashboard ↗](https://app.daytona.io/dashboard/keys)
2. Click the **Create Key** button
3. Enter the name of the API key, set the expiration date, and [select permissions](#permissions--scopes)
4. Click **Create** to create the API key
5. Copy the API key to your clipboard
To use the API key in your application, set the `DAYTONA_API_KEY` environment variable. Daytona supports multiple options to configure your environment: [in code](https://www.daytona.io/docs/en/configuration.md#configuration-in-code), [environment variables](https://www.daytona.io/docs/en/configuration.md#environment-variables), [.env file](https://www.daytona.io/docs/en/configuration.md#env-file), and [default values](https://www.daytona.io/docs/en/configuration.md#default-values).
API keys support optional expiration and can be revoked at any time. After creation, you can only retrieve a masked key value when listing keys.
```bash
curl 'https://app.daytona.io/api/api-keys' \
--request POST \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer YOUR_API_KEY' \
--data '{
"name": "My API Key",
"permissions": ["write:sandboxes", "delete:sandboxes"],
"expiresAt": "2030-01-01T00:00:00.000Z"
}'
```
For more information, see the [API](https://www.daytona.io/docs/en/tools/api.md#daytona/tag/api-keys) reference:
> [**Create API key (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona/tag/api-keys/POST/api-keys)
## Permissions & Scopes
| **Resource** | **Scope** | **Description** |
| ------------ | ----------------------- | ------------------------ |
| Sandboxes | **`write:sandboxes`** | Create/modify sandboxes |
| | **`delete:sandboxes`** | Delete sandboxes |
| Snapshots | **`write:snapshots`** | Create/modify snapshots |
| | **`delete:snapshots`** | Delete snapshots |
| Registries | **`write:registries`** | Create/modify registries |
| | **`delete:registries`** | Delete registries |
| Volumes | **`read:volumes`** | View volumes |
| | **`write:volumes`** | Create/modify volumes |
| | **`delete:volumes`** | Delete volumes |
| Audit | **`read:audit_logs`** | View audit logs |
| Regions | **`write:regions`** | Create/modify regions |
| | **`delete:regions`** | Delete regions |
| Runners | **`read:runners`** | View runners |
| | **`write:runners`** | Create/modify runners |
| | **`delete:runners`** | Delete runners |
## List API keys
Daytona provides methods to list all API keys for the current user or organization.
```bash
curl 'https://app.daytona.io/api/api-keys' \
--header 'Authorization: Bearer YOUR_API_KEY'
```
For more information, see the [API](https://www.daytona.io/docs/en/tools/api.md#daytona/tag/api-keys) reference:
> [**list (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona/tag/api-keys/GET/api-keys)
## Get current API key
Daytona provides methods to get details of the API key used to authenticate the current request.
```bash
curl 'https://app.daytona.io/api/api-keys/current' \
--header 'Authorization: Bearer YOUR_API_KEY'
```
For more information, see the [API](https://www.daytona.io/docs/en/tools/api.md#daytona/tag/api-keys) reference:
> [**get current (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona/tag/api-keys/GET/api-keys/current)
## Get API key
Daytona provides methods to get a single API key by name.
```bash
curl 'https://app.daytona.io/api/api-keys/my-api-key' \
--header 'Authorization: Bearer YOUR_API_KEY'
```
For more information, see the [API](https://www.daytona.io/docs/en/tools/api.md#daytona/tag/api-keys) reference:
> [**get (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona/tag/api-keys/GET/api-keys/{name})
## Delete API key
Daytona provides options to delete an API key in [Daytona Dashboard ↗](https://app.daytona.io/dashboard/keys) or programmatically using the API. The key is revoked immediately and cannot be recovered.
1. Navigate to [Daytona Dashboard ↗](https://app.daytona.io/dashboard/keys)
2. Click **Revoke** next to the API key you want to delete
3. Confirm the revocation
```bash
curl 'https://app.daytona.io/api/api-keys/my-api-key' \
--request DELETE \
--header 'Authorization: Bearer YOUR_API_KEY'
```
For more information, see the [API](https://www.daytona.io/docs/en/tools/api.md#daytona/tag/api-keys) reference:
> [**delete (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona/tag/api-keys/DELETE/api-keys/{name})
## Delete API key for user
Daytona provides options for organization admins to delete an API key for a specific user.
```bash
curl 'https://app.daytona.io/api/api-keys/{userId}/my-api-key' \
--request DELETE \
--header 'Authorization: Bearer YOUR_API_KEY'
```
For more information, see the [API](https://www.daytona.io/docs/en/tools/api.md#daytona/tag/api-keys) reference:
> [**delete for user (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona/tag/api-keys/DELETE/api-keys/{userId}/{name})
Daytona provides **full composable computers** — [sandboxes](https://www.daytona.io/docs/en/sandboxes.md) — for AI agents. Daytona platform is organized into multiple plane components, each serving a specific purpose:
- [Interface plane](#interface-plane) provides client interfaces for interacting with Daytona
- [Control plane](#control-plane) orchestrates all sandbox operations
- [Compute plane](#compute-plane) runs and manages sandbox instances
### Interface plane
The interface plane provides client interfaces for users and agents to interact with Daytona. The following components are part of the interface plane and available to all users and agents:
- **SDK**: [Python](https://www.daytona.io/docs/en/python-sdk.md), [TypeScript](https://www.daytona.io/docs/en/typescript-sdk.md), [Ruby](https://www.daytona.io/docs/en/ruby-sdk.md), and [Go](https://www.daytona.io/docs/en/go-sdk.md) for programmatic sandbox management
- [CLI](https://www.daytona.io/docs/en/tools/cli.md): command-line interface for direct sandbox operations
- [Dashboard](https://app.daytona.io/dashboard/): web interface for visual sandbox management and monitoring
- [MCP](https://www.daytona.io/docs/en/mcp.md): Model Context Protocol server for AI tool integration
- [SSH](https://www.daytona.io/docs/en/ssh-access.md): secure shell access to running sandboxes
### Control plane
The control plane is the central coordination layer of the Daytona platform. It receives all client requests, manages the full sandbox lifecycle, schedules sandboxes onto runners, and continuously reconciles states across the infrastructure. The control plane includes the following components:
- [API](#api) handles authentication, sandbox lifecycle management, and resource allocation
- [Proxy](#proxy) routes external traffic to sandboxes, enabling direct access to services
- [Snapshot builder](#snapshot-builder) builds and manages sandbox [snapshots](https://www.daytona.io/docs/en/snapshots.md)
- [Sandbox manager](#sandbox-manager) handles sandbox lifecycle management and state reconciliation
#### API
The API is a NestJS-based RESTful service that serves as the primary entry point for all platform operations, managing authentication, sandbox lifecycle, snapshots, volumes, and resource allocation. The [snapshot builder](#snapshot-builder) and [sandbox manager](#sandbox-manager) run as internal processes within the API. The API integrates the following internal services and components:
- **Redis** provides caching, session management, and distributed locking
- **PostgreSQL** serves as the primary persistent store for metadata and configuration
- **Auth0/OIDC provider** authenticates users and services via OpenID Connect. The API enforces organization-level multi-tenancy, where each sandbox, snapshot, and volume belongs to an organization, and access control is applied at the organization boundary
- **SMTP server** handles email delivery for organization invitations, account notifications, and alert messages
- [Sandbox manager](#sandbox-manager) schedules sandboxes onto runners, reconciles states, and enforces sandbox lifecycle management policies
- **PostHog** collects platform analytics and usage metrics for monitoring and improvement
To interact with sandboxes from the API, see the [API](https://www.daytona.io/docs/en/tools/api.md) and [Toolbox API](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox) references.
#### Proxy
The proxy is a dedicated HTTP proxy that routes external traffic to the correct sandbox using host-based routing. Each sandbox is reachable at `{port}-{sandboxId}.{proxy-domain}`, where the port maps to a service running inside the sandbox. The proxy resolves the target runner for a given sandbox, injects authentication headers, and forwards the request. It supports both HTTP and WebSocket protocols.
#### Snapshot builder
The snapshot builder is part of the API process and orchestrates the creation of sandbox [snapshots](https://www.daytona.io/docs/en/snapshots.md) from a Dockerfile or a pre-built image from a [container registry](#container-registry). It coordinates with runners to build or pull images, which are then pushed to an internal snapshot registry that implements the OCI distribution specification.
#### Sandbox manager
The sandbox manager is part of the API process and schedules sandboxes onto runners, reconciles states, and enforces [sandbox lifecycle management](https://www.daytona.io/docs/en/sandboxes.md#sandbox-lifecycle) policies.
### Compute plane
The compute plane is the infrastructure layer where sandboxes run. Sandboxes run on [runners](#sandbox-runners), compute nodes that host multiple sandboxes with dedicated resources and scale horizontally across shared or dedicated [regions](https://www.daytona.io/docs/en/regions.md). The compute plane consists of the following components:
- [Sandbox runners](#sandbox-runners) host sandboxes with dedicated resources
- [Sandbox daemon](#sandbox-daemon) provides code execution and environment access inside each sandbox
- [Snapshot store](#snapshot-store) stores sandbox snapshot images
- [Volumes](#volumes) provides persistent storage shared across sandboxes
#### Sandbox runners
Runners are compute nodes that power Daytona's compute plane, providing the underlying infrastructure for running sandbox workloads. Each runner polls the control plane API for jobs and executes sandbox operations: creating, starting, stopping, destroying, resizing, and backing up sandboxes. Runners interact with S3-compatible object storage for snapshot and volume data, and with the internal snapshot registry.
Each sandbox runs as an isolated instance with its own Linux namespaces for processes, network, filesystem mounts, and inter-process communication. Each runner allocates dedicated vCPU, RAM, and disk resources per sandbox.
#### Sandbox daemon
The sandbox daemon is a code execution agent that runs inside each sandbox. It exposes the [Toolbox API](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox), providing direct access to the sandbox environment: file system and Git operations, process and code execution, computer use, log streaming, and terminal sessions.
#### Snapshot store
The snapshot store is an internal OCI-compliant registry that stores sandbox snapshot images using the OCI distribution specification. Runners pull snapshot images from this store when creating new sandboxes. The store uses S3-compatible object storage as its backend.
#### Volumes
[Volumes](https://www.daytona.io/docs/en/volumes.md) provide persistent storage that can be shared across sandboxes. Each volume is backed by S3-compatible object storage and mounted into sandboxes as a read-write directory. Multiple sandboxes can mount the same volume simultaneously, allowing data to be shared across sandboxes and persist independently of the sandbox lifecycle.
### Container registry
Container registries serve as the source for sandbox base images. When creating a [snapshot](https://www.daytona.io/docs/en/snapshots.md), the snapshot builder pulls the specified image from an external registry, and pushes it to the internal snapshot registry for use by runners. For Dockerfile-based snapshots, parent images referenced in `FROM` directives are also pulled from the configured source registries during the build. Daytona supports any OCI-compatible registry:
- [Docker Hub](https://www.daytona.io/docs/en/snapshots.md#docker-hub)
- [Google Artifact Registry](https://www.daytona.io/docs/en/snapshots.md#google-artifact-registry)
- [GitHub Container Registry (GHCR)](https://www.daytona.io/docs/en/snapshots.md#github-container-registry-ghcr)
- [Private registries](https://www.daytona.io/docs/en/snapshots.md#using-images-from-private-registries): any registry that implements the OCI distribution specification
Daytona audit logs provide a detailed record of user and system activity across your organization. Use this feature to track sandbox lifecycle events, user access, system changes, and more.
- **Security audits**: monitor for unauthorized access or sandbox misuse
- **Debugging**: understand sandbox lifecycle issues (e.g. failed starts)
- **Compliance Export**: export logs for internal or external audits (coming soon)
Audit logs are available to [admins](https://www.daytona.io/docs/en/organizations.md#organization-roles) with full access and [members](https://www.daytona.io/docs/en/organizations.md#organization-roles) with audit log permissions. Contact your organization administrator if you cannot access audit logs.
## Access from Dashboard
Access the audit logs page directly from [Daytona Dashboard ↗](https://app.daytona.io/dashboard/audit-logs). The audit logs page displays a list of all audit logs for your organization, including the following columns:
- **Time**: the timestamp of the action
- **User**: the user who performed the action
- [Actions](#actions): the action performed
- [Targets](#targets): the resource affected by the action
- [Outcomes](#outcomes): the result of the action
To filter audit logs by time, use the date range picker in the top-left corner of the page.
## Real-time updates
Daytona provides real-time updates of audit logs. Enable the **Auto Refresh** toggle in the top-right corner of the [Daytona Audit Logs ↗](https://app.daytona.io/dashboard/audit-logs) page to automatically refresh logs as new events occur.
## Programmatic management
Daytona provides API endpoints for programmatic access to audit logs.
### Get all audit logs
To get all audit logs, use the following API endpoint:
```bash
curl https://app.daytona.io/api/audit \
--header 'Authorization: Bearer YOUR_API_KEY'
```
For more information, see the [API](https://www.daytona.io/docs/en/tools/api.md#daytona/tag/audit) reference:
> [**Get all audit logs (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona/tag/audit/GET/audit-logs)
### Get audit logs for organization
To get audit logs for a specific organization, use the following API endpoint:
```bash
curl https://app.daytona.io/api/audit/organizations/{organizationId} \
--header 'Authorization: Bearer YOUR_API_KEY'
```
For more information, see the [API](https://www.daytona.io/docs/en/tools/api.md#daytona/tag/audit) reference:
> [**Get audit logs for organization (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona/tag/audit/GET/audit/organizations/{organizationId})
## Log Structure
Each audit log entry contains the following fields:
| Field | Type | Description |
| -------------------- | ------ | ---------------------------------------------------- |
| **`id`** | string | Unique log entry identifier |
| **`actorId`** | string | ID of the user who performed the action |
| **`actorEmail`** | string | Email of the user who performed the action |
| **`organizationId`** | string | Organization ID |
| **`action`** | string | Operation executed (e.g., `create`, `start`, `stop`) |
| **`targetType`** | string | Resource type affected (e.g., `sandbox`, `snapshot`) |
| **`targetId`** | string | ID of the affected resource |
| **`statusCode`** | number | HTTP status code of the result |
| **`errorMessage`** | string | Error message if the action failed |
| **`ipAddress`** | string | IP address of the request origin |
| **`userAgent`** | string | User agent of the request origin |
| **`source`** | string | Source of the action |
| **`metadata`** | object | Additional context about the action |
| **`createdAt`** | string | ISO 8601 timestamp of when the action occurred |
## Actions
Below is the complete list of actions logged by Daytona:
```text
create, read, update, delete, login,
set_default, update_access, update_quota, update_region_quota,
suspend, unsuspend, accept, decline,
link_account, unlink_account, leave_organization,
regenerate_key_pair, update_scheduling,
start, stop, replace_labels, create_backup,
update_public_status, set_auto_stop_interval,
set_auto_archive_interval, set_auto_delete_interval, archive,
get_port_preview_url, set_general_status, activate, deactivate,
update_network_settings,
send_webhook_message, initialize_webhooks,
update_sandbox_default_limited_network_egress,
create_ssh_access, revoke_ssh_access,
regenerate_proxy_api_key,regenerate_ssh_gateway_api_key,regenerate_snapshot_manager_credentials,
toolbox_delete_file, toolbox_download_file, toolbox_create_folder,
toolbox_move_file, toolbox_set_file_permissions, toolbox_replace_in_files,
toolbox_upload_file, toolbox_bulk_upload_files,
toolbox_git_add_files, toolbox_git_create_branch, toolbox_git_delete_branch,
toolbox_git_clone_repository, toolbox_git_commit_changes,
toolbox_git_pull_changes, toolbox_git_push_changes,
toolbox_git_checkout_branch, toolbox_execute_command,
toolbox_create_session, toolbox_session_execute_command,
toolbox_delete_session, toolbox_computer_use_start,
toolbox_computer_use_stop, toolbox_computer_use_restart_process
```
## Targets
Each action targets a specific resource type. Possible targets include:
```text
api_key, organization, organization_invitation,
organization_role, organization_user, docker_registry,
runner, sandbox, snapshot, user, volume
```
## Outcomes
The outcome field indicates the result of the action. Statuses follow standard HTTP semantics:
| **Outcome** | **Description** |
| ----------- | ----------------------------- |
| Info | Informational (1xx codes) |
| Success | Action succeeded (2xx codes) |
| Redirect | Redirects (3xx codes) |
| Error | Client/server error (4xx/5xx) |
[Daytona Billing ↗](https://app.daytona.io/dashboard/billing/spending) provides an overview of your organization's billing, wallet, and usage details.
Daytona displays a cost breakdown chart that shows a breakdown of costs per resource. You can choose between area and bar charts and filter by RAM, CPU, and storage. You can also filter by date range (last 12, 6, or 3 months).
## Wallet
[Daytona Wallet ↗](https://app.daytona.io/dashboard/billing/wallet) shows the current balance of the organization's wallet and the amount of credits spent this month.
### Add payment method
Daytona provides a payment method to add to your wallet. You can connect your credit card to your wallet to top up your balance.
1. Navigate to [Daytona Wallet ↗](https://app.daytona.io/dashboard/billing/wallet)
2. Click the **Connect** button next to the **Payment method** section
3. Follow the prompts to connect your credit card to your wallet.
Organizations can set automatic top-up rules for their wallets.
- **Threshold** — When the wallet balance drops to this amount, a top-up is triggered.
- **Target** — The wallet balance is topped up to this amount.
Set both **Threshold** and **Target** to `0` to disable automatic top-up.
### Redeem coupon
Daytona provides coupon codes to redeem credits on your wallet.
1. Navigate to [Daytona Wallet ↗](https://app.daytona.io/dashboard/billing/wallet)
2. Enter the coupon code in the **Redeem coupon** input field
3. Click the **Redeem** button to redeem the coupon code.
### Billing emails
Daytona provides billing emails to receive important billing notifications such as invoices and credit depletion notices.
1. Navigate to [Daytona Wallet ↗](https://app.daytona.io/dashboard/billing/wallet)
2. Click the **Add Email** button to add a new email address.
3. Enter the email address and click the **Add Email** button.
A verification email will be sent to the email address to verify it. Once verified, the email address will be added to the list of billing emails.
Computer Use enables programmatic control of desktop environments within sandboxes. It provides mouse, keyboard, screenshot, screen recording, and display operations for automating GUI interactions and testing desktop applications.
Computer Use and [VNC](https://www.daytona.io/docs/en/vnc-access.md) work together to enable both manual and automated desktop interactions. VNC provides the visual interface for users to manually interact with the desktop, while Computer Use provides the programmatic API for AI agents to automate operations.
Computer Use is available for **Linux**. **Windows** and **macOS** support is currently in private alpha.
:::caution[Private Alpha]
Computer Use for macOS and Windows is currently in private alpha and requires access. To request access, fill out the [Windows](https://docs.google.com/forms/d/e/1FAIpQLSfoK-77-VpfsMubw8F4f1opCxIL1AyJUgnM0ONYup5hZ0RTvQ/viewform?usp=dialog) or [macOS](https://docs.google.com/forms/d/e/1FAIpQLSc9xlGZ49OjWNkyzDPC9Ip3InMRR0ZXY3tcoD-PFQj3ck6gzQ/viewform?usp=sharing&ouid=103304973264148733944) access request form. Our team will review your request and reach out with setup instructions.
:::
- **GUI application testing**: automate interactions with native applications, click buttons, fill forms, and validate UI behavior
- **Visual testing & screenshots**: capture screenshots of applications, compare UI states, and perform visual regression testing
- **Desktop automation**: automate repetitive desktop tasks, file management through GUI, and complex workflows
## Start Computer Use
Start all computer use processes (Xvfb, xfce4, x11vnc, novnc) in the Sandbox.
```python
result = sandbox.computer_use.start()
print("Computer use processes started:", result.message)
```
```typescript
const result = await sandbox.computerUse.start();
console.log('Computer use processes started:', result.message);
```
```ruby
result = sandbox.computer_use.start
puts "Computer use processes started: #{result.message}"
```
```go
err := sandbox.ComputerUse.Start(ctx)
if err != nil {
log.Fatal(err)
}
defer sandbox.ComputerUse.Stop(ctx)
fmt.Println("Computer use processes started")
```
```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/start' \
--request POST
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk/sync/computer-use.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk/computer-use.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk/computer-use.md), [Go SDK](https://www.daytona.io/docs/en/go-sdk.md), and [API](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/computer-use) references:
> [**start (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/computer-use.md#computerusestart)
>
> [**start (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/computer-use.md#start)
>
> [**start (Ruby SDK)**](https://www.daytona.io/docs/en/ruby-sdk/computer-use.md#start)
>
> [**Start Computer Use Processes (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/computer-use/POST/computeruse/start)
## Stop Computer Use
Stop all computer use processes in the Sandbox.
```python
result = sandbox.computer_use.stop()
print("Computer use processes stopped:", result.message)
```
```typescript
const result = await sandbox.computerUse.stop();
console.log('Computer use processes stopped:', result.message);
```
```ruby
result = sandbox.computer_use.stop
puts "Computer use processes stopped: #{result.message}"
```
```go
err := sandbox.ComputerUse.Stop(ctx)
if err != nil {
log.Fatal(err)
}
fmt.Println("Computer use processes stopped")
```
```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/stop' \
--request POST
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk/sync/computer-use.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk/computer-use.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk/computer-use.md), [Go SDK](https://www.daytona.io/docs/en/go-sdk.md), and [API](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/computer-use) references:
> [**stop (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/computer-use.md#computerusestop)
>
> [**stop (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/computer-use.md#stop)
>
> [**stop (Ruby SDK)**](https://www.daytona.io/docs/en/ruby-sdk/computer-use.md#stop)
>
> [**Stop Computer Use Processes (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/computer-use/POST/computeruse/stop)
## Get status
Get the status of all computer use processes.
```python
response = sandbox.computer_use.get_status()
print("Computer use status:", response.status)
```
```typescript
const status = await sandbox.computerUse.getStatus();
console.log('Computer use status:', status.status);
```
```ruby
response = sandbox.computer_use.status
puts "Computer use status: #{response.status}"
```
```go
status, err := sandbox.ComputerUse.GetStatus(ctx)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Computer use status: %v\n", status["status"])
```
```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/status'
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk/sync/computer-use.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk/computer-use.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk/computer-use.md), [Go SDK](https://www.daytona.io/docs/en/go-sdk.md), and [API](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/computer-use) references:
> [**get_status (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/computer-use.md#computeruseget_status)
>
> [**getStatus (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/computer-use.md#getstatus)
>
> [**status (Ruby SDK)**](https://www.daytona.io/docs/en/ruby-sdk/computer-use.md#status)
>
> [**Get Computer Use status (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/computer-use/GET/computeruse/status)
## Get process status
Get the status of a specific VNC process.
```python
xvfb_status = sandbox.computer_use.get_process_status("xvfb")
novnc_status = sandbox.computer_use.get_process_status("novnc")
```
```typescript
const xvfbStatus = await sandbox.computerUse.getProcessStatus('xvfb');
const noVncStatus = await sandbox.computerUse.getProcessStatus('novnc');
```
```ruby
xvfb_status = sandbox.computer_use.get_process_status("xvfb")
no_vnc_status = sandbox.computer_use.get_process_status("novnc")
```
```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/process/{processName}/status'
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk/sync/computer-use.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk/computer-use.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk/computer-use.md), and [API](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/computer-use) references:
> [**get_process_status (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/computer-use.md#computeruseget_process_status)
>
> [**getProcessStatus (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/computer-use.md#getprocessstatus)
>
> [**get_process_status (Ruby SDK)**](https://www.daytona.io/docs/en/ruby-sdk/computer-use.md#get_process_status)
>
> [**Get Process Status (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/computer-use/GET/computeruse/process/{processName}/status)
## Restart process
Restart a specific VNC process.
```python
result = sandbox.computer_use.restart_process("xfce4")
print("XFCE4 process restarted:", result.message)
```
```typescript
const result = await sandbox.computerUse.restartProcess('xfce4');
console.log('XFCE4 process restarted:', result.message);
```
```ruby
result = sandbox.computer_use.restart_process("xfce4")
puts "XFCE4 process restarted: #{result.message}"
```
```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/process/{processName}/restart' \
--request POST
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk/sync/computer-use.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk/computer-use.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk/computer-use.md), and [API](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/computer-use) references:
> [**restart_process (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/computer-use.md#computeruserestart_process)
>
> [**restartProcess (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/computer-use.md#restartprocess)
>
> [**restart_process (Ruby SDK)**](https://www.daytona.io/docs/en/ruby-sdk/computer-use.md#restart_process)
>
> [**Restart process (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/computer-use/POST/computeruse/process/{processName}/restart)
## Get process logs
Get logs for a specific VNC process.
```python
logs = sandbox.computer_use.get_process_logs("novnc")
print("NoVNC logs:", logs)
```
```typescript
const logsResp = await sandbox.computerUse.getProcessLogs('novnc');
console.log('NoVNC logs:', logsResp.logs);
```
```ruby
logs = sandbox.computer_use.get_process_logs("novnc")
puts "NoVNC logs: #{logs}"
```
```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/process/{processName}/logs'
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk/sync/computer-use.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk/computer-use.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk/computer-use.md), and [API](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/computer-use) references:
> [**get_process_logs (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/computer-use.md#computeruseget_process_logs)
>
> [**getProcessLogs (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/computer-use.md#getprocesslogs)
>
> [**get_process_logs (Ruby SDK)**](https://www.daytona.io/docs/en/ruby-sdk/computer-use.md#get_process_logs)
>
> [**Get process logs (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/computer-use/GET/computeruse/process/{processName}/logs)
## Get process errors
Get error logs for a specific VNC process.
```python
errors = sandbox.computer_use.get_process_errors("x11vnc")
print("X11VNC errors:", errors)
```
```typescript
const errorsResp = await sandbox.computerUse.getProcessErrors('x11vnc');
console.log('X11VNC errors:', errorsResp.errors);
```
```ruby
errors = sandbox.computer_use.get_process_errors("x11vnc")
puts "X11VNC errors: #{errors}"
```
```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/process/{processName}/errors'
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk/sync/computer-use.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk/computer-use.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk/computer-use.md), and [API](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/computer-use) references:
> [**get_process_errors (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/computer-use.md#computeruseget_process_errors)
>
> [**getProcessErrors (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/computer-use.md#getprocesserrors)
>
> [**get_process_errors (Ruby SDK)**](https://www.daytona.io/docs/en/ruby-sdk/computer-use.md#get_process_errors)
>
> [**Get process errors (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/computer-use/GET/computeruse/process/{processName}/errors)
## Mouse operations
### Click
Click the mouse at the specified coordinates.
```python
# Single left click
result = sandbox.computer_use.mouse.click(100, 200)
# Double click
double_click = sandbox.computer_use.mouse.click(100, 200, "left", True)
# Right click
right_click = sandbox.computer_use.mouse.click(100, 200, "right")
```
```typescript
// Single left click
const result = await sandbox.computerUse.mouse.click(100, 200);
// Double click
const doubleClick = await sandbox.computerUse.mouse.click(100, 200, 'left', true);
// Right click
const rightClick = await sandbox.computerUse.mouse.click(100, 200, 'right');
```
```ruby
# Single left click
result = sandbox.computer_use.mouse.click(x: 100, y: 200)
# Double click
double_click = sandbox.computer_use.mouse.click(x: 100, y: 200, button: 'left', double: true)
# Right click
right_click = sandbox.computer_use.mouse.click(x: 100, y: 200, button: 'right')
```
```go
// Single left click
result, err := sandbox.ComputerUse.Mouse().Click(ctx, 100, 200, nil, nil)
if err != nil {
log.Fatal(err)
}
// Double click
doubleClick := true
result, err = sandbox.ComputerUse.Mouse().Click(ctx, 100, 200, nil, &doubleClick)
// Right click
rightButton := "right"
result, err = sandbox.ComputerUse.Mouse().Click(ctx, 100, 200, &rightButton, nil)
```
```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/mouse/click' \
--request POST \
--header 'Content-Type: application/json' \
--data '{
"button": "",
"double": true,
"x": 1,
"y": 1
}'
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk/sync/computer-use.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk/computer-use.md), [Go SDK](https://www.daytona.io/docs/en/go-sdk.md), and [API](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/computer-use) references:
> [**click (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/computer-use.md#mouseclick)
>
> [**click (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/computer-use.md#click)
>
> [**Click (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#MouseService.Click)
>
> [**Mouse click (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/computer-use/POST/computeruse/mouse/click)
### Move
Move the mouse cursor to the specified coordinates.
```python
result = sandbox.computer_use.mouse.move(100, 200)
print(f"Mouse moved to: {result.x}, {result.y}")
```
```typescript
const result = await sandbox.computerUse.mouse.move(100, 200);
console.log(`Mouse moved to: ${result.x}, ${result.y}`);
```
```ruby
result = sandbox.computer_use.mouse.move(x: 100, y: 200)
puts "Mouse moved to: #{result.x}, #{result.y}"
```
```go
result, err := sandbox.ComputerUse.Mouse().Move(ctx, 100, 200)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Mouse moved to: %v, %v\n", result["x"], result["y"])
```
```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/mouse/move' \
--request POST \
--header 'Content-Type: application/json' \
--data '{
"x": 1,
"y": 1
}'
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk/sync/computer-use.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk/computer-use.md), [Go SDK](https://www.daytona.io/docs/en/go-sdk.md), and [API](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/computer-use) references:
> [**move (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/computer-use.md#mousemove)
>
> [**move (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/computer-use.md#move)
>
> [**Move (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#MouseService.Move)
>
> [**Mouse move (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/computer-use/POST/computeruse/mouse/move)
### Drag
Drag the mouse from start coordinates to end coordinates.
```python
result = sandbox.computer_use.mouse.drag(50, 50, 150, 150)
print(f"Dragged from {result.from_x},{result.from_y} to {result.to_x},{result.to_y}")
```
```typescript
const result = await sandbox.computerUse.mouse.drag(50, 50, 150, 150);
console.log(`Dragged from ${result.from.x},${result.from.y} to ${result.to.x},${result.to.y}`);
```
```ruby
result = sandbox.computer_use.mouse.drag(start_x: 50, start_y: 50, end_x: 150, end_y: 150)
puts "Dragged from #{result.from_x},#{result.from_y} to #{result.to_x},#{result.to_y}"
```
```go
result, err := sandbox.ComputerUse.Mouse().Drag(ctx, 50, 50, 150, 150, nil)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Dragged to %v, %v\n", result["x"], result["y"])
```
```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/mouse/drag' \
--request POST \
--header 'Content-Type: application/json' \
--data '{
"button": "",
"endX": 1,
"endY": 1,
"startX": 1,
"startY": 1
}'
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk/sync/computer-use.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk/computer-use.md), [Go SDK](https://www.daytona.io/docs/en/go-sdk.md), and [API](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/computer-use) references:
> [**drag (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/computer-use.md#mousedrag)
>
> [**drag (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/computer-use.md#drag)
>
> [**Drag (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#MouseService.Drag)
>
> [**Mouse drag (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/computer-use/POST/computeruse/mouse/drag)
### Scroll
Scroll the mouse wheel at the specified coordinates.
```python
# Scroll up
scroll_up = sandbox.computer_use.mouse.scroll(100, 200, "up", 3)
# Scroll down
scroll_down = sandbox.computer_use.mouse.scroll(100, 200, "down", 5)
```
```typescript
// Scroll up
const scrollUp = await sandbox.computerUse.mouse.scroll(100, 200, 'up', 3);
// Scroll down
const scrollDown = await sandbox.computerUse.mouse.scroll(100, 200, 'down', 5);
```
```ruby
# Scroll up
scroll_up = sandbox.computer_use.mouse.scroll(x: 100, y: 200, direction: 'up', amount: 3)
# Scroll down
scroll_down = sandbox.computer_use.mouse.scroll(x: 100, y: 200, direction: 'down', amount: 5)
```
```go
// Scroll up
amount := 3
success, err := sandbox.ComputerUse.Mouse().Scroll(ctx, 100, 200, "up", &amount)
if err != nil {
log.Fatal(err)
}
// Scroll down
amount = 5
success, err = sandbox.ComputerUse.Mouse().Scroll(ctx, 100, 200, "down", &amount)
```
```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/mouse/scroll' \
--request POST \
--header 'Content-Type: application/json' \
--data '{
"amount": 1,
"direction": "",
"x": 1,
"y": 1
}'
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk/sync/computer-use.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk/computer-use.md), [Go SDK](https://www.daytona.io/docs/en/go-sdk.md), and [API](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/computer-use) references:
> [**scroll (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/computer-use.md#mousescroll)
>
> [**scroll (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/computer-use.md#scroll)
>
> [**Scroll (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#MouseService.Scroll)
>
> [**Mouse scroll (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/computer-use/POST/computeruse/mouse/scroll)
### Get position
Get the current mouse cursor position.
```python
position = sandbox.computer_use.mouse.get_position()
print(f"Mouse is at: {position.x}, {position.y}")
```
```typescript
const position = await sandbox.computerUse.mouse.getPosition();
console.log(`Mouse is at: ${position.x}, ${position.y}`);
```
```ruby
position = sandbox.computer_use.mouse.position
puts "Mouse is at: #{position.x}, #{position.y}"
```
```go
position, err := sandbox.ComputerUse.Mouse().GetPosition(ctx)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Mouse is at: %v, %v\n", position["x"], position["y"])
```
```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/mouse/position'
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk/sync/computer-use.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk/computer-use.md), [Go SDK](https://www.daytona.io/docs/en/go-sdk.md), and [API](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/computer-use) references:
> [**get_position (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/computer-use.md#mouseget_position)
>
> [**getPosition (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/computer-use.md#getposition)
>
> [**GetPosition (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#MouseService.GetPosition)
>
> [**Get mouse position (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/computer-use/GET/computeruse/mouse/position)
## Keyboard operations
### Type
Type the specified text.
```python
sandbox.computer_use.keyboard.type("Hello, World!")
# With delay between characters
sandbox.computer_use.keyboard.type("Slow typing", 100)
```
```typescript
await sandbox.computerUse.keyboard.type('Hello, World!');
// With delay between characters
await sandbox.computerUse.keyboard.type('Slow typing', 100);
```
```ruby
sandbox.computer_use.keyboard.type(text: "Hello, World!")
# With delay between characters
sandbox.computer_use.keyboard.type(text: "Slow typing", delay: 100)
```
```go
err := sandbox.ComputerUse.Keyboard().Type(ctx, "Hello, World!", nil)
if err != nil {
log.Fatal(err)
}
// With delay between characters
delay := 100
err = sandbox.ComputerUse.Keyboard().Type(ctx, "Slow typing", &delay)
```
```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/keyboard/type' \
--request POST \
--header 'Content-Type: application/json' \
--data '{
"delay": 1,
"text": ""
}'
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk/sync/computer-use.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk/computer-use.md), [Go SDK](https://www.daytona.io/docs/en/go-sdk.md), and [API](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/computer-use) references:
> [**type (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/computer-use.md#keyboardtype)
>
> [**type (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/computer-use.md#type)
>
> [**Type (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#KeyboardService.Type)
>
> [**Keyboard type (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/computer-use/POST/computeruse/keyboard/type)
### Press
Press a key with optional modifiers.
```python
# Press Enter
sandbox.computer_use.keyboard.press("Return")
# Press Ctrl+C
sandbox.computer_use.keyboard.press("c", ["ctrl"])
# Press Ctrl+Shift+T
sandbox.computer_use.keyboard.press("t", ["ctrl", "shift"])
```
```typescript
// Press Enter
await sandbox.computerUse.keyboard.press('Return');
// Press Ctrl+C
await sandbox.computerUse.keyboard.press('c', ['ctrl']);
// Press Ctrl+Shift+T
await sandbox.computerUse.keyboard.press('t', ['ctrl', 'shift']);
```
```ruby
# Press Enter
sandbox.computer_use.keyboard.press(key: "Return")
# Press Ctrl+C
sandbox.computer_use.keyboard.press(key: "c", modifiers: ["ctrl"])
# Press Ctrl+Shift+T
sandbox.computer_use.keyboard.press(key: "t", modifiers: ["ctrl", "shift"])
```
```go
// Press Enter
err := sandbox.ComputerUse.Keyboard().Press(ctx, "Return", nil)
if err != nil {
log.Fatal(err)
}
// Press Ctrl+C
err = sandbox.ComputerUse.Keyboard().Press(ctx, "c", []string{"ctrl"})
// Press Ctrl+Shift+T
err = sandbox.ComputerUse.Keyboard().Press(ctx, "t", []string{"ctrl", "shift"})
```
```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/keyboard/key' \
--request POST \
--header 'Content-Type: application/json' \
--data '{
"key": "",
"modifiers": [
""
]
}'
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk/sync/computer-use.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk/computer-use.md), [Go SDK](https://www.daytona.io/docs/en/go-sdk.md), and [API](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/computer-use) references:
> [**press (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/computer-use.md#keyboardpress)
>
> [**press (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/computer-use.md#press)
>
> [**Press (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#KeyboardService.Press)
>
> [**Keyboard press (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/computer-use/POST/computeruse/keyboard/press)
### Hotkey
Press a hotkey combination.
```python
# Copy
sandbox.computer_use.keyboard.hotkey("ctrl+c")
# Paste
sandbox.computer_use.keyboard.hotkey("ctrl+v")
# Alt+Tab
sandbox.computer_use.keyboard.hotkey("alt+tab")
```
```typescript
// Copy
await sandbox.computerUse.keyboard.hotkey('ctrl+c');
// Paste
await sandbox.computerUse.keyboard.hotkey('ctrl+v');
// Alt+Tab
await sandbox.computerUse.keyboard.hotkey('alt+tab');
```
```ruby
# Copy
sandbox.computer_use.keyboard.hotkey(keys: "ctrl+c")
# Paste
sandbox.computer_use.keyboard.hotkey(keys: "ctrl+v")
# Alt+Tab
sandbox.computer_use.keyboard.hotkey(keys: "alt+tab")
```
```go
// Copy
err := sandbox.ComputerUse.Keyboard().Hotkey(ctx, "ctrl+c")
if err != nil {
log.Fatal(err)
}
// Paste
err = sandbox.ComputerUse.Keyboard().Hotkey(ctx, "ctrl+v")
// Alt+Tab
err = sandbox.ComputerUse.Keyboard().Hotkey(ctx, "alt+tab")
```
```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/keyboard/hotkey' \
--request POST \
--header 'Content-Type: application/json' \
--data '{
"keys": ""
}'
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk/sync/computer-use.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk/computer-use.md), [Go SDK](https://www.daytona.io/docs/en/go-sdk.md), and [API](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/computer-use) references:
> [**hotkey (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/computer-use.md#keyboardhotkey)
>
> [**hotkey (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/computer-use.md#hotkey)
>
> [**Hotkey (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#KeyboardService.Hotkey)
>
> [**Keyboard hotkey (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/computer-use/POST/computeruse/keyboard/hotkey)
## Screenshot operations
### Take full screen
Take a screenshot of the entire screen.
```python
screenshot = sandbox.computer_use.screenshot.take_full_screen()
print(f"Screenshot size: {screenshot.width}x{screenshot.height}")
# With cursor visible
with_cursor = sandbox.computer_use.screenshot.take_full_screen(True)
```
```typescript
const screenshot = await sandbox.computerUse.screenshot.takeFullScreen();
console.log(`Screenshot size: ${screenshot.width}x${screenshot.height}`);
// With cursor visible
const withCursor = await sandbox.computerUse.screenshot.takeFullScreen(true);
```
```ruby
screenshot = sandbox.computer_use.screenshot.take_full_screen
puts "Screenshot size: #{screenshot.width}x#{screenshot.height}"
# With cursor visible
with_cursor = sandbox.computer_use.screenshot.take_full_screen(show_cursor: true)
```
```go
screenshot, err := sandbox.ComputerUse.Screenshot().TakeFullScreen(ctx, nil)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Screenshot captured, size: %d bytes\n", *screenshot.SizeBytes)
// With cursor visible
showCursor := true
withCursor, err := sandbox.ComputerUse.Screenshot().TakeFullScreen(ctx, &showCursor)
```
```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/screenshot'
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk/sync/computer-use.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk/computer-use.md), [Go SDK](https://www.daytona.io/docs/en/go-sdk.md), and [API](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/computer-use) references:
> [**take_full_screen (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/computer-use.md#screenshottake_full_screen)
>
> [**takeFullScreen (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/computer-use.md#takefullscreen)
>
> [**TakeFullScreen (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#ScreenshotService.TakeFullScreen)
>
> [**Take screenshot (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/computer-use/GET/computeruse/screenshot)
### Take region
Take a screenshot of a specific region.
```python
from daytona import ScreenshotRegion
region = ScreenshotRegion(x=100, y=100, width=300, height=200)
screenshot = sandbox.computer_use.screenshot.take_region(region)
print(f"Captured region: {screenshot.region.width}x{screenshot.region.height}")
```
```typescript
const region = { x: 100, y: 100, width: 300, height: 200 };
const screenshot = await sandbox.computerUse.screenshot.takeRegion(region);
console.log(`Captured region: ${screenshot.region.width}x${screenshot.region.height}`);
```
```ruby
region = Daytona::ComputerUse::ScreenshotRegion.new(x: 100, y: 100, width: 300, height: 200)
screenshot = sandbox.computer_use.screenshot.take_region(region: region)
puts "Captured region: #{screenshot.region.width}x#{screenshot.region.height}"
```
```go
region := types.ScreenshotRegion{X: 100, Y: 100, Width: 300, Height: 200}
screenshot, err := sandbox.ComputerUse.Screenshot().TakeRegion(ctx, region, nil)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Captured region: %dx%d\n", screenshot.Width, screenshot.Height)
```
```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/screenshot/region?x=1&y=1&width=1&height=1'
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk/sync/computer-use.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk/computer-use.md), [Go SDK](https://www.daytona.io/docs/en/go-sdk.md), and [API](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/computer-use) references:
> [**take_region (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/computer-use.md#screenshottake_region)
>
> [**takeRegion (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/computer-use.md#takeregion)
>
> [**TakeRegion (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#ScreenshotService.TakeRegion)
>
> [**Take Screenshot Region (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/computer-use/GET/computeruse/screenshot/region)
### Take compressed
Take a compressed screenshot of the entire screen.
```python
from daytona import ScreenshotOptions
# Default compression
screenshot = sandbox.computer_use.screenshot.take_compressed()
# High quality JPEG
jpeg = sandbox.computer_use.screenshot.take_compressed(
ScreenshotOptions(format="jpeg", quality=95, show_cursor=True)
)
# Scaled down PNG
scaled = sandbox.computer_use.screenshot.take_compressed(
ScreenshotOptions(format="png", scale=0.5)
)
```
```typescript
// Default compression
const screenshot = await sandbox.computerUse.screenshot.takeCompressed();
// High quality JPEG
const jpeg = await sandbox.computerUse.screenshot.takeCompressed({
format: 'jpeg',
quality: 95,
showCursor: true
});
// Scaled down PNG
const scaled = await sandbox.computerUse.screenshot.takeCompressed({
format: 'png',
scale: 0.5
});
```
```ruby
# Default compression
screenshot = sandbox.computer_use.screenshot.take_compressed
# High quality JPEG
jpeg = sandbox.computer_use.screenshot.take_compressed(
options: Daytona::ComputerUse::ScreenshotOptions.new(format: "jpeg", quality: 95, show_cursor: true)
)
# Scaled down PNG
scaled = sandbox.computer_use.screenshot.take_compressed(
options: Daytona::ComputerUse::ScreenshotOptions.new(format: "png", scale: 0.5)
)
```
```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/screenshot/compressed'
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk/sync/computer-use.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk/computer-use.md), and [API](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/computer-use) references:
> [**take_compressed (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/computer-use.md#screenshottake_compressed)
>
> [**takeCompressed (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/computer-use.md#takecompressed)
>
> [**Take compressed screenshot (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/computer-use/GET/computeruse/screenshot/compressed)
### Take compressed region
Take a compressed screenshot of a specific region.
```python
from daytona import ScreenshotRegion, ScreenshotOptions
region = ScreenshotRegion(x=0, y=0, width=800, height=600)
screenshot = sandbox.computer_use.screenshot.take_compressed_region(
region,
ScreenshotOptions(format="webp", quality=80, show_cursor=True)
)
print(f"Compressed size: {screenshot.size_bytes} bytes")
```
```typescript
const region = { x: 0, y: 0, width: 800, height: 600 };
const screenshot = await sandbox.computerUse.screenshot.takeCompressedRegion(region, {
format: 'webp',
quality: 80,
showCursor: true
});
console.log(`Compressed size: ${screenshot.size_bytes} bytes`);
```
```ruby
region = Daytona::ComputerUse::ScreenshotRegion.new(x: 0, y: 0, width: 800, height: 600)
screenshot = sandbox.computer_use.screenshot.take_compressed_region(
region: region,
options: Daytona::ComputerUse::ScreenshotOptions.new(format: "webp", quality: 80, show_cursor: true)
)
puts "Compressed size: #{screenshot.size_bytes} bytes"
```
```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/screenshot/region/compressed?x=1&y=1&width=1&height=1'
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk/sync/computer-use.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk/computer-use.md), and [API](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/computer-use) references:
> [**take_compressed_region (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/computer-use.md#screenshottake_compressed_region)
>
> [**takeCompressedRegion (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/computer-use.md#takecompressedregion)
>
> [**Take compressed screenshot region (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/computer-use/GET/computeruse/screenshot/region/compressed)
## Screen Recording
Computer Use supports screen recording capabilities, allowing you to capture desktop sessions for debugging, documentation, or automation workflows.
### Configure Recording Directory
By default, recordings are saved to `~/.daytona/recordings`. You can specify a custom directory by passing the `DAYTONA_RECORDINGS_DIR` environment variable when creating a sandbox:
```python
from daytona import Daytona, CreateSandboxFromSnapshotParams
daytona = Daytona()
sandbox = daytona.create(
CreateSandboxFromSnapshotParams(
snapshot="daytonaio/sandbox:0.6.0",
name="my-sandbox",
env_vars={"DAYTONA_RECORDINGS_DIR": "/home/daytona/my-recordings"}
)
)
```
```typescript
import { Daytona } from '@daytonaio/sdk';
const daytona = new Daytona();
const sandbox = await daytona.create({
snapshot: 'daytonaio/sandbox:0.6.0',
name: 'my-sandbox',
envVars: { DAYTONA_RECORDINGS_DIR: '/home/daytona/my-recordings' }
});
```
```ruby
require 'daytona'
daytona = Daytona::Client.new
sandbox = daytona.create(
snapshot: 'daytonaio/sandbox:0.6.0',
name: 'my-sandbox',
env_vars: { DAYTONA_RECORDINGS_DIR: '/home/daytona/my-recordings' }
)
```
```go
import (
"github.com/daytonaio/daytona/pkg/client"
"github.com/daytonaio/daytona/pkg/types"
)
daytona := client.New()
envVars := map[string]string{
"DAYTONA_RECORDINGS_DIR": "/home/daytona/my-recordings",
}
sandbox, err := daytona.Create(ctx, &types.CreateSandboxParams{
Snapshot: "daytonaio/sandbox:0.6.0",
Name: "my-sandbox",
EnvVars: envVars,
})
if err != nil {
log.Fatal(err)
}
```
### Start Recording
Start a new screen recording session with an optional name identifier:
```python
# Start recording with a custom name
recording = sandbox.computer_use.recording.start("test-1")
print(f"Recording started: {recording.id}")
print(f"File path: {recording.file_path}")
```
```typescript
// Start recording with a custom name
const recording = await sandbox.computerUse.recording.start('test-1');
console.log(`Recording started: ${recording.id}`);
console.log(`File path: ${recording.file_path}`);
```
```ruby
# Start recording with a custom label
recording = sandbox.computer_use.recording.start(label: 'test-1')
puts "Recording started: #{recording.id}"
puts "File path: #{recording.file_path}"
```
```go
// Start recording with a custom name
name := "test-1"
recording, err := sandbox.ComputerUse.Recording().Start(ctx, &name)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Recording started: %s\n", *recording.Id)
fmt.Printf("File path: %s\n", *recording.FilePath)
```
```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/recordings/start' \
--request POST \
--header 'Content-Type: application/json' \
--data '{
"name": "test-1"
}'
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk/sync/computer-use.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk/computer-use.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk/computer-use.md), [Go SDK](https://www.daytona.io/docs/en/go-sdk.md), and [API](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/computer-use) references:
> [**start (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/computer-use.md#recordingstart)
>
> [**start (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/computer-use.md#start-1)
>
> [**start (Ruby SDK)**](https://www.daytona.io/docs/en/ruby-sdk/computer-use.md)
>
> [**Start (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#RecordingService.Start)
>
> [**Start Recording (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/computer-use/POST/computeruse/recordings/start)
### Stop Recording
Stop an active recording session by providing the recording ID:
```python
# Stop the recording
stopped_recording = sandbox.computer_use.recording.stop(recording.id)
print(f"Recording stopped: {stopped_recording.duration_seconds} seconds")
print(f"Saved to: {stopped_recording.file_path}")
```
```typescript
// Stop the recording
const stoppedRecording = await sandbox.computerUse.recording.stop(recording.id);
console.log(`Recording stopped: ${stoppedRecording.duration_seconds} seconds`);
console.log(`Saved to: ${stoppedRecording.file_path}`);
```
```ruby
# Stop the recording
stopped_recording = sandbox.computer_use.recording.stop(id: recording.id)
puts "Recording stopped: #{stopped_recording.duration_seconds} seconds"
puts "Saved to: #{stopped_recording.file_path}"
```
```go
// Stop the recording
stoppedRecording, err := sandbox.ComputerUse.Recording().Stop(ctx, *recording.Id)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Recording stopped: %f seconds\n", *stoppedRecording.DurationSeconds)
fmt.Printf("Saved to: %s\n", *stoppedRecording.FilePath)
```
```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/recordings/stop' \
--request POST \
--header 'Content-Type: application/json' \
--data '{
"id": "recording-id"
}'
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk/sync/computer-use.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk/computer-use.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk/computer-use.md), [Go SDK](https://www.daytona.io/docs/en/go-sdk.md), and [API](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/computer-use) references:
> [**stop (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/computer-use.md#recordingstop)
>
> [**stop (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/computer-use.md#stop-1)
>
> [**stop (Ruby SDK)**](https://www.daytona.io/docs/en/ruby-sdk/computer-use.md)
>
> [**Stop (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#RecordingService.Stop)
>
> [**Stop Recording (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/computer-use/POST/computeruse/recordings/stop)
### List Recordings
Get a list of all recordings in the sandbox:
```python
recordings_list = sandbox.computer_use.recording.list()
print(f"Total recordings: {len(recordings_list.recordings)}")
for rec in recordings_list.recordings:
print(f"- {rec.name}: {rec.duration_seconds}s ({rec.file_size_bytes} bytes)")
```
```typescript
const recordingsList = await sandbox.computerUse.recording.list();
console.log(`Total recordings: ${recordingsList.recordings.length}`);
recordingsList.recordings.forEach(rec => {
console.log(`- ${rec.name}: ${rec.duration_seconds}s (${rec.file_size_bytes} bytes)`);
});
```
```ruby
recordings_list = sandbox.computer_use.recording.list
puts "Total recordings: #{recordings_list.recordings.length}"
recordings_list.recordings.each do |rec|
puts "- #{rec.name}: #{rec.duration_seconds}s (#{rec.file_size_bytes} bytes)"
end
```
```go
recordingsList, err := sandbox.ComputerUse.Recording().List(ctx)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Total recordings: %d\n", len(recordingsList.Recordings))
for _, rec := range recordingsList.Recordings {
fmt.Printf("- %s: %.2fs (%d bytes)\n", *rec.Name, *rec.DurationSeconds, *rec.FileSizeBytes)
}
```
```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/recordings'
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk/sync/computer-use.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk/computer-use.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk/computer-use.md), [Go SDK](https://www.daytona.io/docs/en/go-sdk.md), and [API](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/computer-use) references:
> [**list (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/computer-use.md#recordinglist)
>
> [**list (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/computer-use.md#list)
>
> [**list (Ruby SDK)**](https://www.daytona.io/docs/en/ruby-sdk/computer-use.md)
>
> [**List (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#RecordingService.List)
>
> [**List Recordings (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/computer-use/GET/computeruse/recordings)
### Get Recording
Get details about a specific recording:
```python
recording_detail = sandbox.computer_use.recording.get("recording-id")
print(f"Recording: {recording_detail.name}")
print(f"Status: {recording_detail.status}")
print(f"Duration: {recording_detail.duration_seconds}s")
```
```typescript
const recordingDetail = await sandbox.computerUse.recording.get('recording-id');
console.log(`Recording: ${recordingDetail.name}`);
console.log(`Status: ${recordingDetail.status}`);
console.log(`Duration: ${recordingDetail.duration_seconds}s`);
```
```ruby
recording_detail = sandbox.computer_use.recording.get(id: 'recording-id')
puts "Recording: #{recording_detail.name}"
puts "Status: #{recording_detail.status}"
puts "Duration: #{recording_detail.duration_seconds}s"
```
```go
recordingDetail, err := sandbox.ComputerUse.Recording().Get(ctx, "recording-id")
if err != nil {
log.Fatal(err)
}
fmt.Printf("Recording: %s\n", *recordingDetail.Name)
fmt.Printf("Status: %s\n", *recordingDetail.Status)
fmt.Printf("Duration: %.2fs\n", *recordingDetail.DurationSeconds)
```
```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/recordings/{id}'
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk/sync/computer-use.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk/computer-use.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk/computer-use.md), [Go SDK](https://www.daytona.io/docs/en/go-sdk.md), and [API](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/computer-use) references:
> [**get (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/computer-use.md#recordingget)
>
> [**get (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/computer-use.md#get)
>
> [**get (Ruby SDK)**](https://www.daytona.io/docs/en/ruby-sdk/computer-use.md)
>
> [**Get (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#RecordingService.Get)
>
> [**Get Recording (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/computer-use/GET/computeruse/recordings/{id})
### Delete Recording
Delete a recording by ID:
```python
sandbox.computer_use.recording.delete("recording-id")
print("Recording deleted successfully")
```
```typescript
await sandbox.computerUse.recording.delete('recording-id');
console.log('Recording deleted successfully');
```
```ruby
sandbox.computer_use.recording.delete(id: 'recording-id')
puts 'Recording deleted successfully'
```
```go
err := sandbox.ComputerUse.Recording().Delete(ctx, "recording-id")
if err != nil {
log.Fatal(err)
}
fmt.Println("Recording deleted successfully")
```
```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/recordings/{id}' \
--request DELETE
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk/sync/computer-use.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk/computer-use.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk/computer-use.md), [Go SDK](https://www.daytona.io/docs/en/go-sdk.md), and [API](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/computer-use) references:
> [**delete (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/computer-use.md#recordingdelete)
>
> [**delete (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/computer-use.md#delete)
>
> [**delete (Ruby SDK)**](https://www.daytona.io/docs/en/ruby-sdk/computer-use.md)
>
> [**Delete (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#RecordingService.Delete)
>
> [**Delete Recording (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/computer-use/DELETE/computeruse/recordings/{id})
### Download Recording
Download a recording file from the sandbox to your local machine. The file is streamed efficiently without loading the entire content into memory, making it suitable for large recordings.
```python
# Download recording to local file
sandbox.computer_use.recording.download(recording.id, "local_recording.mp4")
print("Recording downloaded successfully")
# Or with custom path
import os
download_path = os.path.join("recordings", f"recording_{recording.id}.mp4")
sandbox.computer_use.recording.download(recording.id, download_path)
```
```typescript
// Download recording to local file
await sandbox.computerUse.recording.download(recording.id, 'local_recording.mp4');
console.log('Recording downloaded successfully');
// Or with custom path
const downloadPath = `recordings/recording_${recording.id}.mp4`;
await sandbox.computerUse.recording.download(recording.id, downloadPath);
```
```ruby
# Download recording to local file
sandbox.computer_use.recording.download(id: recording.id, local_path: 'local_recording.mp4')
puts 'Recording downloaded successfully'
# Or with custom path
download_path = "recordings/recording_#{recording.id}.mp4"
sandbox.computer_use.recording.download(id: recording.id, local_path: download_path)
```
```go
// Download recording to local file
err := sandbox.ComputerUse.Recording().Download(ctx, recording.GetId(), "local_recording.mp4")
if err != nil {
log.Fatal(err)
}
fmt.Println("Recording downloaded successfully")
// Or with custom path
downloadPath := fmt.Sprintf("recordings/recording_%s.mp4", recording.GetId())
err = sandbox.ComputerUse.Recording().Download(ctx, recording.GetId(), downloadPath)
```
```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/recordings/{id}/download' \
--output local_recording.mp4
```
:::tip[Streaming Downloads]
All SDK implementations stream the recording file directly to disk without loading the entire content into memory. This allows you to download large recordings (hundreds of MB or even GB) efficiently without running out of memory.
- **Python**: Streams in 64KB chunks using `httpx`
- **TypeScript**: Uses Node.js `pipeline()` with backpressure handling
- **Ruby**: Uses Typhoeus streaming with `on_body` callbacks
- **Go**: Uses `io.Copy()` with 32KB internal buffer
:::
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk/sync/computer-use.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk/computer-use.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk/computer-use.md), [Go SDK](https://www.daytona.io/docs/en/go-sdk.md), and [API](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/computer-use) references:
> [**download (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/computer-use.md#recordingdownload)
>
> [**download (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/computer-use.md#download)
>
> [**download (Ruby SDK)**](https://www.daytona.io/docs/en/ruby-sdk/computer-use.md)
>
> [**Download (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#RecordingService.Download)
>
> [**Download Recording (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/computer-use/GET/computeruse/recordings/{id}/download)
### Recording Dashboard
Every sandbox includes a built-in recording dashboard for managing screen recordings through a web interface. The dashboard allows you to view, download, and delete recordings without writing code.
To access the recording dashboard:
1. Navigate to your sandboxes in the Daytona Dashboard
2. Click the action menu (three dots) for your sandbox
3. Select **Screen Recordings** from the dropdown menu
The recording dashboard provides:
- List of all recordings with metadata (name, duration, file size, creation time)
- Playback controls for reviewing recordings
- Download functionality to save recordings locally
- Delete options for managing storage
:::tip
The recording dashboard runs on a private port and is automatically secured. No additional authentication is required once you access it through the Daytona Dashboard.
:::
## Display operations
### Get info
Get information about the displays.
```python
info = sandbox.computer_use.display.get_info()
print(f"Primary display: {info.primary_display.width}x{info.primary_display.height}")
print(f"Total displays: {info.total_displays}")
for i, display in enumerate(info.displays):
print(f"Display {i}: {display.width}x{display.height} at {display.x},{display.y}")
```
```typescript
const info = await sandbox.computerUse.display.getInfo();
console.log(`Primary display: ${info.primary_display.width}x${info.primary_display.height}`);
console.log(`Total displays: ${info.total_displays}`);
info.displays.forEach((display, index) => {
console.log(`Display ${index}: ${display.width}x${display.height} at ${display.x},${display.y}`);
});
```
```ruby
info = sandbox.computer_use.display.info
puts "Primary display: #{info.primary_display.width}x#{info.primary_display.height}"
puts "Total displays: #{info.total_displays}"
info.displays.each_with_index do |display, i|
puts "Display #{i}: #{display.width}x#{display.height} at #{display.x},#{display.y}"
end
```
```go
info, err := sandbox.ComputerUse.Display().GetInfo(ctx)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Displays: %v\n", info["displays"])
```
```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/display/info'
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk/sync/computer-use.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk/computer-use.md), [Go SDK](https://www.daytona.io/docs/en/go-sdk.md), and [API](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/computer-use) references:
> [**get_info (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/computer-use.md#displayget_info)
>
> [**getInfo (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/computer-use.md#getinfo)
>
> [**GetInfo (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#DisplayService.GetInfo)
>
> [**Get display info (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/computer-use/GET/computeruse/display/info)
### Get windows
Get the list of open windows.
```python
windows = sandbox.computer_use.display.get_windows()
print(f"Found {windows.count} open windows:")
for window in windows.windows:
print(f"- {window.title} (ID: {window.id})")
```
```typescript
const windows = await sandbox.computerUse.display.getWindows();
console.log(`Found ${windows.count} open windows:`);
windows.windows.forEach(window => {
console.log(`- ${window.title} (ID: ${window.id})`);
});
```
```ruby
windows = sandbox.computer_use.display.windows
puts "Found #{windows.count} open windows:"
windows.windows.each do |window|
puts "- #{window.title} (ID: #{window.id})"
end
```
```go
result, err := sandbox.ComputerUse.Display().GetWindows(ctx)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Open windows: %v\n", result["windows"])
```
```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/computeruse/display/windows'
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk/sync/computer-use.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk/computer-use.md), [Go SDK](https://www.daytona.io/docs/en/go-sdk.md), and [API](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/computer-use) references:
> [**get_windows (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/computer-use.md#displayget_windows)
>
> [**getWindows (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/computer-use.md#getwindows)
>
> [**GetWindows (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#DisplayService.GetWindows)
>
> [**Get Windows (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/computer-use/GET/computeruse/display/windows)
Daytona supports multiple methods to configure your environment, in order of precedence:
1. [Configuration in code](#configuration-in-code)
2. [Environment variables](#environment-variables)
3. [.env file](#env-file)
4. [Default values](#default-values)
## Configuration in code
To configure your environment in code, use the `DaytonaConfig` class. The `DaytonaConfig` class accepts the following parameters:
- `api_key`: Your Daytona [API Key](https://www.daytona.io/docs/api-keys.md)
- `api_url`: URL of your [Daytona API](https://www.daytona.io/docs/en/tools/api.md)
- `target`: Target region to create the Sandboxes on (`us` / `eu`)
```python
from daytona import DaytonaConfig
config = DaytonaConfig(
api_key="your-api-key",
api_url="your-api-url",
target="us"
)
```
```typescript
import { DaytonaConfig } from '@daytonaio/sdk'
const config: DaytonaConfig = {
apiKey: 'your-api-key',
apiUrl: 'your-api-url',
target: 'us',
}
```
```ruby
require 'daytona'
config = Daytona::Config.new(
api_key: 'your-api-key',
api_url: 'your-api-url',
target: 'us'
)
```
```go
package main
import (
"github.com/daytonaio/daytona/libs/sdk-go/pkg/daytona"
)
func main() {
config := daytona.Config{
APIKey: "your-api-key",
APIURL: "your-api-url",
Target: "us",
}
client := daytona.NewClient(&config)
_ = client
}
```
```bash
curl https://app.daytona.io/api/api-keys \
--request POST \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer YOUR_SECRET_TOKEN' \
--data '{
"name": "",
"permissions": [
"write:registries"
],
"expiresAt": ""
}'
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk/daytona.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk/daytona.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk/daytona.md), [Go SDK](https://www.daytona.io/docs/en/go-sdk/daytona.md), and [API](https://www.daytona.io/docs/en/tools/api.md#daytona/tag/api-keys) references:
> [**DaytonaConfig (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/daytona.md#daytonaconfig)
>
> [**DaytonaConfig (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/daytona.md#daytonaconfig)
>
> [**Config (Ruby SDK)**](https://www.daytona.io/docs/en/ruby-sdk/config.md#config)
>
> [**DaytonaConfig (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/types.md#DaytonaConfig)
>
> [**Config (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona/tag/api-keys/POST/api-keys)
## Environment variables
Daytona supports environment variables for configuration. The SDK automatically looks for these environment variables:
| Variable | Description | Required |
| --------------------- | ------------------------------------------ | -------- |
| **`DAYTONA_API_KEY`** | Your Daytona API key. | Yes |
| **`DAYTONA_API_URL`** | URL of your Daytona API. | No |
| **`DAYTONA_TARGET`** | Daytona Target to create the sandboxes on. | No |
### Shell
Set environment variables in your shell using the following methods:
```bash
export DAYTONA_API_KEY=your-api-key
export DAYTONA_API_URL=https://your-api-url
export DAYTONA_TARGET=us
```
```bash
$env:DAYTONA_API_KEY="your-api-key"
$env:DAYTONA_API_URL="https://your-api-url"
$env:DAYTONA_TARGET="us"
```
### .env file
Set the environment variables in a `.env` file using the following format:
```bash
DAYTONA_API_KEY=YOUR_API_KEY
DAYTONA_API_URL=https://your_api_url
DAYTONA_TARGET=us
```
## Default values
If no configuration is provided, Daytona will use its built-in default values:
| **Option** | **Value** |
| ---------- | ----------------------------------- |
| API URL | https://app.daytona.io/api |
| Target | Default region for the organization |
Daytona provides a preview proxy service that can be used to handle [preview URLs](https://www.daytona.io/docs/en/preview.md) for sandboxes. This gives you full control over the preview experience, including custom domains, authentication, error handling, and styling.
- **Custom domain**: host your proxy under your own domain (e.g., `preview.yourcompany.com`)
- **User authentication**: implement custom authentication logic for private previews
- **Sandbox management**: automatically start stopped sandboxes before forwarding users
- **Custom error pages**: style error pages to match your brand
- **Preview warning control**: disable Daytona's preview warning
- **CORS management**: override Daytona's default CORS settings
## How it works
When a user visits a preview URL, your custom proxy receives the request and can:
1. Authenticate the user using custom logic
2. Check sandbox status and start it if needed
3. Forward the request to the actual sandbox
4. Handle responses with custom styling and error pages
5. Send custom headers to control Daytona's behavior
Your proxy should forward the `X-Forwarded-Host` header with the original request host when proxying requests to Daytona.
## WebSocket support
The preview proxy fully supports WebSocket connections. WebSocket upgrade requests (`Upgrade: websocket`) are automatically detected and proxied. WebSocket connections skip the preview warning page.
## Reserved ports
The following ports are reserved for internal services and always require authentication, even on public sandboxes:
| Port | Service |
| ----------- | ----------------------------------------- |
| **`22222`** | [**Web** terminal](https://www.daytona.io/docs/en/web-terminal.md) |
| **`2280`** | Toolbox (IDE/development interface) |
| **`33333`** | Recording dashboard |
Your custom proxy should avoid exposing these ports unless you explicitly need access to these services.
## Proxy headers
Your proxy can send special headers to control Daytona's behavior.
### Disable preview warning
To disable Daytona's preview warning page, send:
```
X-Daytona-Skip-Preview-Warning: true
```
The warning page is only shown to browser requests. It sets a `daytona-preview-page-accepted` cookie that persists for 24 hours after acceptance.
### Disable CORS
Daytona's default CORS policy allows all origins with credentials. To override this and use your own CORS settings, send:
```
X-Daytona-Disable-CORS: true
```
### Disable last activity update
To prevent sandbox last activity updates when previewing, set the `X-Daytona-Skip-Last-Activity-Update` header to `true`. This prevents Daytona from keeping sandboxes that have [auto-stop enabled](https://www.daytona.io/docs/en/sandboxes.md#auto-stop-interval) in a started state:
```bash
curl -H "X-Daytona-Skip-Last-Activity-Update: true" \
https://3000-sandbox-123456.proxy.daytona.work
```
### Authentication
For private preview links, send:
```
X-Daytona-Preview-Token: {sandboxToken}
```
The `sandboxToken` can be fetched through the Daytona SDK or API using the [standard preview URL](https://www.daytona.io/docs/en/preview.md#standard-preview-url) methods.
## Examples
Examples of custom preview proxies are available on [GitHub](https://github.com/daytonaio/daytona-proxy-samples).
Declarative Builder provides a powerful, code-first approach to defining dependencies for Daytona Sandboxes. Instead of importing images from a container registry, you can programmatically define them using the Daytona SDK.
The declarative builder system supports two primary workflows:
1. [**Declarative images**](#declarative-image-building): build images with varying dependencies _on demand_ when creating sandboxes
2. [**Pre-built Snapshots**](#creating-pre-built-snapshots): create and register _ready-to-use_ [Snapshots](https://www.daytona.io/docs/snapshots.md) that can be shared across multiple sandboxes
## Build declarative images
Daytona provides an option to create declarative images on-the-fly when creating sandboxes. This is ideal for iterating quickly without creating separate snapshots.
Declarative images are cached for 24 hours, and are automatically reused when running the same script. Thus, subsequent runs on the same runner will be almost instantaneous.
```python
# Define a declarative image with python packages
declarative_image = (
Image.debian_slim("3.12")
.pip_install(["requests", "pytest"])
.workdir("/home/daytona")
)
# Create a new sandbox with the declarative image and stream the build logs
sandbox = daytona.create(
CreateSandboxFromImageParams(image=declarative_image),
timeout=0,
on_snapshot_create_logs=print,
)
```
```typescript
// Define a declarative image with python packages
const declarativeImage = Image.debianSlim('3.12')
.pipInstall(['requests', 'pytest'])
.workdir('/home/daytona')
// Create a new sandbox with the declarative image and stream the build logs
const sandbox = await daytona.create(
{
image: declarativeImage,
},
{
timeout: 0,
onSnapshotCreateLogs: console.log,
}
)
```
```ruby
# Define a simple declarative image with Python packages
declarative_image = Daytona::Image
.debian_slim('3.12')
.pip_install(['requests', 'pytest'])
.workdir('/home/daytona')
# Create a new Sandbox with the declarative image and stream the build logs
sandbox = daytona.create(
Daytona::CreateSandboxFromImageParams.new(image: declarative_image),
on_snapshot_create_logs: proc { |chunk| puts chunk }
)
```
```go
// Define a declarative image with python packages
version := "3.12"
declarativeImage := daytona.DebianSlim(&version).
PipInstall([]string{"requests", "pytest"}).
Workdir("/home/daytona")
// Create a new sandbox with the declarative image and stream the build logs
logChan := make(chan string)
go func() {
for log := range logChan {
fmt.Print(log)
}
}()
sandbox, err := client.Create(ctx, types.ImageParams{
Image: declarativeImage,
}, options.WithTimeout(0), options.WithLogChannel(logChan))
if err != nil {
// handle error
}
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk.md), and [Go SDK](https://www.daytona.io/docs/en/go-sdk.md) references:
> [**CreateSandboxFromImageParams (Python SDK)**](https://www.daytona.io/docs/python-sdk/sync/daytona.md#createsandboxfromimageparams)
>
> [**CreateSandboxFromImageParams (TypeScript SDK)**](https://www.daytona.io/docs/typescript-sdk/daytona.md#createsandboxfromimageparams)
>
> [**CreateSandboxFromImageParams (Ruby SDK)**](https://www.daytona.io/docs/ruby-sdk/daytona.md#createsandboxfromimageparams)
>
> [**Create (Go SDK)**](https://www.daytona.io/docs/go-sdk/daytona.md#Client.Create)
:::note
Use the following best practices when working with the declarative builder:
- **Layer Optimization**: Group related operations to minimize Docker layers
- **Cache Utilization**: Identical build commands and context will be cached and subsequent builds will be almost instant
- **Security**: Create non-root users for application workloads
- **Resource Efficiency**: Use slim base images when appropriate
- **Context Minimization**: Only include necessary files in the build context
:::
## Create pre-built Snapshots
Daytona provides an option to [create pre-built snapshots](https://www.daytona.io/docs/snapshots.md#create-snapshots) that can be reused across multiple sandboxes.
The snapshot remains visible in the [Daytona Dashboard ↗](https://app.daytona.io/dashboard/snapshots) and is permanently cached, ensuring instant availability without rebuilding.
```python
# Create a python data science image
snapshot_name = "data-science-snapshot"
image = (
Image.debian_slim("3.12")
.pip_install(["pandas", "numpy"])
.workdir("/home/daytona")
)
# Create the snapshot and stream the build logs
daytona.snapshot.create(
CreateSnapshotParams(
name=snapshot_name,
image=image,
),
on_logs=print,
)
# Create a new sandbox using the pre-built snapshot
sandbox = daytona.create(
CreateSandboxFromSnapshotParams(snapshot=snapshot_name)
)
```
```typescript
// Create a python data science image
const snapshotName = 'data-science-snapshot'
const image = Image.debianSlim('3.12')
.pipInstall(['pandas', 'numpy'])
.workdir('/home/daytona')
// Create the snapshot and stream the build logs
await daytona.snapshot.create(
{
name: snapshotName,
image,
},
{
onLogs: console.log,
}
)
// Create a new sandbox using the pre-built snapshot
const sandbox = await daytona.create({
snapshot: snapshotName,
})
```
```ruby
# Create a simple Python data science image
snapshot_name = 'data-science-snapshot'
image = Daytona::Image
.debian_slim('3.12')
.pip_install(['pandas', 'numpy'])
.workdir('/home/daytona')
# Create the Snapshot and stream the build logs
daytona.snapshot.create(
Daytona::CreateSnapshotParams.new(
name: snapshot_name,
image: image
),
on_logs: proc { |chunk| puts chunk }
)
# Create a new Sandbox using the pre-built Snapshot
sandbox = daytona.create(
Daytona::CreateSandboxFromSnapshotParams.new(snapshot: snapshot_name)
)
```
```go
// Create a python data science image
snapshotName := "data-science-snapshot"
version := "3.12"
image := daytona.DebianSlim(&version).
PipInstall([]string{"pandas", "numpy"}).
Workdir("/home/daytona")
// Create the snapshot and stream the build logs
_, logChan, err := client.Snapshot.Create(ctx, &types.CreateSnapshotParams{
Name: snapshotName,
Image: image,
})
if err != nil {
// handle error
}
for log := range logChan {
fmt.Print(log)
}
// Create a new sandbox using the pre-built snapshot
sandbox, err := client.Create(ctx, types.SnapshotParams{
Snapshot: snapshotName,
})
if err != nil {
// handle error
}
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk.md), and [Go SDK](https://www.daytona.io/docs/en/go-sdk.md) references:
> [**CreateSnapshotParams (Python SDK)**](https://www.daytona.io/docs/python-sdk/sync/snapshot.md#createsnapshotparams)
>
> [**CreateSnapshotParams (TypeScript SDK)**](https://www.daytona.io/docs/typescript-sdk/snapshot.md#createsnapshotparams)
>
> [**CreateSnapshotParams (Ruby SDK)**](https://www.daytona.io/docs/ruby-sdk/snapshot.md#createsnapshotparams)
>
> [**Create (Go SDK)**](https://www.daytona.io/docs/go-sdk/daytona.md#SnapshotService.Create)
## Image configuration
Daytona provides an option to define images programmatically using the Daytona SDK. You can specify base images, install packages, add files, set environment variables, and more.
For a complete API reference and method signatures, see the [Python](https://www.daytona.io/docs/python-sdk/common/image.md), [TypeScript](https://www.daytona.io/docs/typescript-sdk/image.md), [Ruby](https://www.daytona.io/docs/ruby-sdk/image.md), and [Go](https://www.daytona.io/docs/go-sdk/daytona.md#type-DockerImage) SDK references.
### Base image selection
Daytona provides an option to select base images. The following snippets demonstrate how to select and configure base images:
```python
# Create an image from a base
image = Image.base("python:3.12-slim-bookworm")
# Use a Debian slim image with Python 3.12
image = Image.debian_slim("3.12")
```
```typescript
// Create an image from a base
const image = Image.base('python:3.12-slim-bookworm')
// Use a Debian slim image with Python 3.12
const image = Image.debianSlim('3.12')
```
```ruby
# Create an image from a base
image = Daytona::Image.base('python:3.12-slim-bookworm')
# Use a Debian slim image with Python 3.12
image = Daytona::Image.debian_slim('3.12')
```
```go
// Create an image from a base
image := daytona.Base("python:3.12-slim-bookworm")
// Use a Debian slim image with Python 3.12
version := "3.12"
image := daytona.DebianSlim(&version)
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk.md), and [Go SDK](https://www.daytona.io/docs/en/go-sdk.md) references:
> [**base (Python SDK)**](https://www.daytona.io/docs/python-sdk/common/image.md#imagebase)
>
> [**base (TypeScript SDK)**](https://www.daytona.io/docs/typescript-sdk/image.md#base)
>
> [**Base (Go SDK)**](https://www.daytona.io/docs/go-sdk/daytona.md#Base)
>
> [**debian_slim (Python SDK)**](https://www.daytona.io/docs/python-sdk/common/image.md#imagedebian_slim)
>
> [**debianSlim (TypeScript SDK)**](https://www.daytona.io/docs/typescript-sdk/image.md#debianslim)
>
> [**DebianSlim (Go SDK)**](https://www.daytona.io/docs/go-sdk/daytona.md#DebianSlim)
### Package management
Daytona provides an option to install packages and dependencies to your image.
The following snippets demonstrate how to install packages and dependencies to your image:
```python
# Add pip packages
image = Image.debian_slim("3.12").pip_install(["requests", "pandas"])
# Install from requirements.txt
image = Image.debian_slim("3.12").pip_install_from_requirements("requirements.txt")
# Install from pyproject.toml (with optional dependencies)
image = Image.debian_slim("3.12").pip_install_from_pyproject("pyproject.toml", optional_dependencies=["dev"])
```
```typescript
// Add pip packages
const image = Image.debianSlim('3.12').pipInstall(['requests', 'pandas'])
// Install from requirements.txt
const image = Image.debianSlim('3.12').pipInstallFromRequirements('requirements.txt')
// Install from pyproject.toml (with optional dependencies)
const image = Image.debianSlim('3.12').pipInstallFromPyproject('pyproject.toml', {
optionalDependencies: ['dev']
})
```
```ruby
# Add pip packages
image = Daytona::Image.debian_slim('3.12').pip_install(['requests', 'pandas'])
# Install from requirements.txt
image = Daytona::Image.debian_slim('3.12').pip_install_from_requirements('requirements.txt')
# Install from pyproject.toml (with optional dependencies)
image = Daytona::Image.debian_slim('3.12').pip_install_from_pyproject('pyproject.toml',
optional_dependencies: ['dev']
)
```
```go
// Add pip packages
version := "3.12"
image := daytona.DebianSlim(&version).PipInstall([]string{"requests", "pandas"})
// Install from requirements.txt
image := daytona.DebianSlim(&version).
AddLocalFile("requirements.txt", "/tmp/requirements.txt").
Run("pip install -r /tmp/requirements.txt")
// Install from pyproject.toml (with optional dependencies)
image := daytona.DebianSlim(&version).
AddLocalFile("pyproject.toml", "/tmp/pyproject.toml").
Run("pip install /tmp[dev]")
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk.md), and [Go SDK](https://www.daytona.io/docs/en/go-sdk.md) references:
> [**pip_install (Python SDK)**](https://www.daytona.io/docs/python-sdk/common/image.md#imagepip_install)
>
> [**pipInstall (TypeScript SDK)**](https://www.daytona.io/docs/typescript-sdk/image.md#pipinstall)
>
> [**pip_install (Ruby SDK)**](https://www.daytona.io/docs/ruby-sdk/image.md#pip_install)
>
> [**PipInstall (Go SDK)**](https://www.daytona.io/docs/go-sdk/daytona.md#DockerImage.PipInstall)
>
> [**pip_install_from_requirements (Python SDK)**](https://www.daytona.io/docs/python-sdk/common/image.md#imagepip_install_from_requirements)
>
> [**pipInstallFromRequirements (TypeScript SDK)**](https://www.daytona.io/docs/typescript-sdk/image.md#pipinstallfromrequirements)
>
> [**pip_install_from_requirements (Ruby SDK)**](https://www.daytona.io/docs/ruby-sdk/image.md#pip_install_from_requirements)
>
> [**pip_install_from_pyproject (Python SDK)**](https://www.daytona.io/docs/python-sdk/common/image.md#imagepip_install_from_pyproject)
>
> [**pipInstallFromPyproject (TypeScript SDK)**](https://www.daytona.io/docs/typescript-sdk/image.md#pipinstallfrompyproject)
>
> [**pip_install_from_pyproject (Ruby SDK)**](https://www.daytona.io/docs/ruby-sdk/image.md#pip_install_from_pyproject)
### File system operations
Daytona provides an option to add files and directories to your image.
The following snippets demonstrate how to add files and directories to your image:
```python
# Add a local file
image = Image.debian_slim("3.12").add_local_file("package.json", "/home/daytona/package.json")
# Add a local directory
image = Image.debian_slim("3.12").add_local_dir("src", "/home/daytona/src")
```
```typescript
// Add a local file
const image = Image.debianSlim('3.12').addLocalFile('package.json', '/home/daytona/package.json')
// Add a local directory
const image = Image.debianSlim('3.12').addLocalDir('src', '/home/daytona/src')
```
```ruby
# Add a local file
image = Daytona::Image.debian_slim('3.12').add_local_file('package.json', '/home/daytona/package.json')
# Add a local directory
image = Daytona::Image.debian_slim('3.12').add_local_dir('src', '/home/daytona/src')
```
```go
// Add a local file
version := "3.12"
image := daytona.DebianSlim(&version).AddLocalFile("package.json", "/home/daytona/package.json")
// Add a local directory
image := daytona.DebianSlim(&version).AddLocalDir("src", "/home/daytona/src")
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk.md), and [Go SDK](https://www.daytona.io/docs/en/go-sdk.md) references:
> [**add_local_file (Python SDK)**](https://www.daytona.io/docs/python-sdk/common/image.md#imageadd_local_file)
>
> [**add_local_dir (Python SDK)**](https://www.daytona.io/docs/python-sdk/common/image.md#imageadd_local_dir)
>
> [**addLocalFile (TypeScript SDK)**](https://www.daytona.io/docs/typescript-sdk/image.md#addlocalfile)
>
> [**addLocalDir (TypeScript SDK)**](https://www.daytona.io/docs/typescript-sdk/image.md#addlocaldir)
>
> [**add_local_file (Ruby SDK)**](https://www.daytona.io/docs/ruby-sdk/image.md#add_local_file)
>
> [**add_local_dir (Ruby SDK)**](https://www.daytona.io/docs/ruby-sdk/image.md#add_local_dir)
>
> [**AddLocalFile (Go SDK)**](https://www.daytona.io/docs/go-sdk/daytona.md#DockerImage.AddLocalFile)
>
> [**AddLocalDir (Go SDK)**](https://www.daytona.io/docs/go-sdk/daytona.md#DockerImage.AddLocalDir)
### Environment configuration
Daytona provides an option to configure environment variables and working directories.
The following snippets demonstrate how to configure environment variables and working directories:
```python
# Set environment variables
image = Image.debian_slim("3.12").env({"PROJECT_ROOT": "/home/daytona"})
# Set working directory
image = Image.debian_slim("3.12").workdir("/home/daytona")
```
```typescript
// Set environment variables
const image = Image.debianSlim('3.12').env({ PROJECT_ROOT: '/home/daytona' })
// Set working directory
const image = Image.debianSlim('3.12').workdir('/home/daytona')
```
```ruby
# Set environment variables
image = Daytona::Image.debian_slim('3.12').env({ 'PROJECT_ROOT' => '/home/daytona' })
# Set working directory
image = Daytona::Image.debian_slim('3.12').workdir('/home/daytona')
```
```go
// Set environment variables
version := "3.12"
image := daytona.DebianSlim(&version).Env("PROJECT_ROOT", "/home/daytona")
// Set working directory
image := daytona.DebianSlim(&version).Workdir("/home/daytona")
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk.md), and [Go SDK](https://www.daytona.io/docs/en/go-sdk.md) references:
> [**env (Python SDK)**](https://www.daytona.io/docs/python-sdk/common/image.md#imageenv)
>
> [**workdir (Python SDK)**](https://www.daytona.io/docs/python-sdk/common/image.md#imageworkdir)
>
> [**env (TypeScript SDK)**](https://www.daytona.io/docs/typescript-sdk/image.md#env)
>
> [**workdir (TypeScript SDK)**](https://www.daytona.io/docs/typescript-sdk/image.md#workdir)
>
> [**env (Ruby SDK)**](https://www.daytona.io/docs/ruby-sdk/image.md#env)
>
> [**workdir (Ruby SDK)**](https://www.daytona.io/docs/ruby-sdk/image.md#workdir)
>
> [**Env (Go SDK)**](https://www.daytona.io/docs/go-sdk/daytona.md#DockerImage.Env)
>
> [**Workdir (Go SDK)**](https://www.daytona.io/docs/go-sdk/daytona.md#DockerImage.Workdir)
### Commands and entrypoints
Daytona provides an option to execute commands during build and configure container startup behavior.
The following snippets demonstrate how to execute commands during build and configure container startup behavior:
```python
# Run shell commands during build
image = Image.debian_slim("3.12").run_commands(
'apt-get update && apt-get install -y git',
'groupadd -r daytona && useradd -r -g daytona -m daytona',
'mkdir -p /home/daytona/workspace'
)
# Set entrypoint
image = Image.debian_slim("3.12").entrypoint(["/bin/bash"])
# Set default command
image = Image.debian_slim("3.12").cmd(["/bin/bash"])
```
```typescript
// Run shell commands during build
const image = Image.debianSlim('3.12').runCommands(
'apt-get update && apt-get install -y git',
'groupadd -r daytona && useradd -r -g daytona -m daytona',
'mkdir -p /home/daytona/workspace'
)
// Set entrypoint
const image = Image.debianSlim('3.12').entrypoint(['/bin/bash'])
// Set default command
const image = Image.debianSlim('3.12').cmd(['/bin/bash'])
```
```ruby
# Run shell commands during build
image = Daytona::Image.debian_slim('3.12').run_commands(
'apt-get update && apt-get install -y git',
'groupadd -r daytona && useradd -r -g daytona -m daytona',
'mkdir -p /home/daytona/workspace'
)
# Set entrypoint
image = Daytona::Image.debian_slim('3.12').entrypoint(['/bin/bash'])
# Set default command
image = Daytona::Image.debian_slim('3.12').cmd(['/bin/bash'])
```
```go
// Run shell commands during build
version := "3.12"
image := daytona.DebianSlim(&version).
Run("apt-get update && apt-get install -y git").
Run("groupadd -r daytona && useradd -r -g daytona -m daytona").
Run("mkdir -p /home/daytona/workspace")
// Set entrypoint
image := daytona.DebianSlim(&version).Entrypoint([]string{"/bin/bash"})
// Set default command
image := daytona.DebianSlim(&version).Cmd([]string{"/bin/bash"})
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk.md), and [Go SDK](https://www.daytona.io/docs/en/go-sdk.md) references:
> [**run_commands (Python SDK)**](https://www.daytona.io/docs/python-sdk/common/image.md#imagerun_commands)
>
> [**entrypoint (Python SDK)**](https://www.daytona.io/docs/python-sdk/common/image.md#imageentrypoint)
>
> [**cmd (Python SDK)**](https://www.daytona.io/docs/python-sdk/common/image.md#imagecmd)
>
> [**runCommands (TypeScript SDK)**](https://www.daytona.io/docs/typescript-sdk/image.md#runcommands)
>
> [**entrypoint (TypeScript SDK)**](https://www.daytona.io/docs/typescript-sdk/image.md#entrypoint)
>
> [**cmd (TypeScript SDK)**](https://www.daytona.io/docs/typescript-sdk/image.md#cmd)
>
> [**run_commands (Ruby SDK)**](https://www.daytona.io/docs/ruby-sdk/image.md#run_commands)
>
> [**entrypoint (Ruby SDK)**](https://www.daytona.io/docs/ruby-sdk/image.md#entrypoint)
>
> [**cmd (Ruby SDK)**](https://www.daytona.io/docs/ruby-sdk/image.md#cmd)
>
> [**Run (Go SDK)**](https://www.daytona.io/docs/go-sdk/daytona.md#DockerImage.Run)
>
> [**Entrypoint (Go SDK)**](https://www.daytona.io/docs/go-sdk/daytona.md#DockerImage.Entrypoint)
>
> [**Cmd (Go SDK)**](https://www.daytona.io/docs/go-sdk/daytona.md#DockerImage.Cmd)
### Dockerfile integration
Daytona provides an option to integrate existing Dockerfiles or add custom Dockerfile commands.
The following snippets demonstrate how to integrate existing Dockerfiles or add custom Dockerfile commands:
```python
# Add custom Dockerfile commands
image = Image.debian_slim("3.12").dockerfile_commands(["RUN echo 'Hello, world!'"])
# Use an existing Dockerfile
image = Image.from_dockerfile("Dockerfile")
# Extend an existing Dockerfile
image = Image.from_dockerfile("app/Dockerfile").pip_install(["numpy"])
```
```typescript
// Add custom Dockerfile commands
const image = Image.debianSlim('3.12').dockerfileCommands(['RUN echo "Hello, world!"'])
// Use an existing Dockerfile
const image = Image.fromDockerfile('Dockerfile')
// Extend an existing Dockerfile
const image = Image.fromDockerfile("app/Dockerfile").pipInstall(['numpy'])
```
```ruby
# Add custom Dockerfile commands
image = Daytona::Image.debian_slim('3.12').dockerfile_commands(['RUN echo "Hello, world!"'])
# Use an existing Dockerfile
image = Daytona::Image.from_dockerfile('Dockerfile')
# Extend an existing Dockerfile
image = Daytona::Image.from_dockerfile('app/Dockerfile').pip_install(['numpy'])
```
```go
// Note: In Go, FromDockerfile takes the Dockerfile content as a string
content, err := os.ReadFile("Dockerfile")
if err != nil {
// handle error
}
image := daytona.FromDockerfile(string(content))
// Extend an existing Dockerfile with additional commands
content, err = os.ReadFile("app/Dockerfile")
if err != nil {
// handle error
}
image := daytona.FromDockerfile(string(content)).
PipInstall([]string{"numpy"})
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk.md), and [Go SDK](https://www.daytona.io/docs/en/go-sdk.md) references:
> [**dockerfile_commands (Python SDK)**](https://www.daytona.io/docs/python-sdk/common/image.md#imagedockerfile_commands)
>
> [**from_dockerfile (Python SDK)**](https://www.daytona.io/docs/python-sdk/common/image.md#imagefrom_dockerfile)
>
> [**dockerfileCommands (TypeScript SDK)**](https://www.daytona.io/docs/typescript-sdk/image.md#dockerfilecommands)
>
> [**fromDockerfile (TypeScript SDK)**](https://www.daytona.io/docs/typescript-sdk/image.md#fromdockerfile)
>
> [**dockerfile_commands (Ruby SDK)**](https://www.daytona.io/docs/ruby-sdk/image.md#dockerfile_commands)
>
> [**FromDockerfile (Go SDK)**](https://www.daytona.io/docs/go-sdk/daytona.md#FromDockerfile)
OpenTelemetry (OTEL) tracing allows you to monitor and debug your Daytona SDK operations by collecting distributed traces. This is particularly useful for understanding performance bottlenecks, debugging issues, and gaining visibility into your sandbox operations.
:::caution
OpenTelemetry collection is currently an experimental feature and may change in future releases. To request access to this feature, please contact [support@daytona.io](mailto:support@daytona.io).
:::
---
## Sandbox Telemetry Collection
Daytona can collect traces, logs, and metrics directly from your sandboxes. This provides complete observability across your entire Daytona environment, from [SDK calls](#sdk-tracing-configuration) to sandbox runtime behavior.
### What Gets Collected from Sandboxes
When sandbox telemetry is enabled, the following data is collected:
**Metrics:**
- `daytona.sandbox.cpu.utilization` - CPU usage percentage (0-100%)
- `daytona.sandbox.cpu.limit` - CPU cores limit
- `daytona.sandbox.memory.utilization` - Memory usage percentage (0-100%)
- `daytona.sandbox.memory.usage` - Memory used in bytes
- `daytona.sandbox.memory.limit` - Memory limit in bytes
- `daytona.sandbox.filesystem.utilization` - Disk usage percentage (0-100%)
- `daytona.sandbox.filesystem.usage` - Disk space used in bytes
- `daytona.sandbox.filesystem.available` - Disk space available in bytes
- `daytona.sandbox.filesystem.total` - Total disk space in bytes
**Traces:**
- HTTP requests and responses
- Custom spans from your application code
**Logs:**
- Application logs (stdout/stderr)
- System logs
- Runtime errors and warnings
### Viewing Telemetry in the Dashboard
Logs, traces, and metrics collected from sandboxes can be viewed directly in the Daytona Dashboard. Open the **Sandbox Details** sheet for any sandbox and use the **Logs**, **Traces**, and **Metrics** tabs to inspect the collected telemetry data.
:::note
Daytona retains sandbox telemetry data for **3 days**. If you need to keep the data for longer, it is recommended that you connect your own OTLP-compatible collector using the [sandbox collection configuration](#configure-sandbox-collection).
:::
:::tip
Sandbox telemetry collection works independently from SDK tracing. You can enable one or both depending on your observability needs:
- **SDK tracing only**: Monitor Daytona API operations and SDK calls
- **Sandbox telemetry only**: Monitor application behavior inside sandboxes
- **Both**: Get complete end-to-end observability across your entire stack
:::
### Configure Sandbox Collection
To enable telemetry collection from sandboxes:
1. Navigate to the [Daytona Dashboard](https://app.daytona.io)
2. Go to **Settings** → **Experimental**
3. Configure the following fields:
- **OTLP Endpoint**: Your OpenTelemetry collector endpoint (e.g., `https://otlp.nr-data.net`)
- **OTLP Headers**: Authentication headers in `key=value` format (e.g., `api-key=YOUR_API_KEY`)
Once configured, all sandboxes will automatically export their telemetry data to your specified OTLP endpoint.
---
## SDK Tracing Configuration
When enabled, the Daytona SDK automatically instruments all SDK operations including:
- Sandbox creation, starting, stopping, and deletion
- File system operations
- Code execution
- Process management
- HTTP requests to the Daytona API
Traces are exported using the OTLP (OpenTelemetry Protocol) format and can be sent to any OTLP-compatible backend such as New Relic, Jaeger, or Zipkin.
### 1. Enable OTEL in SDK
To enable OpenTelemetry tracing, pass the `otelEnabled` experimental flag when initializing the Daytona client:
Alternatively, you can set the `DAYTONA_EXPERIMENTAL_OTEL_ENABLED` environment variable to `true` instead of passing the configuration option:
```bash
export DAYTONA_EXPERIMENTAL_OTEL_ENABLED=true
```
```python
from daytona import Daytona, DaytonaConfig
# Using async context manager (recommended)
async with Daytona(DaytonaConfig(
_experimental={"otelEnabled": True}
)) as daytona:
sandbox = await daytona.create()
# All operations will be traced
# OpenTelemetry traces are flushed on close
```
Or without context manager:
```python
daytona = Daytona(DaytonaConfig(
_experimental={"otelEnabled": True}
))
try:
sandbox = await daytona.create()
# All operations will be traced
finally:
await daytona.close() # Flushes traces
```
```typescript
import { Daytona } from '@daytonaio/sdk'
// Using async dispose (recommended)
await using daytona = new Daytona({
_experimental: { otelEnabled: true }
})
const sandbox = await daytona.create()
// All operations will be traced
// Traces are automatically flushed on dispose
```
Or with explicit disposal:
```typescript
const daytona = new Daytona({
_experimental: { otelEnabled: true }
})
try {
const sandbox = await daytona.create()
// All operations will be traced
} finally {
await daytona[Symbol.asyncDispose]() // Flushes traces
}
```
```go
import (
"context"
"log"
"github.com/daytonaio/daytona/libs/sdk-go/pkg/daytona"
"github.com/daytonaio/daytona/libs/sdk-go/pkg/types"
)
client, err := daytona.NewClientWithConfig(&types.DaytonaConfig{
Experimental: &types.ExperimentalConfig{
OtelEnabled: true,
},
})
if err != nil {
log.Fatal(err)
}
defer client.Close(context.Background()) // Flushes traces
sandbox, err := client.Create(context.Background(), nil)
// All operations will be traced
```
```ruby
require 'daytona'
config = Daytona::Config.new(
_experimental: { 'otel_enabled' => true }
)
daytona = Daytona::Daytona.new(config)
sandbox = daytona.create
# All operations will be traced
daytona.close # Flushes traces
```
Or with `ensure` block:
```ruby
daytona = Daytona::Daytona.new(
Daytona::Config.new(_experimental: { 'otel_enabled' => true })
)
begin
sandbox = daytona.create
# All operations will be traced
ensure
daytona.close # Flushes traces
end
```
### 2. Configure OTLP Exporter
The SDK uses standard OpenTelemetry environment variables for configuration. Set these before running your application:
#### Required Environment Variables
```bash
# OTLP endpoint (without the /v1/traces path)
OTEL_EXPORTER_OTLP_ENDPOINT=https://otlp.nr-data.net:4317
# Authentication headers (format: key1=value1,key2=value2)
OTEL_EXPORTER_OTLP_HEADERS="api-key=your-api-key-here"
```
---
## Provider-Specific Examples
### New Relic
```bash
OTEL_EXPORTER_OTLP_ENDPOINT=https://otlp.nr-data.net:4317
OTEL_EXPORTER_OTLP_HEADERS="api-key=YOUR_NEW_RELIC_LICENSE_KEY"
```
### Jaeger (Local)
```bash
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318
```
### Grafana Cloud
```bash
OTEL_EXPORTER_OTLP_ENDPOINT=https://otlp-gateway-prod-.grafana.net/otlp
OTEL_EXPORTER_OTLP_HEADERS="Authorization=Basic "
```
Setup: Go to [Grafana Cloud Portal](https://grafana.com) → **Connections** → **Add new connection** → Search for **OpenTelemetry (OTLP)** → Follow the wizard to create an access token. The endpoint and headers will be provided in the instrumentation instructions. See the [Grafana dashboard example](https://github.com/daytonaio/daytona/tree/main/examples/otel-dashboards/grafana) for detailed setup steps.
---
## Complete Example
Here's a complete example showing how to use OpenTelemetry tracing with the Daytona SDK:
```python
import asyncio
import os
from daytona import Daytona, DaytonaConfig
# Set OTEL configuration
os.environ["OTEL_EXPORTER_OTLP_ENDPOINT"] = "https://otlp.nr-data.net:4317"
os.environ["OTEL_EXPORTER_OTLP_HEADERS"] = "api-key=YOUR_API_KEY"
async def main():
# Initialize Daytona with OTEL enabled
async with Daytona(DaytonaConfig(
_experimental={"otelEnabled": True}
)) as daytona:
# Create a sandbox - this operation will be traced
sandbox = await daytona.create()
print(f"Created sandbox: {sandbox.id}")
# Execute code - this operation will be traced
result = await sandbox.process.code_run(""
import numpy as np
print(f"NumPy version: {np.__version__}")
"")
print(f"Execution result: {result.result}")
# Upload a file - this operation will be traced
await sandbox.fs.upload_file("local.txt", "/home/daytona/remote.txt")
# Delete sandbox - this operation will be traced
await daytona.delete(sandbox)
# Traces are automatically flushed when exiting the context manager
if __name__ == "__main__":
asyncio.run(main())
```
```typescript
// Set OTEL configuration
process.env.OTEL_EXPORTER_OTLP_ENDPOINT = "https://otlp.nr-data.net:4317"
process.env.OTEL_EXPORTER_OTLP_HEADERS = "api-key=YOUR_API_KEY"
import { Daytona } from '@daytonaio/sdk'
async function main() {
// Initialize Daytona with OTEL enabled
await using daytona = new Daytona({
_experimental: { otelEnabled: true }
})
// Create a sandbox - this operation will be traced
const sandbox = await daytona.create()
console.log(`Created sandbox: ${sandbox.id}`)
// Execute code - this operation will be traced
const result = await sandbox.process.codeRun(`
import numpy as np
print(f"NumPy version: {np.__version__}")
`)
console.log(`Execution result: ${result.result}`)
// Upload a file - this operation will be traced
await sandbox.fs.uploadFile('local.txt', '/home/daytona/remote.txt')
// Delete sandbox - this operation will be traced
await daytona.delete(sandbox)
// Traces are automatically flushed when the daytona instance is disposed
}
main().catch(console.error)
```
```go
package main
import (
"context"
"fmt"
"log"
"os"
"github.com/daytonaio/daytona/libs/sdk-go/pkg/daytona"
"github.com/daytonaio/daytona/libs/sdk-go/pkg/types"
)
func main() {
// Set OTEL configuration
os.Setenv("OTEL_EXPORTER_OTLP_ENDPOINT", "https://otlp.nr-data.net:4317")
os.Setenv("OTEL_EXPORTER_OTLP_HEADERS", "api-key=YOUR_API_KEY")
ctx := context.Background()
// Initialize Daytona with OTEL enabled
client, err := daytona.NewClientWithConfig(&types.DaytonaConfig{
Experimental: &types.ExperimentalConfig{
OtelEnabled: true,
},
})
if err != nil {
log.Fatal(err)
}
defer client.Close(ctx) // Flushes traces on exit
// Create a sandbox - this operation will be traced
sandbox, err := client.Create(ctx, nil)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Created sandbox: %s\n", sandbox.ID)
// Execute code - this operation will be traced
result, err := sandbox.Process.CodeRun(ctx, &types.CodeRunParams{
Code: `
import numpy as np
print(f"NumPy version: {np.__version__}")
`,
})
if err != nil {
log.Fatal(err)
}
fmt.Printf("Execution result: %s\n", result.Result)
// Upload a file - this operation will be traced
err = sandbox.Fs.UploadFile(ctx, "local.txt", "/home/daytona/remote.txt")
if err != nil {
log.Fatal(err)
}
// Delete sandbox - this operation will be traced
err = client.Delete(ctx, sandbox, nil)
if err != nil {
log.Fatal(err)
}
// Traces are flushed when client.Close is called via defer
}
```
```ruby
require 'daytona'
# Set OTEL configuration
ENV["OTEL_EXPORTER_OTLP_ENDPOINT"] = "https://otlp.nr-data.net:4317"
ENV["OTEL_EXPORTER_OTLP_HEADERS"] = "api-key=YOUR_API_KEY"
# Initialize Daytona with OTEL enabled
config = Daytona::Config.new(
_experimental: { 'otel_enabled' => true }
)
daytona = Daytona::Daytona.new(config)
begin
# Create a sandbox - this operation will be traced
sandbox = daytona.create
puts "Created sandbox: #{sandbox.id}"
# Execute code - this operation will be traced
result = sandbox.process.code_run("
import numpy as np
print(f'NumPy version: {np.__version__}')
")
puts "Execution result: #{result.result}"
# Upload a file - this operation will be traced
sandbox.fs.upload_file("local.txt", "/home/daytona/remote.txt")
# Delete sandbox - this operation will be traced
daytona.delete(sandbox)
ensure
daytona.close # Flushes traces
end
```
---
## What Gets Traced
The Daytona SDK automatically instruments the following operations:
### SDK-Level Operations
- `create()` - Sandbox creation and initialization
- `get()` - Retrieving sandbox instances
- `list()` - Listing sandboxes
- `start()` - Starting sandboxes
- `stop()` - Stopping sandboxes
- `delete()` - Deleting sandboxes
- All sandbox, snapshot and volume operations (file system, code execution, process management, etc.)
### HTTP Requests
- All API calls to the Daytona backend
- Request duration and response status codes
- Error information for failed requests
### Trace Attributes
Each trace includes valuable metadata such as:
- Service name and version
- HTTP method, URL, and status code
- Request and response duration
- Error details (if applicable)
- Custom SDK operation metadata
---
## Dashboard Examples
- [New Relic](https://github.com/daytonaio/daytona/tree/main/examples/otel-dashboards/new-relic)
- [Grafana](https://github.com/daytonaio/daytona/tree/main/examples/otel-dashboards/grafana)
## Troubleshooting
### Verify Traces Are Being Sent
1. Check that environment variables are set correctly
2. Verify your OTLP endpoint is reachable
3. Confirm API keys/headers are valid
4. Check your observability platform for incoming traces
5. Look for connection errors in application logs
### Common Issues
**Traces not appearing:**
- Ensure `otelEnabled: true` is set in the configuration
- Verify OTLP endpoint and headers are correct
- Check that you're properly closing/disposing the Daytona instance to flush traces
**Connection refused:**
- Verify the OTLP endpoint URL is correct
- Ensure the endpoint is accessible from your application
- Check firewall rules if running in a restricted environment
**Authentication errors:**
- Verify API key format matches your provider's requirements
- Check that the `OTEL_EXPORTER_OTLP_HEADERS` format is correct (key=value pairs)
---
## Best Practices
1. **Always close the client**: Use `async with` (Python), `await using` (TypeScript), `defer client.Close()` (Go), or `ensure daytona.close` (Ruby) to ensure traces are properly flushed
1. **Monitor trace volume**: Be aware that enabling tracing will increase network traffic and storage in your observability platform
1. **Use in development first**: Test OTEL configuration in development before enabling in production
1. **Configure sampling**: For high-volume applications, consider configuring trace sampling to reduce costs
---
## Additional Resources
- [OpenTelemetry Documentation](https://opentelemetry.io/docs/)
- [OTLP Specification](https://opentelemetry.io/docs/specs/otlp/)
- [Daytona SDK Documentation](https://www.daytona.io/docs/en/introduction.md)
Daytona provides comprehensive file system operations through the `fs` module in sandboxes.
## Basic operations
Daytona provides methods to interact with the file system in sandboxes. You can perform various operations like listing files, creating directories, reading and writing files, and more.
File operations assume you are operating in the sandbox user's home directory (e.g. `workspace` implies `/home/[username]/workspace`). Use a leading `/` when providing absolute paths.
### List files and directories
Daytona provides methods to list files and directories in a sandbox by providing the path to the directory. If the path is not provided, the method will list the files and directories in the sandbox working directory.
```python
# List files in a directory
files = sandbox.fs.list_files("workspace")
for file in files:
print(f"Name: {file.name}")
print(f"Is directory: {file.is_dir}")
print(f"Size: {file.size}")
print(f"Modified: {file.mod_time}")
```
```typescript
// List files in a directory
const files = await sandbox.fs.listFiles('workspace')
files.forEach(file => {
console.log(`Name: ${file.name}`)
console.log(`Is directory: ${file.isDir}`)
console.log(`Size: ${file.size}`)
console.log(`Modified: ${file.modTime}`)
})
```
```ruby
# List directory contents
files = sandbox.fs.list_files("workspace/data")
# Print files and their sizes
files.each do |file|
puts "#{file.name}: #{file.size} bytes" unless file.is_dir
end
# List only directories
dirs = files.select(&:is_dir)
puts "Subdirectories: #{dirs.map(&:name).join(', ')}"
```
```go
// List files in a directory
files, err := sandbox.FileSystem.ListFiles(ctx, "workspace")
if err != nil {
log.Fatal(err)
}
for _, file := range files {
fmt.Printf("Name: %s\n", file.Name)
fmt.Printf("Is directory: %t\n", file.IsDirectory)
fmt.Printf("Size: %d\n", file.Size)
fmt.Printf("Modified: %s\n", file.ModifiedTime)
}
```
```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/files'
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk.md), [Go SDK](https://www.daytona.io/docs/en/go-sdk.md), and [API](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox) references:
> [**list_files (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/file-system.md#filesystemlist_files)
>
> [**listFiles (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/file-system.md#listfiles)
>
> [**list_files (Ruby SDK)**](https://www.daytona.io/docs/en/ruby-sdk/file-system.md#list_files)
>
> [**ListFiles (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#FileSystemService.ListFiles)
>
> [**list files and directories (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/file-system/GET/files)
### Get directory or file information
Daytona provides methods to get directory or file information such as group, directory, modified time, mode, name, owner, permissions, and size by providing the path to the directory or file.
```python
# Get file metadata
info = sandbox.fs.get_file_info("workspace/data/file.txt")
print(f"Size: {info.size} bytes")
print(f"Modified: {info.mod_time}")
print(f"Mode: {info.mode}")
# Check if path is a directory
info = sandbox.fs.get_file_info("workspace/data")
if info.is_dir:
print("Path is a directory")
```
```typescript
// Get file details
const info = await fs.getFileDetails('app/config.json')
console.log(`Size: ${info.size}, Modified: ${info.modTime}`)
```
```ruby
# Get file metadata
info = sandbox.fs.get_file_info("workspace/data/file.txt")
puts "Size: #{info.size} bytes"
puts "Modified: #{info.mod_time}"
puts "Mode: #{info.mode}"
# Check if path is a directory
info = sandbox.fs.get_file_info("workspace/data")
puts "Path is a directory" if info.is_dir
```
```go
// Get file metadata
info, err := sandbox.FileSystem.GetFileInfo(ctx, "workspace/data/file.txt")
if err != nil {
log.Fatal(err)
}
fmt.Printf("Size: %d bytes\n", info.Size)
fmt.Printf("Modified: %s\n", info.ModifiedTime)
fmt.Printf("Mode: %s\n", info.Mode)
// Check if path is a directory
info, err = sandbox.FileSystem.GetFileInfo(ctx, "workspace/data")
if err != nil {
log.Fatal(err)
}
if info.IsDirectory {
fmt.Println("Path is a directory")
}
```
```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/files/info?path='
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk.md), [Go SDK](https://www.daytona.io/docs/en/go-sdk.md), and [API](https://www.daytona.io/docs/en/tools/api.md) references:
> [**get_file_info (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/file-system.md#filesystemget_file_info)
>
> [**getFileDetails (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/file-system.md#getfiledetails)
>
> [**get_file_info (Ruby SDK)**](https://www.daytona.io/docs/en/ruby-sdk/file-system.md#get_file_info)
>
> [**GetFileInfo (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#FileSystemService.GetFileInfo)
>
> [**get file information (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/file-system/GET/files/info)
### Create directories
Daytona provides methods to create directories by providing the path to the directory and the permissions to set on the directory.
```python
# Create with specific permissions
sandbox.fs.create_folder("workspace/new-dir", "755")
```
```typescript
// Create with specific permissions
await sandbox.fs.createFolder('workspace/new-dir', '755')
```
```ruby
# Create a directory with standard permissions
sandbox.fs.create_folder("workspace/data", "755")
# Create a private directory
sandbox.fs.create_folder("workspace/secrets", "700")
```
```go
// Create with specific permissions
err := sandbox.FileSystem.CreateFolder(ctx, "workspace/new-dir",
options.WithMode("755"),
)
if err != nil {
log.Fatal(err)
}
```
```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/files/folder?path=&mode=' \
--request POST
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk.md), [Go SDK](https://www.daytona.io/docs/en/go-sdk.md), and [API](https://www.daytona.io/docs/en/tools/api.md) references:
> [**create_folder (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/file-system.md#filesystemcreate_folder)
>
> [**createFolder (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/file-system.md#createfolder)
>
> [**create_folder (Ruby SDK)**](https://www.daytona.io/docs/en/ruby-sdk/file-system.md#create_folder)
>
> [**CreateFolder (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#FileSystemService.CreateFolder)
>
> [**create folder (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/file-system/POST/files/folder)
### Upload files
Daytona provides methods to upload a single or multiple files in sandboxes.
#### Upload a single file
Daytona provides methods to upload a single file in sandboxes by providing the content to upload and the path to the file to upload it to.
```python
# Upload a single file
with open("local_file.txt", "rb") as f:
content = f.read()
sandbox.fs.upload_file(content, "remote_file.txt")
```
```typescript
// Upload a single file
const fileContent = Buffer.from('Hello, World!')
await sandbox.fs.uploadFile(fileContent, 'data.txt')
```
```ruby
# Upload a text file from string content
content = "Hello, World!"
sandbox.fs.upload_file(content, "tmp/hello.txt")
# Upload a local file
sandbox.fs.upload_file("local_file.txt", "tmp/file.txt")
# Upload binary data
data = { key: "value" }.to_json
sandbox.fs.upload_file(data, "tmp/config.json")
```
```go
// Upload from a local file path
err := sandbox.FileSystem.UploadFile(ctx, "local_file.txt", "remote_file.txt")
if err != nil {
log.Fatal(err)
}
// Or upload from byte content
content := []byte("Hello, World!")
err = sandbox.FileSystem.UploadFile(ctx, content, "hello.txt")
if err != nil {
log.Fatal(err)
}
```
```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/files/upload?path=' \
--request POST \
--header 'Content-Type: multipart/form-data' \
--form 'file='
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk.md), [Go SDK](https://www.daytona.io/docs/en/go-sdk.md), and [API](https://www.daytona.io/docs/en/tools/api.md) references:
> [**upload_file (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/file-system.md#filesystemupload_file)
>
> [**uploadFile (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/file-system.md#uploadfile)
>
> [**upload_file (Ruby SDK)**](https://www.daytona.io/docs/en/ruby-sdk/file-system.md#upload_file)
>
> [**UploadFile (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#FileSystemService.UploadFile)
>
> [**upload file (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/file-system/POST/files/upload)
#### Upload multiple files
Daytona provides methods to upload multiple files in sandboxes by providing the content to upload and their destination paths.
```python
# Upload multiple files at once
files_to_upload = []
with open("file1.txt", "rb") as f1:
files_to_upload.append(FileUpload(
source=f1.read(),
destination="data/file1.txt",
))
with open("file2.txt", "rb") as f2:
files_to_upload.append(FileUpload(
source=f2.read(),
destination="data/file2.txt",
))
with open("settings.json", "rb") as f3:
files_to_upload.append(FileUpload(
source=f3.read(),
destination="config/settings.json",
))
sandbox.fs.upload_files(files_to_upload)
```
```typescript
// Upload multiple files at once
const files = [
{
source: Buffer.from('Content of file 1'),
destination: 'data/file1.txt',
},
{
source: Buffer.from('Content of file 2'),
destination: 'data/file2.txt',
},
{
source: Buffer.from('{"key": "value"}'),
destination: 'config/settings.json',
},
]
await sandbox.fs.uploadFiles(files)
```
```ruby
# Upload multiple files
files = [
FileUpload.new("Content of file 1", "/tmp/file1.txt"),
FileUpload.new("workspace/data/file2.txt", "/tmp/file2.txt"),
FileUpload.new('{"key": "value"}', "/tmp/config.json")
]
sandbox.fs.upload_files(files)
```
```go
// Upload multiple files by calling UploadFile for each
filesToUpload := []struct {
source string
destination string
}{
{"file1.txt", "data/file1.txt"},
{"file2.txt", "data/file2.txt"},
{"settings.json", "config/settings.json"},
}
for _, f := range filesToUpload {
err := sandbox.FileSystem.UploadFile(ctx, f.source, f.destination)
if err != nil {
log.Fatal(err)
}
}
```
```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/files/bulk-upload' \
--request POST
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk.md), [Go SDK](https://www.daytona.io/docs/en/go-sdk.md), and [API](https://www.daytona.io/docs/en/tools/api.md) references:
> [**upload_files (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/file-system.md#filesystemupload_files)
>
> [**uploadFiles (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/file-system.md#uploadfiles)
>
> [**upload_files (Ruby SDK)**](https://www.daytona.io/docs/en/ruby-sdk/file-system.md#upload_files)
>
> [**upload multiple files (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/file-system/POST/files/bulk-upload)
### Download files
Daytona provides methods to download files from sandboxes.
#### Download a single file
Daytona provides methods to download a single file from sandboxes by providing the path to the file to download.
```python
content = sandbox.fs.download_file("file1.txt")
with open("local_file.txt", "wb") as f:
f.write(content)
print(content.decode('utf-8'))
```
```typescript
const downloadedFile = await sandbox.fs.downloadFile('file1.txt')
console.log('File content:', downloadedFile.toString())
```
```ruby
# Download and get file content
content = sandbox.fs.download_file("workspace/data/file.txt")
puts content
# Download and save a file locally
sandbox.fs.download_file("workspace/data/file.txt", "local_copy.txt")
size_mb = File.size("local_copy.txt") / 1024.0 / 1024.0
puts "Size of the downloaded file: #{size_mb} MB"
```
```go
// Download and get contents in memory
content, err := sandbox.FileSystem.DownloadFile(ctx, "file1.txt", nil)
if err != nil {
log.Fatal(err)
}
fmt.Println(string(content))
// Download and save to a local file
localPath := "local_file.txt"
content, err = sandbox.FileSystem.DownloadFile(ctx, "file1.txt", &localPath)
if err != nil {
log.Fatal(err)
}
```
```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/files/download?path='
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk.md), [Go SDK](https://www.daytona.io/docs/en/go-sdk.md), and [API](https://www.daytona.io/docs/en/tools/api.md) references:
> [**download_file (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/file-system.md#filesystemdownload_file)
>
> [**downloadFile (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/file-system.md#downloadfile)
>
> [**download_file (Ruby SDK)**](https://www.daytona.io/docs/en/ruby-sdk/file-system.md#download_file)
>
> [**DownloadFile (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#FileSystemService.DownloadFile)
>
> [**download file (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/file-system/GET/files/download)
#### Download multiple files
Daytona provides methods to download multiple files from sandboxes by providing the paths to the files to download.
```python
# Download multiple files at once
files_to_download = [
FileDownloadRequest(source="data/file1.txt"), # No destination - download to memory
FileDownloadRequest(source="data/file2.txt", destination="local_file2.txt"), # Download to local file
]
results = sandbox.fs.download_files(files_to_download)
for result in results:
if result.error:
print(f"Error downloading {result.source}: {result.error}")
elif result.result:
print(f"Downloaded {result.source} to {result.result}")
```
```typescript
// Download multiple files at once
const files = [
{ source: 'data/file1.txt' }, // No destination - download to memory
{ source: 'data/file2.txt', destination: 'local_file2.txt' }, // Download to local file
]
const results = await sandbox.fs.downloadFiles(files)
results.forEach(result => {
if (result.error) {
console.error(`Error downloading ${result.source}: ${result.error}`)
} else if (result.result) {
console.log(`Downloaded ${result.source} to ${result.result}`)
}
})
```
```ruby
# Download multiple files by calling download_file for each
files_to_download = [
{ remote: "data/file1.txt", local: nil }, # Download to memory
{ remote: "data/file2.txt", local: "local_file2.txt" } # Download to local file
]
files_to_download.each do |f|
if f[:local]
sandbox.fs.download_file(f[:remote], f[:local])
puts "Downloaded #{f[:remote]} to #{f[:local]}"
else
content = sandbox.fs.download_file(f[:remote])
puts "Downloaded #{f[:remote]} to memory (#{content.size} bytes)"
end
end
```
```go
// Download multiple files by calling DownloadFile for each
filesToDownload := []struct {
remotePath string
localPath *string
}{
{"data/file1.txt", nil}, // Download to memory
{"data/file2.txt", ptrString("local_file2.txt")}, // Download to local file
}
for _, f := range filesToDownload {
content, err := sandbox.FileSystem.DownloadFile(ctx, f.remotePath, f.localPath)
if err != nil {
fmt.Printf("Error downloading %s: %v\n", f.remotePath, err)
continue
}
if f.localPath == nil {
fmt.Printf("Downloaded %s to memory (%d bytes)\n", f.remotePath, len(content))
} else {
fmt.Printf("Downloaded %s to %s\n", f.remotePath, *f.localPath)
}
}
```
```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/files/bulk-download' \
--request POST \
--header 'Content-Type: application/json' \
--data '{
"paths": [
""
]
}'
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk.md), [Go SDK](https://www.daytona.io/docs/en/go-sdk.md), and [API](https://www.daytona.io/docs/en/tools/api.md) references:
> [**download_files (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/file-system.md#filesystemdownload_files)
>
> [**downloadFiles (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/file-system.md#downloadfiles)
>
> [**download_file (Ruby SDK)**](https://www.daytona.io/docs/en/ruby-sdk/file-system.md#download_file)
>
> [**download multiple files (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/file-system/POST/files/bulk-download)
### Delete files
Daytona provides methods to delete files or directories from sandboxes by providing the path to the file or directory to delete.
```python
sandbox.fs.delete_file("workspace/file.txt")
```
```typescript
await sandbox.fs.deleteFile('workspace/file.txt')
```
```ruby
# Delete a file
sandbox.fs.delete_file("workspace/data/old_file.txt")
# Delete a directory recursively
sandbox.fs.delete_file("workspace/old_dir", recursive: true)
```
```go
// Delete a file
err := sandbox.FileSystem.DeleteFile(ctx, "workspace/file.txt", false)
if err != nil {
log.Fatal(err)
}
// Delete a directory recursively
err = sandbox.FileSystem.DeleteFile(ctx, "workspace/old_dir", true)
if err != nil {
log.Fatal(err)
}
```
```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/files?path=' \
--request DELETE
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk.md), [Go SDK](https://www.daytona.io/docs/en/go-sdk.md), and [API](https://www.daytona.io/docs/en/tools/api.md) references:
> [**delete_file (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/file-system.md#filesystemdelete_file)
>
> [**deleteFile (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/file-system.md#deletefile)
>
> [**delete_file (Ruby SDK)**](https://www.daytona.io/docs/en/ruby-sdk/file-system.md#delete_file)
>
> [**DeleteFile (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#FileSystemService.DeleteFile)
>
> [**delete file or directory (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/file-system/DELETE/files)
## Advanced operations
Daytona provides advanced file system operations such as file permissions, search and replace, and move files.
### File permissions
Daytona provides methods to set file permissions, ownership, and group for a file or directory by providing the path to the file or directory and the permissions to set.
```python
# Set file permissions
sandbox.fs.set_file_permissions("workspace/file.txt", "644")
# Get file permissions
file_info = sandbox.fs.get_file_info("workspace/file.txt")
print(f"Permissions: {file_info.permissions}")
```
```typescript
// Set file permissions
await sandbox.fs.setFilePermissions('workspace/file.txt', { mode: '644' })
// Get file permissions
const fileInfo = await sandbox.fs.getFileDetails('workspace/file.txt')
console.log(`Permissions: ${fileInfo.permissions}`)
```
```ruby
# Make a file executable
sandbox.fs.set_file_permissions(
path: "workspace/scripts/run.sh",
mode: "755" # rwxr-xr-x
)
# Change file owner
sandbox.fs.set_file_permissions(
path: "workspace/data/file.txt",
owner: "daytona",
group: "daytona"
)
```
```go
// Set file permissions
err := sandbox.FileSystem.SetFilePermissions(ctx, "workspace/file.txt",
options.WithPermissionMode("644"),
)
if err != nil {
log.Fatal(err)
}
// Set owner and group
err = sandbox.FileSystem.SetFilePermissions(ctx, "workspace/file.txt",
options.WithOwner("daytona"),
options.WithGroup("daytona"),
)
if err != nil {
log.Fatal(err)
}
// Get file info to check permissions
fileInfo, err := sandbox.FileSystem.GetFileInfo(ctx, "workspace/file.txt")
if err != nil {
log.Fatal(err)
}
fmt.Printf("Mode: %s\n", fileInfo.Mode)
```
```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/files/permissions?path=' \
--request POST
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk.md), [Go SDK](https://www.daytona.io/docs/en/go-sdk.md), and [API](https://www.daytona.io/docs/en/tools/api.md) references:
> [**set_file_permissions (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/file-system.md#filesystemset_file_permissions)
>
> [**setFilePermissions (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/file-system.md#setfilepermissions)
>
> [**set_file_permissions (Ruby SDK)**](https://www.daytona.io/docs/en/ruby-sdk/file-system.md#set_file_permissions)
>
> [**SetFilePermissions (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#FileSystemService.SetFilePermissions)
>
> [**set file permissions (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/file-system/POST/files/permissions)
### Find and replace text in files
Daytona provides methods to find and replace text in files by providing the path to the directory to search in and the pattern to search for.
```python
# Search for text in files by providing the path to the directory to search in and the pattern to search for
results = sandbox.fs.find_files(
path="workspace/src",
pattern="text-of-interest"
)
for match in results:
print(f"Absolute file path: {match.file}")
print(f"Line number: {match.line}")
print(f"Line content: {match.content}")
print("\n")
# Replace text in files
sandbox.fs.replace_in_files(
files=["workspace/file1.txt", "workspace/file2.txt"],
pattern="old_text",
new_value="new_text"
)
```
```typescript
// Search for text in files; if a folder is specified, the search is recursive
const results = await sandbox.fs.findFiles({
path="workspace/src",
pattern: "text-of-interest"
})
results.forEach(match => {
console.log('Absolute file path:', match.file)
console.log('Line number:', match.line)
console.log('Line content:', match.content)
})
// Replace text in files
await sandbox.fs.replaceInFiles(
["workspace/file1.txt", "workspace/file2.txt"],
"old_text",
"new_text"
)
```
```ruby
# Search for TODOs in Ruby files
matches = sandbox.fs.find_files("workspace/src", "TODO:")
matches.each do |match|
puts "#{match.file}:#{match.line}: #{match.content.strip}"
end
# Replace in specific files
results = sandbox.fs.replace_in_files(
files: ["workspace/src/file1.rb", "workspace/src/file2.rb"],
pattern: "old_function",
new_value: "new_function"
)
# Print results
results.each do |result|
if result.success
puts "#{result.file}: #{result.success}"
else
puts "#{result.file}: #{result.error}"
end
end
```
```go
// Search for text in files
result, err := sandbox.FileSystem.FindFiles(ctx, "workspace/src", "text-of-interest")
if err != nil {
log.Fatal(err)
}
matches := result.([]map[string]any)
for _, match := range matches {
fmt.Printf("Absolute file path: %s\n", match["file"])
fmt.Printf("Line number: %v\n", match["line"])
fmt.Printf("Line content: %s\n\n", match["content"])
}
// Replace text in files
_, err = sandbox.FileSystem.ReplaceInFiles(ctx,
[]string{"workspace/file1.txt", "workspace/file2.txt"},
"old_text",
"new_text",
)
if err != nil {
log.Fatal(err)
}
```
Find text in files:
```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/files/find?path=&pattern='
```
Replace text in files:
```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/files/replace' \
--request POST \
--header 'Content-Type: application/json' \
--data '{
"files": [
""
],
"newValue": "",
"pattern": ""
}'
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk.md), [Go SDK](https://www.daytona.io/docs/en/go-sdk.md), and [API](https://www.daytona.io/docs/en/tools/api.md) references:
> [**find_files (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/file-system.md#filesystemfind_files)
>
> [**replace_in_files (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/file-system.md#filesystemreplace_in_files)
>
> [**findFiles (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/file-system.md#findfiles)
>
> [**replaceInFiles (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/file-system.md#replaceinfiles)
>
> [**find_files (Ruby SDK)**](https://www.daytona.io/docs/en/ruby-sdk/file-system.md#find_files)
>
> [**replace_in_files (Ruby SDK)**](https://www.daytona.io/docs/en/ruby-sdk/file-system.md#replace_in_files)
>
> [**FindFiles (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#FileSystemService.FindFiles)
>
> [**ReplaceInFiles (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#FileSystemService.ReplaceInFiles)
>
> [**find text in files (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/file-system/GET/files/find)
>
> [**replace text in files (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/file-system/POST/files/replace)
### Move or rename directory or file
Daytona provides methods to move or rename a directory or file in sandboxes by providing the path to the file or directory (source) and the new path to the file or directory (destination).
```python
# Rename a file
sandbox.fs.move_files(
"workspace/data/old_name.txt",
"workspace/data/new_name.txt"
)
# Move a file to a different directory
sandbox.fs.move_files(
"workspace/data/file.txt",
"workspace/archive/file.txt"
)
# Move a directory
sandbox.fs.move_files(
"workspace/old_dir",
"workspace/new_dir"
)
```
```typescript
// Move a file to a new location
await fs.moveFiles('app/temp/data.json', 'app/data/data.json')
```
```ruby
# Rename a file
sandbox.fs.move_files(
"workspace/data/old_name.txt",
"workspace/data/new_name.txt"
)
# Move a file to a different directory
sandbox.fs.move_files(
"workspace/data/file.txt",
"workspace/archive/file.txt"
)
# Move a directory
sandbox.fs.move_files(
"workspace/old_dir",
"workspace/new_dir"
)
```
```go
// Rename a file
err := sandbox.FileSystem.MoveFiles(ctx, "workspace/data/old_name.txt", "workspace/data/new_name.txt")
if err != nil {
log.Fatal(err)
}
// Move a file to a different directory
err = sandbox.FileSystem.MoveFiles(ctx, "workspace/data/file.txt", "workspace/archive/file.txt")
if err != nil {
log.Fatal(err)
}
// Move a directory
err = sandbox.FileSystem.MoveFiles(ctx, "workspace/old_dir", "workspace/new_dir")
if err != nil {
log.Fatal(err)
}
```
```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/files/move?source=&destination=' \
--request POST
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk.md), [Go SDK](https://www.daytona.io/docs/en/go-sdk.md), and [API](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox) references:
> [**move_files (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/file-system.md#filesystemmove_files)
>
> [**moveFiles (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/file-system.md#movefiles)
>
> [**move_files (Ruby SDK)**](https://www.daytona.io/docs/en/ruby-sdk/file-system.md#move_files)
>
> [**MoveFiles (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#FileSystemService.MoveFiles)
>
> [**move or rename file or directory (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/file-system/POST/files/move)
This section introduces core concepts, common workflows, and next steps for using Daytona.
## Dashboard
[Daytona Dashboard ↗](https://app.daytona.io/) is a visual user interface where you can manage sandboxes, access API keys, view usage, and more.
It serves as the primary point of control for managing your Daytona resources.
## SDKs
Daytona provides [Python](https://www.daytona.io/docs/en/python-sdk.md), [TypeScript](https://www.daytona.io/docs/en/typescript-sdk.md), [Ruby](https://www.daytona.io/docs/en/ruby-sdk.md), and [Go](https://www.daytona.io/docs/en/go-sdk.md) SDKs to programmatically interact with sandboxes. They support sandbox lifecycle management, code execution, resource access, and more.
## CLI
Daytona provides command-line access to core features for interacting with Daytona Sandboxes, including managing their lifecycle, snapshots, and more.
To interact with Daytona Sandboxes from the command line, install the Daytona CLI:
```bash
brew install daytonaio/cli/daytona
```
```bash
powershell -Command "irm https://get.daytona.io/windows | iex"
```
After installing the Daytona CLI, use the `daytona` command to interact with Daytona Sandboxes from the command line.
To upgrade the Daytona CLI to the latest version:
```bash
brew upgrade daytonaio/cli/daytona
```
```bash
powershell -Command "irm https://get.daytona.io/windows | iex"
```
To view all available commands and flags, see the [CLI reference](https://www.daytona.io/docs/en/tools/cli.md).
## API
Daytona provides a RESTful API for interacting with Daytona Sandboxes, including managing their lifecycle, snapshots, and more.
It serves as a flexible and powerful way to interact with Daytona from your own applications.
To interact with Daytona Sandboxes from the API, see the [API reference](https://www.daytona.io/docs/en/tools/api.md).
## MCP server
Daytona provides a Model Context Protocol (MCP) server that enables AI agents to interact with Daytona Sandboxes programmatically. The MCP server integrates with popular AI agents including Claude, Cursor, and Windsurf.
To set up the MCP server with your AI agent:
```bash
daytona mcp init [claude/cursor/windsurf]
```
For more information, see the [MCP server documentation](https://www.daytona.io/docs/en/mcp.md).
## Multiple runtime support
Daytona supports multiple programming language runtimes for direct code execution inside the sandbox.
[TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk.md) works across multiple **JavaScript runtimes** including **Node.js**, **browsers**, and **serverless platforms**: Cloudflare Workers, AWS Lambda, Azure Functions, etc.
Using the Daytona SDK in browser-based environments or frameworks like [**Vite**](https://www.daytona.io/docs/en/getting-started.md#daytona-in-vite-projects) and [**Next.js**](https://www.daytona.io/docs/en/getting-started.md#daytona-in-nextjs-projects) requires configuring node polyfills.
### Daytona in Vite projects
When using Daytona SDK in a Vite-based project, configure node polyfills to ensure compatibility.
Add the following configuration to your `vite.config.ts` file in the `plugins` array:
```typescript
import { nodePolyfills } from 'vite-plugin-node-polyfills'
plugins: [
// ... other plugins
nodePolyfills({
globals: { global: true, process: true, Buffer: true },
overrides: {
path: 'path-browserify-win32',
},
}),
],
// ... rest of your config
})
```
### Daytona in Next.js projects
When using Daytona SDK in a Next.js project, configure node polyfills to ensure compatibility with Webpack and Turbopack bundlers.
Add the following configuration to your `next.config.ts` file:
```typescript
import type { NextConfig } from 'next'
import NodePolyfillPlugin from 'node-polyfill-webpack-plugin'
import { env, nodeless } from 'unenv'
const { alias: turbopackAlias } = env(nodeless, {})
const nextConfig: NextConfig = {
// Turbopack
experimental: {
turbo: {
resolveAlias: {
...turbopackAlias,
},
},
},
// Webpack
webpack: (config, { isServer }) => {
if (!isServer) {
config.plugins.push(new NodePolyfillPlugin())
}
return config
},
}
```
## Guides
Daytona provides a comprehensive set of guides to help you get started. The guides cover a wide range of topics, from basic usage to advanced topics, and showcase various types of integrations between Daytona and other tools.
For more information, see [guides](https://www.daytona.io/docs/en/guides.md).
## Examples
Daytona provides quick examples for common sandbox operations and best practices.
The examples are based on the Daytona [Python SDK](https://www.daytona.io/docs/en/python-sdk/sync/process.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk/process.md), [Go SDK](https://www.daytona.io/docs/en/go-sdk/daytona.md#type-processservice), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk/process.md), [CLI](https://www.daytona.io/docs/en/tools/cli.md), and [API](https://www.daytona.io/docs/en/tools/api.md) references. More examples are available in the [GitHub repository ↗](https://github.com/daytonaio/daytona/tree/main/examples).
### Create a sandbox
Create a [sandbox](https://www.daytona.io/docs/en/sandboxes.md) with default settings.
```python
from daytona import Daytona
daytona = Daytona()
sandbox = daytona.create()
print(f"Sandbox ID: {sandbox.id}")
```
```typescript
import { Daytona } from '@daytonaio/sdk';
const daytona = new Daytona();
const sandbox = await daytona.create();
console.log(`Sandbox ID: ${sandbox.id}`);
```
```go
package main
import (
"context"
"fmt"
"log"
"github.com/daytonaio/daytona/libs/sdk-go/pkg/daytona"
)
func main() {
client, err := daytona.NewClient()
if err != nil {
log.Fatal(err)
}
sandbox, err := client.Create(context.Background(), nil)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Sandbox ID: %s\n", sandbox.ID)
}
```
```ruby
require 'daytona'
daytona = Daytona::Daytona.new
sandbox = daytona.create
puts "Sandbox ID: #{sandbox.id}"
```
```shell
daytona create
```
```bash
curl 'https://app.daytona.io/api/sandbox' \
--request POST \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{}'
```
### Create and run code in a sandbox
Create a [sandbox](https://www.daytona.io/docs/en/sandboxes.md) and run code securely in it.
```python
from daytona import Daytona
daytona = Daytona()
sandbox = daytona.create()
response = sandbox.process.exec("echo 'Hello, World!'")
print(response.result)
sandbox.delete()
```
```typescript
import { Daytona } from '@daytonaio/sdk';
const daytona = new Daytona();
const sandbox = await daytona.create();
const response = await sandbox.process.executeCommand('echo "Hello, World!"');
console.log(response.result);
await sandbox.delete();
```
```go
package main
import (
"context"
"fmt"
"log"
"github.com/daytonaio/daytona/libs/sdk-go/pkg/daytona"
)
func main() {
client, err := daytona.NewClient()
if err != nil {
log.Fatal(err)
}
sandbox, err := client.Create(context.Background(), nil)
if err != nil {
log.Fatal(err)
}
response, err := sandbox.Process.ExecuteCommand(context.Background(), "echo 'Hello, World!'")
if err != nil {
log.Fatal(err)
}
fmt.Println(response.Result)
sandbox.Delete(context.Background())
}
```
```ruby
require 'daytona'
daytona = Daytona::Daytona.new
sandbox = daytona.create
response = sandbox.process.exec(command: "echo 'Hello, World!'")
puts response.result
daytona.delete(sandbox)
```
```shell
daytona create --name my-sandbox
daytona exec my-sandbox -- echo 'Hello, World!'
daytona delete my-sandbox
```
```bash
# Create a sandbox
curl 'https://app.daytona.io/api/sandbox' \
--request POST \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{}'
# Execute a command in the sandbox
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/process/execute' \
--request POST \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"command": "echo '\''Hello, World!'\''"
}'
# Delete the sandbox
curl 'https://app.daytona.io/api/sandbox/{sandboxId}' \
--request DELETE \
--header 'Authorization: Bearer '
```
### Create a sandbox with custom resources
Create a sandbox with [custom resources](https://www.daytona.io/docs/en/sandboxes.md#resources) (CPU, memory, disk).
```python
from daytona import Daytona, CreateSandboxFromImageParams, Image, Resources
daytona = Daytona()
sandbox = daytona.create(
CreateSandboxFromImageParams(
image=Image.debian_slim("3.12"),
resources=Resources(cpu=2, memory=4, disk=8)
)
)
```
```typescript
import { Daytona, Image } from '@daytonaio/sdk';
const daytona = new Daytona();
const sandbox = await daytona.create({
image: Image.debianSlim('3.12'),
resources: { cpu: 2, memory: 4, disk: 8 }
});
```
```go
package main
import (
"context"
"log"
"github.com/daytonaio/daytona/libs/sdk-go/pkg/daytona"
"github.com/daytonaio/daytona/libs/sdk-go/pkg/types"
)
func main() {
client, err := daytona.NewClient()
if err != nil {
log.Fatal(err)
}
sandbox, err := client.Create(context.Background(), types.ImageParams{
Image: daytona.DebianSlim(nil),
Resources: &types.Resources{
CPU: 2,
Memory: 4,
Disk: 8,
},
})
if err != nil {
log.Fatal(err)
}
}
```
```ruby
require 'daytona'
daytona = Daytona::Daytona.new
sandbox = daytona.create(
Daytona::CreateSandboxFromImageParams.new(
image: Daytona::Image.debian_slim('3.12'),
resources: Daytona::Resources.new(cpu: 2, memory: 4, disk: 8)
)
)
```
```shell
daytona create --class small
```
```bash
curl 'https://app.daytona.io/api/sandbox' \
--request POST \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"cpu": 2,
"memory": 4,
"disk": 8
}'
```
### Create an ephemeral sandbox
Create an [ephemeral sandbox](https://www.daytona.io/docs/en/sandboxes.md#ephemeral-sandboxes) that is automatically deleted when stopped.
```python
from daytona import Daytona, CreateSandboxFromSnapshotParams
daytona = Daytona()
sandbox = daytona.create(
CreateSandboxFromSnapshotParams(ephemeral=True, auto_stop_interval=5)
)
```
```typescript
import { Daytona } from '@daytonaio/sdk';
const daytona = new Daytona();
const sandbox = await daytona.create({
ephemeral: true,
autoStopInterval: 5
});
```
```go
package main
import (
"context"
"log"
"github.com/daytonaio/daytona/libs/sdk-go/pkg/daytona"
"github.com/daytonaio/daytona/libs/sdk-go/pkg/types"
)
func main() {
client, err := daytona.NewClient()
if err != nil {
log.Fatal(err)
}
autoStop := 5
sandbox, err := client.Create(context.Background(), types.SnapshotParams{
SandboxBaseParams: types.SandboxBaseParams{
Ephemeral: true,
AutoStopInterval: &autoStop,
},
})
if err != nil {
log.Fatal(err)
}
}
```
```ruby
require 'daytona'
daytona = Daytona::Daytona.new
sandbox = daytona.create(
Daytona::CreateSandboxFromSnapshotParams.new(ephemeral: true, auto_stop_interval: 5)
)
```
```shell
daytona create --auto-stop 5 --auto-delete 0
```
```bash
curl 'https://app.daytona.io/api/sandbox' \
--request POST \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"autoStopInterval": 5,
"autoDeleteInterval": 0
}'
```
### Create a sandbox from a snapshot
Create a sandbox from a pre-built [snapshot](https://www.daytona.io/docs/en/snapshots.md) for faster sandbox creation with pre-installed dependencies.
```python
from daytona import Daytona, CreateSandboxFromSnapshotParams
daytona = Daytona()
sandbox = daytona.create(
CreateSandboxFromSnapshotParams(
snapshot="my-snapshot-name",
language="python"
)
)
```
```typescript
import { Daytona } from '@daytonaio/sdk';
const daytona = new Daytona();
const sandbox = await daytona.create({
snapshot: 'my-snapshot-name',
language: 'typescript'
});
```
```go
package main
import (
"context"
"log"
"github.com/daytonaio/daytona/libs/sdk-go/pkg/daytona"
"github.com/daytonaio/daytona/libs/sdk-go/pkg/types"
)
func main() {
client, err := daytona.NewClient()
if err != nil {
log.Fatal(err)
}
sandbox, err := client.Create(context.Background(), types.SnapshotParams{
Snapshot: "my-snapshot-name",
SandboxBaseParams: types.SandboxBaseParams{
Language: types.CodeLanguagePython,
},
})
if err != nil {
log.Fatal(err)
}
}
```
```ruby
require 'daytona'
daytona = Daytona::Daytona.new
sandbox = daytona.create(
Daytona::CreateSandboxFromSnapshotParams.new(
snapshot: 'my-snapshot-name',
language: Daytona::CodeLanguage::PYTHON
)
)
```
```shell
daytona create --snapshot my-snapshot-name
```
```bash
curl 'https://app.daytona.io/api/sandbox' \
--request POST \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"snapshot": "my-snapshot-name"
}'
```
### Create a sandbox with a declarative image
Create a sandbox with a [declarative image](https://www.daytona.io/docs/en/declarative-builder.md) that defines dependencies programmatically.
```python
from daytona import Daytona, CreateSandboxFromImageParams, Image
daytona = Daytona()
image = (
Image.debian_slim("3.12")
.pip_install(["requests", "pandas", "numpy"])
.workdir("/home/daytona")
)
sandbox = daytona.create(
CreateSandboxFromImageParams(image=image),
on_snapshot_create_logs=print
)
```
```typescript
import { Daytona, Image } from '@daytonaio/sdk';
const daytona = new Daytona();
const image = Image.debianSlim('3.12')
.pipInstall(['requests', 'pandas', 'numpy'])
.workdir('/home/daytona');
const sandbox = await daytona.create(
{ image },
{ onSnapshotCreateLogs: console.log }
);
```
```go
package main
import (
"context"
"log"
"github.com/daytonaio/daytona/libs/sdk-go/pkg/daytona"
"github.com/daytonaio/daytona/libs/sdk-go/pkg/types"
)
func main() {
client, err := daytona.NewClient()
if err != nil {
log.Fatal(err)
}
image := daytona.DebianSlim(nil).
PipInstall([]string{"requests", "pandas", "numpy"}).
Workdir("/home/daytona")
sandbox, err := client.Create(context.Background(), types.ImageParams{
Image: image,
})
if err != nil {
log.Fatal(err)
}
}
```
```ruby
require 'daytona'
daytona = Daytona::Daytona.new
image = Daytona::Image
.debian_slim('3.12')
.pip_install(['requests', 'pandas', 'numpy'])
.workdir('/home/daytona')
sandbox = daytona.create(
Daytona::CreateSandboxFromImageParams.new(image: image),
on_snapshot_create_logs: proc { |chunk| puts chunk }
)
```
```shell
daytona create --dockerfile ./Dockerfile
```
```bash
curl 'https://app.daytona.io/api/sandbox' \
--request POST \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"buildInfo": {
"dockerfileContent": "FROM python:3.12-slim\nRUN pip install requests pandas numpy\nWORKDIR /home/daytona"
}
}'
```
### Create a sandbox with volumes
Create a sandbox with a [volume](https://www.daytona.io/docs/en/volumes.md) mounted to share data across sandboxes.
```python
from daytona import Daytona, CreateSandboxFromSnapshotParams, VolumeMount
daytona = Daytona()
volume = daytona.volume.get("my-volume", create=True)
sandbox = daytona.create(
CreateSandboxFromSnapshotParams(
volumes=[VolumeMount(volume_id=volume.id, mount_path="/home/daytona/data")]
)
)
```
```typescript
import { Daytona } from '@daytonaio/sdk';
const daytona = new Daytona();
const volume = await daytona.volume.get('my-volume', true);
const sandbox = await daytona.create({
volumes: [{ volumeId: volume.id, mountPath: '/home/daytona/data' }]
});
```
```go
package main
import (
"context"
"log"
"github.com/daytonaio/daytona/libs/sdk-go/pkg/daytona"
"github.com/daytonaio/daytona/libs/sdk-go/pkg/types"
)
func main() {
client, err := daytona.NewClient()
if err != nil {
log.Fatal(err)
}
volume, err := client.Volume.Get(context.Background(), "my-volume")
if err != nil {
volume, err = client.Volume.Create(context.Background(), "my-volume")
if err != nil {
log.Fatal(err)
}
}
sandbox, err := client.Create(context.Background(), types.SnapshotParams{
SandboxBaseParams: types.SandboxBaseParams{
Volumes: []types.VolumeMount{{
VolumeID: volume.ID,
MountPath: "/home/daytona/data",
}},
},
})
if err != nil {
log.Fatal(err)
}
}
```
```ruby
require 'daytona'
daytona = Daytona::Daytona.new
volume = daytona.volume.get('my-volume', create: true)
sandbox = daytona.create(
Daytona::CreateSandboxFromSnapshotParams.new(
volumes: [DaytonaApiClient::SandboxVolume.new(
volume_id: volume.id,
mount_path: '/home/daytona/data'
)]
)
)
```
```shell
daytona volume create my-volume
daytona create --volume my-volume:/home/daytona/data
```
```bash
curl 'https://app.daytona.io/api/sandbox' \
--request POST \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"volumes": [
{
"volumeId": "",
"mountPath": "/home/daytona/data"
}
]
}'
```
### Create a sandbox with a Git repository cloned
Create a sandbox with a [Git repository](https://www.daytona.io/docs/en/typescript-sdk/git.md) cloned to manage version control.
```python
from daytona import Daytona
daytona = Daytona()
sandbox = daytona.create()
sandbox.git.clone("https://github.com/daytonaio/daytona.git", "/home/daytona/daytona")
status = sandbox.git.status("/home/daytona/daytona")
print(f"Branch: {status.current_branch}")
```
```typescript
import { Daytona } from '@daytonaio/sdk';
const daytona = new Daytona();
const sandbox = await daytona.create();
await sandbox.git.clone('https://github.com/daytonaio/daytona.git', '/home/daytona/daytona');
const status = await sandbox.git.status('/home/daytona/daytona');
console.log(`Branch: ${status.currentBranch}`);
```
```go
package main
import (
"context"
"fmt"
"log"
"github.com/daytonaio/daytona/libs/sdk-go/pkg/daytona"
)
func main() {
client, err := daytona.NewClient()
if err != nil {
log.Fatal(err)
}
sandbox, err := client.Create(context.Background(), nil)
if err != nil {
log.Fatal(err)
}
sandbox.Git.Clone(context.Background(), "https://github.com/daytonaio/daytona.git", "/home/daytona/daytona")
status, err := sandbox.Git.Status(context.Background(), "/home/daytona/daytona")
if err != nil {
log.Fatal(err)
}
fmt.Printf("Branch: %s\n", status.CurrentBranch)
}
```
```ruby
require 'daytona'
daytona = Daytona::Daytona.new
sandbox = daytona.create
sandbox.git.clone(url: "https://github.com/daytonaio/daytona.git", path: "/home/daytona/daytona")
status = sandbox.git.status("/home/daytona/daytona")
puts "Branch: #{status.current_branch}"
```
```bash
# Create a sandbox
curl 'https://app.daytona.io/api/sandbox' \
--request POST \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{}'
# Clone a Git repository in the sandbox
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/git/clone' \
--request POST \
--header 'Authorization: Bearer ' \
--header 'Content-Type: application/json' \
--data '{
"url": "https://github.com/daytonaio/daytona.git",
"path": "/home/daytona/daytona"
}'
# Get repository status
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/git/status?path=/home/daytona/daytona' \
--header 'Authorization: Bearer '
```
Daytona provides built-in Git support through the `git` module in sandboxes.
## Basic operations
Daytona provides methods to clone, check status, and manage Git repositories in sandboxes.
Similar to [file system operations](https://www.daytona.io/docs/en/file-system-operations.md), the starting cloning directory is the current sandbox working directory. It uses the WORKDIR specified in the Dockerfile if present, or falls back to the user's home directory if not - e.g. `workspace/repo` implies `/my-work-dir/workspace/repo`, but you are free to provide an absolute `workDir` path as well (by starting the path with `/`).
### Clone repositories
Daytona provides methods to clone Git repositories into sandboxes. You can clone public or private repositories, specific branches, and authenticate using personal access tokens.
```python
# Basic clone
sandbox.git.clone(
url="https://github.com/user/repo.git",
path="workspace/repo"
)
# Clone with authentication
sandbox.git.clone(
url="https://github.com/user/repo.git",
path="workspace/repo",
username="git",
password="personal_access_token"
)
# Clone specific branch
sandbox.git.clone(
url="https://github.com/user/repo.git",
path="workspace/repo",
branch="develop"
)
```
```typescript
// Basic clone
await sandbox.git.clone(
"https://github.com/user/repo.git",
"workspace/repo"
);
// Clone with authentication
await sandbox.git.clone(
"https://github.com/user/repo.git",
"workspace/repo",
undefined,
undefined,
"git",
"personal_access_token"
);
// Clone specific branch
await sandbox.git.clone(
"https://github.com/user/repo.git",
"workspace/repo",
"develop"
);
```
```ruby
# Basic clone
sandbox.git.clone(
url: 'https://github.com/user/repo.git',
path: 'workspace/repo'
)
# Clone with authentication
sandbox.git.clone(
url: 'https://github.com/user/repo.git',
path: 'workspace/repo',
username: 'git',
password: 'personal_access_token'
)
# Clone specific branch
sandbox.git.clone(
url: 'https://github.com/user/repo.git',
path: 'workspace/repo',
branch: 'develop'
)
```
```go
// Basic clone
err := sandbox.Git.Clone(ctx, "https://github.com/user/repo.git", "workspace/repo")
if err != nil {
log.Fatal(err)
}
// Clone with authentication
err = sandbox.Git.Clone(ctx, "https://github.com/user/repo.git", "workspace/repo",
options.WithUsername("git"),
options.WithPassword("personal_access_token"),
)
if err != nil {
log.Fatal(err)
}
// Clone specific branch
err = sandbox.Git.Clone(ctx, "https://github.com/user/repo.git", "workspace/repo",
options.WithBranch("develop"),
)
if err != nil {
log.Fatal(err)
}
```
```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/git/clone' \
--request POST \
--header 'Content-Type: application/json' \
--data '{
"branch": "",
"commit_id": "",
"password": "",
"path": "",
"url": "",
"username": ""
}'
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk/sync/git.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk/git.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk/git.md), [Go SDK](https://www.daytona.io/docs/en/go-sdk.md) and [API](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox) references:
> [**clone (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/git.md#gitclone)
>
> [**clone (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/git.md#clone)
>
> [**clone (Ruby SDK)**](https://www.daytona.io/docs/en/ruby-sdk/git.md#clone)
>
> [**Clone (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#GitService.Clone)
>
> [**clone repository (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/git/POST/git/clone)
### Get repository status
Daytona provides methods to check the status of Git repositories in sandboxes. You can get the current branch, modified files, number of commits ahead and behind main branch.
```python
# Get repository status
status = sandbox.git.status("workspace/repo")
print(f"Current branch: {status.current_branch}")
print(f"Commits ahead: {status.ahead}")
print(f"Commits behind: {status.behind}")
for file in status.file_status:
print(f"File: {file.name}")
# List branches
response = sandbox.git.branches("workspace/repo")
for branch in response.branches:
print(f"Branch: {branch}")
```
```typescript
// Get repository status
const status = await sandbox.git.status("workspace/repo");
console.log(`Current branch: ${status.currentBranch}`);
console.log(`Commits ahead: ${status.ahead}`);
console.log(`Commits behind: ${status.behind}`);
status.fileStatus.forEach(file => {
console.log(`File: ${file.name}`);
});
// List branches
const response = await sandbox.git.branches("workspace/repo");
response.branches.forEach(branch => {
console.log(`Branch: ${branch}`);
});
```
```ruby
# Get repository status
status = sandbox.git.status('workspace/repo')
puts "Current branch: #{status.current_branch}"
puts "Commits ahead: #{status.ahead}"
puts "Commits behind: #{status.behind}"
status.file_status.each do |file|
puts "File: #{file.name}"
end
# List branches
response = sandbox.git.branches('workspace/repo')
response.branches.each do |branch|
puts "Branch: #{branch}"
end
```
```go
// Get repository status
status, err := sandbox.Git.Status(ctx, "workspace/repo")
if err != nil {
log.Fatal(err)
}
fmt.Printf("Current branch: %s\n", status.CurrentBranch)
fmt.Printf("Commits ahead: %d\n", status.Ahead)
fmt.Printf("Commits behind: %d\n", status.Behind)
for _, file := range status.FileStatus {
fmt.Printf("File: %s\n", file.Path)
}
// List branches
branches, err := sandbox.Git.Branches(ctx, "workspace/repo")
if err != nil {
log.Fatal(err)
}
for _, branch := range branches {
fmt.Printf("Branch: %s\n", branch)
}
```
```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/git/status?path='
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk/sync/git.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk/git.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk/git.md), [Go SDK](https://www.daytona.io/docs/en/go-sdk.md) and [API](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox) references:
> [**status (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/git.md#gitstatus)
>
> [**status (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/git.md#status)
>
> [**status (Ruby SDK)**](https://www.daytona.io/docs/en/ruby-sdk/git.md#status)
>
> [**Status (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#GitService.Status)
>
> [**get Git repository status (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/git/GET/git/status)
## Branch operations
Daytona provides methods to manage branches in Git repositories. You can create, switch, and delete branches.
### Create branches
Daytona provides methods to create branches in Git repositories. The following snippet creates a new branch called `new-feature`.
```python
# Create a new branch
sandbox.git.create_branch("workspace/repo", "new-feature")
```
```typescript
// Create new branch
await git.createBranch('workspace/repo', 'new-feature');
```
```ruby
# Create a new branch
sandbox.git.create_branch('workspace/repo', 'new-feature')
```
```go
// Create a new branch
err := sandbox.Git.CreateBranch(ctx, "workspace/repo", "new-feature")
if err != nil {
log.Fatal(err)
}
```
```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/git/branches' \
--request POST \
--header 'Content-Type: application/json' \
--data '{
"name": "",
"path": ""
}'
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk/sync/git.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk/git.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk/git.md), [Go SDK](https://www.daytona.io/docs/en/go-sdk.md) and [API](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox) references:
> [**create_branch (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/git.md#gitcreate_branch)
>
> [**createBranch (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/git.md#createbranch)
>
> [**create_branch (Ruby SDK)**](https://www.daytona.io/docs/en/ruby-sdk/git.md#create_branch)
>
> [**CreateBranch (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#GitService.CreateBranch)
>
> [**create branch (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/git/POST/git/branches)
### Checkout branches
Daytona provides methods to checkout branches in Git repositories. The following snippet checks out the branch called `feature-branch`.
```python
# Checkout a branch
sandbox.git.checkout_branch("workspace/repo", "feature-branch")
```
```typescript
// Checkout a branch
await git.checkoutBranch('workspace/repo', 'feature-branch');
```
```ruby
# Checkout a branch
sandbox.git.checkout_branch('workspace/repo', 'feature-branch')
```
```go
// Checkout a branch
err := sandbox.Git.Checkout(ctx, "workspace/repo", "feature-branch")
if err != nil {
log.Fatal(err)
}
```
```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/git/checkout' \
--request POST \
--header 'Content-Type: application/json' \
--data '{
"branch": "",
"path": ""
}'
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk/sync/git.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk/git.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk/git.md), [Go SDK](https://www.daytona.io/docs/en/go-sdk.md) and [API](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox) references:
> [**checkout_branch (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/git.md#gitcheckout_branch)
>
> [**checkoutBranch (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/git.md#checkoutbranch)
>
> [**checkout_branch (Ruby SDK)**](https://www.daytona.io/docs/en/ruby-sdk/git.md#checkout_branch)
>
> [**Checkout (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#GitService.Checkout)
>
> [**checkout branch (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/git/POST/git/checkout)
### Delete branches
Daytona provides methods to delete branches in Git repositories. The following snippet deletes the branch called `old-feature`.
```python
# Delete a branch
sandbox.git.delete_branch("workspace/repo", "old-feature")
```
```typescript
// Delete a branch
await git.deleteBranch('workspace/repo', 'old-feature');
```
```ruby
# Delete a branch
sandbox.git.delete_branch('workspace/repo', 'old-feature')
```
```go
// Delete a branch
err := sandbox.Git.DeleteBranch(ctx, "workspace/repo", "old-feature")
if err != nil {
log.Fatal(err)
}
```
```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/git/branches' \
--request DELETE \
--header 'Content-Type: application/json' \
--data '{
"name": "",
"path": ""
}'
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk/sync/git.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk/git.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk/git.md), [Go SDK](https://www.daytona.io/docs/en/go-sdk.md) and [API](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox) references:
> [**delete_branch (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/git.md#gitdelete_branch)
>
> [**deleteBranch (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/git.md#deletebranch)
>
> [**delete_branch (Ruby SDK)**](https://www.daytona.io/docs/en/ruby-sdk/git.md#delete_branch)
>
> [**DeleteBranch (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#GitService.DeleteBranch)
>
> [**delete branch (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/git/DELETE/git/branches)
## Stage changes
Daytona provides methods to stage changes in Git repositories. You can stage specific files, all changes, and commit with a message. The following snippet stages the file `file.txt` and the `src` directory.
```python
# Stage a single file
sandbox.git.add("workspace/repo", ["file.txt"])
# Stage multiple files
sandbox.git.add("workspace/repo", [
"src/main.py",
"tests/test_main.py",
"README.md"
])
```
```typescript
// Stage a single file
await git.add('workspace/repo', ['file.txt']);
// Stage whole repository
await git.add('workspace/repo', ['.']);
```
```ruby
# Stage a single file
sandbox.git.add('workspace/repo', ['file.txt'])
```
```go
// Stage a single file
err := sandbox.Git.Add(ctx, "workspace/repo", []string{"file.txt"})
if err != nil {
log.Fatal(err)
}
// Stage multiple files
err = sandbox.Git.Add(ctx, "workspace/repo", []string{
"src/main.py",
"tests/test_main.py",
"README.md",
})
if err != nil {
log.Fatal(err)
}
// Stage whole repository
err = sandbox.Git.Add(ctx, "workspace/repo", []string{"."})
if err != nil {
log.Fatal(err)
}
```
```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/git/add' \
--request POST \
--header 'Content-Type: application/json' \
--data '{
"files": [
""
],
"path": ""
}'
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk/sync/git.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk/git.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk/git.md), [Go SDK](https://www.daytona.io/docs/en/go-sdk.md) and [API](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox) references:
> [**add (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/git.md#gitadd)
>
> [**add (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/git.md#add)
>
> [**add (Ruby SDK)**](https://www.daytona.io/docs/en/ruby-sdk/git.md#add)
>
> [**Add (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#GitService.Add)
>
> [**add (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/git/POST/git/add)
## Commit changes
Daytona provides methods to commit changes in Git repositories. You can commit with a message, author, and email. The following snippet commits the changes with the message `Update documentation` and the author `John Doe` and email `john@example.com`.
```python
# Stage and commit changes
sandbox.git.add("workspace/repo", ["README.md"])
sandbox.git.commit(
path="workspace/repo",
message="Update documentation",
author="John Doe",
email="john@example.com",
allow_empty=True
)
```
```typescript
// Stage and commit changes
await git.add('workspace/repo', ['README.md']);
await git.commit(
'workspace/repo',
'Update documentation',
'John Doe',
'john@example.com',
true
);
```
```ruby
# Stage and commit changes
sandbox.git.add('workspace/repo', ['README.md'])
sandbox.git.commit('workspace/repo', 'Update documentation', 'John Doe', 'john@example.com', true)
```
```go
// Stage and commit changes
err := sandbox.Git.Add(ctx, "workspace/repo", []string{"README.md"})
if err != nil {
log.Fatal(err)
}
response, err := sandbox.Git.Commit(ctx, "workspace/repo",
"Update documentation",
"John Doe",
"john@example.com",
options.WithAllowEmpty(true),
)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Commit SHA: %s\n", response.SHA)
```
```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/git/commit' \
--request POST \
--header 'Content-Type: application/json' \
--data '{
"allow_empty": true,
"author": "",
"email": "",
"message": "",
"path": ""
}'
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk/sync/git.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk/git.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk/git.md), [Go SDK](https://www.daytona.io/docs/en/go-sdk.md) and [API](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox) references:
> [**commit (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/git.md#gitcommit)
>
> [**commit (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/git.md#commit)
>
> [**commit (Ruby SDK)**](https://www.daytona.io/docs/en/ruby-sdk/git.md#commit)
>
> [**Commit (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#GitService.Commit)
>
> [**commit (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/git/POST/git/commit)
## Remote operations
Daytona provides methods to work with remote repositories in Git. You can push and pull changes from remote repositories.
### Push changes
Daytona provides methods to push changes to remote repositories. The following snippet pushes the changes to a public repository.
```python
# Push without authentication (for public repos or SSH)
sandbox.git.push("workspace/repo")
# Push with authentication
sandbox.git.push(
path="workspace/repo",
username="user",
password="github_token"
)
```
```typescript
// Push to a public repository
await git.push('workspace/repo');
// Push to a private repository
await git.push(
'workspace/repo',
'user',
'token'
);
```
```ruby
# Push changes
sandbox.git.push('workspace/repo')
```
```go
// Push without authentication (for public repos or SSH)
err := sandbox.Git.Push(ctx, "workspace/repo")
if err != nil {
log.Fatal(err)
}
// Push with authentication
err = sandbox.Git.Push(ctx, "workspace/repo",
options.WithPushUsername("user"),
options.WithPushPassword("github_token"),
)
if err != nil {
log.Fatal(err)
}
```
```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/git/push' \
--request POST \
--header 'Content-Type: application/json' \
--data '{
"password": "",
"path": "",
"username": ""
}'
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk/sync/git.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk/git.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk/git.md), [Go SDK](https://www.daytona.io/docs/en/go-sdk.md) and [API](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox) references:
> [**push (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/git.md#gitpush)
>
> [**push (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/git.md#push)
>
> [**push (Ruby SDK)**](https://www.daytona.io/docs/en/ruby-sdk/git.md#push)
>
> [**Push (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#GitService.Push)
>
> [**push (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/git/POST/git/push)
### Pull changes
Daytona provides methods to pull changes from remote repositories. The following snippet pulls the changes from a public repository.
```python
# Pull without authentication
sandbox.git.pull("workspace/repo")
# Pull with authentication
sandbox.git.pull(
path="workspace/repo",
username="user",
password="github_token"
)
```
```typescript
// Pull from a public repository
await git.pull('workspace/repo');
// Pull from a private repository
await git.pull(
'workspace/repo',
'user',
'token'
);
```
```ruby
# Pull changes
sandbox.git.pull('workspace/repo')
```
```go
// Pull without authentication
err := sandbox.Git.Pull(ctx, "workspace/repo")
if err != nil {
log.Fatal(err)
}
// Pull with authentication
err = sandbox.Git.Pull(ctx, "workspace/repo",
options.WithPullUsername("user"),
options.WithPullPassword("github_token"),
)
if err != nil {
log.Fatal(err)
}
```
```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/git/pull' \
--request POST \
--header 'Content-Type: application/json' \
--data '{
"password": "",
"path": "",
"username": ""
}'
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk/sync/git.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk/git.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk/git.md), [Go SDK](https://www.daytona.io/docs/en/go-sdk.md) and [API](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox) references:
> [**pull (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/git.md#gitpull)
>
> [**pull (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/git.md#pull)
>
> [**pull (Ruby SDK)**](https://www.daytona.io/docs/en/ruby-sdk/git.md#pull)
>
> [**Pull (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#GitService.Pull)
>
> [**pull (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/git/POST/git/pull)
{/* Code generated by gomarkdoc. DO NOT EDIT */}
# daytona
```go
import "github.com/daytonaio/daytona/libs/sdk-go/pkg/daytona"
```
Package daytona provides a Go SDK for interacting with the Daytona platform.
The Daytona SDK enables developers to programmatically create, manage, and interact with sandboxes \- isolated development environments that can run code, execute commands, and manage files.
### Getting Started
Create a client using your API key or JWT token:
```
client, err := daytona.NewClient()
if err != nil {
log.Fatal(err)
}
```
The client reads configuration from environment variables:
- DAYTONA\_API\_KEY: API key for authentication
- DAYTONA\_JWT\_TOKEN: JWT token for authentication \(alternative to API key\)
- DAYTONA\_ORGANIZATION\_ID: Organization ID \(required when using JWT token\)
- DAYTONA\_API\_URL: API URL \(defaults to https://app.daytona.io/api\)
- DAYTONA\_TARGET: Target environment
Or provide configuration explicitly:
```
client, err := daytona.NewClientWithConfig(&types.DaytonaConfig{
APIKey: "your-api-key",
APIUrl: "https://your-instance.daytona.io/api",
})
```
### Creating Sandboxes
Create a sandbox from a snapshot:
```
sandbox, err := client.Create(ctx, types.SnapshotParams{
Snapshot: "my-snapshot",
})
```
Create a sandbox from a Docker image:
```
sandbox, err := client.Create(ctx, types.ImageParams{
Image: "python:3.11",
})
```
### Working with Sandboxes
Execute code in a sandbox:
```
result, err := sandbox.Process.CodeRun(ctx, "print('Hello, World!')")
```
Run shell commands:
```
result, err := sandbox.Process.ExecuteCommand(ctx, "ls -la")
```
## Index
- [Variables](https://www.daytona.io/docs/%3C.md#variables%3E)
- [type Client](https://www.daytona.io/docs/%3C.md#Client%3E)
- [func NewClient\(\) \(\*Client, error\)](https://www.daytona.io/docs/%3C.md#NewClient%3E)
- [func NewClientWithConfig\(config \*types.DaytonaConfig\) \(\*Client, error\)](https://www.daytona.io/docs/%3C.md#NewClientWithConfig%3E)
- [func \(c \*Client\) Close\(ctx context.Context\) error](https://www.daytona.io/docs/%3C.md#Client.Close%3E)
- [func \(c \*Client\) Create\(ctx context.Context, params any, opts ...func\(\*options.CreateSandbox\)\) \(\*Sandbox, error\)](https://www.daytona.io/docs/%3C.md#Client.Create%3E)
- [func \(c \*Client\) Get\(ctx context.Context, sandboxIDOrName string\) \(\*Sandbox, error\)](https://www.daytona.io/docs/%3C.md#Client.Get%3E)
- [func \(c \*Client\) List\(ctx context.Context, labels map\[string\]string, page \*int, limit \*int\) \(\*PaginatedSandboxes, error\)](<#Client.List>)
- [type CodeInterpreterService](https://www.daytona.io/docs/%3C.md#CodeInterpreterService%3E)
- [func NewCodeInterpreterService\(toolboxClient \*toolbox.APIClient, otel \*otelState\) \*CodeInterpreterService](https://www.daytona.io/docs/%3C.md#NewCodeInterpreterService%3E)
- [func \(c \*CodeInterpreterService\) CreateContext\(ctx context.Context, cwd \*string\) \(map\[string\]any, error\)](<#CodeInterpreterService.CreateContext>)
- [func \(c \*CodeInterpreterService\) DeleteContext\(ctx context.Context, contextID string\) error](https://www.daytona.io/docs/%3C.md#CodeInterpreterService.DeleteContext%3E)
- [func \(c \*CodeInterpreterService\) ListContexts\(ctx context.Context\) \(\[\]map\[string\]any, error\)](<#CodeInterpreterService.ListContexts>)
- [func \(c \*CodeInterpreterService\) RunCode\(ctx context.Context, code string, opts ...func\(\*options.RunCode\)\) \(\*OutputChannels, error\)](https://www.daytona.io/docs/%3C.md#CodeInterpreterService.RunCode%3E)
- [type ComputerUseService](https://www.daytona.io/docs/%3C.md#ComputerUseService%3E)
- [func NewComputerUseService\(toolboxClient \*toolbox.APIClient, otel \*otelState\) \*ComputerUseService](https://www.daytona.io/docs/%3C.md#NewComputerUseService%3E)
- [func \(c \*ComputerUseService\) Display\(\) \*DisplayService](https://www.daytona.io/docs/%3C.md#ComputerUseService.Display%3E)
- [func \(c \*ComputerUseService\) GetStatus\(ctx context.Context\) \(map\[string\]any, error\)](<#ComputerUseService.GetStatus>)
- [func \(c \*ComputerUseService\) Keyboard\(\) \*KeyboardService](https://www.daytona.io/docs/%3C.md#ComputerUseService.Keyboard%3E)
- [func \(c \*ComputerUseService\) Mouse\(\) \*MouseService](https://www.daytona.io/docs/%3C.md#ComputerUseService.Mouse%3E)
- [func \(c \*ComputerUseService\) Recording\(\) \*RecordingService](https://www.daytona.io/docs/%3C.md#ComputerUseService.Recording%3E)
- [func \(c \*ComputerUseService\) Screenshot\(\) \*ScreenshotService](https://www.daytona.io/docs/%3C.md#ComputerUseService.Screenshot%3E)
- [func \(c \*ComputerUseService\) Start\(ctx context.Context\) error](https://www.daytona.io/docs/%3C.md#ComputerUseService.Start%3E)
- [func \(c \*ComputerUseService\) Stop\(ctx context.Context\) error](https://www.daytona.io/docs/%3C.md#ComputerUseService.Stop%3E)
- [type DisplayService](https://www.daytona.io/docs/%3C.md#DisplayService%3E)
- [func NewDisplayService\(toolboxClient \*toolbox.APIClient, otel \*otelState\) \*DisplayService](https://www.daytona.io/docs/%3C.md#NewDisplayService%3E)
- [func \(d \*DisplayService\) GetInfo\(ctx context.Context\) \(map\[string\]any, error\)](<#DisplayService.GetInfo>)
- [func \(d \*DisplayService\) GetWindows\(ctx context.Context\) \(map\[string\]any, error\)](<#DisplayService.GetWindows>)
- [type DockerImage](https://www.daytona.io/docs/%3C.md#DockerImage%3E)
- [func Base\(baseImage string\) \*DockerImage](https://www.daytona.io/docs/%3C.md#Base%3E)
- [func DebianSlim\(pythonVersion \*string\) \*DockerImage](https://www.daytona.io/docs/%3C.md#DebianSlim%3E)
- [func FromDockerfile\(dockerfile string\) \*DockerImage](https://www.daytona.io/docs/%3C.md#FromDockerfile%3E)
- [func \(img \*DockerImage\) Add\(source, destination string\) \*DockerImage](https://www.daytona.io/docs/%3C.md#DockerImage.Add%3E)
- [func \(img \*DockerImage\) AddLocalDir\(localPath, remotePath string\) \*DockerImage](https://www.daytona.io/docs/%3C.md#DockerImage.AddLocalDir%3E)
- [func \(img \*DockerImage\) AddLocalFile\(localPath, remotePath string\) \*DockerImage](https://www.daytona.io/docs/%3C.md#DockerImage.AddLocalFile%3E)
- [func \(img \*DockerImage\) AptGet\(packages \[\]string\) \*DockerImage](<#DockerImage.AptGet>)
- [func \(img \*DockerImage\) Cmd\(cmd \[\]string\) \*DockerImage](<#DockerImage.Cmd>)
- [func \(img \*DockerImage\) Contexts\(\) \[\]DockerImageContext](<#DockerImage.Contexts>)
- [func \(img \*DockerImage\) Copy\(source, destination string\) \*DockerImage](https://www.daytona.io/docs/%3C.md#DockerImage.Copy%3E)
- [func \(img \*DockerImage\) Dockerfile\(\) string](https://www.daytona.io/docs/%3C.md#DockerImage.Dockerfile%3E)
- [func \(img \*DockerImage\) Entrypoint\(cmd \[\]string\) \*DockerImage](<#DockerImage.Entrypoint>)
- [func \(img \*DockerImage\) Env\(key, value string\) \*DockerImage](https://www.daytona.io/docs/%3C.md#DockerImage.Env%3E)
- [func \(img \*DockerImage\) Expose\(ports \[\]int\) \*DockerImage](<#DockerImage.Expose>)
- [func \(img \*DockerImage\) Label\(key, value string\) \*DockerImage](https://www.daytona.io/docs/%3C.md#DockerImage.Label%3E)
- [func \(img \*DockerImage\) PipInstall\(packages \[\]string, opts ...func\(\*options.PipInstall\)\) \*DockerImage](<#DockerImage.PipInstall>)
- [func \(img \*DockerImage\) Run\(command string\) \*DockerImage](https://www.daytona.io/docs/%3C.md#DockerImage.Run%3E)
- [func \(img \*DockerImage\) User\(username string\) \*DockerImage](https://www.daytona.io/docs/%3C.md#DockerImage.User%3E)
- [func \(img \*DockerImage\) Volume\(paths \[\]string\) \*DockerImage](<#DockerImage.Volume>)
- [func \(img \*DockerImage\) Workdir\(path string\) \*DockerImage](https://www.daytona.io/docs/%3C.md#DockerImage.Workdir%3E)
- [type DockerImageContext](https://www.daytona.io/docs/%3C.md#DockerImageContext%3E)
- [type FileSystemService](https://www.daytona.io/docs/%3C.md#FileSystemService%3E)
- [func NewFileSystemService\(toolboxClient \*toolbox.APIClient, otel \*otelState\) \*FileSystemService](https://www.daytona.io/docs/%3C.md#NewFileSystemService%3E)
- [func \(f \*FileSystemService\) CreateFolder\(ctx context.Context, path string, opts ...func\(\*options.CreateFolder\)\) error](https://www.daytona.io/docs/%3C.md#FileSystemService.CreateFolder%3E)
- [func \(f \*FileSystemService\) DeleteFile\(ctx context.Context, path string, recursive bool\) error](https://www.daytona.io/docs/%3C.md#FileSystemService.DeleteFile%3E)
- [func \(f \*FileSystemService\) DownloadFile\(ctx context.Context, remotePath string, localPath \*string\) \(\[\]byte, error\)](<#FileSystemService.DownloadFile>)
- [func \(f \*FileSystemService\) FindFiles\(ctx context.Context, path, pattern string\) \(any, error\)](https://www.daytona.io/docs/%3C.md#FileSystemService.FindFiles%3E)
- [func \(f \*FileSystemService\) GetFileInfo\(ctx context.Context, path string\) \(\*types.FileInfo, error\)](https://www.daytona.io/docs/%3C.md#FileSystemService.GetFileInfo%3E)
- [func \(f \*FileSystemService\) ListFiles\(ctx context.Context, path string\) \(\[\]\*types.FileInfo, error\)](<#FileSystemService.ListFiles>)
- [func \(f \*FileSystemService\) MoveFiles\(ctx context.Context, source, destination string\) error](https://www.daytona.io/docs/%3C.md#FileSystemService.MoveFiles%3E)
- [func \(f \*FileSystemService\) ReplaceInFiles\(ctx context.Context, files \[\]string, pattern, newValue string\) \(any, error\)](<#FileSystemService.ReplaceInFiles>)
- [func \(f \*FileSystemService\) SearchFiles\(ctx context.Context, path, pattern string\) \(any, error\)](https://www.daytona.io/docs/%3C.md#FileSystemService.SearchFiles%3E)
- [func \(f \*FileSystemService\) SetFilePermissions\(ctx context.Context, path string, opts ...func\(\*options.SetFilePermissions\)\) error](https://www.daytona.io/docs/%3C.md#FileSystemService.SetFilePermissions%3E)
- [func \(f \*FileSystemService\) UploadFile\(ctx context.Context, source any, destination string\) error](https://www.daytona.io/docs/%3C.md#FileSystemService.UploadFile%3E)
- [type GitService](https://www.daytona.io/docs/%3C.md#GitService%3E)
- [func NewGitService\(toolboxClient \*toolbox.APIClient, otel \*otelState\) \*GitService](https://www.daytona.io/docs/%3C.md#NewGitService%3E)
- [func \(g \*GitService\) Add\(ctx context.Context, path string, files \[\]string\) error](<#GitService.Add>)
- [func \(g \*GitService\) Branches\(ctx context.Context, path string\) \(\[\]string, error\)](<#GitService.Branches>)
- [func \(g \*GitService\) Checkout\(ctx context.Context, path, name string\) error](https://www.daytona.io/docs/%3C.md#GitService.Checkout%3E)
- [func \(g \*GitService\) Clone\(ctx context.Context, url, path string, opts ...func\(\*options.GitClone\)\) error](https://www.daytona.io/docs/%3C.md#GitService.Clone%3E)
- [func \(g \*GitService\) Commit\(ctx context.Context, path, message, author, email string, opts ...func\(\*options.GitCommit\)\) \(\*types.GitCommitResponse, error\)](https://www.daytona.io/docs/%3C.md#GitService.Commit%3E)
- [func \(g \*GitService\) CreateBranch\(ctx context.Context, path, name string\) error](https://www.daytona.io/docs/%3C.md#GitService.CreateBranch%3E)
- [func \(g \*GitService\) DeleteBranch\(ctx context.Context, path, name string, opts ...func\(\*options.GitDeleteBranch\)\) error](https://www.daytona.io/docs/%3C.md#GitService.DeleteBranch%3E)
- [func \(g \*GitService\) Pull\(ctx context.Context, path string, opts ...func\(\*options.GitPull\)\) error](https://www.daytona.io/docs/%3C.md#GitService.Pull%3E)
- [func \(g \*GitService\) Push\(ctx context.Context, path string, opts ...func\(\*options.GitPush\)\) error](https://www.daytona.io/docs/%3C.md#GitService.Push%3E)
- [func \(g \*GitService\) Status\(ctx context.Context, path string\) \(\*types.GitStatus, error\)](https://www.daytona.io/docs/%3C.md#GitService.Status%3E)
- [type KeyboardService](https://www.daytona.io/docs/%3C.md#KeyboardService%3E)
- [func NewKeyboardService\(toolboxClient \*toolbox.APIClient, otel \*otelState\) \*KeyboardService](https://www.daytona.io/docs/%3C.md#NewKeyboardService%3E)
- [func \(k \*KeyboardService\) Hotkey\(ctx context.Context, keys string\) error](https://www.daytona.io/docs/%3C.md#KeyboardService.Hotkey%3E)
- [func \(k \*KeyboardService\) Press\(ctx context.Context, key string, modifiers \[\]string\) error](<#KeyboardService.Press>)
- [func \(k \*KeyboardService\) Type\(ctx context.Context, text string, delay \*int\) error](https://www.daytona.io/docs/%3C.md#KeyboardService.Type%3E)
- [type LspServerService](https://www.daytona.io/docs/%3C.md#LspServerService%3E)
- [func NewLspServerService\(toolboxClient \*toolbox.APIClient, languageID types.LspLanguageID, projectPath string, otel \*otelState\) \*LspServerService](https://www.daytona.io/docs/%3C.md#NewLspServerService%3E)
- [func \(l \*LspServerService\) Completions\(ctx context.Context, path string, position types.Position\) \(any, error\)](https://www.daytona.io/docs/%3C.md#LspServerService.Completions%3E)
- [func \(l \*LspServerService\) DidClose\(ctx context.Context, path string\) error](https://www.daytona.io/docs/%3C.md#LspServerService.DidClose%3E)
- [func \(l \*LspServerService\) DidOpen\(ctx context.Context, path string\) error](https://www.daytona.io/docs/%3C.md#LspServerService.DidOpen%3E)
- [func \(l \*LspServerService\) DocumentSymbols\(ctx context.Context, path string\) \(\[\]any, error\)](<#LspServerService.DocumentSymbols>)
- [func \(l \*LspServerService\) SandboxSymbols\(ctx context.Context, query string\) \(\[\]any, error\)](<#LspServerService.SandboxSymbols>)
- [func \(l \*LspServerService\) Start\(ctx context.Context\) error](https://www.daytona.io/docs/%3C.md#LspServerService.Start%3E)
- [func \(l \*LspServerService\) Stop\(ctx context.Context\) error](https://www.daytona.io/docs/%3C.md#LspServerService.Stop%3E)
- [type MouseService](https://www.daytona.io/docs/%3C.md#MouseService%3E)
- [func NewMouseService\(toolboxClient \*toolbox.APIClient, otel \*otelState\) \*MouseService](https://www.daytona.io/docs/%3C.md#NewMouseService%3E)
- [func \(m \*MouseService\) Click\(ctx context.Context, x, y int, button \*string, double \*bool\) \(map\[string\]any, error\)](<#MouseService.Click>)
- [func \(m \*MouseService\) Drag\(ctx context.Context, startX, startY, endX, endY int, button \*string\) \(map\[string\]any, error\)](<#MouseService.Drag>)
- [func \(m \*MouseService\) GetPosition\(ctx context.Context\) \(map\[string\]any, error\)](<#MouseService.GetPosition>)
- [func \(m \*MouseService\) Move\(ctx context.Context, x, y int\) \(map\[string\]any, error\)](<#MouseService.Move>)
- [func \(m \*MouseService\) Scroll\(ctx context.Context, x, y int, direction string, amount \*int\) \(bool, error\)](https://www.daytona.io/docs/%3C.md#MouseService.Scroll%3E)
- [type OutputChannels](https://www.daytona.io/docs/%3C.md#OutputChannels%3E)
- [type PaginatedSandboxes](https://www.daytona.io/docs/%3C.md#PaginatedSandboxes%3E)
- [type ProcessService](https://www.daytona.io/docs/%3C.md#ProcessService%3E)
- [func NewProcessService\(toolboxClient \*toolbox.APIClient, otel \*otelState\) \*ProcessService](https://www.daytona.io/docs/%3C.md#NewProcessService%3E)
- [func \(p \*ProcessService\) CodeRun\(ctx context.Context, code string, opts ...func\(\*options.CodeRun\)\) \(\*types.ExecuteResponse, error\)](https://www.daytona.io/docs/%3C.md#ProcessService.CodeRun%3E)
- [func \(p \*ProcessService\) ConnectPty\(ctx context.Context, sessionID string\) \(\*PtyHandle, error\)](https://www.daytona.io/docs/%3C.md#ProcessService.ConnectPty%3E)
- [func \(p \*ProcessService\) CreatePty\(ctx context.Context, id string, opts ...func\(\*options.CreatePty\)\) \(\*PtyHandle, error\)](https://www.daytona.io/docs/%3C.md#ProcessService.CreatePty%3E)
- [func \(p \*ProcessService\) CreatePtySession\(ctx context.Context, id string, opts ...func\(\*options.PtySession\)\) \(\*types.PtySessionInfo, error\)](https://www.daytona.io/docs/%3C.md#ProcessService.CreatePtySession%3E)
- [func \(p \*ProcessService\) CreateSession\(ctx context.Context, sessionID string\) error](https://www.daytona.io/docs/%3C.md#ProcessService.CreateSession%3E)
- [func \(p \*ProcessService\) DeleteSession\(ctx context.Context, sessionID string\) error](https://www.daytona.io/docs/%3C.md#ProcessService.DeleteSession%3E)
- [func \(p \*ProcessService\) ExecuteCommand\(ctx context.Context, command string, opts ...func\(\*options.ExecuteCommand\)\) \(\*types.ExecuteResponse, error\)](https://www.daytona.io/docs/%3C.md#ProcessService.ExecuteCommand%3E)
- [func \(p \*ProcessService\) ExecuteSessionCommand\(ctx context.Context, sessionID, command string, runAsync bool, suppressInputEcho bool\) \(map\[string\]any, error\)](<#ProcessService.ExecuteSessionCommand>)
- [func \(p \*ProcessService\) GetEntrypointLogs\(ctx context.Context\) \(string, error\)](https://www.daytona.io/docs/%3C.md#ProcessService.GetEntrypointLogs%3E)
- [func \(p \*ProcessService\) GetEntrypointLogsStream\(ctx context.Context, stdout, stderr chan\<\- string\) error](https://www.daytona.io/docs/%3C.md#ProcessService.GetEntrypointLogsStream%3E)
- [func \(p \*ProcessService\) GetEntrypointSession\(ctx context.Context\) \(\*toolbox.Session, error\)](https://www.daytona.io/docs/%3C.md#ProcessService.GetEntrypointSession%3E)
- [func \(p \*ProcessService\) GetPtySessionInfo\(ctx context.Context, sessionID string\) \(\*types.PtySessionInfo, error\)](https://www.daytona.io/docs/%3C.md#ProcessService.GetPtySessionInfo%3E)
- [func \(p \*ProcessService\) GetSession\(ctx context.Context, sessionID string\) \(map\[string\]any, error\)](<#ProcessService.GetSession>)
- [func \(p \*ProcessService\) GetSessionCommand\(ctx context.Context, sessionID, commandID string\) \(map\[string\]any, error\)](<#ProcessService.GetSessionCommand>)
- [func \(p \*ProcessService\) GetSessionCommandLogs\(ctx context.Context, sessionID, commandID string\) \(map\[string\]any, error\)](<#ProcessService.GetSessionCommandLogs>)
- [func \(p \*ProcessService\) GetSessionCommandLogsStream\(ctx context.Context, sessionID, commandID string, stdout, stderr chan\<\- string\) error](https://www.daytona.io/docs/%3C.md#ProcessService.GetSessionCommandLogsStream%3E)
- [func \(p \*ProcessService\) KillPtySession\(ctx context.Context, sessionID string\) error](https://www.daytona.io/docs/%3C.md#ProcessService.KillPtySession%3E)
- [func \(p \*ProcessService\) ListPtySessions\(ctx context.Context\) \(\[\]\*types.PtySessionInfo, error\)](<#ProcessService.ListPtySessions>)
- [func \(p \*ProcessService\) ListSessions\(ctx context.Context\) \(\[\]map\[string\]any, error\)](<#ProcessService.ListSessions>)
- [func \(p \*ProcessService\) ResizePtySession\(ctx context.Context, sessionID string, ptySize types.PtySize\) \(\*types.PtySessionInfo, error\)](https://www.daytona.io/docs/%3C.md#ProcessService.ResizePtySession%3E)
- [type PtyHandle](https://www.daytona.io/docs/%3C.md#PtyHandle%3E)
- [func \(h \*PtyHandle\) DataChan\(\) \<\-chan \[\]byte](<#PtyHandle.DataChan>)
- [func \(h \*PtyHandle\) Disconnect\(\) error](https://www.daytona.io/docs/%3C.md#PtyHandle.Disconnect%3E)
- [func \(h \*PtyHandle\) Error\(\) \*string](https://www.daytona.io/docs/%3C.md#PtyHandle.Error%3E)
- [func \(h \*PtyHandle\) ExitCode\(\) \*int](https://www.daytona.io/docs/%3C.md#PtyHandle.ExitCode%3E)
- [func \(h \*PtyHandle\) IsConnected\(\) bool](https://www.daytona.io/docs/%3C.md#PtyHandle.IsConnected%3E)
- [func \(h \*PtyHandle\) Kill\(ctx context.Context\) error](https://www.daytona.io/docs/%3C.md#PtyHandle.Kill%3E)
- [func \(h \*PtyHandle\) Read\(p \[\]byte\) \(n int, err error\)](<#PtyHandle.Read>)
- [func \(h \*PtyHandle\) Resize\(ctx context.Context, cols, rows int\) \(\*types.PtySessionInfo, error\)](https://www.daytona.io/docs/%3C.md#PtyHandle.Resize%3E)
- [func \(h \*PtyHandle\) SendInput\(data \[\]byte\) error](<#PtyHandle.SendInput>)
- [func \(h \*PtyHandle\) SessionID\(\) string](https://www.daytona.io/docs/%3C.md#PtyHandle.SessionID%3E)
- [func \(h \*PtyHandle\) Wait\(ctx context.Context\) \(\*types.PtyResult, error\)](https://www.daytona.io/docs/%3C.md#PtyHandle.Wait%3E)
- [func \(h \*PtyHandle\) WaitForConnection\(ctx context.Context\) error](https://www.daytona.io/docs/%3C.md#PtyHandle.WaitForConnection%3E)
- [func \(h \*PtyHandle\) Write\(p \[\]byte\) \(n int, err error\)](<#PtyHandle.Write>)
- [type PushAccessCredentials](https://www.daytona.io/docs/%3C.md#PushAccessCredentials%3E)
- [type RecordingService](https://www.daytona.io/docs/%3C.md#RecordingService%3E)
- [func NewRecordingService\(toolboxClient \*toolbox.APIClient\) \*RecordingService](https://www.daytona.io/docs/%3C.md#NewRecordingService%3E)
- [func \(r \*RecordingService\) Delete\(ctx context.Context, id string\) error](https://www.daytona.io/docs/%3C.md#RecordingService.Delete%3E)
- [func \(r \*RecordingService\) Download\(ctx context.Context, id string, localPath string\) error](https://www.daytona.io/docs/%3C.md#RecordingService.Download%3E)
- [func \(r \*RecordingService\) Get\(ctx context.Context, id string\) \(\*toolbox.Recording, error\)](https://www.daytona.io/docs/%3C.md#RecordingService.Get%3E)
- [func \(r \*RecordingService\) List\(ctx context.Context\) \(\*toolbox.ListRecordingsResponse, error\)](https://www.daytona.io/docs/%3C.md#RecordingService.List%3E)
- [func \(r \*RecordingService\) Start\(ctx context.Context, label \*string\) \(\*toolbox.Recording, error\)](https://www.daytona.io/docs/%3C.md#RecordingService.Start%3E)
- [func \(r \*RecordingService\) Stop\(ctx context.Context, id string\) \(\*toolbox.Recording, error\)](https://www.daytona.io/docs/%3C.md#RecordingService.Stop%3E)
- [type Sandbox](https://www.daytona.io/docs/%3C.md#Sandbox%3E)
- [func NewSandbox\(client \*Client, toolboxClient \*toolbox.APIClient, id string, name string, state apiclient.SandboxState, target string, autoArchiveInterval int, autoDeleteInterval int, networkBlockAll bool, networkAllowList \*string\) \*Sandbox](https://www.daytona.io/docs/%3C.md#NewSandbox%3E)
- [func \(s \*Sandbox\) Archive\(ctx context.Context\) error](https://www.daytona.io/docs/%3C.md#Sandbox.Archive%3E)
- [func \(s \*Sandbox\) Delete\(ctx context.Context\) error](https://www.daytona.io/docs/%3C.md#Sandbox.Delete%3E)
- [func \(s \*Sandbox\) DeleteWithTimeout\(ctx context.Context, timeout time.Duration\) error](https://www.daytona.io/docs/%3C.md#Sandbox.DeleteWithTimeout%3E)
- [func \(s \*Sandbox\) GetPreviewLink\(ctx context.Context, port int\) \(\*types.PreviewLink, error\)](https://www.daytona.io/docs/%3C.md#Sandbox.GetPreviewLink%3E)
- [func \(s \*Sandbox\) GetUserHomeDir\(ctx context.Context\) \(string, error\)](https://www.daytona.io/docs/%3C.md#Sandbox.GetUserHomeDir%3E)
- [func \(s \*Sandbox\) GetWorkingDir\(ctx context.Context\) \(string, error\)](https://www.daytona.io/docs/%3C.md#Sandbox.GetWorkingDir%3E)
- [func \(s \*Sandbox\) RefreshData\(ctx context.Context\) error](https://www.daytona.io/docs/%3C.md#Sandbox.RefreshData%3E)
- [func \(s \*Sandbox\) Resize\(ctx context.Context, resources \*types.Resources\) error](https://www.daytona.io/docs/%3C.md#Sandbox.Resize%3E)
- [func \(s \*Sandbox\) ResizeWithTimeout\(ctx context.Context, resources \*types.Resources, timeout time.Duration\) error](https://www.daytona.io/docs/%3C.md#Sandbox.ResizeWithTimeout%3E)
- [func \(s \*Sandbox\) SetAutoArchiveInterval\(ctx context.Context, intervalMinutes \*int\) error](https://www.daytona.io/docs/%3C.md#Sandbox.SetAutoArchiveInterval%3E)
- [func \(s \*Sandbox\) SetAutoDeleteInterval\(ctx context.Context, intervalMinutes \*int\) error](https://www.daytona.io/docs/%3C.md#Sandbox.SetAutoDeleteInterval%3E)
- [func \(s \*Sandbox\) SetLabels\(ctx context.Context, labels map\[string\]string\) error](<#Sandbox.SetLabels>)
- [func \(s \*Sandbox\) Start\(ctx context.Context\) error](https://www.daytona.io/docs/%3C.md#Sandbox.Start%3E)
- [func \(s \*Sandbox\) StartWithTimeout\(ctx context.Context, timeout time.Duration\) error](https://www.daytona.io/docs/%3C.md#Sandbox.StartWithTimeout%3E)
- [func \(s \*Sandbox\) Stop\(ctx context.Context\) error](https://www.daytona.io/docs/%3C.md#Sandbox.Stop%3E)
- [func \(s \*Sandbox\) StopWithTimeout\(ctx context.Context, timeout time.Duration\) error](https://www.daytona.io/docs/%3C.md#Sandbox.StopWithTimeout%3E)
- [func \(s \*Sandbox\) WaitForResize\(ctx context.Context, timeout time.Duration\) error](https://www.daytona.io/docs/%3C.md#Sandbox.WaitForResize%3E)
- [func \(s \*Sandbox\) WaitForStart\(ctx context.Context, timeout time.Duration\) error](https://www.daytona.io/docs/%3C.md#Sandbox.WaitForStart%3E)
- [func \(s \*Sandbox\) WaitForStop\(ctx context.Context, timeout time.Duration\) error](https://www.daytona.io/docs/%3C.md#Sandbox.WaitForStop%3E)
- [type ScreenshotService](https://www.daytona.io/docs/%3C.md#ScreenshotService%3E)
- [func NewScreenshotService\(toolboxClient \*toolbox.APIClient, otel \*otelState\) \*ScreenshotService](https://www.daytona.io/docs/%3C.md#NewScreenshotService%3E)
- [func \(s \*ScreenshotService\) TakeFullScreen\(ctx context.Context, showCursor \*bool\) \(\*types.ScreenshotResponse, error\)](https://www.daytona.io/docs/%3C.md#ScreenshotService.TakeFullScreen%3E)
- [func \(s \*ScreenshotService\) TakeRegion\(ctx context.Context, region types.ScreenshotRegion, showCursor \*bool\) \(\*types.ScreenshotResponse, error\)](https://www.daytona.io/docs/%3C.md#ScreenshotService.TakeRegion%3E)
- [type SnapshotService](https://www.daytona.io/docs/%3C.md#SnapshotService%3E)
- [func NewSnapshotService\(client \*Client\) \*SnapshotService](https://www.daytona.io/docs/%3C.md#NewSnapshotService%3E)
- [func \(s \*SnapshotService\) Create\(ctx context.Context, params \*types.CreateSnapshotParams\) \(\*types.Snapshot, \<\-chan string, error\)](https://www.daytona.io/docs/%3C.md#SnapshotService.Create%3E)
- [func \(s \*SnapshotService\) Delete\(ctx context.Context, snapshot \*types.Snapshot\) error](https://www.daytona.io/docs/%3C.md#SnapshotService.Delete%3E)
- [func \(s \*SnapshotService\) Get\(ctx context.Context, nameOrID string\) \(\*types.Snapshot, error\)](https://www.daytona.io/docs/%3C.md#SnapshotService.Get%3E)
- [func \(s \*SnapshotService\) List\(ctx context.Context, page \*int, limit \*int\) \(\*types.PaginatedSnapshots, error\)](https://www.daytona.io/docs/%3C.md#SnapshotService.List%3E)
- [type VolumeService](https://www.daytona.io/docs/%3C.md#VolumeService%3E)
- [func NewVolumeService\(client \*Client\) \*VolumeService](https://www.daytona.io/docs/%3C.md#NewVolumeService%3E)
- [func \(v \*VolumeService\) Create\(ctx context.Context, name string\) \(\*types.Volume, error\)](https://www.daytona.io/docs/%3C.md#VolumeService.Create%3E)
- [func \(v \*VolumeService\) Delete\(ctx context.Context, volume \*types.Volume\) error](https://www.daytona.io/docs/%3C.md#VolumeService.Delete%3E)
- [func \(v \*VolumeService\) Get\(ctx context.Context, name string\) \(\*types.Volume, error\)](https://www.daytona.io/docs/%3C.md#VolumeService.Get%3E)
- [func \(v \*VolumeService\) List\(ctx context.Context\) \(\[\]\*types.Volume, error\)](<#VolumeService.List>)
- [func \(v \*VolumeService\) WaitForReady\(ctx context.Context, volume \*types.Volume, timeout time.Duration\) \(\*types.Volume, error\)](https://www.daytona.io/docs/%3C.md#VolumeService.WaitForReady%3E)
## Variables
Version is the semantic version of the Daytona SDK.
This value is embedded at build time from the VERSION file.
Example:
```
fmt.Printf("Daytona SDK version: %s\n", daytona.Version)
```
```go
var Version = strings.TrimSpace(version)
```
## type Client
Client is the main entry point for interacting with the Daytona platform.
Client provides methods to create, retrieve, list, and manage sandboxes. It handles authentication, API communication, and provides access to services like Volume and Snapshot management.
Create a Client using [NewClient](https://www.daytona.io/docs/%3C.md#NewClient%3E) or [NewClientWithConfig](https://www.daytona.io/docs/%3C.md#NewClientWithConfig%3E):
```
client, err := daytona.NewClient()
if err != nil {
log.Fatal(err)
}
```
The Client is safe for concurrent use by multiple goroutines.
```go
type Client struct {
// Otel holds OpenTelemetry state; nil when OTel is disabled.
Otel *otelState
// Volume provides methods for managing persistent volumes.
Volume *VolumeService
// Snapshot provides methods for managing sandbox snapshots.
Snapshot *SnapshotService
// contains filtered or unexported fields
}
```
### func NewClient
```go
func NewClient() (*Client, error)
```
NewClient creates a new Daytona client with default configuration.
NewClient reads configuration from environment variables:
- DAYTONA\_API\_KEY or DAYTONA\_JWT\_TOKEN for authentication \(one is required\)
- DAYTONA\_ORGANIZATION\_ID \(required when using JWT token\)
- DAYTONA\_API\_URL for custom API endpoint
- DAYTONA\_TARGET for target environment
For explicit configuration, use [NewClientWithConfig](https://www.daytona.io/docs/%3C.md#NewClientWithConfig%3E) instead.
### func NewClientWithConfig
```go
func NewClientWithConfig(config *types.DaytonaConfig) (*Client, error)
```
NewClientWithConfig creates a new Daytona client with a custom configuration.
Configuration values provided in config take precedence over environment variables. Any configuration field left empty will fall back to the corresponding environment variable \(see [NewClient](https://www.daytona.io/docs/%3C.md#NewClient%3E) for the list of supported variables\).
Example:
```
client, err := daytona.NewClientWithConfig(&types.DaytonaConfig{
APIKey: "your-api-key",
APIUrl: "https://custom.daytona.io/api",
OrganizationID: "org-123",
})
if err != nil {
log.Fatal(err)
}
```
Returns an error if neither API key nor JWT token is provided, or if JWT token is provided without an organization ID.
### func \(\*Client\) Close
```go
func (c *Client) Close(ctx context.Context) error
```
Close shuts down the client and releases resources. When OpenTelemetry is enabled, Close flushes and shuts down the OTel providers. It is safe to call Close even when OTel is not enabled.
### func \(\*Client\) Create
```go
func (c *Client) Create(ctx context.Context, params any, opts ...func(*options.CreateSandbox)) (*Sandbox, error)
```
Create creates a new sandbox with the specified parameters.
The params argument accepts either \[types.SnapshotParams\] to create from a snapshot, or \[types.ImageParams\] to create from a Docker image:
```
// Create from a snapshot
sandbox, err := client.Create(ctx, types.SnapshotParams{
Snapshot: "my-snapshot",
SandboxBaseParams: types.SandboxBaseParams{
Name: "my-sandbox",
},
})
// Create from a Docker image
sandbox, err := client.Create(ctx, types.ImageParams{
Image: "python:3.11",
Resources: &types.Resources{
CPU: 2,
Memory: 4096,
},
})
```
By default, Create waits for the sandbox to reach the started state before returning. Use \[options.WithWaitForStart\]\(false\) to return immediately after creation.
Optional parameters can be configured using functional options:
- \[options.WithTimeout\]: Set maximum wait time for creation
- \[options.WithWaitForStart\]: Control whether to wait for started state
- \[options.WithLogChannel\]: Receive build logs during image builds
Returns the created [Sandbox](https://www.daytona.io/docs/%3C.md#Sandbox%3E) or an error if creation fails.
### func \(\*Client\) Get
```go
func (c *Client) Get(ctx context.Context, sandboxIDOrName string) (*Sandbox, error)
```
Get retrieves an existing sandbox by its ID or name.
The sandboxIDOrName parameter accepts either the sandbox's unique ID or its human\-readable name. If a sandbox with the given identifier is not found, a [errors.DaytonaNotFoundError](https://www.daytona.io/docs/%3Chttps:/pkg.go.dev/errors.md#DaytonaNotFoundError%3E) is returned.
Example:
```
sandbox, err := client.Get(ctx, "my-sandbox")
if err != nil {
var notFound *errors.DaytonaNotFoundError
if errors.As(err, ¬Found) {
log.Println("Sandbox not found")
}
return err
}
```
### func \(\*Client\) List
```go
func (c *Client) List(ctx context.Context, labels map[string]string, page *int, limit *int) (*PaginatedSandboxes, error)
```
List retrieves sandboxes with optional label filtering and pagination.
Parameters:
- labels: Optional map of labels to filter sandboxes. Pass nil for no filtering.
- page: Optional page number \(1\-indexed\). Pass nil for the first page.
- limit: Optional number of results per page. Pass nil for the default limit.
Example:
```
// List all sandboxes
result, err := client.List(ctx, nil, nil, nil)
// List sandboxes with pagination
page, limit := 1, 10
result, err := client.List(ctx, nil, &page, &limit)
// Filter by labels
result, err := client.List(ctx, map[string]string{"env": "dev"}, nil, nil)
// Iterate through results
for _, sandbox := range result.Items {
fmt.Printf("Sandbox: %s (state: %s)\n", sandbox.Name, sandbox.State)
}
```
Returns a [PaginatedSandboxes](https://www.daytona.io/docs/%3C.md#PaginatedSandboxes%3E) containing the matching sandboxes and pagination metadata.
## type CodeInterpreterService
CodeInterpreterService provides Python code execution capabilities for a sandbox.
CodeInterpreterService enables running Python code in isolated execution contexts with support for streaming output, persistent state, and environment variables. It uses WebSockets for real\-time output streaming. Access through \[Sandbox.CodeInterpreter\].
Example:
```
// Simple code execution
channels, err := sandbox.CodeInterpreter.RunCode(ctx, "print('Hello, World!')")
if err != nil {
return err
}
// Wait for completion and get result
result := <-channels.Done
fmt.Println(result.Stdout)
// With persistent context
ctxInfo, _ := sandbox.CodeInterpreter.CreateContext(ctx, nil)
contextID := ctxInfo["id"].(string)
channels, _ = sandbox.CodeInterpreter.RunCode(ctx, "x = 42",
options.WithCustomContext(contextID),
)
<-channels.Done
channels, _ = sandbox.CodeInterpreter.RunCode(ctx, "print(x)",
options.WithCustomContext(contextID),
)
```
```go
type CodeInterpreterService struct {
// contains filtered or unexported fields
}
```
### func NewCodeInterpreterService
```go
func NewCodeInterpreterService(toolboxClient *toolbox.APIClient, otel *otelState) *CodeInterpreterService
```
NewCodeInterpreterService creates a new CodeInterpreterService.
This is typically called internally by the SDK when creating a [Sandbox](https://www.daytona.io/docs/%3C.md#Sandbox%3E). Users should access CodeInterpreterService through \[Sandbox.CodeInterpreter\] rather than creating it directly.
### func \(\*CodeInterpreterService\) CreateContext
```go
func (c *CodeInterpreterService) CreateContext(ctx context.Context, cwd *string) (map[string]any, error)
```
CreateContext creates an isolated execution context for persistent state.
Contexts allow you to maintain state \(variables, imports, etc.\) across multiple code executions. Without a context, each RunCode call starts fresh.
Parameters:
- cwd: Optional working directory for the context
Example:
```
// Create a context
ctxInfo, err := sandbox.CodeInterpreter.CreateContext(ctx, nil)
if err != nil {
return err
}
contextID := ctxInfo["id"].(string)
// Use the context to maintain state
sandbox.CodeInterpreter.RunCode(ctx, "x = 42", options.WithCustomContext(contextID))
sandbox.CodeInterpreter.RunCode(ctx, "print(x)", options.WithCustomContext(contextID)) // prints 42
// Clean up when done
sandbox.CodeInterpreter.DeleteContext(ctx, contextID)
```
Returns context information including "id", "cwd", "language", "active", and "createdAt".
### func \(\*CodeInterpreterService\) DeleteContext
```go
func (c *CodeInterpreterService) DeleteContext(ctx context.Context, contextID string) error
```
DeleteContext removes an execution context and releases its resources.
Parameters:
- contextID: The context identifier to delete
Example:
```
err := sandbox.CodeInterpreter.DeleteContext(ctx, contextID)
```
Returns an error if the context doesn't exist or deletion fails.
### func \(\*CodeInterpreterService\) ListContexts
```go
func (c *CodeInterpreterService) ListContexts(ctx context.Context) ([]map[string]any, error)
```
ListContexts returns all active execution contexts.
Example:
```
contexts, err := sandbox.CodeInterpreter.ListContexts(ctx)
if err != nil {
return err
}
for _, ctx := range contexts {
fmt.Printf("Context %s (language: %s)\n", ctx["id"], ctx["language"])
}
```
Returns a slice of context information maps.
### func \(\*CodeInterpreterService\) RunCode
```go
func (c *CodeInterpreterService) RunCode(ctx context.Context, code string, opts ...func(*options.RunCode)) (*OutputChannels, error)
```
RunCode executes Python code and returns channels for streaming output.
This method establishes a WebSocket connection to execute code asynchronously, streaming stdout and stderr as they become available.
Optional parameters can be configured using functional options:
- \[options.WithCustomContext\]: Use a persistent context for state
- \[options.WithEnv\]: Set environment variables
- \[options.WithInterpreterTimeout\]: Set execution timeout
Example:
```
// Basic execution
channels, err := sandbox.CodeInterpreter.RunCode(ctx, `
for i in range(5):
print(f"Count: {i}")
`)
if err != nil {
return err
}
// Stream output
for msg := range channels.Stdout {
fmt.Print(msg.Text)
}
// Get final result
result := <-channels.Done
if result.Error != nil {
fmt.Printf("Error: %s\n", result.Error.Value)
}
// With options
channels, err := sandbox.CodeInterpreter.RunCode(ctx, "import os; print(os.environ['API_KEY'])",
options.WithEnv(map[string]string{"API_KEY": "secret"}),
options.WithInterpreterTimeout(30*time.Second),
)
```
Returns [OutputChannels](https://www.daytona.io/docs/%3C.md#OutputChannels%3E) for receiving streamed output, or an error if connection fails.
## type ComputerUseService
ComputerUseService provides desktop automation operations for a sandbox.
ComputerUseService enables GUI automation including mouse control, keyboard input, screenshots, display management, and screen recording. The desktop environment must be started before using these features. Access through \[Sandbox.ComputerUse\].
Example:
```
cu := sandbox.ComputerUse
// Start the desktop environment
if err := cu.Start(ctx); err != nil {
return err
}
defer cu.Stop(ctx)
// Take a screenshot
screenshot, err := cu.Screenshot().TakeFullScreen(ctx, nil)
if err != nil {
return err
}
// Click at coordinates
cu.Mouse().Click(ctx, 100, 200, nil, nil)
// Type text
cu.Keyboard().Type(ctx, "Hello, World!", nil)
```
```go
type ComputerUseService struct {
// contains filtered or unexported fields
}
```
### func NewComputerUseService
```go
func NewComputerUseService(toolboxClient *toolbox.APIClient, otel *otelState) *ComputerUseService
```
NewComputerUseService creates a new ComputerUseService.
This is typically called internally by the SDK when creating a [Sandbox](https://www.daytona.io/docs/%3C.md#Sandbox%3E). Users should access ComputerUseService through \[Sandbox.ComputerUse\] rather than creating it directly.
### func \(\*ComputerUseService\) Display
```go
func (c *ComputerUseService) Display() *DisplayService
```
Display returns the [DisplayService](https://www.daytona.io/docs/%3C.md#DisplayService%3E) for display information.
The service is lazily initialized on first access.
### func \(\*ComputerUseService\) GetStatus
```go
func (c *ComputerUseService) GetStatus(ctx context.Context) (map[string]any, error)
```
GetStatus returns the current status of the desktop environment.
Example:
```
status, err := cu.GetStatus(ctx)
if err != nil {
return err
}
fmt.Printf("Desktop status: %v\n", status["status"])
```
Returns a map containing status information.
### func \(\*ComputerUseService\) Keyboard
```go
func (c *ComputerUseService) Keyboard() *KeyboardService
```
Keyboard returns the [KeyboardService](https://www.daytona.io/docs/%3C.md#KeyboardService%3E) for keyboard operations.
The service is lazily initialized on first access.
### func \(\*ComputerUseService\) Mouse
```go
func (c *ComputerUseService) Mouse() *MouseService
```
Mouse returns the [MouseService](https://www.daytona.io/docs/%3C.md#MouseService%3E) for mouse operations.
The service is lazily initialized on first access.
### func \(\*ComputerUseService\) Recording
```go
func (c *ComputerUseService) Recording() *RecordingService
```
Recording returns the [RecordingService](https://www.daytona.io/docs/%3C.md#RecordingService%3E) for screen recording operations.
The service is lazily initialized on first access.
### func \(\*ComputerUseService\) Screenshot
```go
func (c *ComputerUseService) Screenshot() *ScreenshotService
```
Screenshot returns the [ScreenshotService](https://www.daytona.io/docs/%3C.md#ScreenshotService%3E) for capturing screen images.
The service is lazily initialized on first access.
### func \(\*ComputerUseService\) Start
```go
func (c *ComputerUseService) Start(ctx context.Context) error
```
Start initializes and starts the desktop environment.
The desktop environment must be started before using mouse, keyboard, or screenshot operations. Call [ComputerUseService.Stop](https://www.daytona.io/docs/%3C.md#ComputerUseService.Stop%3E) when finished.
Example:
```
if err := cu.Start(ctx); err != nil {
return err
}
defer cu.Stop(ctx)
```
Returns an error if the desktop fails to start.
### func \(\*ComputerUseService\) Stop
```go
func (c *ComputerUseService) Stop(ctx context.Context) error
```
Stop shuts down the desktop environment and releases resources.
Example:
```
err := cu.Stop(ctx)
```
Returns an error if the desktop fails to stop gracefully.
## type DisplayService
DisplayService provides display information and window management operations.
DisplayService enables querying display configuration and window information. Access through [ComputerUseService.Display](https://www.daytona.io/docs/%3C.md#ComputerUseService.Display%3E).
```go
type DisplayService struct {
// contains filtered or unexported fields
}
```
### func NewDisplayService
```go
func NewDisplayService(toolboxClient *toolbox.APIClient, otel *otelState) *DisplayService
```
NewDisplayService creates a new DisplayService.
### func \(\*DisplayService\) GetInfo
```go
func (d *DisplayService) GetInfo(ctx context.Context) (map[string]any, error)
```
GetInfo returns information about connected displays.
Example:
```
info, err := display.GetInfo(ctx)
if err != nil {
return err
}
displays := info["displays"]
fmt.Printf("Connected displays: %v\n", displays)
```
Returns a map containing display information.
### func \(\*DisplayService\) GetWindows
```go
func (d *DisplayService) GetWindows(ctx context.Context) (map[string]any, error)
```
GetWindows returns information about open windows.
Example:
```
result, err := display.GetWindows(ctx)
if err != nil {
return err
}
windows := result["windows"]
fmt.Printf("Open windows: %v\n", windows)
```
Returns a map containing window information.
## type DockerImage
DockerImage provides a fluent interface for building Docker images declaratively.
DockerImage allows you to define Docker images using Go code instead of Dockerfiles. Methods can be chained to build up the image definition, which is then converted to a Dockerfile when used with [SnapshotService.Create](https://www.daytona.io/docs/%3C.md#SnapshotService.Create%3E).
Example:
```
// Create a Python image with dependencies
image := daytona.Base("python:3.11-slim").
AptGet([]string{"git", "curl"}).
PipInstall([]string{"numpy", "pandas"}).
Workdir("/app").
Env("PYTHONUNBUFFERED", "1")
// Use with snapshot creation
snapshot, logChan, err := client.Snapshots.Create(ctx, &types.CreateSnapshotParams{
Name: "my-python-env",
DockerImage: image,
})
```
```go
type DockerImage struct {
// contains filtered or unexported fields
}
```
### func Base
```go
func Base(baseImage string) *DockerImage
```
Base creates a new Image from a base Docker image.
This is typically the starting point for building an image definition. The baseImage parameter is any valid Docker image reference.
Example:
```
image := daytona.Base("ubuntu:22.04")
image := daytona.Base("python:3.11-slim")
image := daytona.Base("node:18-alpine")
```
### func DebianSlim
```go
func DebianSlim(pythonVersion *string) *DockerImage
```
DebianSlim creates a Python image based on Debian slim.
This is a convenience function for creating Python environments. If pythonVersion is nil, defaults to Python 3.12.
Example:
```
// Use default Python 3.12
image := daytona.DebianSlim(nil)
// Use specific version
version := "3.10"
image := daytona.DebianSlim(&version)
```
### func FromDockerfile
```go
func FromDockerfile(dockerfile string) *DockerImage
```
FromDockerfile creates an Image from an existing Dockerfile string.
Use this when you have an existing Dockerfile you want to use.
Example:
```
dockerfile := `FROM python:3.11
RUN pip install numpy
WORKDIR /app`
image := daytona.FromDockerfile(dockerfile)
```
### func \(\*DockerImage\) Add
```go
func (img *DockerImage) Add(source, destination string) *DockerImage
```
Add adds an ADD instruction to the image.
ADD supports URLs and automatic tar extraction. For simple file copying, prefer [DockerImage.Copy](https://www.daytona.io/docs/%3C.md#DockerImage.Copy%3E).
Example:
```
image := daytona.Base("ubuntu:22.04").
Add("https://example.com/app.tar.gz", "/app/")
```
### func \(\*DockerImage\) AddLocalDir
```go
func (img *DockerImage) AddLocalDir(localPath, remotePath string) *DockerImage
```
AddLocalDir adds a local directory to the build context and copies it to the image.
The directory is uploaded to object storage and included in the Docker build context.
Example:
```
image := daytona.Base("python:3.11").
AddLocalDir("./src", "/app/src")
```
### func \(\*DockerImage\) AddLocalFile
```go
func (img *DockerImage) AddLocalFile(localPath, remotePath string) *DockerImage
```
AddLocalFile adds a local file to the build context and copies it to the image.
The file is uploaded to object storage and included in the Docker build context.
Example:
```
image := daytona.Base("python:3.11").
AddLocalFile("./requirements.txt", "/app/requirements.txt").
Run("pip install -r /app/requirements.txt")
```
### func \(\*DockerImage\) AptGet
```go
func (img *DockerImage) AptGet(packages []string) *DockerImage
```
AptGet adds an apt\-get install instruction for system packages.
This automatically handles updating the package list and cleaning up afterward to minimize image size.
Example:
```
image := daytona.Base("ubuntu:22.04").AptGet([]string{"git", "curl", "build-essential"})
```
### func \(\*DockerImage\) Cmd
```go
func (img *DockerImage) Cmd(cmd []string) *DockerImage
```
Cmd sets the default command for the image.
If an entrypoint is set, the cmd provides default arguments to it.
Example:
```
image := daytona.Base("python:3.11").
Cmd([]string{"python", "app.py"})
```
### func \(\*DockerImage\) Contexts
```go
func (img *DockerImage) Contexts() []DockerImageContext
```
Contexts returns the build contexts for local files/directories.
This is called internally when creating snapshots to upload local files.
### func \(\*DockerImage\) Copy
```go
func (img *DockerImage) Copy(source, destination string) *DockerImage
```
Copy adds a COPY instruction to copy files into the image.
For local files, use [DockerImage.AddLocalFile](https://www.daytona.io/docs/%3C.md#DockerImage.AddLocalFile%3E) instead, which handles uploading to the build context.
Example:
```
image := daytona.Base("python:3.11").
Copy("requirements.txt", "/app/requirements.txt")
```
### func \(\*DockerImage\) Dockerfile
```go
func (img *DockerImage) Dockerfile() string
```
Dockerfile returns the generated Dockerfile content.
This is called internally when creating snapshots.
Example:
```
image := daytona.Base("python:3.11").PipInstall([]string{"numpy"})
fmt.Println(image.Dockerfile())
// Output:
// FROM python:3.11
// RUN pip install numpy
```
### func \(\*DockerImage\) Entrypoint
```go
func (img *DockerImage) Entrypoint(cmd []string) *DockerImage
```
Entrypoint sets the entrypoint for the image.
The cmd parameter is the command and arguments as a slice.
Example:
```
image := daytona.Base("python:3.11").
Entrypoint([]string{"python", "-m", "myapp"})
```
### func \(\*DockerImage\) Env
```go
func (img *DockerImage) Env(key, value string) *DockerImage
```
Env sets an environment variable in the image.
Example:
```
image := daytona.Base("python:3.11").
Env("PYTHONUNBUFFERED", "1").
Env("APP_ENV", "production")
```
### func \(\*DockerImage\) Expose
```go
func (img *DockerImage) Expose(ports []int) *DockerImage
```
Expose declares ports that the container listens on.
This is documentation for users and tools; it doesn't actually publish ports.
Example:
```
image := daytona.Base("python:3.11").
Expose([]int{8080, 8443})
```
### func \(\*DockerImage\) Label
```go
func (img *DockerImage) Label(key, value string) *DockerImage
```
Label adds metadata to the image.
Example:
```
image := daytona.Base("python:3.11").
Label("maintainer", "team@example.com").
Label("version", "1.0.0")
```
### func \(\*DockerImage\) PipInstall
```go
func (img *DockerImage) PipInstall(packages []string, opts ...func(*options.PipInstall)) *DockerImage
```
PipInstall adds a pip install instruction for Python packages.
Optional parameters can be configured using functional options:
- \[options.WithFindLinks\]: Add find\-links URLs
- \[options.WithIndexURL\]: Set custom PyPI index
- \[options.WithExtraIndexURLs\]: Add extra index URLs
- \[options.WithPre\]: Allow pre\-release versions
- \[options.WithExtraOptions\]: Add additional pip options
Example:
```
// Basic installation
image := daytona.Base("python:3.11").PipInstall([]string{"numpy", "pandas"})
// With options
image := daytona.Base("python:3.11").PipInstall(
[]string{"torch"},
options.WithIndexURL("https://download.pytorch.org/whl/cpu"),
options.WithExtraOptions("--no-cache-dir"),
)
```
### func \(\*DockerImage\) Run
```go
func (img *DockerImage) Run(command string) *DockerImage
```
Run adds a RUN instruction to execute a shell command.
Example:
```
image := daytona.Base("ubuntu:22.04").
Run("mkdir -p /app/data").
Run("chmod 755 /app")
```
### func \(\*DockerImage\) User
```go
func (img *DockerImage) User(username string) *DockerImage
```
User sets the user for subsequent instructions and container runtime.
Example:
```
image := daytona.Base("python:3.11").
Run("useradd -m appuser").
User("appuser").
Workdir("/home/appuser")
```
### func \(\*DockerImage\) Volume
```go
func (img *DockerImage) Volume(paths []string) *DockerImage
```
Volume declares mount points for the container.
Example:
```
image := daytona.Base("python:3.11").
Volume([]string{"/data", "/logs"})
```
### func \(\*DockerImage\) Workdir
```go
func (img *DockerImage) Workdir(path string) *DockerImage
```
Workdir sets the working directory for subsequent instructions.
Example:
```
image := daytona.Base("python:3.11").
Workdir("/app").
Run("pip install -r requirements.txt")
```
## type DockerImageContext
DockerImageContext represents a local file or directory to include in the build context.
When using [DockerImage.AddLocalFile](https://www.daytona.io/docs/%3C.md#DockerImage.AddLocalFile%3E) or [DockerImage.AddLocalDir](https://www.daytona.io/docs/%3C.md#DockerImage.AddLocalDir%3E), the file/directory is uploaded to object storage and included in the Docker build context.
```go
type DockerImageContext struct {
SourcePath string // Local path to the file or directory
ArchivePath string // Path within the build context archive
}
```
## type FileSystemService
FileSystemService provides file system operations for a sandbox.
FileSystemService enables file and directory management including creating, reading, writing, moving, and deleting files. It also supports file searching and permission management. Access through \[Sandbox.FileSystem\].
Example:
```
// List files in a directory
files, err := sandbox.FileSystem.ListFiles(ctx, "/home/user")
// Create a directory
err = sandbox.FileSystem.CreateFolder(ctx, "/home/user/mydir")
// Upload a file
err = sandbox.FileSystem.UploadFile(ctx, "/local/path/file.txt", "/home/user/file.txt")
// Download a file
data, err := sandbox.FileSystem.DownloadFile(ctx, "/home/user/file.txt", nil)
```
```go
type FileSystemService struct {
// contains filtered or unexported fields
}
```
### func NewFileSystemService
```go
func NewFileSystemService(toolboxClient *toolbox.APIClient, otel *otelState) *FileSystemService
```
NewFileSystemService creates a new FileSystemService with the provided toolbox client.
This is typically called internally by the SDK when creating a [Sandbox](https://www.daytona.io/docs/%3C.md#Sandbox%3E). Users should access FileSystemService through \[Sandbox.FileSystem\] rather than creating it directly.
### func \(\*FileSystemService\) CreateFolder
```go
func (f *FileSystemService) CreateFolder(ctx context.Context, path string, opts ...func(*options.CreateFolder)) error
```
CreateFolder creates a directory at the specified path.
The path parameter specifies the absolute path for the new directory. Parent directories are created automatically if they don't exist.
Optional parameters can be configured using functional options:
- \[options.WithMode\]: Set Unix file permissions \(defaults to "0755"\)
Example:
```
// Create with default permissions
err := sandbox.FileSystem.CreateFolder(ctx, "/home/user/mydir")
// Create with custom permissions
err := sandbox.FileSystem.CreateFolder(ctx, "/home/user/private",
options.WithMode("0700"),
)
```
Returns an error if the directory creation fails.
### func \(\*FileSystemService\) DeleteFile
```go
func (f *FileSystemService) DeleteFile(ctx context.Context, path string, recursive bool) error
```
DeleteFile deletes a file or directory.
Parameters:
- path: The file or directory path to delete
- recursive: If true, delete directories and their contents recursively
Example:
```
// Delete a file
err := sandbox.FileSystem.DeleteFile(ctx, "/home/user/file.txt", false)
// Delete a directory recursively
err := sandbox.FileSystem.DeleteFile(ctx, "/home/user/mydir", true)
```
Returns an error if the deletion fails \(e.g., path doesn't exist, permission denied, or attempting to delete a non\-empty directory without recursive=true\).
### func \(\*FileSystemService\) DownloadFile
```go
func (f *FileSystemService) DownloadFile(ctx context.Context, remotePath string, localPath *string) ([]byte, error)
```
DownloadFile downloads a file from the sandbox.
Parameters:
- remotePath: The path to the file in the sandbox
- localPath: Optional local path to save the file. If nil, only returns the data.
Returns the file contents as a byte slice. If localPath is provided, also writes the contents to that local file.
Example:
```
// Download and get contents
data, err := sandbox.FileSystem.DownloadFile(ctx, "/home/user/file.txt", nil)
fmt.Println(string(data))
// Download and save to local file
localPath := "/tmp/downloaded.txt"
data, err := sandbox.FileSystem.DownloadFile(ctx, "/home/user/file.txt", &localPath)
```
Returns an error if the file doesn't exist or cannot be read.
### func \(\*FileSystemService\) FindFiles
```go
func (f *FileSystemService) FindFiles(ctx context.Context, path, pattern string) (any, error)
```
FindFiles searches for text content within files.
Parameters:
- path: The directory to search in
- pattern: The text pattern to search for \(supports regex\)
Returns a list of matches, each containing the file path, line number, and matching content.
Example:
```
result, err := sandbox.FileSystem.FindFiles(ctx, "/home/user/project", "TODO:")
if err != nil {
return err
}
matches := result.([]map[string]any)
for _, match := range matches {
fmt.Printf("%s:%d: %s\n", match["file"], match["line"], match["content"])
}
```
Returns an error if the search fails.
### func \(\*FileSystemService\) GetFileInfo
```go
func (f *FileSystemService) GetFileInfo(ctx context.Context, path string) (*types.FileInfo, error)
```
GetFileInfo retrieves metadata for a file or directory.
The path parameter specifies the file or directory path.
Returns \[types.FileInfo\] containing the file's name, size, permissions, modification time, and whether it's a directory.
Example:
```
info, err := sandbox.FileSystem.GetFileInfo(ctx, "/home/user/file.txt")
if err != nil {
return err
}
fmt.Printf("Size: %d bytes, Modified: %s\n", info.Size, info.ModifiedTime)
```
Returns an error if the path doesn't exist.
### func \(\*FileSystemService\) ListFiles
```go
func (f *FileSystemService) ListFiles(ctx context.Context, path string) ([]*types.FileInfo, error)
```
ListFiles lists files and directories in the specified path.
The path parameter specifies the directory to list.
Returns a slice of \[types.FileInfo\] containing metadata for each file and directory, including name, size, permissions, modification time, and whether it's a directory.
Example:
```
files, err := sandbox.FileSystem.ListFiles(ctx, "/home/user")
if err != nil {
return err
}
for _, file := range files {
if file.IsDirectory {
fmt.Printf("[DIR] %s\n", file.Name)
} else {
fmt.Printf("[FILE] %s (%d bytes)\n", file.Name, file.Size)
}
}
```
Returns an error if the path doesn't exist or isn't accessible.
### func \(\*FileSystemService\) MoveFiles
```go
func (f *FileSystemService) MoveFiles(ctx context.Context, source, destination string) error
```
MoveFiles moves or renames a file or directory.
Parameters:
- source: The current path of the file or directory
- destination: The new path for the file or directory
This operation can be used for both moving and renaming:
- Same directory, different name = rename
- Different directory = move
Example:
```
// Rename a file
err := sandbox.FileSystem.MoveFiles(ctx, "/home/user/old.txt", "/home/user/new.txt")
// Move a file to another directory
err := sandbox.FileSystem.MoveFiles(ctx, "/home/user/file.txt", "/home/user/backup/file.txt")
```
Returns an error if the operation fails.
### func \(\*FileSystemService\) ReplaceInFiles
```go
func (f *FileSystemService) ReplaceInFiles(ctx context.Context, files []string, pattern, newValue string) (any, error)
```
ReplaceInFiles replaces text in multiple files.
Parameters:
- files: List of file paths to process
- pattern: The text pattern to search for \(supports regex\)
- newValue: The replacement text
Returns a list of results for each file, indicating success or failure.
Example:
```
files := []string{"/home/user/file1.txt", "/home/user/file2.txt"}
result, err := sandbox.FileSystem.ReplaceInFiles(ctx, files, "oldValue", "newValue")
if err != nil {
return err
}
results := result.([]map[string]any)
for _, r := range results {
if r["success"].(bool) {
fmt.Printf("Updated: %s\n", r["file"])
} else {
fmt.Printf("Failed: %s - %s\n", r["file"], r["error"])
}
}
```
Returns an error if the operation fails entirely.
### func \(\*FileSystemService\) SearchFiles
```go
func (f *FileSystemService) SearchFiles(ctx context.Context, path, pattern string) (any, error)
```
SearchFiles searches for files matching a pattern in a directory.
Parameters:
- path: The directory to search in
- pattern: The glob pattern to match file names \(e.g., "\*.txt", "test\_\*"\)
Returns a map containing a "files" key with a list of matching file paths.
Example:
```
result, err := sandbox.FileSystem.SearchFiles(ctx, "/home/user", "*.go")
if err != nil {
return err
}
files := result.(map[string]any)["files"].([]string)
for _, file := range files {
fmt.Println(file)
}
```
Returns an error if the search fails.
### func \(\*FileSystemService\) SetFilePermissions
```go
func (f *FileSystemService) SetFilePermissions(ctx context.Context, path string, opts ...func(*options.SetFilePermissions)) error
```
SetFilePermissions sets file permissions, owner, and group.
The path parameter specifies the file or directory to modify.
Optional parameters can be configured using functional options:
- \[options.WithPermissionMode\]: Set Unix file permissions \(e.g., "0644"\)
- \[options.WithOwner\]: Set file owner username
- \[options.WithGroup\]: Set file group name
Example:
```
// Set permissions only
err := sandbox.FileSystem.SetFilePermissions(ctx, "/home/user/script.sh",
options.WithPermissionMode("0755"),
)
// Set owner and group
err := sandbox.FileSystem.SetFilePermissions(ctx, "/home/user/file.txt",
options.WithOwner("root"),
options.WithGroup("users"),
)
// Set all at once
err := sandbox.FileSystem.SetFilePermissions(ctx, "/home/user/file.txt",
options.WithPermissionMode("0640"),
options.WithOwner("user"),
options.WithGroup("staff"),
)
```
Returns an error if the operation fails.
### func \(\*FileSystemService\) UploadFile
```go
func (f *FileSystemService) UploadFile(ctx context.Context, source any, destination string) error
```
UploadFile uploads a file to the sandbox.
Parameters:
- source: Either a local file path \(string\) or file contents \(\[\]byte\)
- destination: The destination path in the sandbox
Example:
```
// Upload from local file path
err := sandbox.FileSystem.UploadFile(ctx, "/local/path/file.txt", "/home/user/file.txt")
// Upload from byte slice
content := []byte("Hello, World!")
err := sandbox.FileSystem.UploadFile(ctx, content, "/home/user/hello.txt")
```
Returns an error if the upload fails.
## type GitService
GitService provides Git operations for a sandbox.
GitService enables common Git workflows including cloning repositories, staging and committing changes, managing branches, and syncing with remote repositories. It is accessed through the \[Sandbox.Git\] field.
Example:
```
// Clone a repository
err := sandbox.Git.Clone(ctx, "https://github.com/user/repo.git", "/home/user/repo")
// Make changes and commit
err = sandbox.Git.Add(ctx, "/home/user/repo", []string{"."})
resp, err := sandbox.Git.Commit(ctx, "/home/user/repo", "Initial commit", "John Doe", "john@example.com")
// Push to remote
err = sandbox.Git.Push(ctx, "/home/user/repo",
options.WithPushUsername("username"),
options.WithPushPassword("token"),
)
```
```go
type GitService struct {
// contains filtered or unexported fields
}
```
### func NewGitService
```go
func NewGitService(toolboxClient *toolbox.APIClient, otel *otelState) *GitService
```
NewGitService creates a new GitService with the provided toolbox client.
This is typically called internally by the SDK when creating a [Sandbox](https://www.daytona.io/docs/%3C.md#Sandbox%3E). Users should access GitService through \[Sandbox.Git\] rather than creating it directly.
### func \(\*GitService\) Add
```go
func (g *GitService) Add(ctx context.Context, path string, files []string) error
```
Add stages files for the next commit.
The path parameter specifies the repository directory. The files parameter is a list of file paths \(relative to the repository root\) to stage. Use "." to stage all changes.
Example:
```
// Stage specific files
err := sandbox.Git.Add(ctx, "/home/user/repo", []string{"file1.txt", "src/main.go"})
// Stage all changes
err := sandbox.Git.Add(ctx, "/home/user/repo", []string{"."})
```
Returns an error if the add operation fails.
### func \(\*GitService\) Branches
```go
func (g *GitService) Branches(ctx context.Context, path string) ([]string, error)
```
Branches lists all branches in a Git repository.
The path parameter specifies the repository directory.
Example:
```
branches, err := sandbox.Git.Branches(ctx, "/home/user/repo")
if err != nil {
return err
}
for _, branch := range branches {
fmt.Println(branch)
}
```
Returns a slice of branch names or an error if the operation fails.
### func \(\*GitService\) Checkout
```go
func (g *GitService) Checkout(ctx context.Context, path, name string) error
```
Checkout switches to a different branch or commit.
The path parameter specifies the repository directory. The name parameter specifies the branch name or commit SHA to checkout.
Example:
```
// Switch to a branch
err := sandbox.Git.Checkout(ctx, "/home/user/repo", "develop")
// Checkout a specific commit
err := sandbox.Git.Checkout(ctx, "/home/user/repo", "abc123def")
```
Returns an error if the checkout fails \(e.g., branch doesn't exist, uncommitted changes\).
### func \(\*GitService\) Clone
```go
func (g *GitService) Clone(ctx context.Context, url, path string, opts ...func(*options.GitClone)) error
```
Clone clones a Git repository into the specified path.
The url parameter specifies the repository URL \(HTTPS or SSH format\). The path parameter specifies the destination directory for the cloned repository.
Optional parameters can be configured using functional options:
- \[options.WithBranch\]: Clone a specific branch instead of the default
- \[options.WithCommitId\]: Checkout a specific commit after cloning
- \[options.WithUsername\]: Username for authentication \(HTTPS\)
- \[options.WithPassword\]: Password or token for authentication \(HTTPS\)
Example:
```
// Clone the default branch
err := sandbox.Git.Clone(ctx, "https://github.com/user/repo.git", "/home/user/repo")
// Clone a specific branch with authentication
err := sandbox.Git.Clone(ctx, "https://github.com/user/private-repo.git", "/home/user/repo",
options.WithBranch("develop"),
options.WithUsername("username"),
options.WithPassword("github_token"),
)
// Clone and checkout a specific commit
err := sandbox.Git.Clone(ctx, "https://github.com/user/repo.git", "/home/user/repo",
options.WithCommitId("abc123"),
)
```
Returns an error if the clone operation fails.
### func \(\*GitService\) Commit
```go
func (g *GitService) Commit(ctx context.Context, path, message, author, email string, opts ...func(*options.GitCommit)) (*types.GitCommitResponse, error)
```
Commit creates a new Git commit with the staged changes.
Parameters:
- path: The repository directory
- message: The commit message
- author: The author name for the commit
- email: The author email for the commit
Optional parameters can be configured using functional options:
- \[options.WithAllowEmpty\]: Allow creating commits with no changes
Example:
```
// Create a commit
resp, err := sandbox.Git.Commit(ctx, "/home/user/repo",
"Add new feature",
"John Doe",
"john@example.com",
)
if err != nil {
return err
}
fmt.Printf("Created commit: %s\n", resp.SHA)
// Create an empty commit
resp, err := sandbox.Git.Commit(ctx, "/home/user/repo",
"Empty commit for CI trigger",
"John Doe",
"john@example.com",
options.WithAllowEmpty(true),
)
```
Returns the \[types.GitCommitResponse\] containing the commit SHA, or an error if the commit fails.
### func \(\*GitService\) CreateBranch
```go
func (g *GitService) CreateBranch(ctx context.Context, path, name string) error
```
CreateBranch creates a new branch at the current HEAD.
The path parameter specifies the repository directory. The name parameter specifies the name for the new branch.
Note: This creates the branch but does not switch to it. Use [GitService.Checkout](https://www.daytona.io/docs/%3C.md#GitService.Checkout%3E) to switch to the new branch after creation.
Example:
```
// Create a new branch
err := sandbox.Git.CreateBranch(ctx, "/home/user/repo", "feature/new-feature")
if err != nil {
return err
}
// Switch to the new branch
err = sandbox.Git.Checkout(ctx, "/home/user/repo", "feature/new-feature")
```
Returns an error if the branch creation fails \(e.g., branch already exists\).
### func \(\*GitService\) DeleteBranch
```go
func (g *GitService) DeleteBranch(ctx context.Context, path, name string, opts ...func(*options.GitDeleteBranch)) error
```
DeleteBranch deletes a branch from the repository.
The path parameter specifies the repository directory. The name parameter specifies the branch to delete.
Optional parameters can be configured using functional options:
- \[options.WithForce\]: Force delete the branch even if not fully merged
Note: You cannot delete the currently checked out branch.
Example:
```
// Delete a merged branch
err := sandbox.Git.DeleteBranch(ctx, "/home/user/repo", "feature/old-feature")
// Force delete an unmerged branch
err := sandbox.Git.DeleteBranch(ctx, "/home/user/repo", "feature/abandoned",
options.WithForce(true),
)
```
Returns an error if the deletion fails.
### func \(\*GitService\) Pull
```go
func (g *GitService) Pull(ctx context.Context, path string, opts ...func(*options.GitPull)) error
```
Pull fetches and merges changes from the remote repository.
The path parameter specifies the repository directory.
Optional parameters can be configured using functional options:
- \[options.WithPullUsername\]: Username for authentication
- \[options.WithPullPassword\]: Password or token for authentication
Example:
```
// Pull from a public repository
err := sandbox.Git.Pull(ctx, "/home/user/repo")
// Pull with authentication
err := sandbox.Git.Pull(ctx, "/home/user/repo",
options.WithPullUsername("username"),
options.WithPullPassword("github_token"),
)
```
Returns an error if the pull fails \(e.g., merge conflicts, authentication failure\).
### func \(\*GitService\) Push
```go
func (g *GitService) Push(ctx context.Context, path string, opts ...func(*options.GitPush)) error
```
Push pushes local commits to the remote repository.
The path parameter specifies the repository directory.
Optional parameters can be configured using functional options:
- \[options.WithPushUsername\]: Username for authentication
- \[options.WithPushPassword\]: Password or token for authentication
Example:
```
// Push to a public repository (no auth required)
err := sandbox.Git.Push(ctx, "/home/user/repo")
// Push with authentication
err := sandbox.Git.Push(ctx, "/home/user/repo",
options.WithPushUsername("username"),
options.WithPushPassword("github_token"),
)
```
Returns an error if the push fails \(e.g., authentication failure, remote rejection\).
### func \(\*GitService\) Status
```go
func (g *GitService) Status(ctx context.Context, path string) (*types.GitStatus, error)
```
Status returns the current Git status of a repository.
The path parameter specifies the repository directory to check.
The returned \[types.GitStatus\] contains:
- CurrentBranch: The name of the currently checked out branch
- Ahead: Number of commits ahead of the remote tracking branch
- Behind: Number of commits behind the remote tracking branch
- BranchPublished: Whether the branch has been pushed to remote
- FileStatus: List of files with their staging and working tree status
Example:
```
status, err := sandbox.Git.Status(ctx, "/home/user/repo")
if err != nil {
return err
}
fmt.Printf("On branch %s\n", status.CurrentBranch)
fmt.Printf("Ahead: %d, Behind: %d\n", status.Ahead, status.Behind)
for _, file := range status.FileStatus {
fmt.Printf("%s %s\n", file.Status, file.Path)
}
```
Returns an error if the status operation fails or the path is not a Git repository.
## type KeyboardService
KeyboardService provides keyboard input operations.
KeyboardService enables typing text, pressing keys, and executing keyboard shortcuts. Access through [ComputerUseService.Keyboard](https://www.daytona.io/docs/%3C.md#ComputerUseService.Keyboard%3E).
```go
type KeyboardService struct {
// contains filtered or unexported fields
}
```
### func NewKeyboardService
```go
func NewKeyboardService(toolboxClient *toolbox.APIClient, otel *otelState) *KeyboardService
```
NewKeyboardService creates a new KeyboardService.
### func \(\*KeyboardService\) Hotkey
```go
func (k *KeyboardService) Hotkey(ctx context.Context, keys string) error
```
Hotkey executes a keyboard shortcut.
Parameters:
- keys: The hotkey combination as a string \(e.g., "ctrl\+c", "alt\+tab"\)
Example:
```
// Copy (Ctrl+C)
err := keyboard.Hotkey(ctx, "ctrl+c")
// Paste (Ctrl+V)
err := keyboard.Hotkey(ctx, "ctrl+v")
// Switch windows (Alt+Tab)
err := keyboard.Hotkey(ctx, "alt+tab")
```
Returns an error if the hotkey fails.
### func \(\*KeyboardService\) Press
```go
func (k *KeyboardService) Press(ctx context.Context, key string, modifiers []string) error
```
Press simulates pressing a key with optional modifiers.
Parameters:
- key: The key to press \(e.g., "a", "Enter", "Tab", "F1"\)
- modifiers: Modifier keys to hold \(e.g., "ctrl", "alt", "shift", "meta"\)
Example:
```
// Press Enter
err := keyboard.Press(ctx, "Enter", nil)
// Press Ctrl+S
err := keyboard.Press(ctx, "s", []string{"ctrl"})
// Press Ctrl+Shift+N
err := keyboard.Press(ctx, "n", []string{"ctrl", "shift"})
```
Returns an error if the key press fails.
### func \(\*KeyboardService\) Type
```go
func (k *KeyboardService) Type(ctx context.Context, text string, delay *int) error
```
Type simulates typing the specified text.
Parameters:
- text: The text to type
- delay: Delay in milliseconds between keystrokes, nil for default
Example:
```
// Type text with default speed
err := keyboard.Type(ctx, "Hello, World!", nil)
// Type with custom delay between keystrokes
delay := 50
err := keyboard.Type(ctx, "Slow typing", &delay)
```
Returns an error if typing fails.
## type LspServerService
LspServerService provides Language Server Protocol \(LSP\) operations for a sandbox.
LspServerService enables IDE\-like features such as code completion, symbol search, and document analysis through LSP. The service manages a language server instance for a specific language and project path. Access through \[Sandbox.Lsp\].
Example:
```
// Get LSP service for Python
lsp := sandbox.Lsp(types.LspLanguageIDPython, "/home/user/project")
// Start the language server
if err := lsp.Start(ctx); err != nil {
return err
}
defer lsp.Stop(ctx)
// Open a file for analysis
if err := lsp.DidOpen(ctx, "/home/user/project/main.py"); err != nil {
return err
}
// Get code completions
completions, err := lsp.Completions(ctx, "/home/user/project/main.py",
types.Position{Line: 10, Character: 5})
```
```go
type LspServerService struct {
// contains filtered or unexported fields
}
```
### func NewLspServerService
```go
func NewLspServerService(toolboxClient *toolbox.APIClient, languageID types.LspLanguageID, projectPath string, otel *otelState) *LspServerService
```
NewLspServerService creates a new LspServerService.
This is typically called internally by the SDK through \[Sandbox.Lsp\]. Users should access LspServerService through \[Sandbox.Lsp\] rather than creating it directly.
Parameters:
- toolboxClient: The toolbox API client
- languageID: The language identifier \(e.g., \[types.LspLanguageIDPython\]\)
- projectPath: The root path of the project for LSP analysis
### func \(\*LspServerService\) Completions
```go
func (l *LspServerService) Completions(ctx context.Context, path string, position types.Position) (any, error)
```
Completions returns code completion suggestions at a position.
The file should be opened with [LspServerService.DidOpen](https://www.daytona.io/docs/%3C.md#LspServerService.DidOpen%3E) before requesting completions.
Parameters:
- path: Absolute path to the file
- position: Cursor position \(line and character, 0\-indexed\)
Example:
```
lsp.DidOpen(ctx, "/home/user/project/main.py")
completions, err := lsp.Completions(ctx, "/home/user/project/main.py",
types.Position{Line: 10, Character: 5})
if err != nil {
return err
}
fmt.Printf("Completions: %v\n", completions)
```
Returns completion items or an error.
### func \(\*LspServerService\) DidClose
```go
func (l *LspServerService) DidClose(ctx context.Context, path string) error
```
DidClose notifies the language server that a file was closed.
Call this when you're done working with a file to allow the server to release resources associated with it.
Parameters:
- path: Absolute path to the file
Example:
```
err := lsp.DidClose(ctx, "/home/user/project/main.py")
```
Returns an error if the notification fails.
### func \(\*LspServerService\) DidOpen
```go
func (l *LspServerService) DidOpen(ctx context.Context, path string) error
```
DidOpen notifies the language server that a file was opened.
This should be called before requesting completions or symbols for a file. The path is automatically converted to a file:// URI if needed.
Parameters:
- path: Absolute path to the file
Example:
```
err := lsp.DidOpen(ctx, "/home/user/project/main.py")
```
Returns an error if the notification fails.
### func \(\*LspServerService\) DocumentSymbols
```go
func (l *LspServerService) DocumentSymbols(ctx context.Context, path string) ([]any, error)
```
DocumentSymbols returns all symbols \(functions, classes, variables\) in a document.
Parameters:
- path: Absolute path to the file
Example:
```
symbols, err := lsp.DocumentSymbols(ctx, "/home/user/project/main.py")
if err != nil {
return err
}
for _, sym := range symbols {
fmt.Printf("Symbol: %v\n", sym)
}
```
Returns a slice of symbol information or an error.
### func \(\*LspServerService\) SandboxSymbols
```go
func (l *LspServerService) SandboxSymbols(ctx context.Context, query string) ([]any, error)
```
SandboxSymbols searches for symbols across the entire workspace.
Use this to find symbols \(functions, classes, etc.\) by name across all files in the project.
Parameters:
- query: Search query to match symbol names
Example:
```
symbols, err := lsp.SandboxSymbols(ctx, "MyClass")
if err != nil {
return err
}
for _, sym := range symbols {
fmt.Printf("Found: %v\n", sym)
}
```
Returns a slice of matching symbols or an error.
### func \(\*LspServerService\) Start
```go
func (l *LspServerService) Start(ctx context.Context) error
```
Start initializes and starts the language server.
The language server must be started before using other LSP operations. Call [LspServerService.Stop](https://www.daytona.io/docs/%3C.md#LspServerService.Stop%3E) when finished to release resources.
Example:
```
if err := lsp.Start(ctx); err != nil {
return err
}
defer lsp.Stop(ctx)
```
Returns an error if the server fails to start.
### func \(\*LspServerService\) Stop
```go
func (l *LspServerService) Stop(ctx context.Context) error
```
Stop shuts down the language server and releases resources.
Example:
```
err := lsp.Stop(ctx)
```
Returns an error if the server fails to stop gracefully.
## type MouseService
MouseService provides mouse control operations.
MouseService enables cursor movement, clicking, dragging, and scrolling. Access through [ComputerUseService.Mouse](https://www.daytona.io/docs/%3C.md#ComputerUseService.Mouse%3E).
```go
type MouseService struct {
// contains filtered or unexported fields
}
```
### func NewMouseService
```go
func NewMouseService(toolboxClient *toolbox.APIClient, otel *otelState) *MouseService
```
NewMouseService creates a new MouseService.
### func \(\*MouseService\) Click
```go
func (m *MouseService) Click(ctx context.Context, x, y int, button *string, double *bool) (map[string]any, error)
```
Click performs a mouse click at the specified coordinates.
Parameters:
- x: X coordinate to click
- y: Y coordinate to click
- button: Mouse button \("left", "right", "middle"\), nil for left click
- double: Whether to double\-click, nil for single click
Example:
```
// Single left click
pos, err := mouse.Click(ctx, 100, 200, nil, nil)
// Right click
button := "right"
pos, err := mouse.Click(ctx, 100, 200, &button, nil)
// Double click
doubleClick := true
pos, err := mouse.Click(ctx, 100, 200, nil, &doubleClick)
```
Returns a map with the click "x" and "y" coordinates.
### func \(\*MouseService\) Drag
```go
func (m *MouseService) Drag(ctx context.Context, startX, startY, endX, endY int, button *string) (map[string]any, error)
```
Drag performs a mouse drag operation from start to end coordinates.
Parameters:
- startX, startY: Starting coordinates
- endX, endY: Ending coordinates
- button: Mouse button to use, nil for left button
Example:
```
// Drag from (100, 100) to (300, 300)
pos, err := mouse.Drag(ctx, 100, 100, 300, 300, nil)
```
Returns a map with the final "x" and "y" coordinates.
### func \(\*MouseService\) GetPosition
```go
func (m *MouseService) GetPosition(ctx context.Context) (map[string]any, error)
```
GetPosition returns the current cursor position.
Example:
```
pos, err := mouse.GetPosition(ctx)
if err != nil {
return err
}
fmt.Printf("Cursor at (%v, %v)\n", pos["x"], pos["y"])
```
Returns a map with "x" and "y" coordinates.
### func \(\*MouseService\) Move
```go
func (m *MouseService) Move(ctx context.Context, x, y int) (map[string]any, error)
```
Move moves the cursor to the specified coordinates.
Parameters:
- x: Target X coordinate
- y: Target Y coordinate
Example:
```
pos, err := mouse.Move(ctx, 500, 300)
```
Returns a map with the new "x" and "y" coordinates.
### func \(\*MouseService\) Scroll
```go
func (m *MouseService) Scroll(ctx context.Context, x, y int, direction string, amount *int) (bool, error)
```
Scroll performs a mouse scroll operation at the specified coordinates.
Parameters:
- x, y: Coordinates where the scroll occurs
- direction: Scroll direction \("up", "down", "left", "right"\)
- amount: Scroll amount, nil for default
Example:
```
// Scroll down at position (500, 400)
success, err := mouse.Scroll(ctx, 500, 400, "down", nil)
// Scroll up with specific amount
amount := 5
success, err := mouse.Scroll(ctx, 500, 400, "up", &amount)
```
Returns true if the scroll was successful.
## type OutputChannels
OutputChannels provides channels for streaming execution output.
All channels are closed when execution completes or encounters an error. The Done channel always receives exactly one message with the final result.
```go
type OutputChannels struct {
Stdout <-chan *types.OutputMessage // Receives stdout messages as they occur
Stderr <-chan *types.OutputMessage // Receives stderr messages as they occur
Errors <-chan *types.ExecutionError // Receives execution errors
Done <-chan *types.ExecutionResult // Receives final result when execution completes
}
```
## type PaginatedSandboxes
PaginatedSandboxes represents a paginated list of sandboxes.
```go
type PaginatedSandboxes struct {
Items []*Sandbox // Sandboxes in this page
Total int // Total number of sandboxes
Page int // Current page number
TotalPages int // Total number of pages
}
```
## type ProcessService
ProcessService provides process execution operations for a sandbox.
ProcessService enables command execution, session management, and PTY \(pseudo\-terminal\) operations. It supports both synchronous command execution and interactive terminal sessions. Access through \[Sandbox.Process\].
Example:
```
// Execute a command
result, err := sandbox.Process.ExecuteCommand(ctx, "echo 'Hello, World!'")
fmt.Println(result.Result)
// Execute with options
result, err := sandbox.Process.ExecuteCommand(ctx, "ls -la",
options.WithCwd("/home/user/project"),
options.WithExecuteTimeout(30*time.Second),
)
// Create an interactive PTY session
handle, err := sandbox.Process.CreatePty(ctx, "my-terminal")
defer handle.Disconnect()
```
```go
type ProcessService struct {
// contains filtered or unexported fields
}
```
### func NewProcessService
```go
func NewProcessService(toolboxClient *toolbox.APIClient, otel *otelState) *ProcessService
```
NewProcessService creates a new ProcessService with the provided toolbox client.
This is typically called internally by the SDK when creating a [Sandbox](https://www.daytona.io/docs/%3C.md#Sandbox%3E). Users should access ProcessService through \[Sandbox.Process\] rather than creating it directly.
### func \(\*ProcessService\) CodeRun
```go
func (p *ProcessService) CodeRun(ctx context.Context, code string, opts ...func(*options.CodeRun)) (*types.ExecuteResponse, error)
```
CodeRun executes code in a language\-specific way.
NOTE: This method is currently unavailable as the toolbox\-api\-client\-go does not expose a CodeRun endpoint. For code execution, use [ProcessService.ExecuteCommand](https://www.daytona.io/docs/%3C.md#ProcessService.ExecuteCommand%3E) or [CodeInterpreterService](https://www.daytona.io/docs/%3C.md#CodeInterpreterService%3E).
Optional parameters can be configured using functional options:
- \[options.WithCodeRunParams\]: Set code execution parameters
- \[options.WithCodeRunTimeout\]: Set execution timeout
### func \(\*ProcessService\) ConnectPty
```go
func (p *ProcessService) ConnectPty(ctx context.Context, sessionID string) (*PtyHandle, error)
```
ConnectPty establishes a WebSocket connection to an existing PTY session.
Returns a [PtyHandle](https://www.daytona.io/docs/%3C.md#PtyHandle%3E) for interacting with the terminal. The handle provides:
- DataChan\(\): Channel for receiving terminal output
- SendInput\(\): Method for sending keyboard input
- Resize\(\): Method for changing terminal size
- Disconnect\(\): Method for closing the connection
Parameters:
- sessionID: The PTY session to connect to
Example:
```
handle, err := sandbox.Process.ConnectPty(ctx, "my-terminal")
if err != nil {
return err
}
defer handle.Disconnect()
// Wait for connection
if err := handle.WaitForConnection(ctx); err != nil {
return err
}
// Read output
for data := range handle.DataChan() {
fmt.Print(string(data))
}
```
Returns a [PtyHandle](https://www.daytona.io/docs/%3C.md#PtyHandle%3E) for terminal interaction, or an error.
### func \(\*ProcessService\) CreatePty
```go
func (p *ProcessService) CreatePty(ctx context.Context, id string, opts ...func(*options.CreatePty)) (*PtyHandle, error)
```
CreatePty creates a new PTY session and immediately connects to it.
This is a convenience method that combines [ProcessService.CreatePtySession](https://www.daytona.io/docs/%3C.md#ProcessService.CreatePtySession%3E) and [ProcessService.ConnectPty](https://www.daytona.io/docs/%3C.md#ProcessService.ConnectPty%3E) into a single operation.
Parameters:
- id: Unique identifier for the PTY session
Optional parameters can be configured using functional options:
- \[options.WithCreatePtySize\]: Set terminal dimensions
- \[options.WithCreatePtyEnv\]: Set environment variables
Example:
```
handle, err := sandbox.Process.CreatePty(ctx, "interactive-shell",
options.WithCreatePtySize(types.PtySize{Rows: 24, Cols: 80}),
options.WithCreatePtyEnv(map[string]string{"TERM": "xterm-256color"}),
)
if err != nil {
return err
}
defer handle.Disconnect()
// Wait for connection
if err := handle.WaitForConnection(ctx); err != nil {
return err
}
// Send a command
handle.SendInput([]byte("ls -la\n"))
// Read output
for data := range handle.DataChan() {
fmt.Print(string(data))
}
```
Returns a [PtyHandle](https://www.daytona.io/docs/%3C.md#PtyHandle%3E) for terminal interaction, or an error.
### func \(\*ProcessService\) CreatePtySession
```go
func (p *ProcessService) CreatePtySession(ctx context.Context, id string, opts ...func(*options.PtySession)) (*types.PtySessionInfo, error)
```
CreatePtySession creates a PTY \(pseudo\-terminal\) session.
A PTY session provides a terminal interface for interactive applications. Use [ProcessService.ConnectPty](https://www.daytona.io/docs/%3C.md#ProcessService.ConnectPty%3E) to connect to the session after creation.
Parameters:
- id: Unique identifier for the session
Optional parameters can be configured using functional options:
- \[options.WithPtySize\]: Set terminal dimensions \(rows and columns\)
- \[options.WithPtyEnv\]: Set environment variables
Example:
```
// Create with default settings
session, err := sandbox.Process.CreatePtySession(ctx, "my-terminal")
// Create with custom size
session, err := sandbox.Process.CreatePtySession(ctx, "my-terminal",
options.WithPtySize(types.PtySize{Rows: 24, Cols: 80}),
)
```
Returns \[types.PtySessionInfo\] containing session details, or an error.
### func \(\*ProcessService\) CreateSession
```go
func (p *ProcessService) CreateSession(ctx context.Context, sessionID string) error
```
CreateSession creates a named session for executing multiple commands.
Sessions allow you to execute multiple commands while maintaining state \(like environment variables and working directory\) between commands.
Example:
```
// Create a session
err := sandbox.Process.CreateSession(ctx, "my-session")
if err != nil {
return err
}
defer sandbox.Process.DeleteSession(ctx, "my-session")
// Execute commands in the session
result, err := sandbox.Process.ExecuteSessionCommand(ctx, "my-session", "cd /home/user", false)
result, err = sandbox.Process.ExecuteSessionCommand(ctx, "my-session", "pwd", false)
```
Returns an error if session creation fails.
### func \(\*ProcessService\) DeleteSession
```go
func (p *ProcessService) DeleteSession(ctx context.Context, sessionID string) error
```
DeleteSession removes a session and releases its resources.
The sessionID parameter identifies the session to delete.
Example:
```
err := sandbox.Process.DeleteSession(ctx, "my-session")
```
Returns an error if the session doesn't exist or deletion fails.
### func \(\*ProcessService\) ExecuteCommand
```go
func (p *ProcessService) ExecuteCommand(ctx context.Context, command string, opts ...func(*options.ExecuteCommand)) (*types.ExecuteResponse, error)
```
ExecuteCommand executes a shell command and returns the result.
The command is executed in a shell context. For complex commands, consider using proper shell escaping or wrapping in a script.
Optional parameters can be configured using functional options:
- \[options.WithCwd\]: Set the working directory for command execution
- \[options.WithCommandEnv\]: Set environment variables
- \[options.WithExecuteTimeout\]: Set execution timeout
Example:
```
// Simple command
result, err := sandbox.Process.ExecuteCommand(ctx, "echo 'Hello'")
if err != nil {
return err
}
fmt.Println(result.Result)
// Command with options
result, err := sandbox.Process.ExecuteCommand(ctx, "npm install",
options.WithCwd("/home/user/project"),
options.WithExecuteTimeout(5*time.Minute),
)
// Check exit code
if result.ExitCode != 0 {
fmt.Printf("Command failed with exit code %d\n", result.ExitCode)
}
```
Returns \[types.ExecuteResponse\] containing the output and exit code, or an error.
### func \(\*ProcessService\) ExecuteSessionCommand
```go
func (p *ProcessService) ExecuteSessionCommand(ctx context.Context, sessionID, command string, runAsync bool, suppressInputEcho bool) (map[string]any, error)
```
ExecuteSessionCommand executes a command within a session.
Parameters:
- sessionID: The session to execute the command in
- command: The command to execute
- runAsync: If true, return immediately without waiting for completion
- suppressInputEcho: If true, suppress input echo
When runAsync is true, use [ProcessService.GetSessionCommand](https://www.daytona.io/docs/%3C.md#ProcessService.GetSessionCommand%3E) to check status and [ProcessService.GetSessionCommandLogs](https://www.daytona.io/docs/%3C.md#ProcessService.GetSessionCommandLogs%3E) to retrieve output.
Example:
```
// Synchronous execution
result, err := sandbox.Process.ExecuteSessionCommand(ctx, "my-session", "ls -la", false)
if err != nil {
return err
}
fmt.Println(result["stdout"])
// Asynchronous execution
result, err := sandbox.Process.ExecuteSessionCommand(ctx, "my-session", "long-running-cmd", true)
cmdID := result["id"].(string)
// Later: check status with GetSessionCommand(ctx, "my-session", cmdID)
```
Returns command result including id, exitCode \(if completed\), stdout, and stderr.
### func \(\*ProcessService\) GetEntrypointLogs
```go
func (p *ProcessService) GetEntrypointLogs(ctx context.Context) (string, error)
```
GetEntrypointLogs retrieves the output logs of the sandbox entrypoint.
Example:
```
logs, err := sandbox.Process.GetEntrypointLogs(ctx)
if err != nil {
return err
}
fmt.Println(logs)
```
Returns a string containing the entrypoint command output logs.
### func \(\*ProcessService\) GetEntrypointLogsStream
```go
func (p *ProcessService) GetEntrypointLogsStream(ctx context.Context, stdout, stderr chan<- string) error
```
GetEntrypointLogsStream streams entrypoint logs as they become available.
This method establishes a WebSocket connection to stream sandbox entrypoint logs in real\-time. The stdout and stderr channels receive log chunks as strings and are closed when the stream ends or an error occurs.
Parameters:
- stdout: Channel to receive stdout output
- stderr: Channel to receive stderr output
The caller should provide buffered channels to avoid blocking.
Example:
```
stdout := make(chan string, 100)
stderr := make(chan string, 100)
go func() {
err := sandbox.Process.GetEntrypointLogsStream(ctx, stdout, stderr)
if err != nil {
log.Printf("Stream error: %v", err)
}
}()
for {
select {
case chunk, ok := <-stdout:
if !ok {
stdout = nil
} else {
fmt.Print(chunk)
}
case chunk, ok := <-stderr:
if !ok {
stderr = nil
} else {
fmt.Fprint(os.Stderr, chunk)
}
}
if stdout == nil && stderr == nil {
break
}
}
```
Returns an error if the connection fails or stream encounters an error.
### func \(\*ProcessService\) GetEntrypointSession
```go
func (p *ProcessService) GetEntrypointSession(ctx context.Context) (*toolbox.Session, error)
```
GetEntrypointSession retrieves information about the entrypoint session.
Returns an entrypoint session information containing:
- SessionId: The entrypoint session identifier
- Commands: List of commands executed in the entrypoint session
Example:
```
info, err := sandbox.Process.GetEntrypointSession(ctx)
if err != nil {
return err
}
fmt.Printf("Session: %s\n", info.SessionId)
```
Returns an error if the session doesn't exist.
### func \(\*ProcessService\) GetPtySessionInfo
```go
func (p *ProcessService) GetPtySessionInfo(ctx context.Context, sessionID string) (*types.PtySessionInfo, error)
```
GetPtySessionInfo retrieves information about a PTY session.
Parameters:
- sessionID: The PTY session identifier
Example:
```
info, err := sandbox.Process.GetPtySessionInfo(ctx, "my-terminal")
if err != nil {
return err
}
fmt.Printf("Terminal size: %dx%d\n", info.Cols, info.Rows)
```
Returns \[types.PtySessionInfo\] with session details, or an error.
### func \(\*ProcessService\) GetSession
```go
func (p *ProcessService) GetSession(ctx context.Context, sessionID string) (map[string]any, error)
```
GetSession retrieves information about a session.
The sessionID parameter identifies the session to query.
Returns a map containing:
- sessionId: The session identifier
- commands: List of commands executed in the session
Example:
```
info, err := sandbox.Process.GetSession(ctx, "my-session")
if err != nil {
return err
}
fmt.Printf("Session: %s\n", info["sessionId"])
```
Returns an error if the session doesn't exist.
### func \(\*ProcessService\) GetSessionCommand
```go
func (p *ProcessService) GetSessionCommand(ctx context.Context, sessionID, commandID string) (map[string]any, error)
```
GetSessionCommand retrieves the status of a command in a session.
Parameters:
- sessionID: The session containing the command
- commandID: The command identifier \(from ExecuteSessionCommand result\)
Example:
```
status, err := sandbox.Process.GetSessionCommand(ctx, "my-session", cmdID)
if err != nil {
return err
}
if exitCode, ok := status["exitCode"]; ok {
fmt.Printf("Command completed with exit code: %v\n", exitCode)
} else {
fmt.Println("Command still running")
}
```
Returns command status including id, command text, and exitCode \(if completed\).
### func \(\*ProcessService\) GetSessionCommandLogs
```go
func (p *ProcessService) GetSessionCommandLogs(ctx context.Context, sessionID, commandID string) (map[string]any, error)
```
GetSessionCommandLogs retrieves the output logs of a command.
Parameters:
- sessionID: The session containing the command
- commandID: The command identifier
Example:
```
logs, err := sandbox.Process.GetSessionCommandLogs(ctx, "my-session", cmdID)
if err != nil {
return err
}
fmt.Println(logs["logs"])
```
Returns a map containing the "logs" key with command output.
### func \(\*ProcessService\) GetSessionCommandLogsStream
```go
func (p *ProcessService) GetSessionCommandLogsStream(ctx context.Context, sessionID, commandID string, stdout, stderr chan<- string) error
```
GetSessionCommandLogsStream streams command logs as they become available.
This method establishes a WebSocket connection to stream logs in real\-time. The stdout and stderr channels receive log chunks as strings and are closed when the stream ends or an error occurs.
Parameters:
- sessionID: The session containing the command
- commandID: The command identifier
- stdout: Channel to receive stdout output
- stderr: Channel to receive stderr output
The caller should provide buffered channels to avoid blocking.
Example:
```
stdout := make(chan string, 100)
stderr := make(chan string, 100)
go func() {
err := sandbox.Process.GetSessionCommandLogsStream(ctx, "session", "cmd", stdout, stderr)
if err != nil {
log.Printf("Stream error: %v", err)
}
}()
for {
select {
case chunk, ok := <-stdout:
if !ok {
stdout = nil
} else {
fmt.Print(chunk)
}
case chunk, ok := <-stderr:
if !ok {
stderr = nil
} else {
fmt.Fprint(os.Stderr, chunk)
}
}
if stdout == nil && stderr == nil {
break
}
}
```
Returns an error if the connection fails or stream encounters an error.
### func \(\*ProcessService\) KillPtySession
```go
func (p *ProcessService) KillPtySession(ctx context.Context, sessionID string) error
```
KillPtySession terminates a PTY session.
This ends the terminal session and any processes running in it.
Parameters:
- sessionID: The PTY session to terminate
Example:
```
err := sandbox.Process.KillPtySession(ctx, "my-terminal")
```
Returns an error if the session doesn't exist or termination fails.
### func \(\*ProcessService\) ListPtySessions
```go
func (p *ProcessService) ListPtySessions(ctx context.Context) ([]*types.PtySessionInfo, error)
```
ListPtySessions returns all active PTY sessions.
Example:
```
sessions, err := sandbox.Process.ListPtySessions(ctx)
if err != nil {
return err
}
for _, session := range sessions {
fmt.Printf("PTY: %s (%dx%d)\n", session.ID, session.Cols, session.Rows)
}
```
Returns a slice of \[types.PtySessionInfo\], or an error.
### func \(\*ProcessService\) ListSessions
```go
func (p *ProcessService) ListSessions(ctx context.Context) ([]map[string]any, error)
```
ListSessions returns all active sessions.
Example:
```
sessions, err := sandbox.Process.ListSessions(ctx)
if err != nil {
return err
}
for _, session := range sessions {
fmt.Printf("Session: %s\n", session["sessionId"])
}
```
Returns a slice of session information maps, or an error.
### func \(\*ProcessService\) ResizePtySession
```go
func (p *ProcessService) ResizePtySession(ctx context.Context, sessionID string, ptySize types.PtySize) (*types.PtySessionInfo, error)
```
ResizePtySession changes the terminal dimensions of a PTY session.
This sends a SIGWINCH signal to applications, notifying them of the size change.
Parameters:
- sessionID: The PTY session to resize
- ptySize: New terminal dimensions
Example:
```
newSize := types.PtySize{Rows: 40, Cols: 120}
info, err := sandbox.Process.ResizePtySession(ctx, "my-terminal", newSize)
if err != nil {
return err
}
fmt.Printf("New size: %dx%d\n", info.Cols, info.Rows)
```
Returns updated \[types.PtySessionInfo\], or an error.
## type PtyHandle
PtyHandle manages a WebSocket connection to a PTY \(pseudo\-terminal\) session.
PtyHandle provides methods for sending input, receiving output via channels, resizing the terminal, and managing the connection lifecycle. It implements [io.Reader](https://www.daytona.io/docs/%3Chttps:/pkg.go.dev/io.md#Reader%3E) and [io.Writer](https://www.daytona.io/docs/%3Chttps:/pkg.go.dev/io.md#Writer%3E) interfaces for integration with standard Go I/O.
Create a PtyHandle using [ProcessService.CreatePty](https://www.daytona.io/docs/%3C.md#ProcessService.CreatePty%3E).
Example:
```
// Create a PTY session
handle, err := sandbox.Process.CreatePty(ctx, "my-pty", nil)
if err != nil {
return err
}
defer handle.Disconnect()
// Wait for connection to be established
if err := handle.WaitForConnection(ctx); err != nil {
return err
}
// Send input
handle.SendInput([]byte("ls -la\n"))
// Read output from channel
for data := range handle.DataChan() {
fmt.Print(string(data))
}
// Or use as io.Reader
io.Copy(os.Stdout, handle)
```
```go
type PtyHandle struct {
// contains filtered or unexported fields
}
```
### func \(\*PtyHandle\) DataChan
```go
func (h *PtyHandle) DataChan() <-chan []byte
```
DataChan returns a channel for receiving PTY output.
The channel receives raw bytes from the terminal. It is closed when the PTY session ends or the connection is closed.
Example:
```
for data := range handle.DataChan() {
fmt.Print(string(data))
}
```
### func \(\*PtyHandle\) Disconnect
```go
func (h *PtyHandle) Disconnect() error
```
Disconnect closes the WebSocket connection and releases resources.
Call this when done with the PTY session. This does not terminate the underlying process \- use [PtyHandle.Kill](https://www.daytona.io/docs/%3C.md#PtyHandle.Kill%3E) for that.
Example:
```
defer handle.Disconnect()
```
Returns an error if the WebSocket close fails.
### func \(\*PtyHandle\) Error
```go
func (h *PtyHandle) Error() *string
```
Error returns the error message if the PTY session failed, or nil otherwise.
### func \(\*PtyHandle\) ExitCode
```go
func (h *PtyHandle) ExitCode() *int
```
ExitCode returns the exit code of the PTY process, or nil if still running.
### func \(\*PtyHandle\) IsConnected
```go
func (h *PtyHandle) IsConnected() bool
```
IsConnected returns true if the WebSocket connection is active.
### func \(\*PtyHandle\) Kill
```go
func (h *PtyHandle) Kill(ctx context.Context) error
```
Kill terminates the PTY session and its associated process.
This operation is irreversible. The process receives a SIGKILL signal and terminates immediately.
Example:
```
err := handle.Kill(ctx)
```
Returns an error if the kill operation fails.
### func \(\*PtyHandle\) Read
```go
func (h *PtyHandle) Read(p []byte) (n int, err error)
```
Read implements [io.Reader](https://www.daytona.io/docs/%3Chttps:/pkg.go.dev/io.md#Reader%3E) for reading PTY output.
This method blocks until data is available or the PTY closes \(returns [io.EOF](https://www.daytona.io/docs/%3Chttps:/pkg.go.dev/io.md#EOF%3E)\). Use with [io.Copy](https://www.daytona.io/docs/%3Chttps:/pkg.go.dev/io.md#Copy%3E), [bufio.Scanner](https://www.daytona.io/docs/%3Chttps:/pkg.go.dev/bufio.md#Scanner%3E), or any standard Go I/O utilities.
Example:
```
// Copy all output to stdout
io.Copy(os.Stdout, handle)
// Use with bufio.Scanner
scanner := bufio.NewScanner(handle)
for scanner.Scan() {
fmt.Println(scanner.Text())
}
```
### func \(\*PtyHandle\) Resize
```go
func (h *PtyHandle) Resize(ctx context.Context, cols, rows int) (*types.PtySessionInfo, error)
```
Resize changes the PTY terminal dimensions.
This notifies terminal applications about the new dimensions via SIGWINCH signal. Call this when the terminal display size changes.
Parameters:
- cols: Number of columns \(width in characters\)
- rows: Number of rows \(height in characters\)
Example:
```
info, err := handle.Resize(ctx, 120, 40)
```
Returns updated \[types.PtySessionInfo\] or an error.
### func \(\*PtyHandle\) SendInput
```go
func (h *PtyHandle) SendInput(data []byte) error
```
SendInput sends input data to the PTY session.
The data is sent as raw bytes and will be processed as if typed in the terminal. Use this to send commands, keystrokes, or any terminal input.
Example:
```
// Send a command
handle.SendInput([]byte("ls -la\n"))
// Send Ctrl+C
handle.SendInput([]byte{0x03})
```
Returns an error if the PTY is not connected or sending fails.
### func \(\*PtyHandle\) SessionID
```go
func (h *PtyHandle) SessionID() string
```
SessionID returns the unique identifier for this PTY session.
### func \(\*PtyHandle\) Wait
```go
func (h *PtyHandle) Wait(ctx context.Context) (*types.PtyResult, error)
```
Wait blocks until the PTY process exits and returns the result.
Example:
```
result, err := handle.Wait(ctx)
if err != nil {
return err
}
if result.ExitCode != nil {
fmt.Printf("Process exited with code: %d\n", *result.ExitCode)
}
```
Returns \[types.PtyResult\] with exit code and any error, or an error if the context is cancelled.
### func \(\*PtyHandle\) WaitForConnection
```go
func (h *PtyHandle) WaitForConnection(ctx context.Context) error
```
WaitForConnection waits for the WebSocket connection to be established.
This method blocks until the PTY session is ready to receive input and send output, or until a timeout \(10 seconds\) expires. Always call this after creating a PTY to ensure the connection is ready.
Example:
```
handle, _ := sandbox.Process.CreatePty(ctx, "my-pty", nil)
if err := handle.WaitForConnection(ctx); err != nil {
return fmt.Errorf("PTY connection failed: %w", err)
}
```
Returns an error if the connection times out or fails.
### func \(\*PtyHandle\) Write
```go
func (h *PtyHandle) Write(p []byte) (n int, err error)
```
Write implements [io.Writer](https://www.daytona.io/docs/%3Chttps:/pkg.go.dev/io.md#Writer%3E) for sending input to the PTY.
Example:
```
// Write directly
handle.Write([]byte("echo hello\n"))
// Use with io.Copy
io.Copy(handle, strings.NewReader("echo hello\n"))
```
## type PushAccessCredentials
PushAccessCredentials holds temporary credentials for uploading to object storage.
These credentials are obtained from the API and used for uploading build contexts when creating snapshots with custom [DockerImage](https://www.daytona.io/docs/%3C.md#DockerImage%3E) definitions.
```go
type PushAccessCredentials struct {
StorageURL string `json:"storageUrl"`
AccessKey string `json:"accessKey"`
Secret string `json:"secret"`
SessionToken string `json:"sessionToken"`
Bucket string `json:"bucket"`
OrganizationID string `json:"organizationId"`
}
```
## type RecordingService
RecordingService provides screen recording operations.
RecordingService enables starting, stopping, and managing screen recordings. Access through [ComputerUseService.Recording](https://www.daytona.io/docs/%3C.md#ComputerUseService.Recording%3E).
```go
type RecordingService struct {
// contains filtered or unexported fields
}
```
### func NewRecordingService
```go
func NewRecordingService(toolboxClient *toolbox.APIClient) *RecordingService
```
NewRecordingService creates a new RecordingService.
### func \(\*RecordingService\) Delete
```go
func (r *RecordingService) Delete(ctx context.Context, id string) error
```
Delete deletes a recording by ID.
Parameters:
- id: The ID of the recording to delete
Example:
```
err := cu.Recording().Delete(ctx, recordingID)
if err != nil {
return err
}
fmt.Println("Recording deleted")
```
Returns an error if the deletion fails.
### func \(\*RecordingService\) Download
```go
func (r *RecordingService) Download(ctx context.Context, id string, localPath string) error
```
Download downloads a recording file and saves it to a local path.
The file is streamed directly to disk without loading the entire content into memory.
Parameters:
- id: The ID of the recording to download
- localPath: Path to save the recording file locally
Example:
```
err := cu.Recording().Download(ctx, recordingID, "local_recording.mp4")
if err != nil {
return err
}
fmt.Println("Recording downloaded")
```
Returns an error if the download fails.
### func \(\*RecordingService\) Get
```go
func (r *RecordingService) Get(ctx context.Context, id string) (*toolbox.Recording, error)
```
Get gets details of a specific recording by ID.
Parameters:
- id: The ID of the recording to retrieve
Example:
```
recording, err := cu.Recording().Get(ctx, recordingID)
if err != nil {
return err
}
fmt.Printf("Recording: %s\n", recording.GetFileName())
fmt.Printf("Status: %s\n", recording.GetStatus())
fmt.Printf("Duration: %v seconds\n", recording.GetDurationSeconds())
```
Returns \[toolbox.Recording\] with recording details.
### func \(\*RecordingService\) List
```go
func (r *RecordingService) List(ctx context.Context) (*toolbox.ListRecordingsResponse, error)
```
List lists all recordings \(active and completed\).
Example:
```
recordings, err := cu.Recording().List(ctx)
if err != nil {
return err
}
fmt.Printf("Found %d recordings\n", len(recordings.GetRecordings()))
for _, rec := range recordings.GetRecordings() {
fmt.Printf("- %s: %s\n", rec.GetFileName(), rec.GetStatus())
}
```
Returns \[toolbox.ListRecordingsResponse\] with all recordings.
### func \(\*RecordingService\) Start
```go
func (r *RecordingService) Start(ctx context.Context, label *string) (*toolbox.Recording, error)
```
Start starts a new screen recording session.
Parameters:
- label: Optional custom label for the recording
Example:
```
// Start a recording with a label
recording, err := cu.Recording().Start(ctx, stringPtr("my-test-recording"))
if err != nil {
return err
}
fmt.Printf("Recording started: %s\n", recording.GetId())
fmt.Printf("File: %s\n", recording.GetFilePath())
```
Returns \[toolbox.Recording\] with recording details.
### func \(\*RecordingService\) Stop
```go
func (r *RecordingService) Stop(ctx context.Context, id string) (*toolbox.Recording, error)
```
Stop stops an active screen recording session.
Parameters:
- id: The ID of the recording to stop
Example:
```
result, err := cu.Recording().Stop(ctx, recordingID)
if err != nil {
return err
}
fmt.Printf("Recording stopped: %v seconds\n", result.GetDurationSeconds())
fmt.Printf("Saved to: %s\n", result.GetFilePath())
```
Returns \[toolbox.Recording\] with recording details.
## type Sandbox
Sandbox represents a Daytona sandbox environment.
A Sandbox provides an isolated development environment with file system, git, process execution, code interpretation, and desktop automation capabilities. Sandboxes can be started, stopped, archived, and deleted.
Access sandbox capabilities through the service fields:
- FileSystem: File and directory operations
- Git: Git repository operations
- Process: Command execution and PTY sessions
- CodeInterpreter: Python code execution
- ComputerUse: Desktop automation \(mouse, keyboard, screenshots\)
Example:
```
// Create and use a sandbox
sandbox, err := client.Create(ctx)
if err != nil {
return err
}
defer sandbox.Delete(ctx)
// Execute a command
result, err := sandbox.Process.ExecuteCommand(ctx, "echo 'Hello'")
// Work with files
err = sandbox.FileSystem.UploadFile(ctx, "local.txt", "/home/user/remote.txt")
```
```go
type Sandbox struct {
ID string // Unique sandbox identifier
Name string // Human-readable sandbox name
State apiclient.SandboxState // Current sandbox state
Target string // Target region/environment where the sandbox runs
ToolboxClient *toolbox.APIClient // Internal API client
// AutoArchiveInterval is the time in minutes after stopping before auto-archiving.
// Set to 0 to disable auto-archiving.
AutoArchiveInterval int
// AutoDeleteInterval is the time in minutes after stopping before auto-deletion.
// Set to -1 to disable auto-deletion.
// Set to 0 to delete immediately upon stopping.
AutoDeleteInterval int
// NetworkBlockAll blocks all network access when true.
NetworkBlockAll bool
// NetworkAllowList is a comma-separated list of allowed CIDR addresses.
NetworkAllowList *string
FileSystem *FileSystemService // File system operations
Git *GitService // Git operations
Process *ProcessService // Process and PTY operations
CodeInterpreter *CodeInterpreterService // Python code execution
ComputerUse *ComputerUseService // Desktop automation
// contains filtered or unexported fields
}
```
### func NewSandbox
```go
func NewSandbox(client *Client, toolboxClient *toolbox.APIClient, id string, name string, state apiclient.SandboxState, target string, autoArchiveInterval int, autoDeleteInterval int, networkBlockAll bool, networkAllowList *string) *Sandbox
```
NewSandbox creates a new Sandbox instance.
This is typically called internally by the SDK. Users should create sandboxes using [Client.Create](https://www.daytona.io/docs/%3C.md#Client.Create%3E) rather than calling this directly.
### func \(\*Sandbox\) Archive
```go
func (s *Sandbox) Archive(ctx context.Context) error
```
Archive archives the sandbox, preserving its state in cost\-effective storage.
When sandboxes are archived, the entire filesystem state is moved to object storage, making it possible to keep sandboxes available for extended periods at reduced cost. Use [Sandbox.Start](https://www.daytona.io/docs/%3C.md#Sandbox.Start%3E) to unarchive and resume.
Example:
```
err := sandbox.Archive(ctx)
if err != nil {
return err
}
// Sandbox is now archived and can be restored later
```
### func \(\*Sandbox\) Delete
```go
func (s *Sandbox) Delete(ctx context.Context) error
```
Delete deletes the sandbox with a default timeout of 60 seconds.
This operation is irreversible. All data in the sandbox will be lost. For custom timeout, use [Sandbox.DeleteWithTimeout](https://www.daytona.io/docs/%3C.md#Sandbox.DeleteWithTimeout%3E).
Example:
```
err := sandbox.Delete(ctx)
```
### func \(\*Sandbox\) DeleteWithTimeout
```go
func (s *Sandbox) DeleteWithTimeout(ctx context.Context, timeout time.Duration) error
```
DeleteWithTimeout deletes the sandbox with a custom timeout. 0 means no timeout.
Example:
```
err := sandbox.DeleteWithTimeout(ctx, 2*time.Minute)
```
### func \(\*Sandbox\) GetPreviewLink
```go
func (s *Sandbox) GetPreviewLink(ctx context.Context, port int) (*types.PreviewLink, error)
```
GetPreviewLink returns a preview link for accessing a port on the sandbox.
The returned PreviewLink contains both the URL and an authentication token. For private sandboxes, the token must be sent via the "x\-daytona\-preview\-token" request header.
Example:
```
preview, err := sandbox.GetPreviewLink(ctx, 3000)
if err != nil {
return err
}
fmt.Printf("URL: %s\nToken: %s\n", preview.URL, preview.Token)
```
### func \(\*Sandbox\) GetUserHomeDir
```go
func (s *Sandbox) GetUserHomeDir(ctx context.Context) (string, error)
```
GetUserHomeDir returns the user's home directory path in the sandbox.
Example:
```
homeDir, err := sandbox.GetUserHomeDir(ctx)
if err != nil {
return err
}
fmt.Printf("Home directory: %s\n", homeDir) // e.g., "/home/daytona"
```
### func \(\*Sandbox\) GetWorkingDir
```go
func (s *Sandbox) GetWorkingDir(ctx context.Context) (string, error)
```
GetWorkingDir returns the current working directory in the sandbox.
Example:
```
workDir, err := sandbox.GetWorkingDir(ctx)
if err != nil {
return err
}
fmt.Printf("Working directory: %s\n", workDir)
```
### func \(\*Sandbox\) RefreshData
```go
func (s *Sandbox) RefreshData(ctx context.Context) error
```
RefreshData refreshes the sandbox data from the API.
This updates the sandbox's State and other properties from the server. Useful for checking if the sandbox state has changed.
Example:
```
err := sandbox.RefreshData(ctx)
if err != nil {
return err
}
fmt.Printf("Current state: %s\n", sandbox.State)
```
### func \(\*Sandbox\) Resize
```go
func (s *Sandbox) Resize(ctx context.Context, resources *types.Resources) error
```
Resize resizes the sandbox resources with a default timeout of 60 seconds.
Changes the CPU, memory, or disk allocation for the sandbox. Resizing a started sandbox allows increasing CPU and memory. To resize disk or decrease resources, the sandbox must be stopped first.
Example:
```
// Resize a started sandbox (CPU and memory can be increased)
err := sandbox.Resize(ctx, &types.Resources{CPU: 4, Memory: 8})
// Resize a stopped sandbox (CPU, memory, and disk can be changed)
sandbox.Stop(ctx)
err := sandbox.Resize(ctx, &types.Resources{CPU: 2, Memory: 4, Disk: 30})
```
### func \(\*Sandbox\) ResizeWithTimeout
```go
func (s *Sandbox) ResizeWithTimeout(ctx context.Context, resources *types.Resources, timeout time.Duration) error
```
ResizeWithTimeout resizes the sandbox resources with a custom timeout.
Changes the CPU, memory, or disk allocation for the sandbox. Resizing a started sandbox allows increasing CPU and memory. To resize disk or decrease resources, the sandbox must be stopped first. 0 means no timeout.
Example:
```
err := sandbox.ResizeWithTimeout(ctx, &types.Resources{CPU: 4, Memory: 8}, 2*time.Minute)
```
### func \(\*Sandbox\) SetAutoArchiveInterval
```go
func (s *Sandbox) SetAutoArchiveInterval(ctx context.Context, intervalMinutes *int) error
```
SetAutoArchiveInterval sets the auto\-archive interval in minutes.
The sandbox will be automatically archived after being stopped for this many minutes. Set to 0 to disable auto\-archiving \(sandbox will never auto\-archive\).
Example:
```
// Archive after 30 minutes of being stopped
interval := 30
err := sandbox.SetAutoArchiveInterval(ctx, &interval)
// Disable auto-archiving
interval := 0
err := sandbox.SetAutoArchiveInterval(ctx, &interval)
```
### func \(\*Sandbox\) SetAutoDeleteInterval
```go
func (s *Sandbox) SetAutoDeleteInterval(ctx context.Context, intervalMinutes *int) error
```
SetAutoDeleteInterval sets the auto\-delete interval in minutes.
The sandbox will be automatically deleted after being stopped for this many minutes.
Special values:
- \-1: Disable auto\-deletion \(sandbox will never auto\-delete\)
- 0: Delete immediately upon stopping
Example:
```
// Delete after 60 minutes of being stopped
interval := 60
err := sandbox.SetAutoDeleteInterval(ctx, &interval)
// Delete immediately when stopped
interval := 0
err := sandbox.SetAutoDeleteInterval(ctx, &interval)
// Never auto-delete
interval := -1
err := sandbox.SetAutoDeleteInterval(ctx, &interval)
```
### func \(\*Sandbox\) SetLabels
```go
func (s *Sandbox) SetLabels(ctx context.Context, labels map[string]string) error
```
SetLabels sets custom labels on the sandbox.
Labels are key\-value pairs that can be used for organization and filtering. This replaces all existing labels.
Example:
```
err := sandbox.SetLabels(ctx, map[string]string{
"environment": "development",
"team": "backend",
"project": "api-server",
})
```
### func \(\*Sandbox\) Start
```go
func (s *Sandbox) Start(ctx context.Context) error
```
Start starts the sandbox with a default timeout of 60 seconds.
If the sandbox is already running, this is a no\-op. For custom timeout, use [Sandbox.StartWithTimeout](https://www.daytona.io/docs/%3C.md#Sandbox.StartWithTimeout%3E).
Example:
```
err := sandbox.Start(ctx)
if err != nil {
return err
}
// Sandbox is now running
```
### func \(\*Sandbox\) StartWithTimeout
```go
func (s *Sandbox) StartWithTimeout(ctx context.Context, timeout time.Duration) error
```
StartWithTimeout starts the sandbox with a custom timeout.
The method blocks until the sandbox reaches the "started" state or the timeout is exceeded. 0 means no timeout.
Example:
```
err := sandbox.StartWithTimeout(ctx, 2*time.Minute)
if err != nil {
return err
}
```
### func \(\*Sandbox\) Stop
```go
func (s *Sandbox) Stop(ctx context.Context) error
```
Stop stops the sandbox with a default timeout of 60 seconds.
Stopping a sandbox preserves its state. Use [Sandbox.Start](https://www.daytona.io/docs/%3C.md#Sandbox.Start%3E) to resume. For custom timeout, use [Sandbox.StopWithTimeout](https://www.daytona.io/docs/%3C.md#Sandbox.StopWithTimeout%3E).
Example:
```
err := sandbox.Stop(ctx)
```
### func \(\*Sandbox\) StopWithTimeout
```go
func (s *Sandbox) StopWithTimeout(ctx context.Context, timeout time.Duration) error
```
StopWithTimeout stops the sandbox with a custom timeout.
The method blocks until the sandbox reaches the "stopped" state or the timeout is exceeded. 0 means no timeout.
Example:
```
err := sandbox.StopWithTimeout(ctx, 2*time.Minute)
```
### func \(\*Sandbox\) WaitForResize
```go
func (s *Sandbox) WaitForResize(ctx context.Context, timeout time.Duration) error
```
WaitForResize waits for the sandbox resize operation to complete.
This method polls the sandbox state until it's no longer resizing, encounters an error state, or the timeout is exceeded. 0 means no timeout.
Example:
```
err := sandbox.WaitForResize(ctx, 2*time.Minute)
```
### func \(\*Sandbox\) WaitForStart
```go
func (s *Sandbox) WaitForStart(ctx context.Context, timeout time.Duration) error
```
WaitForStart waits for the sandbox to reach the "started" state.
This method polls the sandbox state until it's started, encounters an error state, or the timeout is exceeded. 0 means no timeout.
Example:
```
err := sandbox.WaitForStart(ctx, 2*time.Minute)
if err != nil {
return err
}
// Sandbox is now running
```
### func \(\*Sandbox\) WaitForStop
```go
func (s *Sandbox) WaitForStop(ctx context.Context, timeout time.Duration) error
```
WaitForStop waits for the sandbox to reach the "stopped" state.
This method polls the sandbox state until it's stopped or the timeout is exceeded. 0 means no timeout.
Example:
```
err := sandbox.WaitForStop(ctx, 2*time.Minute)
```
## type ScreenshotService
ScreenshotService provides screen capture operations.
ScreenshotService enables capturing full screen or region screenshots. Access through [ComputerUseService.Screenshot](https://www.daytona.io/docs/%3C.md#ComputerUseService.Screenshot%3E).
```go
type ScreenshotService struct {
// contains filtered or unexported fields
}
```
### func NewScreenshotService
```go
func NewScreenshotService(toolboxClient *toolbox.APIClient, otel *otelState) *ScreenshotService
```
NewScreenshotService creates a new ScreenshotService.
### func \(\*ScreenshotService\) TakeFullScreen
```go
func (s *ScreenshotService) TakeFullScreen(ctx context.Context, showCursor *bool) (*types.ScreenshotResponse, error)
```
TakeFullScreen captures a screenshot of the entire screen.
Parameters:
- showCursor: Whether to include the cursor in the screenshot, nil for default
Example:
```
// Capture full screen
screenshot, err := ss.TakeFullScreen(ctx, nil)
if err != nil {
return err
}
// screenshot.Image contains the base64-encoded image data
// Capture with cursor visible
showCursor := true
screenshot, err := ss.TakeFullScreen(ctx, &showCursor)
```
Returns \[types.ScreenshotResponse\] with the captured image.
### func \(\*ScreenshotService\) TakeRegion
```go
func (s *ScreenshotService) TakeRegion(ctx context.Context, region types.ScreenshotRegion, showCursor *bool) (*types.ScreenshotResponse, error)
```
TakeRegion captures a screenshot of a specific screen region.
Parameters:
- region: The region to capture \(X, Y, Width, Height\)
- showCursor: Whether to include the cursor in the screenshot, nil for default
Example:
```
// Capture a 200x100 region starting at (50, 50)
region := types.ScreenshotRegion{X: 50, Y: 50, Width: 200, Height: 100}
screenshot, err := ss.TakeRegion(ctx, region, nil)
if err != nil {
return err
}
```
Returns \[types.ScreenshotResponse\] with the captured image.
## type SnapshotService
SnapshotService provides snapshot \(image template\) management operations.
SnapshotService enables creating, managing, and deleting snapshots that serve as templates for sandboxes. Snapshots can be built from Docker images or custom [DockerImage](https://www.daytona.io/docs/%3C.md#DockerImage%3E) definitions with build contexts. Access through \[Client.Snapshots\].
Example:
```
// Create a snapshot from an existing image
snapshot, logChan, err := client.Snapshots.Create(ctx, &types.CreateSnapshotParams{
Name: "my-python-env",
Image: "python:3.11-slim",
})
if err != nil {
return err
}
// Stream build logs
for log := range logChan {
fmt.Println(log)
}
// Create a snapshot from a custom Image definition
image := daytona.Base("python:3.11-slim").
PipInstall([]string{"numpy", "pandas"}).
Workdir("/app")
snapshot, logChan, err := client.Snapshots.Create(ctx, &types.CreateSnapshotParams{
Name: "custom-python-env",
Image: image,
})
```
```go
type SnapshotService struct {
// contains filtered or unexported fields
}
```
### func NewSnapshotService
```go
func NewSnapshotService(client *Client) *SnapshotService
```
NewSnapshotService creates a new SnapshotService.
This is typically called internally by the SDK when creating a [Client](https://www.daytona.io/docs/%3C.md#Client%3E). Users should access SnapshotService through \[Client.Snapshots\] rather than creating it directly.
### func \(\*SnapshotService\) Create
```go
func (s *SnapshotService) Create(ctx context.Context, params *types.CreateSnapshotParams) (*types.Snapshot, <-chan string, error)
```
Create builds a new snapshot from an image and streams build logs.
The image parameter can be either a Docker image reference string \(e.g., "python:3.11"\) or an [DockerImage](https://www.daytona.io/docs/%3C.md#DockerImage%3E) builder object for custom Dockerfile definitions.
Parameters:
- params: Snapshot creation parameters including name, image, resources, and entrypoint
Example:
```
// Create from Docker Hub image
snapshot, logChan, err := client.Snapshots.Create(ctx, &types.CreateSnapshotParams{
Name: "my-env",
Image: "python:3.11-slim",
})
if err != nil {
return err
}
// Stream build logs
for log := range logChan {
fmt.Println(log)
}
// Create with custom image and resources
image := daytona.Base("python:3.11").PipInstall([]string{"numpy"})
snapshot, logChan, err := client.Snapshots.Create(ctx, &types.CreateSnapshotParams{
Name: "custom-env",
Image: image,
Resources: &types.Resources{CPU: 2, Memory: 4096},
})
```
Returns the created \[types.Snapshot\], a channel for streaming build logs, or an error. The log channel is closed when the build completes or fails.
### func \(\*SnapshotService\) Delete
```go
func (s *SnapshotService) Delete(ctx context.Context, snapshot *types.Snapshot) error
```
Delete permanently removes a snapshot.
Sandboxes created from this snapshot will continue to work, but no new sandboxes can be created from it after deletion.
Parameters:
- snapshot: The snapshot to delete
Example:
```
err := client.Snapshots.Delete(ctx, snapshot)
if err != nil {
return err
}
```
Returns an error if deletion fails.
### func \(\*SnapshotService\) Get
```go
func (s *SnapshotService) Get(ctx context.Context, nameOrID string) (*types.Snapshot, error)
```
Get retrieves a snapshot by name or ID.
Parameters:
- nameOrID: The snapshot name or unique ID
Example:
```
snapshot, err := client.Snapshots.Get(ctx, "my-python-env")
if err != nil {
return err
}
fmt.Printf("Snapshot %s: %s\n", snapshot.Name, snapshot.State)
```
Returns the \[types.Snapshot\] or an error if not found.
### func \(\*SnapshotService\) List
```go
func (s *SnapshotService) List(ctx context.Context, page *int, limit *int) (*types.PaginatedSnapshots, error)
```
List returns snapshots with optional pagination.
Parameters:
- page: Page number \(1\-indexed\), nil for first page
- limit: Maximum snapshots per page, nil for default
Example:
```
// List first page with default limit
result, err := client.Snapshots.List(ctx, nil, nil)
if err != nil {
return err
}
// List with pagination
page, limit := 2, 10
result, err := client.Snapshots.List(ctx, &page, &limit)
fmt.Printf("Page %d of %d, total: %d\n", result.Page, result.TotalPages, result.Total)
```
Returns \[types.PaginatedSnapshots\] containing the snapshots and pagination info.
## type VolumeService
VolumeService provides persistent storage volume management operations.
VolumeService enables creating, managing, and deleting persistent storage volumes that can be attached to sandboxes. Volumes persist data independently of sandbox lifecycle and can be shared between sandboxes. Access through \[Client.Volumes\].
Example:
```
// Create a new volume
volume, err := client.Volumes.Create(ctx, "my-data-volume")
if err != nil {
return err
}
// Wait for volume to be ready
volume, err = client.Volumes.WaitForReady(ctx, volume, 60*time.Second)
if err != nil {
return err
}
// List all volumes
volumes, err := client.Volumes.List(ctx)
```
```go
type VolumeService struct {
// contains filtered or unexported fields
}
```
### func NewVolumeService
```go
func NewVolumeService(client *Client) *VolumeService
```
NewVolumeService creates a new VolumeService.
This is typically called internally by the SDK when creating a [Client](https://www.daytona.io/docs/%3C.md#Client%3E). Users should access VolumeService through \[Client.Volumes\] rather than creating it directly.
### func \(\*VolumeService\) Create
```go
func (v *VolumeService) Create(ctx context.Context, name string) (*types.Volume, error)
```
Create creates a new persistent storage volume.
The volume starts in "pending" state and transitions to "ready" when available. Use [VolumeService.WaitForReady](https://www.daytona.io/docs/%3C.md#VolumeService.WaitForReady%3E) to wait for the volume to become ready.
Parameters:
- name: Unique name for the volume
Example:
```
volume, err := client.Volumes.Create(ctx, "my-data-volume")
if err != nil {
return err
}
// Wait for volume to be ready
volume, err = client.Volumes.WaitForReady(ctx, volume, 60*time.Second)
```
Returns the created \[types.Volume\] or an error.
### func \(\*VolumeService\) Delete
```go
func (v *VolumeService) Delete(ctx context.Context, volume *types.Volume) error
```
Delete permanently removes a volume and all its data.
This operation is irreversible. Ensure no sandboxes are using the volume before deletion.
Parameters:
- volume: The volume to delete
Example:
```
err := client.Volumes.Delete(ctx, volume)
if err != nil {
return err
}
```
Returns an error if deletion fails.
### func \(\*VolumeService\) Get
```go
func (v *VolumeService) Get(ctx context.Context, name string) (*types.Volume, error)
```
Get retrieves a volume by its name.
Parameters:
- name: The volume name
Example:
```
volume, err := client.Volumes.Get(ctx, "my-data-volume")
if err != nil {
return err
}
fmt.Printf("Volume state: %s\n", volume.State)
```
Returns the \[types.Volume\] or an error if not found.
### func \(\*VolumeService\) List
```go
func (v *VolumeService) List(ctx context.Context) ([]*types.Volume, error)
```
List returns all volumes in the organization.
Example:
```
volumes, err := client.Volumes.List(ctx)
if err != nil {
return err
}
for _, vol := range volumes {
fmt.Printf("Volume %s: %s\n", vol.Name, vol.State)
}
```
Returns a slice of \[types.Volume\] or an error if the request fails.
### func \(\*VolumeService\) WaitForReady
```go
func (v *VolumeService) WaitForReady(ctx context.Context, volume *types.Volume, timeout time.Duration) (*types.Volume, error)
```
WaitForReady waits for a volume to reach the "ready" state.
This method polls the volume status until it becomes ready, reaches an error state, or the timeout expires. The polling interval is 1 second.
Parameters:
- volume: The volume to wait for
- timeout: Maximum time to wait for the volume to become ready
Example:
```
volume, err := client.Volumes.Create(ctx, "my-volume")
if err != nil {
return err
}
// Wait up to 2 minutes for the volume to be ready
volume, err = client.Volumes.WaitForReady(ctx, volume, 2*time.Minute)
if err != nil {
return fmt.Errorf("volume failed to become ready: %w", err)
}
```
Returns the updated \[types.Volume\] when ready, or an error if the timeout expires or the volume enters an error state.
{/* Code generated by gomarkdoc. DO NOT EDIT */}
# errors
```go
import "github.com/daytonaio/daytona/libs/sdk-go/pkg/errors"
```
## Index
- [func ConvertAPIError\(err error, httpResp \*http.Response\) error](https://www.daytona.io/docs/%3C.md#ConvertAPIError%3E)
- [func ConvertToolboxError\(err error, httpResp \*http.Response\) error](https://www.daytona.io/docs/%3C.md#ConvertToolboxError%3E)
- [type DaytonaError](https://www.daytona.io/docs/%3C.md#DaytonaError%3E)
- [func NewDaytonaError\(message string, statusCode int, headers http.Header\) \*DaytonaError](https://www.daytona.io/docs/%3C.md#NewDaytonaError%3E)
- [func \(e \*DaytonaError\) Error\(\) string](https://www.daytona.io/docs/%3C.md#DaytonaError.Error%3E)
- [type DaytonaNotFoundError](https://www.daytona.io/docs/%3C.md#DaytonaNotFoundError%3E)
- [func NewDaytonaNotFoundError\(message string, headers http.Header\) \*DaytonaNotFoundError](https://www.daytona.io/docs/%3C.md#NewDaytonaNotFoundError%3E)
- [func \(e \*DaytonaNotFoundError\) Error\(\) string](https://www.daytona.io/docs/%3C.md#DaytonaNotFoundError.Error%3E)
- [type DaytonaRateLimitError](https://www.daytona.io/docs/%3C.md#DaytonaRateLimitError%3E)
- [func NewDaytonaRateLimitError\(message string, headers http.Header\) \*DaytonaRateLimitError](https://www.daytona.io/docs/%3C.md#NewDaytonaRateLimitError%3E)
- [func \(e \*DaytonaRateLimitError\) Error\(\) string](https://www.daytona.io/docs/%3C.md#DaytonaRateLimitError.Error%3E)
- [type DaytonaTimeoutError](https://www.daytona.io/docs/%3C.md#DaytonaTimeoutError%3E)
- [func NewDaytonaTimeoutError\(message string\) \*DaytonaTimeoutError](https://www.daytona.io/docs/%3C.md#NewDaytonaTimeoutError%3E)
- [func \(e \*DaytonaTimeoutError\) Error\(\) string](https://www.daytona.io/docs/%3C.md#DaytonaTimeoutError.Error%3E)
## func ConvertAPIError
```go
func ConvertAPIError(err error, httpResp *http.Response) error
```
ConvertAPIError converts api\-client\-go errors to SDK error types
## func ConvertToolboxError
```go
func ConvertToolboxError(err error, httpResp *http.Response) error
```
ConvertToolboxError converts toolbox\-api\-client\-go errors to SDK error types
## type DaytonaError
DaytonaError is the base error type for all Daytona SDK errors
```go
type DaytonaError struct {
Message string
StatusCode int
Headers http.Header
}
```
### func NewDaytonaError
```go
func NewDaytonaError(message string, statusCode int, headers http.Header) *DaytonaError
```
NewDaytonaError creates a new DaytonaError
### func \(\*DaytonaError\) Error
```go
func (e *DaytonaError) Error() string
```
## type DaytonaNotFoundError
DaytonaNotFoundError represents a resource not found error \(404\)
```go
type DaytonaNotFoundError struct {
*DaytonaError
}
```
### func NewDaytonaNotFoundError
```go
func NewDaytonaNotFoundError(message string, headers http.Header) *DaytonaNotFoundError
```
NewDaytonaNotFoundError creates a new DaytonaNotFoundError
### func \(\*DaytonaNotFoundError\) Error
```go
func (e *DaytonaNotFoundError) Error() string
```
## type DaytonaRateLimitError
DaytonaRateLimitError represents a rate limit error \(429\)
```go
type DaytonaRateLimitError struct {
*DaytonaError
}
```
### func NewDaytonaRateLimitError
```go
func NewDaytonaRateLimitError(message string, headers http.Header) *DaytonaRateLimitError
```
NewDaytonaRateLimitError creates a new DaytonaRateLimitError
### func \(\*DaytonaRateLimitError\) Error
```go
func (e *DaytonaRateLimitError) Error() string
```
## type DaytonaTimeoutError
DaytonaTimeoutError represents a timeout error
```go
type DaytonaTimeoutError struct {
*DaytonaError
}
```
### func NewDaytonaTimeoutError
```go
func NewDaytonaTimeoutError(message string) *DaytonaTimeoutError
```
NewDaytonaTimeoutError creates a new DaytonaTimeoutError
### func \(\*DaytonaTimeoutError\) Error
```go
func (e *DaytonaTimeoutError) Error() string
```
The Daytona Go SDK provides a powerful interface for programmatically interacting with Daytona Sandboxes.
## Installation
Install the Daytona Go SDK using go get:
```bash
go get github.com/daytonaio/daytona/libs/sdk-go
```
## Getting Started
### Create a Sandbox
Create a Daytona Sandbox to run your code securely in an isolated environment. The following snippet is an example "Hello World" program that runs securely inside a Daytona Sandbox.
```go
package main
import (
"context"
"fmt"
"log"
"github.com/daytonaio/daytona/libs/sdk-go/pkg/daytona"
)
func main() {
// Initialize the SDK (uses environment variables by default)
client, err := daytona.NewClient()
if err != nil {
log.Fatal(err)
}
// Create a new sandbox
sandbox, err := client.Create(context.Background(), nil)
if err != nil {
log.Fatal(err)
}
// Execute a command
response, err := sandbox.Process.ExecuteCommand(context.Background(), "echo 'Hello, World!'")
if err != nil {
log.Fatal(err)
}
fmt.Println(response.Result)
}
```
## Configuration
The Daytona SDK can be configured using environment variables or by passing options to the constructor:
```go
package main
import (
"github.com/daytonaio/daytona/libs/sdk-go/pkg/daytona"
"github.com/daytonaio/daytona/libs/sdk-go/pkg/types"
)
func main() {
// Using environment variables (DAYTONA_API_KEY, DAYTONA_API_URL, DAYTONA_TARGET)
client, _ := daytona.NewClient()
// Using explicit configuration
config := &types.DaytonaConfig{
APIKey: "YOUR_API_KEY",
APIUrl: "https://app.daytona.io/api",
Target: "us",
}
client, _ = daytona.NewClientWithConfig(config)
}
```
For more information on configuring the Daytona SDK, see [configuration](https://www.daytona.io/docs/en/configuration.md).
{/* Code generated by gomarkdoc. DO NOT EDIT */}
# options
```go
import "github.com/daytonaio/daytona/libs/sdk-go/pkg/options"
```
Package options provides functional option types for configuring SDK operations.
This package uses the functional options pattern to provide a clean, extensible API for configuring optional parameters. Each option function returns a closure that modifies the corresponding options struct.
### Usage
Options are passed as variadic arguments to SDK methods:
```
err := sandbox.Git.Clone(ctx, url, path,
options.WithBranch("develop"),
options.WithUsername("user"),
options.WithPassword("token"),
)
```
### Generic Apply Function
The [Apply](https://www.daytona.io/docs/%3C.md#Apply%3E) function creates a new options struct and applies all provided option functions to it:
```
opts := options.Apply(
options.WithBranch("main"),
options.WithUsername("user"),
)
// opts.Branch == "main", opts.Username == "user"
```
## Index
- [func Apply\[T any\]\(opts ...func\(\*T\)\) \*T](<#Apply>)
- [func WithAllowEmpty\(allowEmpty bool\) func\(\*GitCommit\)](https://www.daytona.io/docs/%3C.md#WithAllowEmpty%3E)
- [func WithBranch\(branch string\) func\(\*GitClone\)](https://www.daytona.io/docs/%3C.md#WithBranch%3E)
- [func WithCodeRunParams\(params types.CodeRunParams\) func\(\*CodeRun\)](https://www.daytona.io/docs/%3C.md#WithCodeRunParams%3E)
- [func WithCodeRunTimeout\(timeout time.Duration\) func\(\*CodeRun\)](https://www.daytona.io/docs/%3C.md#WithCodeRunTimeout%3E)
- [func WithCommandEnv\(env map\[string\]string\) func\(\*ExecuteCommand\)](<#WithCommandEnv>)
- [func WithCommitId\(commitID string\) func\(\*GitClone\)](https://www.daytona.io/docs/%3C.md#WithCommitId%3E)
- [func WithCreatePtyEnv\(env map\[string\]string\) func\(\*CreatePty\)](<#WithCreatePtyEnv>)
- [func WithCreatePtySize\(ptySize types.PtySize\) func\(\*CreatePty\)](https://www.daytona.io/docs/%3C.md#WithCreatePtySize%3E)
- [func WithCustomContext\(contextID string\) func\(\*RunCode\)](https://www.daytona.io/docs/%3C.md#WithCustomContext%3E)
- [func WithCwd\(cwd string\) func\(\*ExecuteCommand\)](https://www.daytona.io/docs/%3C.md#WithCwd%3E)
- [func WithEnv\(env map\[string\]string\) func\(\*RunCode\)](<#WithEnv>)
- [func WithExecuteTimeout\(timeout time.Duration\) func\(\*ExecuteCommand\)](https://www.daytona.io/docs/%3C.md#WithExecuteTimeout%3E)
- [func WithExtraIndexURLs\(urls ...string\) func\(\*PipInstall\)](https://www.daytona.io/docs/%3C.md#WithExtraIndexURLs%3E)
- [func WithExtraOptions\(options string\) func\(\*PipInstall\)](https://www.daytona.io/docs/%3C.md#WithExtraOptions%3E)
- [func WithFindLinks\(links ...string\) func\(\*PipInstall\)](https://www.daytona.io/docs/%3C.md#WithFindLinks%3E)
- [func WithForce\(force bool\) func\(\*GitDeleteBranch\)](https://www.daytona.io/docs/%3C.md#WithForce%3E)
- [func WithGroup\(group string\) func\(\*SetFilePermissions\)](https://www.daytona.io/docs/%3C.md#WithGroup%3E)
- [func WithIndexURL\(url string\) func\(\*PipInstall\)](https://www.daytona.io/docs/%3C.md#WithIndexURL%3E)
- [func WithInterpreterTimeout\(timeout time.Duration\) func\(\*RunCode\)](https://www.daytona.io/docs/%3C.md#WithInterpreterTimeout%3E)
- [func WithLogChannel\(logChannel chan string\) func\(\*CreateSandbox\)](https://www.daytona.io/docs/%3C.md#WithLogChannel%3E)
- [func WithMode\(mode string\) func\(\*CreateFolder\)](https://www.daytona.io/docs/%3C.md#WithMode%3E)
- [func WithOwner\(owner string\) func\(\*SetFilePermissions\)](https://www.daytona.io/docs/%3C.md#WithOwner%3E)
- [func WithPassword\(password string\) func\(\*GitClone\)](https://www.daytona.io/docs/%3C.md#WithPassword%3E)
- [func WithPermissionMode\(mode string\) func\(\*SetFilePermissions\)](https://www.daytona.io/docs/%3C.md#WithPermissionMode%3E)
- [func WithPre\(\) func\(\*PipInstall\)](https://www.daytona.io/docs/%3C.md#WithPre%3E)
- [func WithPtyEnv\(env map\[string\]string\) func\(\*PtySession\)](<#WithPtyEnv>)
- [func WithPtySize\(size types.PtySize\) func\(\*PtySession\)](https://www.daytona.io/docs/%3C.md#WithPtySize%3E)
- [func WithPullPassword\(password string\) func\(\*GitPull\)](https://www.daytona.io/docs/%3C.md#WithPullPassword%3E)
- [func WithPullUsername\(username string\) func\(\*GitPull\)](https://www.daytona.io/docs/%3C.md#WithPullUsername%3E)
- [func WithPushPassword\(password string\) func\(\*GitPush\)](https://www.daytona.io/docs/%3C.md#WithPushPassword%3E)
- [func WithPushUsername\(username string\) func\(\*GitPush\)](https://www.daytona.io/docs/%3C.md#WithPushUsername%3E)
- [func WithTimeout\(timeout time.Duration\) func\(\*CreateSandbox\)](https://www.daytona.io/docs/%3C.md#WithTimeout%3E)
- [func WithUsername\(username string\) func\(\*GitClone\)](https://www.daytona.io/docs/%3C.md#WithUsername%3E)
- [func WithWaitForStart\(waitForStart bool\) func\(\*CreateSandbox\)](https://www.daytona.io/docs/%3C.md#WithWaitForStart%3E)
- [type CodeRun](https://www.daytona.io/docs/%3C.md#CodeRun%3E)
- [type CreateFolder](https://www.daytona.io/docs/%3C.md#CreateFolder%3E)
- [type CreatePty](https://www.daytona.io/docs/%3C.md#CreatePty%3E)
- [type CreateSandbox](https://www.daytona.io/docs/%3C.md#CreateSandbox%3E)
- [type ExecuteCommand](https://www.daytona.io/docs/%3C.md#ExecuteCommand%3E)
- [type GitClone](https://www.daytona.io/docs/%3C.md#GitClone%3E)
- [type GitCommit](https://www.daytona.io/docs/%3C.md#GitCommit%3E)
- [type GitDeleteBranch](https://www.daytona.io/docs/%3C.md#GitDeleteBranch%3E)
- [type GitPull](https://www.daytona.io/docs/%3C.md#GitPull%3E)
- [type GitPush](https://www.daytona.io/docs/%3C.md#GitPush%3E)
- [type PipInstall](https://www.daytona.io/docs/%3C.md#PipInstall%3E)
- [type PtySession](https://www.daytona.io/docs/%3C.md#PtySession%3E)
- [type RunCode](https://www.daytona.io/docs/%3C.md#RunCode%3E)
- [type SetFilePermissions](https://www.daytona.io/docs/%3C.md#SetFilePermissions%3E)
## func Apply
```go
func Apply[T any](https://www.daytona.io/docs/opts%20...func(*T.md)) *T
```
Apply creates a new instance of type T and applies all provided option functions.
This generic function enables a consistent pattern for applying functional options across different option types. It allocates a zero\-value instance of T, then applies each option function in order.
Example:
```
opts := options.Apply(
options.WithBranch("main"),
options.WithUsername("user"),
)
```
## func WithAllowEmpty
```go
func WithAllowEmpty(allowEmpty bool) func(*GitCommit)
```
WithAllowEmpty allows creating a commit even when there are no staged changes.
This is useful for triggering CI/CD pipelines or marking points in history without actual code changes.
Example:
```
resp, err := sandbox.Git.Commit(ctx, path, "Trigger rebuild", author, email,
options.WithAllowEmpty(true),
)
```
## func WithBranch
```go
func WithBranch(branch string) func(*GitClone)
```
WithBranch sets the branch to clone instead of the repository's default branch.
Example:
```
err := sandbox.Git.Clone(ctx, url, path, options.WithBranch("develop"))
```
## func WithCodeRunParams
```go
func WithCodeRunParams(params types.CodeRunParams) func(*CodeRun)
```
WithCodeRunParams sets the code execution parameters.
Example:
```
result, err := sandbox.Process.CodeRun(ctx, code,
options.WithCodeRunParams(types.CodeRunParams{Language: "python"}),
)
```
## func WithCodeRunTimeout
```go
func WithCodeRunTimeout(timeout time.Duration) func(*CodeRun)
```
WithCodeRunTimeout sets the timeout for code execution.
Example:
```
result, err := sandbox.Process.CodeRun(ctx, code,
options.WithCodeRunTimeout(30*time.Second),
)
```
## func WithCommandEnv
```go
func WithCommandEnv(env map[string]string) func(*ExecuteCommand)
```
WithCommandEnv sets environment variables for the command.
These variables are added to the command's environment in addition to the sandbox's default environment.
Example:
```
result, err := sandbox.Process.ExecuteCommand(ctx, "echo $MY_VAR",
options.WithCommandEnv(map[string]string{"MY_VAR": "hello"}),
)
```
## func WithCommitId
```go
func WithCommitId(commitID string) func(*GitClone)
```
WithCommitId sets a specific commit SHA to checkout after cloning.
The repository is first cloned, then the specified commit is checked out, resulting in a detached HEAD state.
Example:
```
err := sandbox.Git.Clone(ctx, url, path, options.WithCommitId("abc123def"))
```
## func WithCreatePtyEnv
```go
func WithCreatePtyEnv(env map[string]string) func(*CreatePty)
```
WithCreatePtyEnv sets environment variables for CreatePty.
Example:
```
handle, err := sandbox.Process.CreatePty(ctx, "my-pty",
options.WithCreatePtyEnv(map[string]string{"TERM": "xterm-256color"}),
)
```
## func WithCreatePtySize
```go
func WithCreatePtySize(ptySize types.PtySize) func(*CreatePty)
```
WithCreatePtySize sets the PTY terminal dimensions for CreatePty.
Example:
```
handle, err := sandbox.Process.CreatePty(ctx, "my-pty",
options.WithCreatePtySize(types.PtySize{Rows: 24, Cols: 80}),
)
```
## func WithCustomContext
```go
func WithCustomContext(contextID string) func(*RunCode)
```
WithCustomContext sets the interpreter context ID for code execution.
Using a context allows you to maintain state \(variables, imports, etc.\) across multiple code executions. Create a context with CreateContext first.
Example:
```
ctx, _ := sandbox.CodeInterpreter.CreateContext(ctx, nil)
channels, err := sandbox.CodeInterpreter.RunCode(ctx, "x = 42",
options.WithCustomContext(ctx["id"].(string)),
)
```
## func WithCwd
```go
func WithCwd(cwd string) func(*ExecuteCommand)
```
WithCwd sets the working directory for command execution.
Example:
```
result, err := sandbox.Process.ExecuteCommand(ctx, "ls -la",
options.WithCwd("/home/user/project"),
)
```
## func WithEnv
```go
func WithEnv(env map[string]string) func(*RunCode)
```
WithEnv sets environment variables for code execution.
These variables are available to the code during execution.
Example:
```
channels, err := sandbox.CodeInterpreter.RunCode(ctx, "import os; print(os.environ['API_KEY'])",
options.WithEnv(map[string]string{"API_KEY": "secret"}),
)
```
## func WithExecuteTimeout
```go
func WithExecuteTimeout(timeout time.Duration) func(*ExecuteCommand)
```
WithExecuteTimeout sets the timeout for command execution.
If the command doesn't complete within the timeout, it will be terminated.
Example:
```
result, err := sandbox.Process.ExecuteCommand(ctx, "sleep 60",
options.WithExecuteTimeout(5*time.Second),
)
```
## func WithExtraIndexURLs
```go
func WithExtraIndexURLs(urls ...string) func(*PipInstall)
```
WithExtraIndexURLs adds extra index URLs for pip install.
Extra indexes are checked in addition to the main index URL. Useful for installing packages from both PyPI and a private index.
Example:
```
image := daytona.Base("python:3.11").PipInstall(
[]string{"mypackage"},
options.WithExtraIndexURLs("https://private.example.com/simple/"),
)
```
## func WithExtraOptions
```go
func WithExtraOptions(options string) func(*PipInstall)
```
WithExtraOptions adds extra command\-line options for pip install.
Use this for pip options not covered by other With\* functions.
Example:
```
image := daytona.Base("python:3.11").PipInstall(
[]string{"mypackage"},
options.WithExtraOptions("--no-cache-dir --upgrade"),
)
```
## func WithFindLinks
```go
func WithFindLinks(links ...string) func(*PipInstall)
```
WithFindLinks adds find\-links URLs for pip install.
Find\-links URLs are searched for packages before the package index. Useful for installing packages from local directories or custom URLs.
Example:
```
image := daytona.Base("python:3.11").PipInstall(
[]string{"mypackage"},
options.WithFindLinks("/path/to/wheels", "https://example.com/wheels/"),
)
```
## func WithForce
```go
func WithForce(force bool) func(*GitDeleteBranch)
```
WithForce enables force deletion of a branch even if it's not fully merged.
Use with caution as this can result in lost commits if the branch contains work that hasn't been merged elsewhere.
Example:
```
err := sandbox.Git.DeleteBranch(ctx, path, "feature/abandoned",
options.WithForce(true),
)
```
## func WithGroup
```go
func WithGroup(group string) func(*SetFilePermissions)
```
WithGroup sets the file group.
The group should be a valid group name on the sandbox system.
Example:
```
err := sandbox.FileSystem.SetFilePermissions(ctx, "/home/user/file.txt",
options.WithGroup("users"),
)
```
## func WithIndexURL
```go
func WithIndexURL(url string) func(*PipInstall)
```
WithIndexURL sets the base URL of the Python Package Index.
Replaces the default PyPI \(https://pypi.org/simple\) with a custom index.
Example:
```
image := daytona.Base("python:3.11").PipInstall(
[]string{"mypackage"},
options.WithIndexURL("https://my-pypi.example.com/simple/"),
)
```
## func WithInterpreterTimeout
```go
func WithInterpreterTimeout(timeout time.Duration) func(*RunCode)
```
WithInterpreterTimeout sets the execution timeout for code.
If the code doesn't complete within the timeout, execution is terminated.
Example:
```
channels, err := sandbox.CodeInterpreter.RunCode(ctx, "import time; time.sleep(60)",
options.WithInterpreterTimeout(5*time.Second),
)
```
## func WithLogChannel
```go
func WithLogChannel(logChannel chan string) func(*CreateSandbox)
```
WithLogChannel provides a channel for receiving build logs during sandbox creation.
When creating a sandbox from a custom image that requires building, build logs are streamed to the provided channel. The channel is closed when streaming completes. If no build is required, no logs are sent and the channel remains unused.
Example:
```
logChan := make(chan string)
go func() {
for log := range logChan {
fmt.Println(log)
}
}()
sandbox, err := client.Create(ctx, params,
options.WithLogChannel(logChan),
)
```
## func WithMode
```go
func WithMode(mode string) func(*CreateFolder)
```
WithMode sets the Unix file permissions for the created folder.
The mode should be specified as an octal string \(e.g., "0755", "0700"\). If not specified, defaults to "0755".
Example:
```
err := sandbox.FileSystem.CreateFolder(ctx, "/home/user/mydir",
options.WithMode("0700"),
)
```
## func WithOwner
```go
func WithOwner(owner string) func(*SetFilePermissions)
```
WithOwner sets the file owner.
The owner should be a valid username on the sandbox system.
Example:
```
err := sandbox.FileSystem.SetFilePermissions(ctx, "/home/user/file.txt",
options.WithOwner("root"),
)
```
## func WithPassword
```go
func WithPassword(password string) func(*GitClone)
```
WithPassword sets the password or access token for HTTPS authentication when cloning.
For GitHub, use a Personal Access Token \(PAT\). For GitLab, use a Project Access Token or Personal Access Token. For Bitbucket, use an App Password.
Example:
```
err := sandbox.Git.Clone(ctx, url, path,
options.WithUsername("username"),
options.WithPassword("ghp_xxxxxxxxxxxx"),
)
```
## func WithPermissionMode
```go
func WithPermissionMode(mode string) func(*SetFilePermissions)
```
WithPermissionMode sets the Unix file permissions.
The mode should be specified as an octal string \(e.g., "0644", "0755"\).
Example:
```
err := sandbox.FileSystem.SetFilePermissions(ctx, "/home/user/file.txt",
options.WithPermissionMode("0644"),
)
```
## func WithPre
```go
func WithPre() func(*PipInstall)
```
WithPre enables installation of pre\-release and development versions.
Example:
```
image := daytona.Base("python:3.11").PipInstall(
[]string{"mypackage"},
options.WithPre(),
)
```
## func WithPtyEnv
```go
func WithPtyEnv(env map[string]string) func(*PtySession)
```
WithPtyEnv sets environment variables for the PTY session.
Example:
```
session, err := sandbox.Process.CreatePtySession(ctx, "my-session",
options.WithPtyEnv(map[string]string{"TERM": "xterm-256color"}),
)
```
## func WithPtySize
```go
func WithPtySize(size types.PtySize) func(*PtySession)
```
WithPtySize sets the PTY terminal dimensions.
Example:
```
session, err := sandbox.Process.CreatePtySession(ctx, "my-session",
options.WithPtySize(types.PtySize{Rows: 24, Cols: 80}),
)
```
## func WithPullPassword
```go
func WithPullPassword(password string) func(*GitPull)
```
WithPullPassword sets the password or access token for HTTPS authentication when pulling.
Example:
```
err := sandbox.Git.Pull(ctx, path,
options.WithPullUsername("username"),
options.WithPullPassword("ghp_xxxxxxxxxxxx"),
)
```
## func WithPullUsername
```go
func WithPullUsername(username string) func(*GitPull)
```
WithPullUsername sets the username for HTTPS authentication when pulling.
Example:
```
err := sandbox.Git.Pull(ctx, path,
options.WithPullUsername("username"),
options.WithPullPassword("github_token"),
)
```
## func WithPushPassword
```go
func WithPushPassword(password string) func(*GitPush)
```
WithPushPassword sets the password or access token for HTTPS authentication when pushing.
Example:
```
err := sandbox.Git.Push(ctx, path,
options.WithPushUsername("username"),
options.WithPushPassword("ghp_xxxxxxxxxxxx"),
)
```
## func WithPushUsername
```go
func WithPushUsername(username string) func(*GitPush)
```
WithPushUsername sets the username for HTTPS authentication when pushing.
Example:
```
err := sandbox.Git.Push(ctx, path,
options.WithPushUsername("username"),
options.WithPushPassword("github_token"),
)
```
## func WithTimeout
```go
func WithTimeout(timeout time.Duration) func(*CreateSandbox)
```
WithTimeout sets the maximum duration to wait for sandbox creation to complete.
If the timeout is exceeded before the sandbox is ready, Create returns an error. The default timeout is 60 seconds.
Example:
```
sandbox, err := client.Create(ctx, params,
options.WithTimeout(5*time.Minute),
)
```
## func WithUsername
```go
func WithUsername(username string) func(*GitClone)
```
WithUsername sets the username for HTTPS authentication when cloning.
For GitHub, GitLab, and similar services, the username is typically your account username or a placeholder like "git" when using tokens.
Example:
```
err := sandbox.Git.Clone(ctx, url, path,
options.WithUsername("username"),
options.WithPassword("github_token"),
)
```
## func WithWaitForStart
```go
func WithWaitForStart(waitForStart bool) func(*CreateSandbox)
```
WithWaitForStart controls whether \[daytona.Client.Create\] waits for the sandbox to reach the started state before returning.
When true \(the default\), Create blocks until the sandbox is fully started and ready for use. When false, Create returns immediately after the sandbox is created, which may be in a pending or building state.
Example:
```
// Return immediately without waiting for the sandbox to start
sandbox, err := client.Create(ctx, params,
options.WithWaitForStart(false),
)
```
## type CodeRun
CodeRun holds optional parameters for \[daytona.ProcessService.CodeRun\].
```go
type CodeRun struct {
Params *types.CodeRunParams // Code execution parameters
Timeout *time.Duration // Execution timeout
}
```
## type CreateFolder
CreateFolder holds optional parameters for \[daytona.FileSystemService.CreateFolder\].
```go
type CreateFolder struct {
Mode *string // Unix file permissions (e.g., "0755")
}
```
## type CreatePty
CreatePty holds optional parameters for \[daytona.ProcessService.CreatePty\].
```go
type CreatePty struct {
PtySize *types.PtySize // Terminal dimensions (rows and columns)
Env map[string]string // Environment variables for the PTY session
}
```
## type CreateSandbox
CreateSandbox holds optional parameters for \[daytona.Client.Create\].
```go
type CreateSandbox struct {
Timeout *time.Duration // Maximum time to wait for sandbox creation
WaitForStart bool // Whether to wait for the sandbox to reach started state
LogChannel chan string // Channel for receiving build logs during image builds
}
```
## type ExecuteCommand
ExecuteCommand holds optional parameters for \[daytona.ProcessService.ExecuteCommand\].
```go
type ExecuteCommand struct {
Cwd *string // Working directory for command execution
Env map[string]string // Environment variables
Timeout *time.Duration // Command execution timeout
}
```
## type GitClone
GitClone holds optional parameters for \[daytona.GitService.Clone\].
Fields are pointers to distinguish between unset values and zero values. Use the corresponding With\* functions to set these options.
```go
type GitClone struct {
Branch *string // Branch to clone (defaults to repository's default branch)
CommitId *string // Specific commit SHA to checkout after cloning
Username *string // Username for HTTPS authentication
Password *string // Password or token for HTTPS authentication
}
```
## type GitCommit
GitCommit holds optional parameters for \[daytona.GitService.Commit\].
```go
type GitCommit struct {
AllowEmpty *bool // Allow creating commits with no staged changes
}
```
## type GitDeleteBranch
GitDeleteBranch holds optional parameters for \[daytona.GitService.DeleteBranch\].
```go
type GitDeleteBranch struct {
Force *bool // Force delete even if branch is not fully merged
}
```
## type GitPull
GitPull holds optional parameters for \[daytona.GitService.Pull\].
```go
type GitPull struct {
Username *string // Username for HTTPS authentication
Password *string // Password or token for HTTPS authentication
}
```
## type GitPush
GitPush holds optional parameters for \[daytona.GitService.Push\].
```go
type GitPush struct {
Username *string // Username for HTTPS authentication
Password *string // Password or token for HTTPS authentication
}
```
## type PipInstall
PipInstall holds optional parameters for \[daytona.Image.PipInstall\].
```go
type PipInstall struct {
FindLinks []string // URLs to search for packages
IndexURL string // Base URL of the Python Package Index
ExtraIndexURLs []string // Extra index URLs for package lookup
Pre bool // Allow pre-release and development versions
ExtraOptions string // Additional pip command-line options
}
```
## type PtySession
PtySession holds optional parameters for \[daytona.ProcessService.CreatePtySession\].
```go
type PtySession struct {
PtySize *types.PtySize // Terminal dimensions (rows and columns)
Env map[string]string // Environment variables for the PTY session
}
```
## type RunCode
RunCode holds optional parameters for \[daytona.CodeInterpreterService.RunCode\].
```go
type RunCode struct {
ContextID string // Interpreter context ID for persistent state
Env map[string]string // Environment variables for code execution
Timeout *time.Duration // Execution timeout
}
```
## type SetFilePermissions
SetFilePermissions holds optional parameters for \[daytona.FileSystemService.SetFilePermissions\].
```go
type SetFilePermissions struct {
Mode *string // Unix file permissions (e.g., "0644")
Owner *string // File owner username
Group *string // File group name
}
```
{/* Code generated by gomarkdoc. DO NOT EDIT */}
# types
```go
import "github.com/daytonaio/daytona/libs/sdk-go/pkg/types"
```
## Index
- [type Chart](https://www.daytona.io/docs/%3C.md#Chart%3E)
- [type ChartType](https://www.daytona.io/docs/%3C.md#ChartType%3E)
- [type CodeLanguage](https://www.daytona.io/docs/%3C.md#CodeLanguage%3E)
- [type CodeRunParams](https://www.daytona.io/docs/%3C.md#CodeRunParams%3E)
- [type CreateSnapshotParams](https://www.daytona.io/docs/%3C.md#CreateSnapshotParams%3E)
- [type DaytonaConfig](https://www.daytona.io/docs/%3C.md#DaytonaConfig%3E)
- [type ExecuteResponse](https://www.daytona.io/docs/%3C.md#ExecuteResponse%3E)
- [type ExecutionArtifacts](https://www.daytona.io/docs/%3C.md#ExecutionArtifacts%3E)
- [type ExecutionError](https://www.daytona.io/docs/%3C.md#ExecutionError%3E)
- [type ExecutionResult](https://www.daytona.io/docs/%3C.md#ExecutionResult%3E)
- [type ExperimentalConfig](https://www.daytona.io/docs/%3C.md#ExperimentalConfig%3E)
- [type FileDownloadRequest](https://www.daytona.io/docs/%3C.md#FileDownloadRequest%3E)
- [type FileDownloadResponse](https://www.daytona.io/docs/%3C.md#FileDownloadResponse%3E)
- [type FileInfo](https://www.daytona.io/docs/%3C.md#FileInfo%3E)
- [type FileStatus](https://www.daytona.io/docs/%3C.md#FileStatus%3E)
- [type FileUpload](https://www.daytona.io/docs/%3C.md#FileUpload%3E)
- [type GitCommitResponse](https://www.daytona.io/docs/%3C.md#GitCommitResponse%3E)
- [type GitStatus](https://www.daytona.io/docs/%3C.md#GitStatus%3E)
- [type ImageParams](https://www.daytona.io/docs/%3C.md#ImageParams%3E)
- [type LspLanguageID](https://www.daytona.io/docs/%3C.md#LspLanguageID%3E)
- [type OutputMessage](https://www.daytona.io/docs/%3C.md#OutputMessage%3E)
- [type PaginatedSnapshots](https://www.daytona.io/docs/%3C.md#PaginatedSnapshots%3E)
- [type Position](https://www.daytona.io/docs/%3C.md#Position%3E)
- [type PreviewLink](https://www.daytona.io/docs/%3C.md#PreviewLink%3E)
- [type PtyResult](https://www.daytona.io/docs/%3C.md#PtyResult%3E)
- [type PtySessionInfo](https://www.daytona.io/docs/%3C.md#PtySessionInfo%3E)
- [type PtySize](https://www.daytona.io/docs/%3C.md#PtySize%3E)
- [type Resources](https://www.daytona.io/docs/%3C.md#Resources%3E)
- [type SandboxBaseParams](https://www.daytona.io/docs/%3C.md#SandboxBaseParams%3E)
- [type ScreenshotOptions](https://www.daytona.io/docs/%3C.md#ScreenshotOptions%3E)
- [type ScreenshotRegion](https://www.daytona.io/docs/%3C.md#ScreenshotRegion%3E)
- [type ScreenshotResponse](https://www.daytona.io/docs/%3C.md#ScreenshotResponse%3E)
- [type Snapshot](https://www.daytona.io/docs/%3C.md#Snapshot%3E)
- [type SnapshotParams](https://www.daytona.io/docs/%3C.md#SnapshotParams%3E)
- [type Volume](https://www.daytona.io/docs/%3C.md#Volume%3E)
- [type VolumeMount](https://www.daytona.io/docs/%3C.md#VolumeMount%3E)
## type Chart
Chart represents a chart
```go
type Chart struct {
Type ChartType
Title string
Elements any
PNG *string // Optional base64-encoded PNG representation
}
```
## type ChartType
```go
type ChartType string
```
```go
const (
ChartTypeLine ChartType = "line"
ChartTypeScatter ChartType = "scatter"
ChartTypeBar ChartType = "bar"
ChartTypePie ChartType = "pie"
ChartTypeBoxAndWhisker ChartType = "box_and_whisker"
ChartTypeCompositeChart ChartType = "composite_chart"
ChartTypeUnknown ChartType = "unknown"
)
```
## type CodeLanguage
CodeLanguage
```go
type CodeLanguage string
```
```go
const (
CodeLanguagePython CodeLanguage = "python"
CodeLanguageJavaScript CodeLanguage = "javascript"
CodeLanguageTypeScript CodeLanguage = "typescript"
)
```
## type CodeRunParams
CodeRunParams represents parameters for code execution
```go
type CodeRunParams struct {
Argv []string
Env map[string]string
}
```
## type CreateSnapshotParams
CreateSnapshotParams represents parameters for creating a snapshot
```go
type CreateSnapshotParams struct {
Name string
Image any // string or *Image
Resources *Resources
Entrypoint []string
SkipValidation *bool
}
```
## type DaytonaConfig
DaytonaConfig represents the configuration for the Daytona client. When a field is nil, the client will fall back to environment variables or defaults.
```go
type DaytonaConfig struct {
APIKey string
JWTToken string
OrganizationID string
APIUrl string
Target string
Experimental *ExperimentalConfig
}
```
## type ExecuteResponse
ExecuteResponse represents a command execution response
```go
type ExecuteResponse struct {
ExitCode int
Result string
Artifacts *ExecutionArtifacts // nil when no artifacts available
}
```
## type ExecutionArtifacts
ExecutionArtifacts represents execution output artifacts
```go
type ExecutionArtifacts struct {
Stdout string
Charts []Chart
}
```
## type ExecutionError
ExecutionError represents a code execution error
```go
type ExecutionError struct {
Name string
Value string
Traceback *string // Optional stack trace; nil when not available
}
```
## type ExecutionResult
ExecutionResult represents code interpreter execution result
```go
type ExecutionResult struct {
Stdout string
Stderr string
Charts []Chart // Optional charts from matplotlib
Error *ExecutionError // nil = success, non-nil = execution failed
}
```
## type ExperimentalConfig
ExperimentalConfig holds experimental feature flags for the Daytona client.
```go
type ExperimentalConfig struct {
OtelEnabled bool // Enable OpenTelemetry tracing and metrics
}
```
## type FileDownloadRequest
FileDownloadRequest
```go
type FileDownloadRequest struct {
Source string
Destination *string // nil = download to memory (return []byte), non-nil = save to file path
}
```
## type FileDownloadResponse
FileDownloadResponse represents a file download response
```go
type FileDownloadResponse struct {
Source string
Result any // []byte or string (path)
Error *string // nil = success, non-nil = error message
}
```
## type FileInfo
FileInfo represents file metadata
```go
type FileInfo struct {
Name string
Size int64
Mode string
ModifiedTime time.Time
IsDirectory bool
}
```
## type FileStatus
FileStatus represents the status of a file in git
```go
type FileStatus struct {
Path string
Status string
}
```
## type FileUpload
FileUpload represents a file to upload
```go
type FileUpload struct {
Source any // []byte or string (path)
Destination string
}
```
## type GitCommitResponse
GitCommitResponse
```go
type GitCommitResponse struct {
SHA string
}
```
## type GitStatus
GitStatus represents git repository status
```go
type GitStatus struct {
CurrentBranch string
Ahead int
Behind int
BranchPublished bool
FileStatus []FileStatus
}
```
## type ImageParams
ImageParams represents parameters for creating a sandbox from an image
```go
type ImageParams struct {
SandboxBaseParams
Image any // string or *Image
Resources *Resources
}
```
## type LspLanguageID
```go
type LspLanguageID string
```
```go
const (
LspLanguagePython LspLanguageID = "python"
LspLanguageJavaScript LspLanguageID = "javascript"
LspLanguageTypeScript LspLanguageID = "typescript"
)
```
## type OutputMessage
OutputMessage represents an output message
```go
type OutputMessage struct {
Type string `json:"type"`
Text string `json:"text"`
Name string `json:"name"`
Value string `json:"value"`
Traceback string `json:"traceback"`
}
```
## type PaginatedSnapshots
PaginatedSnapshots represents a paginated list of snapshots
```go
type PaginatedSnapshots struct {
Items []*Snapshot
Total int
Page int
TotalPages int
}
```
## type Position
Position represents a position in a document
```go
type Position struct {
Line int // zero-based
Character int // zero-based
}
```
## type PreviewLink
PreviewLink contains the URL and authentication token for a sandbox preview.
```go
type PreviewLink struct {
URL string
Token string
}
```
## type PtyResult
PtyResult represents PTY session exit information
```go
type PtyResult struct {
ExitCode *int // nil = process still running, non-nil = exit code
Error *string // nil = success, non-nil = error message
}
```
## type PtySessionInfo
PtySessionInfo represents PTY session information
```go
type PtySessionInfo struct {
ID string
Active bool
CWD string // Current working directory; may be empty unavailable
Cols int
Rows int
ProcessID *int // Process ID; may be nil if unavailable
CreatedAt time.Time
}
```
## type PtySize
PtySize represents terminal dimensions
```go
type PtySize struct {
Rows int
Cols int
}
```
## type Resources
Resources represents resource allocation for a sandbox.
```go
type Resources struct {
CPU int
GPU int
Memory int
Disk int
}
```
## type SandboxBaseParams
SandboxBaseParams contains common parameters for sandbox creation.
```go
type SandboxBaseParams struct {
Name string
User string
Language CodeLanguage
EnvVars map[string]string
Labels map[string]string
Public bool
AutoStopInterval *int // nil = no auto-stop, 0 = immediate stop
AutoArchiveInterval *int // nil = no auto-archive, 0 = immediate archive
AutoDeleteInterval *int // nil = no auto-delete, 0 = immediate delete
Volumes []VolumeMount
NetworkBlockAll bool
NetworkAllowList *string
Ephemeral bool
}
```
## type ScreenshotOptions
```go
type ScreenshotOptions struct {
ShowCursor *bool // nil = default, true = show, false = hide
Format *string // nil = default format (PNG), or "jpeg", "webp", etc.
Quality *int // nil = default quality, 0-100 for JPEG/WebP
Scale *float64 // nil = 1.0, scaling factor for the screenshot
}
```
## type ScreenshotRegion
ScreenshotRegion represents a screenshot region
```go
type ScreenshotRegion struct {
X int
Y int
Width int
Height int
}
```
## type ScreenshotResponse
```go
type ScreenshotResponse struct {
Image string // base64-encoded image data
Width int
Height int
SizeBytes *int // Size in bytes
}
```
## type Snapshot
Snapshot represents a Daytona snapshot
```go
type Snapshot struct {
ID string `json:"id"`
OrganizationID string `json:"organizationId,omitempty"`
General bool `json:"general"`
Name string `json:"name"`
ImageName string `json:"imageName,omitempty"`
State string `json:"state"`
Size *float64 `json:"size,omitempty"`
Entrypoint []string `json:"entrypoint,omitempty"`
CPU int `json:"cpu"`
GPU int `json:"gpu"`
Memory int `json:"mem"` // API uses "mem" not "memory"
Disk int `json:"disk"`
ErrorReason *string `json:"errorReason,omitempty"` // nil = success, non-nil = error reason if snapshot failed
SkipValidation bool `json:"skipValidation"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
LastUsedAt *time.Time `json:"lastUsedAt,omitempty"`
}
```
## type SnapshotParams
SnapshotParams represents parameters for creating a sandbox from a snapshot
```go
type SnapshotParams struct {
SandboxBaseParams
Snapshot string
}
```
## type Volume
Volume represents a Daytona volume
```go
type Volume struct {
ID string `json:"id"`
Name string `json:"name"`
OrganizationID string `json:"organizationId"`
State string `json:"state"`
ErrorReason *string `json:"errorReason,omitempty"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
LastUsedAt time.Time `json:"lastUsedAt,omitempty"`
}
```
## type VolumeMount
VolumeMount represents a volume mount configuration
```go
type VolumeMount struct {
VolumeID string
MountPath string
Subpath *string // Optional subpath within the volume; nil = mount entire volume
}
```
import { Image } from 'astro:assets'
import notesAppResult from '../../../../../assets/docs/images/inngest-agentkit-notes-app.gif'
This guide demonstrates how to set up and use a fully autonomous coding agent that performs software development tasks in a [Daytona](https://daytona.io) sandbox environment. The agent is built using [AgentKit](https://agentkit.inngest.com/) and leverages Daytona sandboxes for secure, isolated execution. It can create web apps, run tests, execute scripts, and more; automating multi-step workflows based on user prompts.
---
### 1. Workflow Overview
You provide a natural language prompt describing the software task. The agent reasons about your request, plans the steps, and executes them securely in a Daytona sandbox; handling everything from project setup to live previews.
### 2. Project Setup
#### Clone the Repository
Clone the [repository](https://github.com/daytonaio/daytona) and navigate to the example directory:
```bash
git clone https://github.com/daytonaio/daytona.git
cd daytona/guides/typescript/agentkit-inngest/coding-agent/anthropic
```
#### Configure Environment
Get your API keys:
- **Daytona API key:** [Daytona Dashboard](https://app.daytona.io/dashboard/keys)
- **Anthropic API key:** [Anthropic Console](https://console.anthropic.com/)
Copy `.env.example` to `.env` and add your keys:
```bash
DAYTONA_API_KEY=your_daytona_key
ANTHROPIC_API_KEY=your_anthropic_key
```
#### Local Usage
:::note[Node.js Version]
Node.js 18 or newer is required to run the coding agent locally. Please ensure your environment meets this requirement before proceeding.
:::
Install dependencies:
```bash
npm install
```
Run the agent:
```bash
npm run start
```
#### Docker
Build the Docker image:
```bash
docker buildx build . -t coding-agent
```
Run the container:
```bash
docker run --rm -it coding-agent
```
### 3. Configuration
- **Prompt Setting:** Edit the main prompt in `network.run(...)` in `src/index.ts` to change the agent's task.
- **Debug Logs:** Set `enableDebugLogs=true` for detailed agent flow tracking.
### 4. Example Usage
Try the default prompt in `src/index.ts`:
```typescript
const result = await network.run(
`Create a minimal React app called "Notes" that lets users add, view, and delete notes. Each note should have a title and content. Use Create React App or Vite for setup. Include a simple UI with a form to add notes and a list to display them.`
)
```
**The agent will:**
- Scaffold the app
- Install dependencies
- Start the dev server
- Generate a preview link
Terminal output example:
```
✔️ App is ready!
Preview: https://5173-3a828150-1573-42e3-bf9f-9793a2c2c0c2.proxy.daytona.works
```
The image below shows the result generated in this run:
### 5. Understanding the Agent's Execution Flow
The agent operates by leveraging a large language model (LLM) under the hood and has access to a suite of specialized tools. These tools enable the agent to perform everything needed inside the Daytona sandbox environment; from project setup to app deployment. At each step, the agent reasons about the current goal, decides which tool to call, and orchestrates the workflow to achieve the desired outcome.
Below is a step-by-step breakdown of how the agent builds the demo Notes app showing each iteration, the agent's message, and the tool used:
#### Project Initialization
**Agent message:**
```
I'll create a React app for Notes using Vite, which provides a faster and more modern setup compared to Create React App. I'll break this down into steps:
- First, I'll create the project using Vite
- Install necessary dependencies
- Create the components for the Notes app
- Implement the core functionality
Let's get started:
```
**Tool used:**
`shellTool` was called with command:
```
npm create vite@latest notes -- --template react
```
#### Install Dependencies
**Agent message:**
```
Now, I'll navigate to the project directory and install dependencies:
```
**Tool used:**
`shellTool` was called with command:
```
cd notes && npm install
```
#### Create Components & Update App Structure
**Agent message:**
```
Now, I'll create the necessary components and update the app structure:
1. Update App.jsx
2. Update App.css for basic styling
```
**Tool used:**
`uploadFilesTool` was called to upload:
```
App.jsx (main component logic)
App.css (basic styling)
```
#### Start Development Server
**Agent message:**
```
Now, I'll start the development server:
```
**Tool used:**
`startDevServerTool` was called with command:
```
cd notes && npm run dev
```
#### Check Dev Server Health
**Agent message:**
```
Let's check the dev server health:
```
**Tool used:**
`checkDevServerHealthTool` was called to verify that the development server is running and accessible.
#### App Summary & Features
**Agent message:**
```
Great! I've created a minimal React Notes app with the following features:
- Add notes with a title and content
- View the list of notes
- Delete individual notes
- Basic responsive styling
Key details:
- Used Vite for project setup
- Implemented state management with React hooks (useState)
- Simple form for adding notes
- Notes are stored in local state
- Each note has a unique ID, title, and content
- Delete functionality for individual notes
DEV_SERVER_PORT=5173
TASK_COMPLETED
The app is now running and ready to use. Users can:
1. Enter a note title in the first input
2. Enter note content in the textarea
3. Click "Add Note" to save the note
4. View notes in the list below
5. Delete notes by clicking the "Delete" button next to each note
Would you like me to explain any part of the implementation or make any modifications?
```
Notice `DEV_SERVER_PORT` and `TASK_COMPLETED` fields in the agent output message.
`DEV_SERVER_PORT` value is auto-detected by the agent and used to generate the preview link for your app.
`TASK_COMPLETED` signals that the task is finished which is used inside the agent routing logic.
---
**Key advantages:**
- Secure, isolated execution
- Multi-language support
- Auto-detects dev server, starts it, and generates preview link
- Detailed debug logs for agent actions
This guide demonstrates how to run a two-agent autonomous coding system using the [Claude Agent SDK](https://platform.claude.com/docs/en/agent-sdk/overview) and Daytona sandboxes. The system consists of a **Project Manager Agent** (local) and a **Developer Agent** (in-sandbox), enabling advanced delegation, planning, and secure code execution.
The Project Manager Agent runs locally and uses the basic Anthropic interface with the `claude-sonnet-4-20250514` model for high-level planning and task delegation. The Developer Agent runs inside the Daytona sandbox and is created using the Claude Agent SDK, which leverages Claude Code for advanced coding and automation capabilities. This architecture separates high-level planning from low-level code execution for more robust automation.
A key advantage of this approach is its **extensibility**: you can easily replace the Project Manager Agent with your own custom orchestrator logic, or even another agent, making the system highly reusable and adaptable to a wide range of advanced automation and coordination use cases.
---
### 1. Workflow Overview
When the main module is launched, a Daytona sandbox is created for the Developer Agent, and a Project Manager Agent is initialized locally. Interaction with the system occurs via a command line chat interface. The Project Manager Agent receives prompts, plans the workflow, and delegates coding tasks to the Developer Agent. The Developer Agent executes tasks in the sandbox and streams results back to the Project Manager, who reviews and coordinates further actions. All logs and outputs from both agents are streamed in real time to the terminal, providing full visibility into the process as it is managed by the Project Manager Agent.
The Developer Agent can also host web apps and provide preview links using [Daytona Preview Links](https://www.daytona.io/docs/en/preview-and-authentication.md). The Project Manager Agent will present these links and summarize the results for you.
You can continue interacting with the system until you are finished. When you exit the program, the sandbox is deleted automatically.
---
### 2. Project Setup
#### Clone the Repository
First, clone the daytona [repository](https://github.com/daytonaio/daytona.git) and navigate to the example directory:
```bash
git clone https://github.com/daytonaio/daytona.git
cd daytona/guides/typescript/anthropic/multi-agent-claude-sdk
```
#### Configure Environment
To run this example, you need to set the following environment variables:
- `DAYTONA_API_KEY`: Required for access to Daytona sandboxes. Get it from [Daytona Dashboard](https://app.daytona.io/dashboard/keys)
- `ANTHROPIC_API_KEY`: Required for the **Project Manager Agent** (runs locally). Get it from [Claude Developer Platform](https://console.anthropic.com/settings/keys)
- `SANDBOX_ANTHROPIC_API_KEY`: **Optional** for the **Developer Agent** (runs in sandbox). If not provided, defaults to using `ANTHROPIC_API_KEY`. Get it from [Claude Developer Platform](https://console.anthropic.com/settings/keys)
Copy `.env.example` to `.env` and add your keys:
```bash
DAYTONA_API_KEY=your_daytona_key
ANTHROPIC_API_KEY=your_anthropic_key
SANDBOX_ANTHROPIC_API_KEY=your_anthropic_key
```
:::tip[Agent API Key Options]
You can use a single `ANTHROPIC_API_KEY` for both agents, or provide a separate `SANDBOX_ANTHROPIC_API_KEY` for billing/tracking purposes.
:::
:::caution[API Key Security]
The `SANDBOX_ANTHROPIC_API_KEY` is passed into the Daytona sandbox environment and is accessible to any code executed inside the sandbox.
:::
#### Local Usage
:::note[Node.js Version]
Node.js 18 or newer is required to run this example. Please ensure your environment meets this requirement before proceeding.
:::
Install dependencies:
```bash
npm install
```
Run the two-agent system:
```bash
npm run start
```
The system will start and wait for your prompt.
---
### 3. Example Usage
Example chat session:
```
$ npm run start
Creating Developer Agent sandbox...
Installing Developer Agent SDK...
Initializing Developer Agent...
Initializing Project Manager Agent...
=== Two-Agent System Ready ===
Project Manager Agent: Manages tasks and delegates to Developer (Green text)
Developer Agent: Executes code in Daytona sandbox (White text)
Press Ctrl+C at any time to exit.
User: make a lunar lander web app
[Project Manager] Processing your request...
[Project Manager]: I'll help you create a lunar lander web app! Let me delegate this task to the Developer Agent.
Create a lunar lander web game with the following features:
- HTML/CSS/JavaScript based
- Canvas graphics for the game
- Physics simulation (gravity, thrust, velocity)
- Keyboard controls (arrow keys)
- Landing detection (safe landing vs crash)
- Fuel management system
- Start the game on port 80 and provide the preview URL
[Delegating to Developer Agent]...
I'll help you create a lunar lander web app! Let me build a complete game with physics simulation, graphics, and controls.
🔨 Write
🔨 Write
🔨 Bash
Perfect! The web server is now running.
Your Lunar Lander game is live at:
🌐 https://80-17ac1c0f-d684-4122-93b5-8f52fd5393f8.proxy.daytona.works
[Project Manager]: Excellent! The Developer Agent has successfully created your lunar lander web app. The game is now running and accessible at the preview URL above. The implementation includes:
✓ Physics simulation with gravity and thrust
✓ Canvas-based graphics
✓ Keyboard controls for gameplay
✓ Landing detection system
✓ Fuel management
✓ Web server running on port 80
TASK_COMPLETE
[Project Manager] All tasks completed!
```
---
### 4. Understanding the Agent Architecture
This system is composed of two collaborating agents, each with a distinct role and implementation. Below is a step-by-step guide to how each agent operates and interacts within the workflow.
#### Project Manager Agent (Terminal Orchestration)
1. **User Interaction:**
- All user interaction occurs via the terminal with the Project Manager Agent.
- The Project Manager Agent is configured with a system prompt that defines its role and maintains the full conversation history.
2. **Awareness of Developer Agent:**
- The Project Manager Agent knows that a Developer Agent is available inside a Daytona sandbox and can be invoked as needed.
3. **Task Delegation:**
- When the Project Manager Agent determines that a coding task should be delegated, it encapsulates the task within `` tags in its response.
- The system parses these tags and, when present, invokes the Developer Agent with the specified task.
4. **Iterative Workflow:**
- This process can repeat multiple times, with the Project Manager Agent reasoning about progress and delegating further tasks as needed.
5. **Session Completion:**
- When the Project Manager Agent determines the overall task is complete, it outputs `TASK_COMPLETE`, which signals the system to terminate the session.
#### Developer Agent (Sandbox Execution)
1. **Provisioning:**
- The Developer Agent is provisioned inside a Daytona sandbox and is responsible for executing coding tasks.
2. **SDK Installation:**
- The system installs the Claude Agent SDK in the sandbox by running `pip install` (see [process execution](https://www.daytona.io/docs/en/process-code-execution.md#process-execution)).
3. **Interpreter Context:**
- A new [code interpreter context](https://www.daytona.io/docs/en/process-code-execution.md#stateful-code-interpreter) is created for isolated execution.
4. **Script Upload:**
- The coding agent script is uploaded to the sandbox using [file uploading](https://www.daytona.io/docs/file-system-operations.md#uploading-a-single-file).
5. **SDK Initialization:**
- The Claude Agent SDK is initialized in the interpreter context (e.g., `import coding_agent`).
6. **Task Execution:**
- When a `` is received, the system sends the task to the Developer Agent by running a Python command in the interpreter context:
```typescript
const result = await sandbox.codeInterpreter.runCode(
`coding_agent.run_query_sync(os.environ.get('PROMPT', ''))`,
{
context: ctx,
envs: { PROMPT: task },
onStdout,
onStderr,
}
);
```
- The Developer Agent executes the task, streams output, and returns results to the Project Manager Agent for review and further coordination.
---
### 5. Customization
You can customize the Project Manager Agent's behavior by modifying the system prompt in `src/index.ts`. The current implementation:
- Uses `` tags for delegation
- Automatically reviews Developer Agent outputs
- Says "TASK_COMPLETE" when finished
---
### 6. Cleanup
When you exit the main program, the Daytona sandbox and all files are automatically deleted.
---
**Key advantages:**
- Secure, isolated execution in Daytona sandboxes
- Hierarchical agent architecture for robust automation
- Extensible and reusable architecture
- Automatic dev server detection and live preview links
- Multi-language and full-stack support
- Simple setup and automatic cleanup
import { Image } from 'astro:assets'
import claudeAgentSDKInteractiveTerminalSandboxResult from '../../../../../assets/docs/images/claude-agent-sdk-interactive-terminal-sandbox-result.gif'
This guide demonstrates how to run an autonomous coding agent based on [Claude Code](https://code.claude.com/docs/en/overview) inside a Daytona sandbox environment. The agent uses the [Claude Agent SDK](https://platform.claude.com/docs/en/agent-sdk/overview) to follow user prompts.
The agent can develop full-stack web apps, write code in any language, install dependencies, and run scripts. It can also start and manage dev servers, and generate preview links for live apps.
---
### 1. Workflow Overview
When you launch the main module, a Daytona sandbox is created and a Python agent is initialized inside it. The agent is based on the [Claude Agent SDK](https://platform.claude.com/docs/en/agent-sdk/overview).
You interact with the main program via a command line chat interface. The program sends your prompts to the agent inside the sandbox, which executes them and returns the results:
```
$ npm run start 174s
Creating sandbox...
Installing Agent SDK...
Initializing Agent SDK...
Press Ctrl+C at any time to exit.
User: Build a Zelda-like game where I can move around the screen and talk to famous programmers
Thinking...
I'll build a Zelda-like game for you! This will be a fun project with player movement and NPC interactions with famous programmers.
🔨 Write
🔨 Write
Now let me start a simple HTTP server to host the game:
🔨 Bash
Perfect! I've created a Zelda-like game called "Programmer's Quest" for you! 🎮
## Game Features:
✨ Zelda-style gameplay:
- Top-down 2D view with classic retro aesthetics
- Player character with sword and shield
- Grid-based movement system
- Environmental obstacles (trees and rocks)
👥 Famous Programmers as NPCs:
1. Linus Torvalds - Creator of Linux
2. Grace Hopper - COBOL pioneer and Admiral
3. Alan Turing - Father of computer science
4. Ada Lovelace - First computer programmer
5. Dennis Ritchie - Creator of C and UNIX
🎮 Controls:
- Arrow Keys or WASD - Move your character
- SPACE - Talk to NPCs when you're near them
🌟 Gameplay:
- Explore the grassy map and find all 5 legendary programmers
- Each NPC has multiple quotes that cycle when you talk to them
- NPCs glow when you're near them
- Dialog boxes appear with their famous quotes
- Track your progress in the HUD
## Play Now:
🎯 [Click here to play the game!](https://80-8e2c4d23-212a-4f1e-bb6c-abfa71aeed3a.proxy.daytona.works)
The game features smooth movement, collision detection with trees and rocks, and an immersive dialog system. Try to find and talk to all 5 famous programmers to learn their wisdom! Each has 3 different quotes that cycle as you keep talking to them.
Enjoy your adventure! 🗡️✨
User:
```
The agent can also host web apps and provide you with a preview link using the [Daytona Preview Links](https://www.daytona.io/docs/en/preview-and-authentication.md) feature. When your task involves running or previewing a web application, the agent automatically reasons about this need, hosts the app, and generates a preview link for you to inspect the live result:
You can continue interacting with your agent until you are finished. When you exit the program, the sandbox will be deleted automatically.
### 2. Project Setup
#### Clone the Repository
First, clone the daytona [repository](https://github.com/daytonaio/daytona.git) and navigate to the example directory:
```bash
git clone https://github.com/daytonaio/daytona.git
cd daytona/guides/typescript/anthropic/single-claude-agent-sdk
```
#### Configure Environment
Get your API keys:
- **Daytona API key:** [Daytona Dashboard](https://app.daytona.io/dashboard/keys)
- **Anthropic API key:** [Anthropic Console](https://console.anthropic.com/)
Copy `.env.example` to `.env` and add your keys:
```bash
DAYTONA_API_KEY=your_daytona_key
SANDBOX_ANTHROPIC_API_KEY=your_anthropic_key
```
:::caution[API Key Security]
Note: The `SANDBOX_ANTHROPIC_API_KEY` key is passed into the Daytona sandbox environment and is accessible to any code executed inside the sandbox.
:::
#### Local Usage
:::note[Node.js Version]
Node.js 18 or newer is required to run this example. Please ensure your environment meets this requirement before proceeding.
:::
Install dependencies:
```bash
npm install
```
Run the agent:
```bash
npm run start
```
The agent will start and wait for your prompt.
### 3. Example Usage
Example chat session:
```
$ npm run start
Creating sandbox...
Installing Agent SDK...
Initializing Agent SDK...
Press Ctrl+C at any time to exit.
User: Create a fun pet store landing page in Svelte
Thinking...
I'll create a fun pet store landing page in Svelte for you! Let me set up the project and build an engaging landing page with animations and a colorful design.
🔨 Bash
🔨 Bash
Now let me create a fun and engaging pet store landing page with animations, colorful sections, and interactive elements:
🔨 Read
> 🔨 Write
Now let me create the component files:
🔨 Write
🔨 Write
🔨 Write
🔨 Write
🔨 Write
Now let's update the main CSS file and start the development server:
🔨 Read
🔨 Write
Now let's start the development server:
🔨 Bash
🔨 TaskOutput
Perfect! 🎉 I've created a fun and colorful pet store landing page in Svelte! Here's what I built:
## Features:
✨ Hero Section
- Beautiful gradient background with animated floating cards
- Eye-catching navigation bar
- Call-to-action buttons with hover effects
- Bouncing emoji animations
🎯 Features Section
- 4 key benefits (Free Delivery, Premium Quality, Special Offers, Award Winning)
- Interactive cards with hover animations
- Icons that rotate and scale on hover
🛍️ Products Section
- 6 featured products with colorful backgrounds
- Star ratings
- Add to cart functionality
- Smooth hover animations
📧 Newsletter Section
- Vibrant gradient background with floating pet emojis
- Email subscription form
- Success message animation
- Special 20% off offer
👣 Footer
- Comprehensive navigation links
- Social media icons
- Dark gradient design
## Live Preview:
Your pet store is now running at: https://80-b3739199-d90e-4bde-ab18-450d74c950e8.proxy.daytona.works
The page includes:
- Smooth scroll behavior
- Responsive design for mobile devices
- Fun animations throughout
- Interactive elements with hover effects
- Colorful gradients and modern styling
- Emoji-based icons for a playful feel
Click the link to see your fun pet store landing page in action! 🐾
User:
```
### 4. Understanding the Agent's Architecture
This example consists of two main components:
- **Main Program:** The main program is a Node.js script (`index.ts`) that runs on your local machine. It uses the Daytona SDK to create and manage a Daytona sandbox. The main program provides a command line interface for interacting with the agent inside the sandbox.
- **Sandbox Agent:** The sandbox agent is a Python script (`coding_agent.py`) that runs inside the Daytona sandbox. It uses the Claude Agent SDK to create a customized coding agent similar to Claude Code.
#### Initialization
On initialization, the main program:
1. Creates a new [Daytona sandbox](https://www.daytona.io/docs/en/sandboxes.md) with your Anthropic API key included in the environment variables.
2. Installs the Claude Agent SDK by running `pip install` in the sandbox with [process execution](https://www.daytona.io/docs/en/process-code-execution.md#process-execution).
3. Creates a new [code interpreter context](https://www.daytona.io/docs/en/process-code-execution.md#stateful-code-interpreter).
4. Uploads the coding agent script to the sandbox with [file uploading](https://www.daytona.io/docs/file-system-operations.md#uploading-a-single-file).
5. Initializes the Claude Agent SDK by running `import coding_agent` in the code interpreter context.
6. Waits for user input and sends prompts to the agent in the code interpreter context as shown below.
#### Main Program Code
Once the agent is running, the program creates a readline interface to read user input and sends it to the agent.
Each user request is passed to the agent by running a Python command in the code interpreter context:
```typescript
const result = await sandbox.codeInterpreter.runCode(
`coding_agent.run_query_sync(os.environ.get('PROMPT', ''))`,
{
context: ctx,
envs: { PROMPT: prompt },
onStdout,
onStderr,
}
)
```
The `onStdout` and `onStderr` callbacks are used to pass the agent's output back to the main program. After the agent finishes responding to the prompt, the main program waits for the next user input.
#### Sandbox Agent Code
The sandbox agent uses the [Claude Agent SDK](https://platform.claude.com/docs/en/agent-sdk/overview) to create a customized coding agent based on Claude Code.
The agent is initialized with a system prompt that includes the workspace directory and an example of the [preview URL format](https://www.daytona.io/docs/en/preview-and-authentication.md):
```python
system_prompt = """
You are running in a Daytona sandbox.
Use the /home/daytona directory instead of /workspace for file operations.
Your public preview URL for port 80 is: {}.
""".format(preview_url)
```
It also specifies the [tools and permission mode](https://platform.claude.com/docs/en/agent-sdk/quickstart#key-concepts) of the agent:
```python
client = ClaudeSDKClient(
options=ClaudeAgentOptions(
allowed_tools=["Read", "Edit", "Glob", "Grep", "Bash"],
permission_mode="acceptEdits",
system_prompt=system_prompt
)
)
```
The code to run queries and receive responses follows the examples in Anthropic's [Claude Agent Python SDK documentation](https://platform.claude.com/docs/en/agent-sdk/python).
#### Clean up
When you exit the main program, the Daytona sandbox and all files are automatically deleted.
**Key advantages:**
- Secure, isolated execution in Daytona sandboxes
- Communicate with the agent directly in your terminal
- Automatic dev server detection and live preview links
- Multi-language and full-stack support
- Simple setup and automatic cleanup
This guide walks you through running Claude Code inside a Daytona sandbox using the Daytona CLI.
### Prerequisites
- Daytona account and API key (Get it from [Daytona Dashboard](https://app.daytona.io/dashboard/keys))
- Local terminal (macOS, Linux, or Windows)
### Install the Daytona CLI
```bash
brew install daytonaio/cli/daytona
```
```bash
powershell -Command "irm https://get.daytona.io/windows | iex"
```
:::note
Already have the CLI? Check your version with `daytona --version`. If it's below **0.135.0**, [upgrade to the latest version](https://www.daytona.io/docs/en/getting-started.md#cli).
:::
### Authenticate with Daytona
Log in to your Daytona account using your API key:
```bash
daytona login --api-key=YOUR_API_KEY
```
Replace `YOUR_API_KEY` with your actual Daytona API key.
### Create a Sandbox
Create a new sandbox for running Claude Code:
```bash
daytona sandbox create --name claude-sandbox
```
This creates a sandbox named `claude-sandbox`, visible in your [Dashboard](https://app.daytona.io/dashboard/sandboxes). The default Daytona snapshot includes Claude Code, so the command above is all you need.
:::tip
Need more power? Pass `--snapshot daytona-large` or `--snapshot daytona-medium` flag to increase your sandbox resources. See [default snapshots](https://www.daytona.io/docs/en/snapshots.md#default-snapshots) for resource details.
:::
### Connect to the Sandbox
SSH into your sandbox:
```bash
daytona ssh claude-sandbox
```
You now have an interactive terminal session inside the sandbox.
### Run Claude Code
Inside the SSH session, start Claude Code:
```bash
claude
```
On first run, Claude Code will prompt you to authenticate:
1. Copy the authentication URL displayed in the terminal
2. Open the URL in your local browser
3. Complete the authentication flow
4. Copy the code provided by the browser
5. Paste the code back into the terminal
Once authenticated, you're all set. Claude Code runs inside the sandbox while you control it from your terminal.
Claude Code allows you to automate and orchestrate tasks using natural language and code. With Daytona, you can easily run Claude Code inside isolated sandboxes, making it simple to experiment and execute tasks securely.
## Running Claude Code in a Daytona Sandbox
You can run Claude Code and execute tasks with it directly inside a Daytona sandbox. The following examples show how to set up a sandbox, install Claude Code, run tasks programmatically, and stream logs in real time.
> **Note:** While both sync and async modes support streaming PTY output, `AsyncDaytona` is recommended as it provides automatic background callbacks via `on_data`. The synchronous API requires blocking iteration or manual threading to handle output.
```python
import os
import asyncio
from daytona import AsyncDaytona
async def run_claude_code():
async with AsyncDaytona() as daytona:
sandbox = await daytona.create()
# Define the Claude Code command to be executed
claude_command = "claude --dangerously-skip-permissions -p 'write a dad joke about penguins' --output-format stream-json --verbose"
# Install Claude Code in the sandbox
await sandbox.process.exec("npm install -g @anthropic-ai/claude-code")
pty_handle = await sandbox.process.create_pty_session(
id="claude", on_data=lambda data: print(data.decode(), end="")
)
await pty_handle.wait_for_connection()
# Run the Claude Code command inside the sandbox
await pty_handle.send_input(
f"ANTHROPIC_API_KEY={os.environ['ANTHROPIC_API_KEY']} {claude_command}\n"
)
# Use this to close the terminal session if no more commands will be executed
# await pty_handle.send_input("exit\n")
await pty_handle.wait()
# If you are done and have closed the PTY terminal, it is recommended to clean up resources by deleting the sandbox
# await sandbox.delete()
if __name__ == "__main__":
asyncio.run(run_claude_code())
````
```typescript
import { Daytona } from "@daytonaio/sdk";
const daytona = new Daytona();
try {
const sandbox = await daytona.create();
// Define the Claude Code command to be executed
const claudeCommand =
"claude --dangerously-skip-permissions -p 'write a dad joke about penguins' --output-format stream-json --verbose";
// Install Claude Code in the sandbox
await sandbox.process.executeCommand("npm install -g @anthropic-ai/claude-code");
const ptyHandle = await sandbox.process.createPty({
id: "claude",
onData: (data) => {
process.stdout.write(data);
},
});
await ptyHandle.waitForConnection();
// Run the Claude Code command inside the sandbox
ptyHandle.sendInput(
`ANTHROPIC_API_KEY=${process.env.ANTHROPIC_API_KEY} ${claudeCommand}\n`
);
// Use this to close the terminal session if no more commands will be executed
// ptyHandle.sendInput("exit\n")
await ptyHandle.wait();
// If you are done and have closed the PTY terminal, it is recommended to clean up resources by deleting the sandbox
// await sandbox.delete();
} catch (error) {
console.error("Failed to run Claude Code in Daytona sandbox:", error);
}
````
Guides for integrating Claude with Daytona.
import { Image } from 'astro:assets'
import codexSdkLunarLanderResult from '../../../../../assets/docs/images/codex-sdk-lunar-lander-result.gif'
This guide demonstrates how to run an autonomous coding agent based on [OpenAI Codex](https://chatgpt.com/features/codex) inside a Daytona sandbox environment. The agent can develop full-stack web apps, write code in any language, install dependencies, and run scripts. It can also start and manage dev servers, and generate preview links for live apps.
---
### 1. Workflow Overview
When you launch the main module, a Daytona sandbox is created and a Node.js agent is initialized inside it. The agent is based on the [Codex SDK](https://developers.openai.com/codex/sdk/).
You interact with the main program via a command line chat interface. The program sends your prompts to the agent inside the sandbox, which executes them and returns the results:
```
$ npm run start
Creating sandbox...
Installing Codex agent in sandbox...
Press Ctrl+C at any time to exit.
User: create a 3d animated web-based, lunar lander game
Thinking...
🔨 ✓ Run: /bin/sh -lc ls
🔨 ✓ Run: /bin/sh -lc 'ls -a'
🔨 ✓ Run: /bin/sh -lc 'ls .daytona'
🔨 ✓ Run: /bin/sh -lc 'find /home/daytona -maxdepth 4 -name .git'
📝 Add /home/daytona/index.html
📝 Add /home/daytona/style.css
📝 Add /home/daytona/main.js
📝 Update /home/daytona/main.js
- Built a self-contained 3D lunar lander experience with HUD in index.html wired to main.js.
- Styled a glassy mission card, typography, and neon accents in style.css.
- Implemented the Three.js scene in main.js: starfield + noisy terrain with a flattened pad, modeled lander, thrust/fuel/rotation controls, gravity/drag physics, landing/crash checks, exhaust particles, and a chase camera. Controls: Space/↑ thrust, ←/→ yaw, W/S pitch, R restart.
Next steps:
1) Serve locally (e.g., cd /home/daytona && python3 -m http.server 8080) and open https://8080-e7c5deb5-7723-4bb8-93c6-25258d9b7c53.proxy.daytona.works.
2) Tune physics constants or terrain size if you want a harder/easier landing.
🗒️ To-do list:
- [x] Inspect workspace and set up project structure for web-based lunar lander game
- [x] Implement 3D scene, lunar lander controls, physics, and game loop
- [x] Add UI elements, polish, and quick sanity check (open file if feasible)
Usage Summary: Cached: 71936, Input: 103238, Output: 11311
User: start the server
Thinking...
🔨 ✓ Run: /bin/sh -lc 'cd /home/daytona && nohup python3 -m http.server 8080 --bind 0.0.0.0 >/home/daytona/server.log 2>&1 & echo $!'
Server started on port 8080 (pid 274). Open the game at:
https://8080-e7c5deb5-7723-4bb8-93c6-25258d9b7c53.proxy.daytona.works
If you need to stop it later: kill 274.
Usage Summary: Cached: 4096, Input: 22231, Output: 272
User:
Cleaning up...
```
The agent can also host web apps and provide you with a preview link using the [Daytona Preview Links](https://www.daytona.io/docs/en/preview-and-authentication.md) feature. When your task involves running or previewing a web application, the agent automatically reasons about this need, hosts the app, and generates a preview link for you to inspect the live result:
You can continue interacting with your agent until you are finished. When you exit the program, the sandbox will be deleted automatically.
### 2. Project Setup
#### Clone the Repository
First, clone the daytona [repository](https://github.com/daytonaio/daytona.git) and navigate to the example directory:
```bash
git clone https://github.com/daytonaio/daytona.git
cd daytona/guides/typescript/openai/codex-sdk
```
#### Configure Environment
Get your API keys:
- **Daytona API key:** [Daytona Dashboard](https://app.daytona.io/dashboard/keys)
- **OpenAI API key:** [OpenAI Developer Platform](https://platform.openai.com/api-keys)
Copy `.env.example` to `.env` and add your keys:
```bash
DAYTONA_API_KEY=your_daytona_key
SANDBOX_OPENAI_API_KEY=your_openai_key
```
:::caution[API Key Security]
Note: The `SANDBOX_OPENAI_API_KEY` key is passed into the Daytona sandbox environment and is accessible to any code executed inside the sandbox.
:::
#### Local Usage
:::note[Node.js Version]
Node.js 18 or newer is required to run this example. Please ensure your environment meets this requirement before proceeding.
:::
Install dependencies:
```bash
npm install
```
Run the agent:
```bash
npm run start
```
The agent will start and wait for your prompt.
### 3. Understanding the Agent's Architecture
This example consists of two main components:
- **Main Program:** The main program is a Node.js script (`src/index.ts`) that runs on your local machine. It uses the Daytona SDK to create and manage a Daytona sandbox. The main program provides a command line interface for interacting with the agent inside the sandbox.
- **Sandbox Agent:** The sandbox agent is a Node.js script (`agent/index.ts`) that runs inside the Daytona sandbox. It uses the Codex SDK to create a customized coding agent.
#### Initialization
On initialization, the main program:
1. Creates a new [Daytona sandbox](https://www.daytona.io/docs/en/sandboxes.md) with your OpenAI API key included in the environment variables.
2. Configures the Codex system prompt with Daytona-specific instructions and writes it to a `.codex/config.toml` file in the sandbox.
3. Uploads the agent package to the sandbox with [file uploading](https://www.daytona.io/docs/file-system-operations.md#uploading-a-single-file).
4. Installs the agent dependencies by running `npm install` in the uploaded agent directory.
5. Waits for user input and runs the agent asynchronously for each prompt.
#### Main Program Code
Custom system prompts for Codex must be configured via a `.codex/config.toml` file, so the main program creates this file in the sandbox before starting the agent:
```typescript
const systemPrompt = [
'You are running in a Daytona sandbox.',
'Use the /home/daytona directory instead of /workspace for file operations.',
`When running services on localhost, they will be accessible as: ${previewUrlPattern}`,
].join(' ')
const config = `developer_instructions = "${systemPrompt}"`
await sandbox.fs.createFolder('.codex', '755')
await sandbox.fs.uploadFile(Buffer.from(config, 'utf8'), '.codex/config.toml')
```
This prompt instructs the agent to use the correct file paths and preview link format for Daytona sandboxes.
After installing dependencies, the main program enters a loop to read user input and send it to the agent. For each user prompt it receives, it creates a new Daytona process session to run the agent command asynchronously and stream back the output:
```typescript
// Create a session to stream the agent output
const sessionId = `codex-session-${Date.now()}`
await sandbox.process.createSession(sessionId)
// Run the agent asynchronously, passing the prompt and OpenAI API key
const command = await sandbox.process.executeSessionCommand(sessionId, {
command: `${environmentPrefix({ PROMPT: prompt })} npm exec --prefix /tmp/agent tsx -- /tmp/agent/index.ts`,
runAsync: true,
})
// Stream agent output as it arrives
if (!command.cmdId) throw new Error('Failed to start agent command in sandbox')
await sandbox.process.getSessionCommandLogs(
sessionId,
command.cmdId,
onStdout,
onStderr,
)
// Delete the session
await sandbox.process.deleteSession(sessionId)
```
The `onStdout` and `onStderr` callbacks are used to pass the agent's output back to the main program. After the agent finishes responding to the prompt, the main program waits for the next user input.
#### Sandbox Agent Code
The sandbox agent uses the [Codex SDK](https://developers.openai.com/codex/sdk/) to create a customized coding agent.
The agent is initialized with custom options that include the workspace directory:
```typescript
// Configure Codex options
const options: ThreadOptions = {
workingDirectory: '/home/daytona',
skipGitRepoCheck: true,
sandboxMode: 'danger-full-access',
}
```
The agent maintains thread state between requests by writing the thread ID to a file, allowing it to maintain context across multiple interactions:
```typescript
const threadIdPath = '/tmp/codex-thread-id'
const threadId = (await readFileIfExisting(threadIdPath))?.trim()
const thread: Thread = threadId
? codex.resumeThread(threadId, options)
: codex.startThread(options)
```
Additional code to stream agent responses follows the examples in OpenAI's [Codex SDK documentation](https://github.com/openai/codex/blob/main/sdk/typescript/README.md).
#### Clean up
When you exit the main program, the Daytona sandbox and all files are automatically deleted.
**Key advantages:**
- Secure, isolated execution in Daytona sandboxes
- Communicate with the agent directly in your terminal
- Automatic dev server detection and live preview links
- Multi-language and full-stack support
- Thread persistence across multiple requests
- Simple setup and automatic cleanup
import { Image } from 'astro:assets'
import chartImage from '../../../../assets/docs/images/chart-0.png'
You can use Daytona Sandbox to run AI-generated code to analyze data. Here's how the AI data analysis workflow typically looks:
1. Your user has a dataset in CSV format or other formats.
2. You prompt the LLM to generate code (usually Python) based on the user's data.
3. The sandbox runs the AI-generated code and returns the results.
4. The LLM receives feedback from the execution and can iterate multiple times to refine the code if needed.
5. You display the final results to the user.
---
## Build an AI Data Analyst with Daytona
This example shows how to build an AI-powered data analyst that automatically generates insights and visualizations from CSV data using Daytona's secure sandbox environment.
**What we'll build:** A system that analyzes a vehicle valuation dataset, identifies price relation to manufacturing year, and generates professional visualizations - all through natural language prompts to Claude. The system uses an agentic loop that allows Claude to iteratively refine the code based on execution results.
### 1. Project Setup
#### 1.1 Install Dependencies
Install the Daytona SDK and Anthropic SDK to your project:
`bash pip install daytona anthropic python-dotenv `
`bash npm install @daytonaio/sdk @anthropic-ai/sdk dotenv `
`bash gem install daytona anthropic dotenv `
#### 1.2 Configure Environment
Get your API keys and configure your environment:
1. **Daytona API key:** Get it from [Daytona Dashboard](https://app.daytona.io/dashboard/keys)
2. **Anthropic API key:** Get it from [Anthropic Console](https://console.anthropic.com/)
Create a `.env` file in your project:
```bash
DAYTONA_API_KEY=dtn_***
ANTHROPIC_API_KEY=sk-ant-***
```
### 2. Dataset Preparation
#### 2.1 Download Dataset
We'll be using a publicly available dataset of vehicle valuation. You can download it directly from:
[https://download.daytona.io/dataset.csv](https://download.daytona.io/dataset.csv)
Download the file and save it as `dataset.csv` in your project directory.
#### 2.2 Initialize Sandbox
Now create a [Daytona sandbox](https://www.daytona.io/docs/en/sandboxes.md#basic-sandbox-creation) and upload your dataset:
```python
from dotenv import load_dotenv
from daytona import Daytona
import os
load_dotenv()
# Create sandbox
daytona = Daytona() # The sandbox language is Python by default.
sandbox = daytona.create()
# Upload the dataset to the sandbox
sandbox.fs.upload_file("dataset.csv", "/home/daytona/dataset.csv")
```
```typescript
import 'dotenv/config'
import { Daytona } from '@daytonaio/sdk';
// Create sandbox
const daytona = new Daytona(); // The sandbox language is Python by default.
const sandbox = await daytona.create()
// Upload the dataset to the sandbox
await sandbox.fs.uploadFile('dataset.csv', '/home/daytona/dataset.csv')
```
```ruby
require 'daytona'
require 'dotenv/load'
# Create sandbox
daytona = Daytona::Daytona.new # The sandbox language is Python by default.
sandbox = daytona.create
# Upload the dataset to the sandbox
sandbox.fs.upload_file(File.read('dataset.csv'), '/home/daytona/dataset.csv')
```
### 3. Building the AI Data Analyst
Now we'll create the core functionality that connects Claude with Daytona to analyze data and generate visualizations.
#### 3.1 Code Execution Handler
First, let's create a function to handle code execution and chart extraction. This function returns execution results that can be fed back to the AI model:
```python
import base64
from typing import TypedDict
class ExecutionResult(TypedDict):
stdout: str
exit_code: int
charts: list
def run_ai_generated_code(sandbox, ai_generated_code: str) -> ExecutionResult:
execution = sandbox.process.code_run(ai_generated_code)
result = ExecutionResult(
stdout=execution.result or "",
exit_code=execution.exit_code,
charts=execution.artifacts.charts if execution.artifacts else []
)
# Save any charts that were generated
if execution.artifacts and execution.artifacts.charts:
result_idx = 0
for chart in execution.artifacts.charts:
if chart.png:
filename = f'chart-{result_idx}.png'
with open(filename, 'wb') as f:
f.write(base64.b64decode(chart.png))
print(f'✓ Chart saved to {filename}')
result_idx += 1
return result
```
```typescript
import fs from 'fs'
import { Sandbox } from '@daytonaio/sdk'
interface ExecutionResult {
stdout: string
exitCode: number
charts?: Array<{ png?: string }>
}
async function runAIGeneratedCode(
sandbox: Sandbox,
aiGeneratedCode: string
): Promise {
const execution = await sandbox.process.codeRun(aiGeneratedCode)
const result: ExecutionResult = {
stdout: execution.result || "",
exitCode: execution.exitCode,
charts: execution.artifacts?.charts
}
// Save any charts that were generated
if (execution.artifacts?.charts) {
let resultIdx = 0
for (const chart of execution.artifacts.charts) {
if (chart.png) {
const filename = `chart-${resultIdx}.png`
fs.writeFileSync(filename, chart.png, { encoding: 'base64' })
console.log(`✓ Chart saved to ${filename}`)
resultIdx++
}
}
}
return result
}
```
#### 3.2 Creating the Analysis Prompt
Next, we'll create the prompt that tells Claude about our dataset and what analysis we want. This prompt includes:
- Dataset schema and column descriptions
- The specific analysis request (vehicle price variation by manufacturing year)
- Instructions for code generation
```python
from anthropic import Anthropic
prompt = f"""
I have a CSV file with vehicle valuations saved in the sandbox at /home/daytona/dataset.csv.
Relevant columns:
- 'year': integer, the manufacturing year of the vehicle
- 'price_in_euro': float, the listed price of the vehicle in Euros
Analyze how price varies by manufacturing year.
Drop rows where 'year' or 'price_in_euro' is missing, non-numeric, or an outlier.
Create a line chart showing average price per year.
Write Python code that analyzes the dataset based on my request and produces a matplotlib chart accordingly.
Always finish with plt.show() to display the chart."""
anthropic = Anthropic()
```
```typescript
import Anthropic from '@anthropic-ai/sdk'
const prompt = `
I have a CSV file with vehicle valuations saved in the sandbox at /home/daytona/dataset.csv.
Relevant columns:
- 'year': integer, the manufacturing year of the vehicle
- 'price_in_euro': float, the listed price of the vehicle in Euros
Analyze how price varies by manufacturing year.
Drop rows where 'year' or 'price_in_euro' is missing, non-numeric, or an outlier.
Create a line chart showing average price per year.
Write Python code that analyzes the dataset based on my request and produces a matplotlib chart accordingly.
Always finish with plt.show() to display the chart.`
const anthropic = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY })
```
#### 3.3 Tool Definition
Define the tool that allows Claude to execute Python code in the sandbox:
```python
tools = [
{
'name': 'run_python_code',
'description': 'Run Python code in the sandbox environment and get execution results',
'input_schema': {
'type': 'object',
'properties': {
'code': {
'type': 'string',
'description': 'The Python code to run',
},
},
'required': ['code'],
},
},
]
```
```typescript
import type { Tool, ToolUseBlock } from '@anthropic-ai/sdk/resources/messages.mjs'
const tools: Tool[] = [
{
name: 'run_python_code',
description: 'Run Python code in the sandbox environment and get execution results',
input_schema: {
type: 'object',
properties: {
code: {
type: 'string',
description: 'The Python code to run',
},
},
required: ['code'],
},
},
]
```
#### 3.4 Agentic Loop Implementation
Now we'll implement the agentic loop that allows Claude to iteratively refine the code based on execution feedback. This enables Claude to fix errors, handle edge cases, and improve the analysis through multiple iterations:
```python
# Initialize conversation history
messages = [{'role': 'user', 'content': prompt}]
continue_loop = True
iteration_count = 0
max_iterations = 10
print("Starting agentic loop...\n")
while continue_loop and iteration_count < max_iterations:
iteration_count += 1
print(f"\n=== Iteration {iteration_count} ===")
print("Waiting for the model response...")
# Get response from Claude
msg = anthropic.messages.create(
model='claude-sonnet-4-5',
max_tokens=64000,
messages=messages,
tools=tools
)
# Log Claude's text response
for content_block in msg.content:
if content_block.type == 'text':
print("\nClaude's response:")
print(content_block.text)
# Check if Claude wants to use any tools
tool_uses = [block for block in msg.content if block.type == 'tool_use']
if len(tool_uses) == 0:
# No more tool uses, Claude is done
print("\nTask completed - no more actions needed.")
continue_loop = False
break
# Add Claude's response to message history
messages.append({'role': 'assistant', 'content': msg.content})
# Execute all tool calls and collect results
tool_results = []
for tool_use in tool_uses:
if tool_use.name == 'run_python_code':
code = tool_use.input['code']
print("\n--- Executing Python code in sandbox ---")
print(code)
print("--- End of code ---\n")
# Execute the code in the sandbox
execution_result = run_ai_generated_code(sandbox, code)
# Format the tool result
result_content = ""
if execution_result['exit_code'] == 0:
result_content += "Execution successful!\n\n"
if execution_result['stdout']:
result_content += f"Output:\n{execution_result['stdout']}\n"
if execution_result['charts'] and len(execution_result['charts']) > 0:
result_content += f"\nGenerated {len(execution_result['charts'])} chart(s)."
else:
result_content += "\nNote: No charts were generated. Make sure to use plt.show() to display the chart."
else:
result_content += f"Execution failed with exit code {execution_result['exit_code']}\n\n"
if execution_result['stdout']:
result_content += f"Output:\n{execution_result['stdout']}\n"
tool_results.append({
'type': 'tool_result',
'tool_use_id': tool_use.id,
'content': result_content
})
print("Execution result sent back to Claude.")
# Add tool results to conversation history
messages.append({'role': 'user', 'content': tool_results})
if iteration_count >= max_iterations:
print("\n⚠️ Reached maximum iteration limit. Task may not be complete.")
print("\n=== Agentic loop completed ===")
```
```typescript
import type { MessageParam } from '@anthropic-ai/sdk/resources/messages.mjs'
interface CodeRunToolInput {
code: string
}
// Initialize conversation history
const messages: MessageParam[] = [
{ role: 'user', content: initialPrompt }
]
let continueLoop = true
let iterationCount = 0
const maxIterations = 10
console.log("Starting agentic loop...\n")
while (continueLoop && iterationCount < maxIterations) {
iterationCount++
console.log(`\n=== Iteration ${iterationCount} ===`)
console.log("Waiting for the model response...")
// Get response from Claude
const stream = anthropic.messages.stream({
model: 'claude-sonnet-4-5',
max_tokens: 64000,
messages: messages,
tools: tools
})
const message = await stream.finalMessage()
// Log Claude's text response
for (const contentBlock of message.content) {
if (contentBlock.type === 'text') {
console.log("\nClaude's response:")
console.log(contentBlock.text)
}
}
// Check if Claude wants to use any tools
const toolUses = message.content.filter(
(block): block is ToolUseBlock => block.type === 'tool_use'
)
if (toolUses.length === 0) {
// No more tool uses, Claude is done
console.log("\nTask completed - no more actions needed.")
continueLoop = false
break
}
// Add Claude's response to message history
messages.push({
role: 'assistant',
content: message.content
})
// Execute all tool calls and collect results
const toolResults = []
for (const toolUse of toolUses) {
if (toolUse.name === 'run_python_code') {
const code = (toolUse.input as CodeRunToolInput).code
console.log("\n--- Executing Python code in sandbox ---")
console.log(code)
console.log("--- End of code ---\n")
// Execute the code in the sandbox
const executionResult = await runAIGeneratedCode(sandbox, code)
// Format the tool result
let resultContent = ""
if (executionResult.exitCode === 0) {
resultContent += "Execution successful!\n\n"
if (executionResult.stdout) {
resultContent += `Output:\n${executionResult.stdout}\n`
}
if (executionResult.charts && executionResult.charts.length > 0) {
resultContent += `\nGenerated ${executionResult.charts.length} chart(s).`
} else {
resultContent += "\nNote: No charts were generated. Make sure to use plt.show() to display the chart."
}
} else {
resultContent += `Execution failed with exit code ${executionResult.exitCode}\n\n`
if (executionResult.stdout) {
resultContent += `Output:\n${executionResult.stdout}\n`
}
}
toolResults.push({
type: 'tool_result' as const,
tool_use_id: toolUse.id,
content: resultContent
})
console.log("Execution result sent back to Claude.")
}
}
// Add tool results to conversation history
messages.push({
role: 'user',
content: toolResults
})
}
if (iterationCount >= maxIterations) {
console.log("\n⚠️ Reached maximum iteration limit. Task may not be complete.")
}
console.log("\n=== Agentic loop completed ===")
```
The agentic loop works as follows:
1. **Initial Request**: Send the initial prompt to Claude with the tool definition
2. **Iteration Loop**: For each iteration (up to 10 times):
- Claude generates a response with optional tool calls
- If there are tool calls, execute the Python code in the sandbox
- Send execution results back to Claude (including errors or success messages)
- Claude can then refine the code based on the feedback
3. **Completion**: Loop ends when Claude signals no more tool calls are needed or max iterations reached
This approach allows Claude to:
- Fix errors if the initial code fails
- Iterate on the analysis if results aren't satisfactory
- Handle edge cases discovered during execution
- Improve visualizations based on the actual data
**Key advantages of this approach:**
- **Secure execution:** Code runs in isolated Daytona sandboxes
- **Automatic artifact capture:** Charts, tables, and outputs are automatically extracted
- **Error handling:** Built-in error detection and logging
- **Language agnostic:** While we used Python here, Daytona supports multiple languages
### 4. Running Your Analysis
Now you can run the complete code to see the results.
```bash
python data-analysis.py
```
```bash
npx tsx data-analysis.ts
```
You should see the chart in your project directory that will look similar to this:
### 5. Complete Implementation
Here are the complete, ready-to-run examples with the agentic loop:
```python
import base64
from dotenv import load_dotenv
from daytona import Daytona, Sandbox
from anthropic import Anthropic
from typing import TypedDict
class ExecutionResult(TypedDict):
stdout: str
exit_code: int
charts: list
def main():
load_dotenv()
# Create sandbox
daytona = Daytona()
sandbox = daytona.create()
# Upload the dataset to the sandbox
sandbox.fs.upload_file("dataset.csv", "/home/daytona/dataset.csv")
initial_prompt = """
I have a CSV file with vehicle valuations saved in the sandbox at /home/daytona/dataset.csv.
Relevant columns:
- 'year': integer, the manufacturing year of the vehicle
- 'price_in_euro': float, the listed price of the vehicle in Euros
Analyze how price varies by manufacturing year.
Drop rows where 'year' or 'price_in_euro' is missing, non-numeric, or an outlier.
Create a line chart showing average price per year.
Write Python code that analyzes the dataset based on my request and produces a matplotlib chart accordingly.
Always finish with plt.show() to display the chart."""
anthropic = Anthropic()
tools = [
{
'name': 'run_python_code',
'description': 'Run Python code in the sandbox environment and get execution results',
'input_schema': {
'type': 'object',
'properties': {
'code': {
'type': 'string',
'description': 'The Python code to run',
},
},
'required': ['code'],
},
},
]
# Initialize conversation history
messages = [{'role': 'user', 'content': initial_prompt}]
continue_loop = True
iteration_count = 0
max_iterations = 10
print("Starting agentic loop...\n")
while continue_loop and iteration_count < max_iterations:
iteration_count += 1
print(f"\n=== Iteration {iteration_count} ===")
print("Waiting for the model response...")
# Get response from Claude
msg = anthropic.messages.create(
model='claude-sonnet-4-5',
max_tokens=64000,
messages=messages,
tools=tools
)
# Log Claude's text response
for content_block in msg.content:
if content_block.type == 'text':
print("\nClaude's response:")
print(content_block.text)
# Check if Claude wants to use any tools
tool_uses = [block for block in msg.content if block.type == 'tool_use']
if len(tool_uses) == 0:
# No more tool uses, Claude is done
print("\nTask completed - no more actions needed.")
continue_loop = False
break
# Add Claude's response to message history
messages.append({'role': 'assistant', 'content': msg.content})
# Execute all tool calls and collect results
tool_results = []
for tool_use in tool_uses:
if tool_use.name == 'run_python_code':
code = tool_use.input['code']
print("\n--- Executing Python code in sandbox ---")
print(code)
print("--- End of code ---\n")
# Execute the code in the sandbox
execution_result = run_ai_generated_code(sandbox, code)
# Format the tool result
result_content = ""
if execution_result['exit_code'] == 0:
result_content += "Execution successful!\n\n"
if execution_result['stdout']:
result_content += f"Output:\n{execution_result['stdout']}\n"
if execution_result['charts'] and len(execution_result['charts']) > 0:
result_content += f"\nGenerated {len(execution_result['charts'])} chart(s)."
else:
result_content += "\nNote: No charts were generated. Make sure to use plt.show() to display the chart."
else:
result_content += f"Execution failed with exit code {execution_result['exit_code']}\n\n"
if execution_result['stdout']:
result_content += f"Output:\n{execution_result['stdout']}\n"
tool_results.append({
'type': 'tool_result',
'tool_use_id': tool_use.id,
'content': result_content
})
print("Execution result sent back to Claude.")
# Add tool results to conversation history
messages.append({'role': 'user', 'content': tool_results})
if iteration_count >= max_iterations:
print("\n⚠️ Reached maximum iteration limit. Task may not be complete.")
print("\n=== Agentic loop completed ===")
def run_ai_generated_code(sandbox: Sandbox, ai_generated_code: str) -> ExecutionResult:
execution = sandbox.process.code_run(ai_generated_code)
result = ExecutionResult(
stdout=execution.result or "",
exit_code=execution.exit_code,
charts=execution.artifacts.charts if execution.artifacts else []
)
# Save any charts that were generated
if execution.artifacts and execution.artifacts.charts:
result_idx = 0
for chart in execution.artifacts.charts:
if chart.png:
filename = f'chart-{result_idx}.png'
with open(filename, 'wb') as f:
f.write(base64.b64decode(chart.png))
print(f'✓ Chart saved to {filename}')
result_idx += 1
return result
if __name__ == "__main__":
main()
```
```typescript
import "dotenv/config";
import fs from "fs";
import Anthropic from "@anthropic-ai/sdk";
import { Daytona, Sandbox } from "@daytonaio/sdk";
import type {
MessageParam,
Tool,
ToolUseBlock,
} from "@anthropic-ai/sdk/resources/messages.mjs";
interface CodeRunToolInput {
code: string;
}
interface ExecutionResult {
stdout: string;
exitCode: number;
charts?: Array<{ png?: string }>;
}
async function main() {
// Create sandbox
const daytona = new Daytona();
const sandbox = await daytona.create();
// Upload the dataset to the sandbox
await sandbox.fs.uploadFile("dataset.csv", "/home/daytona/dataset.csv");
const initialPrompt = `
I have a CSV file with vehicle valuations saved in the sandbox at /home/daytona/dataset.csv.
Relevant columns:
- 'year': integer, the manufacturing year of the vehicle
- 'price_in_euro': float, the listed price of the vehicle in Euros
Analyze how price varies by manufacturing year.
Drop rows where 'year' or 'price_in_euro' is missing, non-numeric, or an outlier.
Create a line chart showing average price per year.
Write Python code that analyzes the dataset based on my request and produces a matplotlib chart accordingly.
Always finish with plt.show() to display the chart.`;
const anthropic = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY });
const tools: Tool[] = [
{
name: "run_python_code",
description: "Run Python code in the sandbox environment and get execution results",
input_schema: {
type: "object",
properties: {
code: {
type: "string",
description: "The Python code to run",
},
},
required: ["code"],
},
},
];
// Initialize conversation history
const messages: MessageParam[] = [
{ role: "user", content: initialPrompt },
];
let continueLoop = true;
let iterationCount = 0;
const maxIterations = 10;
console.log("Starting agentic loop...\n");
while (continueLoop && iterationCount < maxIterations) {
iterationCount++;
console.log(`\n=== Iteration ${iterationCount} ===`);
console.log("Waiting for the model response...");
// Get response from Claude
const stream = anthropic.messages.stream({
model: "claude-sonnet-4-5",
max_tokens: 64000,
messages: messages,
tools: tools,
});
const message = await stream.finalMessage();
// Log Claude's text response
for (const contentBlock of message.content) {
if (contentBlock.type === "text") {
console.log("\nClaude's response:");
console.log(contentBlock.text);
}
}
// Check if Claude wants to use any tools
const toolUses = message.content.filter(
(block): block is ToolUseBlock => block.type === "tool_use"
);
if (toolUses.length === 0) {
// No more tool uses, Claude is done
console.log("\nTask completed - no more actions needed.");
continueLoop = false;
break;
}
// Add Claude's response to message history
messages.push({
role: "assistant",
content: message.content,
});
// Execute all tool calls and collect results
const toolResults = [];
for (const toolUse of toolUses) {
if (toolUse.name === "run_python_code") {
const code = (toolUse.input as CodeRunToolInput).code;
console.log("\n--- Executing Python code in sandbox ---");
console.log(code);
console.log("--- End of code ---\n");
// Execute the code in the sandbox
const executionResult = await runAIGeneratedCode(sandbox, code);
// Format the tool result
let resultContent = "";
if (executionResult.exitCode === 0) {
resultContent += `Execution successful!\n\n`;
if (executionResult.stdout) {
resultContent += `Output:\n${executionResult.stdout}\n`;
}
if (executionResult.charts && executionResult.charts.length > 0) {
resultContent += `\nGenerated ${executionResult.charts.length} chart(s).`;
} else {
resultContent += `\nNote: No charts were generated. Make sure to use plt.show() to display the chart.`;
}
} else {
resultContent += `Execution failed with exit code ${executionResult.exitCode}\n\n`;
if (executionResult.stdout) {
resultContent += `Output:\n${executionResult.stdout}\n`;
}
}
toolResults.push({
type: "tool_result" as const,
tool_use_id: toolUse.id,
content: resultContent,
});
console.log("Execution result sent back to Claude.");
}
}
// Add tool results to conversation history
messages.push({
role: "user",
content: toolResults,
});
}
if (iterationCount >= maxIterations) {
console.log(
"\n⚠️ Reached maximum iteration limit. Task may not be complete."
);
}
console.log("\n=== Agentic loop completed ===");
}
async function runAIGeneratedCode(
sandbox: Sandbox,
aiGeneratedCode: string
): Promise {
const execution = await sandbox.process.codeRun(aiGeneratedCode);
const result: ExecutionResult = {
stdout: execution.result || "",
exitCode: execution.exitCode,
charts: execution.artifacts?.charts,
};
// Save any charts that were generated
if (execution.artifacts?.charts) {
let resultIdx = 0;
for (const chart of execution.artifacts.charts) {
if (chart.png) {
const filename = `chart-${resultIdx}.png`;
fs.writeFileSync(filename, chart.png, {
encoding: "base64",
});
console.log(`✓ Chart saved to ${filename}`);
resultIdx++;
}
}
}
return result;
}
main().catch(console.error);
```
This guide demonstrates how to use the `DaytonaPlugin` for Google ADK to build an agent that generates, tests, and verifies code in a secure sandbox environment. The plugin enables agents to execute Python, JavaScript, and TypeScript code, run shell commands, and manage files within isolated Daytona sandboxes.
In this example, we build a code generator agent that takes a natural language description of a function, generates the implementation in TypeScript, creates test cases, executes them in the sandbox, and iterates until all tests pass before returning the verified code.
---
### 1. Workflow Overview
You describe the function you want in plain English, specifying the language (Python, JavaScript, or TypeScript). The agent generates the implementation, writes tests for it, and executes everything in a Daytona sandbox. If tests fail, the agent automatically fixes the code and re-runs until all tests pass. Only then does it return the verified, working code.
The key benefit: you receive code that has already been tested and verified, not just generated.
### 2. Project Setup
#### Clone the Repository
Clone the Daytona repository and navigate to the example directory:
```bash
git clone https://github.com/daytonaio/daytona
cd daytona/guides/python/google-adk/code-generator-agent/gemini
```
#### Install Dependencies
:::note[Python Version Requirement]
This example requires **Python 3.10 or higher**. It's recommended to use a virtual environment (e.g., `venv` or `poetry`) to isolate project dependencies.
:::
Install the required packages for this example:
```bash
pip install -U google-adk daytona-adk python-dotenv
```
The packages include:
- `google-adk`: Google's Agent Development Kit for building AI agents
- `daytona-adk`: Provides the `DaytonaPlugin` that enables secure code execution in Daytona sandboxes
- `python-dotenv`: Used for loading environment variables from `.env` file
#### Configure Environment
Get your API keys and configure your environment:
1. **Daytona API key:** Get it from [Daytona Dashboard](https://app.daytona.io/dashboard/keys)
2. **Google API key:** Get it from [Google AI Studio](https://aistudio.google.com/apikey)
Create a `.env` file in your project:
```bash
DAYTONA_API_KEY=dtn_***
GOOGLE_API_KEY=***
```
### 3. Understanding the Core Components
Before diving into the implementation, let's understand the key components we'll use:
#### Google ADK Components
- **Agent**: The AI model wrapper that processes requests and decides which tools to use. It receives instructions, has access to tools, and generates responses.
- **App**: A top-level container that bundles agents with plugins into a single configuration unit. It provides centralized management for shared resources and defines the root agent for your workflow.
- **InMemoryRunner**: The execution engine that runs agents and manages conversation state. It orchestrates the event-driven execution loop, handles message processing, and manages services like session history and artifact storage.
:::note[Running the Agent]
There are two ways to run Google ADK agents: using the `App` class with `InMemoryRunner`, or using `InMemoryRunner` directly with just an agent. The `App` serves as a configuration container that bundles agents with plugins, while the `Runner` handles actual execution and lifecycle management. This guide uses the `App` approach for cleaner organization of agents and plugins.
:::
#### Daytona Plugin
The `DaytonaPlugin` provides tools that allow the agent to:
- Execute code in Python, JavaScript, or TypeScript
- Run shell commands
- Upload and read files
- Start long-running background processes
All operations happen in an isolated sandbox that is automatically cleaned up when done.
### 4. Initialize Environment and Imports
First, we set up our imports and load environment variables:
```python
import asyncio
import logging
from dotenv import load_dotenv
from google.adk.agents import Agent
from google.adk.apps import App
from google.adk.runners import InMemoryRunner
from daytona_adk import DaytonaPlugin
load_dotenv()
logging.basicConfig(level=logging.DEBUG)
```
**What each import does:**
- `asyncio`: Required for running the async ADK runner
- `logging`: Enables debug output to see agent reasoning
- `load_dotenv`: Loads API keys from your `.env` file
- `Agent`, `App`, `InMemoryRunner`: Core Google ADK components
- `DaytonaPlugin`: Provides sandbox execution tools to the agent
**Logging configuration:**
The `logging.basicConfig(level=logging.DEBUG)` line configures Python's logging to show detailed debug output. You can adjust the logging level by passing different values:
- `logging.DEBUG`: Most verbose, shows all internal operations including DaytonaPlugin sandbox creation and tool invocations
- `logging.INFO`: Shows informational messages about agent progress
- `logging.WARNING`: Shows only warnings and errors
- `logging.ERROR`: Shows only errors
:::tip[Behind the Scenes]
With `DEBUG` level logging enabled, you can see the DaytonaPlugin's internal operations, including when the sandbox is created, when the `execute_code_in_daytona` tool is invoked, and when cleanup occurs. The plugin's `plugin_name` (configurable, defaults to `daytona_plugin`) appears in these log messages, making it easy to trace plugin activity.
:::
### 5. Define the Response Extractor
The ADK runner returns a list of events from the agent's execution. We need a helper function to extract the final text response:
```python
def extract_final_response(response: list) -> str:
"""Extract the final text response from a list of ADK events."""
for event in reversed(response):
text_parts = []
if hasattr(event, "text") and event.text:
return event.text
if hasattr(event, "content") and event.content:
content = event.content
if hasattr(content, "parts") and content.parts:
for part in content.parts:
if hasattr(part, "text") and part.text:
text_parts.append(part.text)
if text_parts:
return "".join(text_parts)
if hasattr(content, "text") and content.text:
return content.text
if isinstance(event, dict):
text = event.get("text") or event.get("content", {}).get("text")
if text:
return text
return ""
```
This function iterates through events in reverse order to find the last text response. It handles multiple possible event structures that the ADK may return.
### 6. Define the Agent Instruction
The instruction is critical - it defines how the agent behaves. Our instruction enforces a test-driven workflow:
```python
AGENT_INSTRUCTION = """You are a code generator agent that writes verified, working code.
You support Python, JavaScript, and TypeScript.
Your workflow for every code request:
1. Write the function
2. Write tests for it
3. EXECUTE the code in the sandbox to verify it works - do not skip this step
4. If execution fails, fix and re-execute until tests pass
5. Once verified, respond with ONLY the function (no tests)
You must always execute code before responding. Never return untested code.
Only include tests in your response if the user explicitly asks for them.
"""
```
**Key aspects of this instruction:**
- **Enforces execution**: The agent must run code in the sandbox before responding
- **Iterative fixing**: If tests fail, the agent fixes and retries
- **Controlled output**: By default, the final response contains only the working function. If you want to see the tests, include an instruction to return them in your prompt.
- **Multi-language**: Supports Python, JavaScript, and TypeScript
### 7. Configure the Daytona Plugin
Initialize the plugin that provides sandbox execution capabilities:
```python
plugin = DaytonaPlugin(
labels={"example": "code-generator"},
)
```
**Configuration options:**
- `labels`: Custom metadata tags for the sandbox (useful for tracking/filtering)
- `api_key`: Daytona API key (defaults to `DAYTONA_API_KEY` env var)
- `sandbox_name`: Custom name for the sandbox
- `plugin_name`: Name displayed in logs when the plugin logs messages (defaults to `daytona_plugin`)
- `env_vars`: Environment variables to set in the sandbox
- `auto_stop_interval`: Minutes before auto-stop (default: 15)
- `auto_delete_interval`: Minutes before auto-delete (disabled by default)
### 8. Create the Agent
Create the agent with the Gemini model, our instruction, and the Daytona tools:
```python
agent = Agent(
model="gemini-2.5-pro",
name="code_generator_agent",
instruction=AGENT_INSTRUCTION,
tools=plugin.get_tools(),
)
```
**Parameters explained:**
- `model`: The Gemini model to use for reasoning and code generation
- `name`: Identifier for the agent
- `instruction`: The behavioral guidelines we defined
- `tools`: List of tools from the Daytona plugin that the agent can use
### 9. Create the App and Runner
Bundle the agent and plugin into an App, then run it:
```python
app = App(
name="code_generator_app",
root_agent=agent,
plugins=[plugin],
)
async with InMemoryRunner(app=app) as runner:
prompt = "Write a TypeScript function called 'groupBy' that takes an array and a key function, and groups array elements by the key. Use proper type annotations."
response = await runner.run_debug(prompt)
final_response = extract_final_response(response)
print(final_response)
```
**What happens here:**
1. The `App` bundles the agent with the plugin for proper lifecycle management
2. `InMemoryRunner` is used as an async context manager (the `async with` statement). A context manager in Python automatically handles setup and cleanup - when the code enters the `async with` block, the runner initializes; when it exits (either normally or due to an error), the runner cleans up resources.
3. `run_debug` sends the prompt and returns all execution events
4. The sandbox is automatically deleted when the `async with` block exits - this cleanup happens regardless of whether the code completed successfully or raised an exception
### 10. Running the Example
Run the complete example:
```bash
python main.py
```
#### Understanding the Agent's Execution Flow
When you run the code, the agent works through your request step by step. With `logging.DEBUG` enabled, you'll see detailed output including:
- **DaytonaPlugin operations**: Sandbox creation, tool invocations (`execute_code_in_daytona`), and cleanup
- **LLM requests and responses**: The prompts sent to Gemini and the responses received
- **Plugin registration**: Confirmation that the `daytona_plugin` was registered with the agent
Here's what the debug output reveals about each step:
**Step 1: Sandbox Creation**
```
DEBUG:daytona_adk.plugin:Daytona sandbox created: e38f8574-48ac-48f1-a0ff-d922d02b0fcb
INFO:google_adk.google.adk.plugins.plugin_manager:Plugin 'daytona_plugin' registered.
```
The DaytonaPlugin creates an isolated sandbox and registers itself with the agent.
**Step 2: Agent receives the request**
The agent receives your prompt and understands it needs to create a TypeScript `groupBy` function with proper type annotations.
**Step 3: Agent generates code and tests**
The agent writes both the implementation and test cases, then calls the `execute_code_in_daytona` tool:
```
DEBUG:google_adk.google.adk.models.google_llm:
LLM Response:
-----------------------------------------------------------
Function calls:
name: execute_code_in_daytona, args: {'code': "...", 'language': 'typescript'}
```
**Step 4: Code execution in sandbox**
```
DEBUG:daytona_adk.plugin:Before tool: execute_code_in_daytona
DEBUG:daytona_adk.tools:Executing typescript code (length: 1570 chars)
DEBUG:daytona_adk.tools:Code execution completed with exit_code: 0
DEBUG:daytona_adk.plugin:After tool: execute_code_in_daytona
```
The plugin executes the code in the isolated TypeScript environment and returns the result.
**Step 5: Agent iterates if needed**
If tests fail (exit_code != 0), the agent analyzes the error, fixes the code, and re-executes until all tests pass.
**Step 6: Agent returns verified code**
Once tests pass, the agent responds with only the working function. If you included an instruction to return tests in your prompt, the tests will also be included in the response.
**Step 7: Cleanup**
```
INFO:daytona_adk.plugin:Deleting Daytona sandbox...
INFO:daytona_adk.plugin:Daytona sandbox deleted.
INFO:google_adk.google.adk.runners:Runner closed.
```
When the context manager exits, the sandbox is automatically deleted.
#### Example Output
When the agent completes the task, you'll see output like:
````
AGENT RESPONSE:
------------------------------------------------------------
```typescript
function groupBy(
array: T[],
keyFn: (item: T) => K
): Record {
return array.reduce((result, item) => {
const key = keyFn(item);
if (!result[key]) {
result[key] = [];
}
result[key].push(item);
return result;
}, {} as Record);
}
```
============================================================
App closed, sandbox cleaned up. Done!
````
The agent has already tested this code in the sandbox before returning it, so you can trust that the implementation works correctly.
#### Requesting Tests in the Response
If you want to see the tests that were executed in the sandbox, include an instruction to return them in your prompt:
```python
prompt = "Write a TypeScript function called 'groupBy' that takes an array and a key function, and groups array elements by the key. Use proper type annotations. Return the tests also in a separate code block"
```
With this prompt, the agent will return both the function and the tests:
````
```typescript
function groupBy(
array: T[],
keyFn: (item: T) => K
): Record {
return array.reduce((result, item) => {
const key = keyFn(item);
if (!result[key]) {
result[key] = [];
}
result[key].push(item);
return result;
}, {} as Record);
}
```
```typescript
import { deepStrictEqual } from 'assert';
// Test case 1: Group by a property of an object
const array1 = [
{ id: 1, category: 'A' },
{ id: 2, category: 'B' },
{ id: 3, category: 'A' },
];
const result1 = groupBy(array1, (item) => item.category);
deepStrictEqual(result1, {
A: [
{ id: 1, category: 'A' },
{ id: 3, category: 'A' },
],
B: [{ id: 2, category: 'B' }],
});
// Test case 2: Group by length of strings
const array2 = ['apple', 'banana', 'cherry', 'date'];
const result2 = groupBy(array2, (item) => item.length);
deepStrictEqual(result2, {
5: ['apple'],
6: ['banana', 'cherry'],
4: ['date'],
});
console.log('All tests passed!');
```
````
### 11. Complete Implementation
Here is the complete, ready-to-run example with additional output formatting for better readability:
```python
"""Code Generator & Tester Agent Example."""
import asyncio
import logging
from dotenv import load_dotenv
from google.adk.agents import Agent
from google.adk.apps import App
from google.adk.runners import InMemoryRunner
from daytona_adk import DaytonaPlugin
load_dotenv()
logging.basicConfig(level=logging.DEBUG)
def extract_final_response(response: list) -> str:
"""Extract the final text response from a list of ADK events."""
for event in reversed(response):
text_parts = []
if hasattr(event, "text") and event.text:
return event.text
if hasattr(event, "content") and event.content:
content = event.content
if hasattr(content, "parts") and content.parts:
for part in content.parts:
if hasattr(part, "text") and part.text:
text_parts.append(part.text)
if text_parts:
return "".join(text_parts)
if hasattr(content, "text") and content.text:
return content.text
if isinstance(event, dict):
text = event.get("text") or event.get("content", {}).get("text")
if text:
return text
return ""
AGENT_INSTRUCTION = """You are a code generator agent that writes verified, working code.
You support Python, JavaScript, and TypeScript.
Your workflow for every code request:
1. Write the function
2. Write tests for it
3. EXECUTE the code in the sandbox to verify it works - do not skip this step
4. If execution fails, fix and re-execute until tests pass
5. Once verified, respond with ONLY the function (no tests)
You must always execute code before responding. Never return untested code.
Only include tests in your response if the user explicitly asks for them.
"""
async def main() -> None:
"""Run the code generator agent example."""
plugin = DaytonaPlugin(
labels={"example": "code-generator"},
)
agent = Agent(
model="gemini-2.5-pro",
name="code_generator_agent",
instruction=AGENT_INSTRUCTION,
tools=plugin.get_tools(),
)
app = App(
name="code_generator_app",
root_agent=agent,
plugins=[plugin],
)
async with InMemoryRunner(app=app) as runner:
prompt = "Write a TypeScript function called 'groupBy' that takes an array and a key function, and groups array elements by the key. Use proper type annotations."
print("\n" + "=" * 60)
print("USER PROMPT:")
print("=" * 60)
print(prompt)
print("-" * 60)
response = await runner.run_debug(prompt)
final_response = extract_final_response(response)
print("\nAGENT RESPONSE:")
print("-" * 60)
print(final_response)
print("=" * 60)
print("\nApp closed, sandbox cleaned up. Done!")
if __name__ == "__main__":
asyncio.run(main())
```
**Key advantages of this approach:**
- **Verified code:** Every response has been tested in a real execution environment
- **Secure execution:** Code runs in isolated Daytona sandboxes, not on your machine
- **Multi-language support:** Generate and test Python, JavaScript, or TypeScript
- **Automatic iteration:** Agent fixes issues until tests pass
- **Flexible output:** Returns only the working function by default, or includes tests if explicitly requested in the prompt
### 12. API Reference
For the complete API reference of the Daytona ADK plugin, including all available tools and configuration options, see the [daytona-adk documentation](https://github.com/daytonaio/daytona-adk-plugin#available-tools).
Daytona provides a comprehensive set of guides to help you get started.
The guides cover a wide range of topics, from basic usage to advanced topics, and showcase various types of integrations between Daytona and other tools.
import { Image } from 'astro:assets'
import chartImage from '../../../../../assets/docs/images/langchain-data-analysis-chart.png'
This package provides the `DaytonaDataAnalysisTool` - LangChain tool integration that enables agents to perform secure Python data analysis in a sandboxed environment. It supports multi-step workflows, file uploads/downloads, and custom result handling, making it ideal for automating data analysis tasks with LangChain agents.
This page demonstrates the use of this tool with a basic example analyzing a vehicle valuations dataset. Our goal is to analyze how vehicle prices vary by manufacturing year and create a line chart showing average price per year.
---
### 1. Workflow Overview
You upload your dataset and provide a natural language prompt describing the analysis you want. The agent reasons about your request, determines how to use the `DaytonaDataAnalysisTool` to perform the task on your dataset, and executes the analysis securely in a Daytona sandbox.
You provide the data and describe what insights you need - the agent handles the rest.
### 2. Project Setup
#### Clone the Repository
Clone the [repository](https://github.com/daytonaio/daytona) and navigate to the example directory:
```bash
git clone https://github.com/daytonaio/daytona.git
cd daytona/guides/python/langchain/data-analysis/anthropic
```
#### Install Dependencies
:::note[Python Version Requirement]
This example requires **Python 3.10 or higher** because it uses LangChain 1.0+ syntax. It's recommended to use a virtual environment (e.g., `venv` or `poetry`) to isolate project dependencies.
:::
Install the required packages for this example:
```bash
pip install -U langchain langchain-anthropic langchain-daytona-data-analysis python-dotenv
```
The packages include:
- `langchain`: LangChain framework for building AI agents
- `langchain-anthropic`: Integration package connecting Claude (Anthropic) APIs and LangChain
- `langchain-daytona-data-analysis`: Provides the `DaytonaDataAnalysisTool` for LangChain agents
- `python-dotenv`: Used for loading environment variables from `.env` file
#### Configure Environment
Get your API keys and configure your environment:
1. **Daytona API key:** Get it from [Daytona Dashboard](https://app.daytona.io/dashboard/keys)
2. **Anthropic API key:** Get it from [Anthropic Console](https://console.anthropic.com/)
Create a `.env` file in your project:
```bash
DAYTONA_API_KEY=dtn_***
ANTHROPIC_API_KEY=sk-ant-***
```
### 3. Download Dataset
We'll be using a publicly available dataset of vehicle valuation. You can download it directly from:
[https://download.daytona.io/dataset.csv](https://download.daytona.io/dataset.csv)
Download the file and save it as `dataset.csv` in your project directory.
### 4. Initialize the Language Model
Models are the reasoning engine of LangChain agents - they drive decision-making, determine which tools to call, and interpret results.
In this example, we'll use Anthropic's Claude model, which excels at code generation and analytical tasks.
Configure the Claude model with the following parameters:
```python
from langchain_anthropic import ChatAnthropic
model = ChatAnthropic(
model_name="claude-sonnet-4-5-20250929",
temperature=0,
timeout=None,
max_retries=2,
stop=None
)
```
**Parameters explained:**
- `model_name`: Specifies the Claude model to use
- `temperature`: Tunes the degree of randomness in generation
- `max_retries`: Number of retries allowed for Anthropic API requests
:::tip[Learn More About Models]
For detailed information about LangChain models, different providers, and how to choose the right model for your use case, visit the [LangChain Models documentation](https://docs.langchain.com/oss/python/langchain/models).
:::
### 5. Define the Result Handler
When the agent executes Python code in the sandbox, it generates artifacts like charts and output logs. We can define a handler function to process these results.
This function will extract chart data from the execution artifacts and save them as PNG files:
```python
import base64
from daytona import ExecutionArtifacts
def process_data_analysis_result(result: ExecutionArtifacts):
# Print the standard output from code execution
print("Result stdout", result.stdout)
result_idx = 0
for chart in result.charts:
if chart.png:
# Charts are returned in base64 format
# Decode and save them as PNG files
with open(f'chart-{result_idx}.png', 'wb') as f:
f.write(base64.b64decode(chart.png))
print(f'Chart saved to chart-{result_idx}.png')
result_idx += 1
```
This handler processes execution artifacts by:
- Logging stdout output from the executed code
- Extracting chart data from the artifacts
- Decoding base64-encoded PNG charts
- Saving them to local files
### 6. Configure the Data Analysis Tool
Now we'll initialize the `DaytonaDataAnalysisTool` and upload our dataset.
```python
from langchain_daytona_data_analysis import DaytonaDataAnalysisTool
# Initialize the tool with our result handler
DataAnalysisTool = DaytonaDataAnalysisTool(
on_result=process_data_analysis_result
)
# Upload the dataset with metadata describing its structure
with open("./dataset.csv", "rb") as f:
DataAnalysisTool.upload_file(
f,
description=(
"This is a CSV file containing vehicle valuations. "
"Relevant columns:\n"
"- 'year': integer, the manufacturing year of the vehicle\n"
"- 'price_in_euro': float, the listed price of the vehicle in Euros\n"
"Drop rows where 'year' or 'price_in_euro' is missing, non-numeric, or an outlier."
)
)
```
**Key points:**
- The `on_result` parameter connects our custom result handler
- The `description` provides context about the dataset structure to the agent
- Column descriptions help the agent understand how to process the data
- Data cleaning instructions ensure quality analysis
### 7. Create and Run the Agent
Finally, we'll create the LangChain agent with our configured model and tool, then invoke it with our analysis request.
```python
from langchain.agents import create_agent
# Create the agent with the model and data analysis tool
agent = create_agent(model, tools=[DataAnalysisTool], debug=True)
# Invoke the agent with our analysis request
agent_response = agent.invoke({
"messages": [{
"role": "user",
"content": "Analyze how vehicles price varies by manufacturing year. Create a line chart showing average price per year."
}]
})
# Always close the tool to clean up sandbox resources
DataAnalysisTool.close()
```
**What happens here:**
1. The agent receives your natural language request
2. It determines it needs to use the `DaytonaDataAnalysisTool`
3. Agent generates Python code to analyze the data
4. Code executes securely in the Daytona sandbox
5. Results are processed by our handler function
6. Charts are saved to your local directory
7. Sandbox resources are cleaned up at the end
### 8. Running Your Analysis
Now you can run the complete code to see the results.
```bash
python data_analysis.py
```
#### Understanding the Agent's Execution Flow
When you run the code, the agent works through your request step by step. Here's what happens in the background:
**Step 1: Agent receives and interprets the request**
The agent acknowledges your analysis request:
```
AI Message: "I'll analyze how vehicle prices vary by manufacturing year and create a line chart showing the average price per year."
```
**Step 2: Agent generates Python code**
The agent generates Python code to explore the dataset first:
```python
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
# Load the dataset
df = pd.read_csv('/home/daytona/dataset.csv')
# Display basic info about the dataset
print("Dataset shape:", df.shape)
print("\nFirst few rows:")
print(df.head())
print("\nColumn names:")
print(df.columns.tolist())
print("\nData types:")
print(df.dtypes)
```
**Step 3: Code executes in Daytona sandbox**
The tool runs this code in a secure sandbox and returns the output:
```
Result stdout Dataset shape: (100000, 15)
First few rows:
Unnamed: 0 ... offer_description
0 75721 ... ST-Line Hybrid Adapt.LED+Head-Up-Display Klima
1 80184 ... blue Trend,Viele Extras,Top-Zustand
2 19864 ... 35 e-tron S line/Matrix/Pano/ACC/SONOS/LM 21
3 76699 ... 2.0 Lifestyle Plus Automatik Navi FAP
4 92991 ... 1.6 T 48V 2WD Spirit LED, WR
[5 rows x 15 columns]
Column names:
['Unnamed: 0', 'brand', 'model', 'color', 'registration_date', 'year',
'price_in_euro', 'power_kw', 'power_ps', 'transmission_type', 'fuel_type',
'fuel_consumption_l_100km', 'fuel_consumption_g_km', 'mileage_in_km',
'offer_description']
Data types:
Unnamed: 0 int64
brand object
model object
color object
registration_date object
year object
price_in_euro object
power_kw object
power_ps object
transmission_type object
fuel_type object
fuel_consumption_l_100km object
fuel_consumption_g_km object
mileage_in_km float64
offer_description object
dtype: object
```
**Step 4: Agent generates detailed analysis code**
Based on the initial dataset information, the agent generates more specific code to examine the key columns:
```python
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
# Load the dataset
df = pd.read_csv('/home/daytona/dataset.csv')
print("Dataset shape:", df.shape)
print("\nColumn names:")
print(df.columns.tolist())
# Check for year and price_in_euro columns
print("\nChecking 'year' column:")
print(df['year'].describe())
print("\nMissing values in 'year':", df['year'].isna().sum())
print("\nChecking 'price_in_euro' column:")
print(df['price_in_euro'].describe())
print("\nMissing values in 'price_in_euro':", df['price_in_euro'].isna().sum())
```
**Step 5: Execution results from sandbox**
The code executes and returns column statistics:
```
Result stdout Dataset shape: (100000, 15)
Column names:
['Unnamed: 0', 'brand', 'model', 'color', 'registration_date', 'year',
'price_in_euro', 'power_kw', 'power_ps', 'transmission_type', 'fuel_type',
'fuel_consumption_l_100km', 'fuel_consumption_g_km', 'mileage_in_km',
'offer_description']
Checking 'year' column:
count 100000
unique 49
top 2019
freq 12056
Name: year, dtype: object
Missing values in 'year': 0
Checking 'price_in_euro' column:
count 100000
unique 11652
top 19990
freq 665
Name: price_in_euro, dtype: object
Missing values in 'price_in_euro': 0
```
**Step 6: Agent generates final analysis and visualization code**
Now that the agent understands the data structure, it generates the complete analysis code with data cleaning, processing, and visualization:
```python
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
# Load the dataset
df = pd.read_csv('/home/daytona/dataset.csv')
print("Original dataset shape:", df.shape)
# Clean the data - remove rows with missing values in year or price_in_euro
df_clean = df.dropna(subset=['year', 'price_in_euro'])
print(f"After removing missing values: {df_clean.shape}")
# Convert to numeric and remove non-numeric values
df_clean['year'] = pd.to_numeric(df_clean['year'], errors='coerce')
df_clean['price_in_euro'] = pd.to_numeric(df_clean['price_in_euro'], errors='coerce')
# Remove rows where conversion failed
df_clean = df_clean.dropna(subset=['year', 'price_in_euro'])
print(f"After removing non-numeric values: {df_clean.shape}")
# Remove outliers using IQR method for both year and price
def remove_outliers(df, column):
Q1 = df[column].quantile(0.25)
Q3 = df[column].quantile(0.75)
IQR = Q3 - Q1
lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR
return df[(df[column] >= lower_bound) & (df[column] <= upper_bound)]
df_clean = remove_outliers(df_clean, 'year')
print(f"After removing year outliers: {df_clean.shape}")
df_clean = remove_outliers(df_clean, 'price_in_euro')
print(f"After removing price outliers: {df_clean.shape}")
print("\nCleaned data summary:")
print(df_clean[['year', 'price_in_euro']].describe())
# Calculate average price per year
avg_price_by_year = df_clean.groupby('year')['price_in_euro'].mean().sort_index()
print("\nAverage price by year:")
print(avg_price_by_year)
# Create line chart
plt.figure(figsize=(14, 7))
plt.plot(avg_price_by_year.index, avg_price_by_year.values, marker='o',
linewidth=2, markersize=6, color='#2E86AB')
plt.xlabel('Manufacturing Year', fontsize=12, fontweight='bold')
plt.ylabel('Average Price (€)', fontsize=12, fontweight='bold')
plt.title('Average Vehicle Price by Manufacturing Year', fontsize=14,
fontweight='bold', pad=20)
plt.grid(True, alpha=0.3, linestyle='--')
plt.xticks(rotation=45)
# Format y-axis to show currency
ax = plt.gca()
ax.yaxis.set_major_formatter(plt.FuncFormatter(lambda x, p: f'€{x:,.0f}'))
plt.tight_layout()
plt.show()
# Additional statistics
print(f"\nTotal number of vehicles analyzed: {len(df_clean)}")
print(f"Year range: {int(df_clean['year'].min())} - {int(df_clean['year'].max())}")
print(f"Price range: €{df_clean['price_in_euro'].min():.2f} - €{df_clean['price_in_euro'].max():.2f}")
print(f"Overall average price: €{df_clean['price_in_euro'].mean():.2f}")
```
This comprehensive code performs data cleaning, outlier removal, calculates averages by year, and creates a professional visualization.
**Step 7: Final execution and chart generation**
The code executes successfully in the sandbox, processes the data, and generates the visualization:
```
Result stdout Original dataset shape: (100000, 15)
After removing missing values: (100000, 15)
After removing non-numeric values: (99946, 15)
After removing year outliers: (96598, 15)
After removing price outliers: (90095, 15)
Cleaned data summary:
year price_in_euro
count 90095.000000 90095.000000
mean 2016.698563 22422.266707
std 4.457647 12964.727116
min 2005.000000 150.000000
25% 2014.000000 12980.000000
50% 2018.000000 19900.000000
75% 2020.000000 29500.000000
max 2023.000000 62090.000000
Average price by year:
year
2005.0 5968.124319
2006.0 6870.881523
2007.0 8015.234473
2008.0 8788.644495
2009.0 8406.198576
2010.0 10378.815972
2011.0 11540.640435
2012.0 13306.642261
2013.0 14512.707025
2014.0 15997.682899
2015.0 18563.864358
2016.0 20124.556294
2017.0 22268.083322
2018.0 24241.123673
2019.0 26757.469111
2020.0 29400.163494
2021.0 30720.168646
2022.0 33861.717552
2023.0 33119.840175
Name: price_in_euro, dtype: float64
Total number of vehicles analyzed: 90095
Year range: 2005 - 2023
Price range: €150.00 - €62090.00
Overall average price: €22422.27
Chart saved to chart-0.png
```
The agent successfully completed the analysis, showing that vehicle prices generally increased from 2005 (€5,968) to 2022 (€33,862), with a slight decrease in 2023. The result handler captured the generated chart and saved it as `chart-0.png`.
You should see the chart in your project directory that will look similar to this:
### 9. Complete Implementation
Here is the complete, ready-to-run example:
```python
import base64
from dotenv import load_dotenv
from langchain.agents import create_agent
from langchain_anthropic import ChatAnthropic
from daytona import ExecutionArtifacts
from langchain_daytona_data_analysis import DaytonaDataAnalysisTool
load_dotenv()
model = ChatAnthropic(
model_name="claude-sonnet-4-5-20250929",
temperature=0,
timeout=None,
max_retries=2,
stop=None
)
def process_data_analysis_result(result: ExecutionArtifacts):
# Print the standard output from code execution
print("Result stdout", result.stdout)
result_idx = 0
for chart in result.charts:
if chart.png:
# Save the png to a file
# The png is in base64 format.
with open(f'chart-{result_idx}.png', 'wb') as f:
f.write(base64.b64decode(chart.png))
print(f'Chart saved to chart-{result_idx}.png')
result_idx += 1
def main():
DataAnalysisTool = DaytonaDataAnalysisTool(
on_result=process_data_analysis_result
)
try:
with open("./dataset.csv", "rb") as f:
DataAnalysisTool.upload_file(
f,
description=(
"This is a CSV file containing vehicle valuations. "
"Relevant columns:\n"
"- 'year': integer, the manufacturing year of the vehicle\n"
"- 'price_in_euro': float, the listed price of the vehicle in Euros\n"
"Drop rows where 'year' or 'price_in_euro' is missing, non-numeric, or an outlier."
)
)
agent = create_agent(model, tools=[DataAnalysisTool], debug=True)
agent_response = agent.invoke(
{"messages": [{"role": "user", "content": "Analyze how vehicles price varies by manufacturing year. Create a line chart showing average price per year."}]}
)
finally:
DataAnalysisTool.close()
if __name__ == "__main__":
main()
```
**Key advantages of this approach:**
- **Secure execution:** Code runs in isolated Daytona sandbox
- **Automatic artifact capture:** Charts, tables, and outputs are automatically extracted
- **Natural language interface:** Describe analysis tasks in plain English
- **Framework integration:** Seamlessly works with LangChain's agent ecosystem
### 10. API Reference
The following public methods are available on `DaytonaDataAnalysisTool`:
#### download_file
```python
def download_file(remote_path: str) -> bytes
```
Downloads a file from the sandbox by its remote path.
**Arguments**:
- `remote_path` - str: Path to the file in the sandbox.
**Returns**:
- `bytes` - File contents.
**Example**:
```python
# Download a file from the sandbox
file_bytes = tool.download_file("/home/daytona/results.csv")
```
#### upload_file
```python
def upload_file(file: IO, description: str) -> SandboxUploadedFile
```
Uploads a file to the sandbox. The file is placed in `/home/daytona/`.
**Arguments**:
- `file` - IO: File-like object to upload.
- `description` - str: Description of the file, explaining its purpose and the type of data it contains.
**Returns**:
- [`SandboxUploadedFile`](#sandboxuploadedfile) - Metadata about the uploaded file.
**Example**:
Suppose you want to analyze sales data for a retail business. You have a CSV file named `sales_q3_2025.csv` containing columns like `transaction_id`, `date`, `product`, `quantity`, and `revenue`. You want to upload this file and provide a description that gives context for the analysis.
```python
with open("sales_q3_2025.csv", "rb") as f:
uploaded = tool.upload_file(
f,
"CSV file containing Q3 2025 retail sales transactions. Columns: transaction_id, date, product, quantity, revenue."
)
```
#### remove_uploaded_file
```python
def remove_uploaded_file(uploaded_file: SandboxUploadedFile) -> None
```
Removes a previously uploaded file from the sandbox.
**Arguments**:
- `uploaded_file` - [`SandboxUploadedFile`](#sandboxuploadedfile): The file to remove.
**Returns**:
- None
**Example**:
```python
# Remove an uploaded file
tool.remove_uploaded_file(uploaded)
```
#### get_sandbox
```python
def get_sandbox() -> Sandbox
```
Gets the current sandbox instance.
This method provides access to the Daytona sandbox instance, allowing you to inspect sandbox properties and metadata, as well as perform any sandbox-related operations. For details on available attributes and methods, see the [Sandbox](#sandbox) data structure section below.
**Arguments**:
- None
**Returns**:
- [`Sandbox`](#sandbox) - Sandbox instance.
**Example**:
```python
sandbox = tool.get_sandbox()
```
#### install_python_packages
```python
def install_python_packages(package_names: str | list[str]) -> None
```
Installs one or more Python packages in the sandbox using pip.
**Arguments**:
- `package_names` - str | list[str]: Name(s) of the package(s) to install.
**Returns**:
- None
:::note
The list of preinstalled packages in a sandbox can be found at [Daytona's Default Snapshot documentation](https://www.daytona.io/docs/en/snapshots.md#default-snapshots).
:::
**Example**:
```python
# Install a single package
tool.install_python_packages("pandas")
# Install multiple packages
tool.install_python_packages(["numpy", "matplotlib"])
```
#### close
```python
def close() -> None
```
Closes and deletes the sandbox environment.
**Arguments**:
- None
**Returns**:
- None
:::note
Call this method when you are finished with all data analysis tasks to properly clean up resources and avoid unnecessary usage.
:::
**Example**:
```python
# Close the sandbox and clean up
tool.close()
```
### 11. Data Structures
#### SandboxUploadedFile
Represents metadata about a file uploaded to the sandbox.
- `name`: `str` - Name of the uploaded file in the sandbox
- `remote_path`: `str` - Full path to the file in the sandbox
- `description`: `str` - Description provided during upload
#### Sandbox
Represents a Daytona sandbox instance.
See the full structure and API in the [Daytona Python SDK Sandbox documentation](https://www.daytona.io/docs/en/python-sdk/sync/sandbox.md#sandbox).
import { Image } from 'astro:assets'
import lettaCodeAgentResult from '../../../../../assets/docs/images/letta-code-agent-result.gif'
This guide demonstrates how to run an autonomous coding agent based on [Letta Code](https://docs.letta.com/letta-code/) inside a Daytona sandbox environment. The agent can develop web apps, write code in any language, install dependencies, and run scripts. Letta Code uses stateful agents with built-in memory, allowing conversations to persist across sessions.
---
### 1. Workflow Overview
When you launch the main script, a Daytona sandbox is created and Letta Code is installed inside it. The agent is configured with a custom Daytona-aware system prompt.
The script provides an interactive CLI interface where you can chat with the agent and issue commands:
```
$ npm run start
Creating sandbox...
Installing Letta Code...
Starting Letta Code...
Initializing agent...
Agent initialized. Press Ctrl+C at any time to exit.
User: create a beautiful, professional themed app that lets me write markdown documents and render them live
Thinking...
🔧 TodoWrite
🔧 Write /home/daytona/markdown-editor/index.html
🔧 TodoWrite
🔧 Start HTTP server on port 8080
🔧 TodoWrite
Perfect! I've created a beautiful markdown editor with live preview for you! 🎉
## Access your app here:
https://8080-c157e5cb-5e11-4bb6-883d-c873169223b8.proxy.daytona.works
## Features:
✨ **Live Preview** — Real-time markdown rendering
📝 **Full Markdown Support** — Headers, text styles, lists, code blocks, tables, links, images
💾 **Auto-Save** — Persists to browser localStorage
📥 **Export** — Download as `.md` or standalone `.html`
```
The agent can host web apps and provide you with a preview link using the [Daytona Preview Links](https://www.daytona.io/docs/en/preview-and-authentication.md) feature. When your task involves running or previewing a web application, the agent automatically hosts the app and generates a link for you to inspect the live result:
You can continue interacting with your agent until you are finished. When you exit the program, the sandbox will be deleted automatically.
### 2. Project Setup
#### Clone the Repository
First, clone the daytona [repository](https://github.com/daytonaio/daytona.git) and navigate to the example directory:
```bash
git clone https://github.com/daytonaio/daytona.git
cd daytona/guides/typescript/letta-code
```
#### Configure Environment
Get your Daytona API key from the [Daytona Dashboard](https://app.daytona.io/dashboard/keys) and your Letta API key from [Letta Platform](https://app.letta.com/api-keys).
Copy `.env.example` to `.env` and add your keys:
```bash
DAYTONA_API_KEY=your_daytona_key
SANDBOX_LETTA_API_KEY=your_letta_api_key
```
:::caution[API Key Security]
In this example, your Letta API key is passed into the sandbox environment and may be accessible to any code executed within it.
:::
#### Local Usage
:::note[Node.js Version]
Node.js 18 or newer is required to run this example. Please ensure your environment meets this requirement before proceeding.
:::
Install dependencies:
```bash
npm install
```
Run the example:
```bash
npm run start
```
The Letta Code agent will initialize and present an interactive prompt where you can issue commands.
### 3. Understanding the Agent's Architecture
This example consists of two main TypeScript files:
- **index.ts**: The main program that creates the Daytona sandbox, installs Letta Code, configures the system prompt, and provides an interactive CLI interface.
- **letta-session.ts**: A helper class that manages PTY-based bidirectional communication with Letta Code, handling JSON message streaming and response parsing.
#### Initialization
On initialization, the main program:
1. Creates a new [Daytona sandbox](https://www.daytona.io/docs/en/sandboxes.md) with your Letta API key included in the environment variables.
2. Installs Letta Code globally inside the sandbox by running `npm install` with [process execution](https://www.daytona.io/docs/en/process-code-execution.md#process-execution).
3. Creates a [PTY (pseudoterminal)](https://www.daytona.io/docs/en/pty.md) session in the sandbox for bidirectional communication with Letta Code.
4. Launches Letta Code in [bidirectional headless mode](https://docs.letta.com/letta-code/headless/) with stream-json format through the PTY.
5. Waits for user input and sends prompts to the agent through the PTY session.
#### Main Program Code
The program creates a [Daytona sandbox](https://www.daytona.io/docs/en/sandboxes.md) with the Letta API key passed as an environment variable:
```typescript
sandbox = await daytona.create({
envVars: { LETTA_API_KEY: process.env.SANDBOX_LETTA_API_KEY },
})
```
#### Running Letta Code in a Pseudoterminal
A [PTY (pseudoterminal)](https://www.daytona.io/docs/en/pty.md) is created for bidirectional communication with Letta Code:
```typescript
this.ptyHandle = await this.sandbox.process.createPty({
id: `letta-pty-${Date.now()}`,
onData: (data: Uint8Array) => this.handleData(data),
})
```
Letta Code is then launched in [bidirectional headless mode](https://docs.letta.com/letta-code/headless/#bidirectional-mode) through the PTY:
```typescript
await this.ptyHandle.sendInput(
`letta --new --system-custom "${systemPrompt.replace(/"/g, '\\"')}" --input-format stream-json --output-format stream-json --yolo -p\n`,
)
```
The `stream-json` setting is used for the input and output formats, enabling our program to send and receive JSON messages to and from the agent in real-time.
The `--system-custom` prompt allows us to pass a custom system prompt to the agent. Our prompt configures the agent with Daytona-specific instructions, including a URL pattern so the agent can generate preview links.
The `--yolo` flag allows the agent to run shell commands without requiring explicit user approval for each command.
#### Message Handling
To send prompts to the agent, the main script calls the `processPrompt()` method, which formats the user input as a JSON message and sends it to the PTY using `this.ptyHandle.sendInput()` as demonstrated above.
Formatted user messages look like this:
```json
{"type": "user", "message": {"role": "user", "content": "create a simple web server"}}
```
The agent responds with streaming JSON messages. Tool calls arrive as fragments:
```json
{"type": "message", "message_type": "approval_request_message", "tool_call": {"tool_call_id": "call_123", "name": "Bash", "arguments": "{\"command\": \"python3 -m http.server 8080\"}"}}
```
These JSON fragments are parsed by the `handleParsedMessage()` method. When multiple consecutive fragments are received for the same tool call, they are combined into a single tool call object. When a tool call or message is finished, the result is formatted and displayed to the user.
#### Clean up
When you exit the main program, the Daytona sandbox and all files are automatically deleted.
**Key advantages:**
- Secure, isolated execution in Daytona sandboxes
- Stateful agents with persistent memory across sessions
- Full Letta Code capabilities including file operations and shell commands
- Agents can be viewed in [Letta's Agent Development Environment](https://app.letta.com/)
- Automatic preview link generation for hosted services
- Multi-language and full-stack support
- Simple setup and automatic cleanup
This guide demonstrates how to configure the [Mastra coding agent](https://github.com/mastra-ai/template-coding-agent) to use Daytona sandboxes, enabling you to leverage AI capabilities for any coding-related task in a secure, isolated environment.
---
### 1. Workflow Overview
Once configured, you can use Mastra Studio to interact with the coding agent through a ChatGPT-like interface. This enables human-in-the-loop workflows where you can guide the agent, review its decisions, and iterate on solutions in real-time; all while the agent executes tasks securely within Daytona sandboxes.
### 2. Project Setup
:::note[Node.js Version]
Node.js version 20 or higher is required to run the coding agent. Please ensure your environment meets this requirement before proceeding.
:::
#### Clone the Repository
Clone the Mastra coding agent template repository, which includes the agent implementation and Daytona integration:
```bash
git clone https://github.com/mastra-ai/template-coding-agent.git
cd template-coding-agent
```
#### Configure Environment
Create a `.env` file in the project root directory:
```bash
touch .env
```
The `.env` file requires the following configuration:
- **LLM Provider**: The AI model provider for your coding agent
- **Model**: The specific model to use from your chosen provider
- **Sandbox Provider**: Daytona configuration for isolated execution
For this guide, we'll use OpenAI as the LLM provider with the `gpt-4o-mini` model:
```env
OPENAI_API_KEY=your_openai_key
MODEL=openai/gpt-4o-mini
```
Next, configure Daytona as your sandbox provider by adding your API key (available from the [Daytona Dashboard](https://app.daytona.io/dashboard/keys)):
```env
DAYTONA_API_KEY=your-daytona-api-key-here
```
#### Install Dependencies
Install the required packages using pnpm:
```bash
pnpm install
```
### 3. Running the Agent
Mastra Studio provides a ChatGPT-like interface for interacting with your coding agent. This mode offers:
- **Conversation History**: Previous conversations are stored and organized in threads
- **Visual Debugging**: Inspect agent execution steps, workflow, and tool calls
- **Model Switching**: Easily switch between different AI models
- **Tool Inspection**: View which tools your agent is using in real-time
For a complete overview of all features and capabilities, visit the [Mastra Studio documentation](https://mastra.ai/docs/getting-started/studio).
Start the dev server with:
```bash
pnpm run dev
```
If the dev server starts successfully, you'll see the terminal output displaying the URLs where you can access Mastra Studio:
```bash
│ Studio: http://localhost:4111
│ API: http://localhost:4111/api
```
Once started, open the provided URL in your browser to access the interactive interface. You can interact with your agent while monitoring its workflow in the terminal, where detailed logs show execution steps and low-level parameters.
Below is an example of terminal logs generated when the agent calls the `writeFile` tool to create a JavaScript file with a basic "Hello, world!" output:
```json
{
"text": "",
"toolCalls": [
{
"type": "tool-call",
"runId": "ab2a1d08-91c6-4028-9046-3446a721527f",
"from": "AGENT",
"payload": {
"toolCallId": "call_NiLLgBmgrYLSL0MsrG54E4A5",
"toolName": "writeFile",
"args": {
"sandboxId": "2152d23b-5742-47c2-9992-4414d4144869",
"path": "hello.js",
"content": "console.log('Hello, world!');"
},
"providerMetadata": {
"openai": {
"itemId": "fc_00bba3412cd22a2b0069399fbaeef881909b0583f359cbc33c"
}
}
}
}
],
"toolResults": [
{
"type": "tool-result",
"runId": "ab2a1d08-91c6-4028-9046-3446a721527f",
"from": "AGENT",
"payload": {
"args": {
"sandboxId": "2152d23b-5742-47c2-9992-4414d4144869",
"path": "hello.js",
"content": "console.log('Hello, world!');"
},
"toolCallId": "call_NiLLgBmgrYLSL0MsrG54E4A5",
"toolName": "writeFile",
"result": {
"success": true,
"path": "/home/daytona/hello.js"
},
"providerMetadata": {
"openai": {
"itemId": "fc_00bba3412cd22a2b0069399fbaeef881909b0583f359cbc33c"
}
}
}
}
],
"finishReason": "tool-calls",
"usage": {
"inputTokens": 4243,
"outputTokens": 53,
"totalTokens": 4296,
"reasoningTokens": 0,
"cachedInputTokens": 4096
},
"runId": "ab2a1d08-91c6-4028-9046-3446a721527f"
}
```
These logs show complete visibility into tool execution including arguments, results, token usage with caching metrics, and unique identifiers for debugging.
### 4. Example Usage
Let's walk through a practical example to see the Mastra coding agent and Daytona sandbox integration in action. We'll ask the agent to complete the following task:
> _"Create a Python file with a function that reverses a string, write a test file for it, and run the tests."_
#### Agent Workflow
The agent executes this task through a series of coordinated steps, utilizing different tools to interact with the Daytona sandbox:
##### 1. Create Sandbox
The agent first provisions a new Daytona sandbox for Python development:
**Tool:** `createSandbox`
**Arguments:**
```json
{
"name": "reverse_string_project",
"labels": null,
"language": "python",
"envVars": null
}
```
**Result:**
```json
{
"sandboxId": "bdfa9456-4945-43a7-97df-b9bfbcbdc62e"
}
```
##### 2. Write Project Files
Next, the agent creates both the implementation and test files in a single operation:
**Tool:** `writeFiles`
**Arguments:**
```json
{
"sandboxId": "bdfa9456-4945-43a7-97df-b9bfbcbdc62e",
"files": [
{
"path": "reverse_string.py",
"data": "def reverse_string(s):\n \"\"\"Return the reversed version of the input string s.\"\"\"\n return s[::-1]\n"
},
{
"path": "test_reverse_string.py",
"data": "import unittest\nfrom reverse_string import reverse_string\n\nclass TestReverseString(unittest.TestCase):\n def test_regular(self):\n self.assertEqual(reverse_string(\"hello\"), \"olleh\")\n def test_empty(self):\n self.assertEqual(reverse_string(\"\"), \"\")\n def test_single_char(self):\n self.assertEqual(reverse_string(\"a\"), \"a\")\n def test_numbers(self):\n self.assertEqual(reverse_string(\"12345\"), \"54321\")\n\nif __name__ == \"__main__\":\n unittest.main()\n"
}
]
}
```
**Result:**
```json
{
"success": true,
"filesWritten": [
"/home/daytona/reverse_string.py",
"/home/daytona/test_reverse_string.py"
]
}
```
##### 3. Execute Tests
Finally, the agent runs the test suite to verify the implementation:
**Tool:** `runCommand`
**Arguments:**
```json
{
"sandboxId": "bdfa9456-4945-43a7-97df-b9bfbcbdc62e",
"command": "python3 test_reverse_string.py",
"envs": null,
"workingDirectory": null,
"timeoutSeconds": 20,
"captureOutput": true
}
```
**Result:**
```json
{
"success": true,
"exitCode": 0,
"stdout": "....\n----------------------------------------------------------------------\nRan 4 tests in 0.000s\n\nOK\n",
"command": "python3 test_reverse_string.py",
"executionTime": 218
}
```
#### Agent Response
After successfully completing all steps, the agent provides a detailed summary:
```
The project is complete! Here's what was done:
✓ Created reverse_string.py with a function to reverse a string.
✓ Created test_reverse_string.py using Python's unittest to test the function with several cases.
✓ Ran the tests—all tests passed successfully.
Test Output:
....
----------------------------------------------------------------------
Ran 4 tests in 0.000s
OK
Would you like to see the code for either file or make any changes?
```
This example demonstrates how the agent autonomously handles the entire development workflow, from environment setup to test execution, all within the secure Daytona sandbox environment.
:::tip[Sandbox Management]
After the agent completes its task, you'll see the active sandbox in your [Daytona Dashboard](https://app.daytona.io/dashboard). It's recommended to clean up resources when finished, unless your use case requires the sandbox to remain active (e.g. for preview URLs or ongoing development).
:::
**Key Advantages**
- **Secure Isolation**: All agent operations run in isolated Daytona sandboxes, protecting your local environment
- **Multi-Language Support**: Execute code across different programming languages without local setup
- **Enhanced Debugging**: Use Mastra Studio to visualize and debug agent workflows in real-time
- **Scalable Execution**: Leverage Daytona's cloud infrastructure for resource-intensive tasks
Guides for running OpenClaw with Daytona.
This guide walks you through setting up [OpenClaw](https://openclaw.ai/) inside a Daytona sandbox and configuring Telegram and WhatsApp channels.
Running OpenClaw in a Daytona sandbox keeps your AI assistant isolated from your local machine, provides a secure environment for code execution, and ensures your bot stays online 24/7 without tying up your personal computer.
### Prerequisites
- Daytona account and API key (Get it from [Daytona Dashboard](https://app.daytona.io/dashboard/keys))
- Local terminal (macOS, Linux, or Windows)
### Install the Daytona CLI
```bash
brew install daytonaio/cli/daytona
```
```bash
powershell -Command "irm https://get.daytona.io/windows | iex"
```
:::note
Already have the CLI? Check your version with `daytona --version`. If it's below **0.135.0**, [upgrade to the latest version](https://www.daytona.io/docs/en/getting-started.md#cli).
:::
### Authenticate with Daytona
Log in to your Daytona account using your API key:
```bash
daytona login --api-key=YOUR_API_KEY
```
Replace `YOUR_API_KEY` with your actual Daytona API key.
### Create a Sandbox
Create a sandbox for running OpenClaw:
```bash
daytona sandbox create --name openclaw --snapshot daytona-medium --auto-stop 0
```
OpenClaw comes preinstalled in the default Daytona snapshot, so the command above is all you need.
:::note
The `--auto-stop 0` flag disables automatic shutdown, keeping OpenClaw accessible until you manually stop or delete the sandbox. The `daytona-medium` snapshot is required because the OpenClaw gateway needs a minimum of 2GB memory.
:::
### Connect to the Sandbox
SSH into your sandbox:
```bash
daytona ssh openclaw
```
### Run OpenClaw Onboarding
Start the onboarding process:
```bash
openclaw onboard
```
:::note
The model provider steps below are for Anthropic. If using a different provider, follow the prompts for your chosen option.
:::
Follow the prompts:
1. **Security acknowledgment:** Accept to continue
2. **Onboarding mode:** Select **Quickstart**
3. **Model/auth provider:** Select **Anthropic**
4. **Anthropic auth method:** Select **Anthropic API key**
5. **Enter Anthropic API key:** Paste your API key
6. **Default model:** Keep current (default: `anthropic/claude-opus-4-5`)
7. **Select channel:** Choose **Skip for now** (we'll configure channels later)
8. **Configure skills:** Select **No** (configure later based on your needs)
9. **Enable hooks:** Select **Skip for now** (configure later based on your needs)
10. **Gateway service:** Select **Skip** (already installed)
When onboarding finishes, the output will display a **Dashboard ready** section with a dashboard link. Your gateway token is the value after `?token=` in the URL. Save this token - you'll need it to connect to the dashboard.
Also, OpenClaw will ask you to **Install shell completion script?** - choose whatever you prefer, this is optional and doesn't affect functionality.
### Start the Gateway
Run the gateway in the background:
```bash
nohup openclaw gateway run > /tmp/gateway.log 2>&1 &
```
The `&` runs the gateway as a background process, keeping your terminal free for other commands. The `nohup` ensures the gateway keeps running even after you close the SSH connection.
### Access the Dashboard
The OpenClaw dashboard is a web interface for managing your assistant, monitoring connections, and configuring channels. To access it, you need a [preview URL](https://www.daytona.io/docs/en/preview.md) that exposes the gateway port running inside your sandbox.
In your local terminal (not inside the sandbox SSH session), generate the preview URL:
```bash
daytona preview-url openclaw --port 18789
```
This command generates a [signed preview URL](https://www.daytona.io/docs/en/preview.md#signed-preview-url) that securely exposes the port.
Open the URL in your browser, go to the **Overview** section, paste your gateway token in the **Gateway Token** field, and click **Connect**.
:::tip
The preview URL expires after 1 hour by default (customizable with `--expires` flag). When it expires, simply run the same CLI command to generate a new one.
:::
### Pair Your Browser
OpenClaw uses device pairing as a security measure - only approved devices can connect to and control your assistant. When you first attempt to connect from the dashboard, your browser registers as a new device that needs approval.
List pending device requests:
```bash
openclaw devices list
```
Approve your device:
```bash
openclaw devices approve REQUEST_ID
```
Replace `REQUEST_ID` with the value from the **Request** column.
Click **Connect** again in the dashboard.
Once connected, you should see a green status indicator - your OpenClaw is now ready to use.
### Security
Running OpenClaw this way provides three layers of security:
1. **Preview URL:** Time-limited access to the dashboard port
2. **Gateway token:** Required to authenticate with the dashboard
3. **Device approval:** Only approved devices can connect and control your assistant
Even if someone obtains your dashboard URL, they cannot connect without the gateway token and an approved device.
:::caution
Keep your gateway token and preview URL secret. Do not share them publicly.
:::
---
### Configure Telegram
Set up a Telegram bot to chat with OpenClaw.
#### Create a Telegram Bot
1. Open Telegram and search for **@BotFather**
2. Send `/start`, then `/newbot`
3. Enter a name for your bot
4. Enter a username for your bot
5. Copy the bot token provided
#### Configure OpenClaw
Enable Telegram and set your bot token:
```bash
openclaw config set channels.telegram.enabled true
openclaw config set channels.telegram.botToken YOUR_BOT_TOKEN
```
Verify the configuration:
```bash
openclaw config get channels.telegram
```
#### Restart the Gateway
```bash
openclaw gateway stop
nohup openclaw gateway run > /tmp/gateway.log 2>&1 &
```
#### Complete Verification
1. Open your bot's chat in Telegram and click **Start**
2. A pairing code will appear. Approve the pairing request:
```bash
openclaw pairing approve telegram PAIRING_CODE
```
You can now message your OpenClaw through Telegram.
---
### Configure WhatsApp
Set up WhatsApp to chat with OpenClaw.
#### Run Configuration
```bash
openclaw config --section channels
```
When prompted:
1. Select **Local (this machine)** for gateway location
2. Choose **Configure/link**
3. Select **WhatsApp (QR link)**
4. Select **Yes** for "Link WhatsApp now (QR)?"
#### Scan the QR Code
Open WhatsApp on your phone, go to **Settings → Linked Devices → Link a Device**, and scan the QR code displayed in your terminal.
Once paired, you'll see:
```
✅ Linked after restart; web session ready.
```
#### Set Up Your Phone Number
Select **This is my personal phone number** (or choose the other option if you have a separate phone for OpenClaw) and enter your phone number when prompted.
#### Finish Configuration
When prompted to select another channel, choose **Finished**. You'll see:
```
└ Configure complete.
```
#### Start Chatting
Send a message to yourself in WhatsApp - OpenClaw will respond. You can give it instructions and information on how to behave directly in the chat.
:::tip
To allow other users to chat with OpenClaw, add their phone numbers to the **Allow From** list in **Channels → WhatsApp** inside the dashboard. When they send a message, OpenClaw will respond.
:::
import { Image } from 'astro:assets'
import openclawSandbox from '../../../../../assets/docs/images/openclaw-sandbox.gif'
This guide shows how to run [OpenClaw](https://openclaw.ai/) inside a Daytona sandbox using the Daytona SDK. The script automatically creates and configures a sandbox with OpenClaw and provides an authenticated [preview URL](https://www.daytona.io/docs/en/preview.md) for using OpenClaw in the browser.
---
### 1. Workflow Overview
When you run the script, it creates a Daytona sandbox, starts the OpenClaw gateway inside it, and prints a preview link for the dashboard:
```
$ npm start
Creating Daytona sandbox...
Configuring OpenClaw...
Starting OpenClaw...
(Ctrl+C to shut down and delete the sandbox)
🔗 Secret link to Control UI: https://18789-xxxx.proxy.daytona.works?token=...
```
Open the provided link in your browser to connect to the OpenClaw Control UI. This link contains a configuration token, and anyone can use it to connect to OpenClaw without device approval.
You can use the Control UI to chat with your assistant, configure Telegram and WhatsApp, and manage sessions. When you exit the script (Ctrl+C), the sandbox will not be deleted unless [sandbox persistence is disabled](https://www.daytona.io/docs/en/guides/openclaw/openclaw-sdk-sandbox.md#4-key-constants).
### 2. Project Setup
#### Clone the Repository
Clone the Daytona [repository](https://github.com/daytonaio/daytona) and go to the example directory:
```bash
git clone https://github.com/daytonaio/daytona.git
cd daytona/guides/typescript/openclaw
```
#### Configure Environment
Get your API key from the [Daytona Dashboard](https://app.daytona.io/dashboard/keys).
Copy `.env.example` to `.env` and add your Daytona API key:
```bash
DAYTONA_API_KEY=your_daytona_key
```
A default OpenClaw configuration is stored in `openclaw.json`. You can customize it according to the [configuration reference](https://docs.openclaw.ai/gateway/configuration-reference). You can also add additional environment variables to `.env.sandbox` (e.g. `ANTHROPIC_API_KEY` for Claude) and they will be loaded into the sandbox.
#### Run the Example
:::note[Node.js]
Node.js 18 or newer is required.
:::
Install dependencies and run:
```bash
npm install
npm start
```
The script creates the sandbox, starts the OpenClaw gateway, and prints a secret link with the token in the URL.
### 3. How It Works
1. The script creates a [Daytona sandbox](https://www.daytona.io/docs/en/sandboxes.md) with `DAYTONA_SNAPSHOT` (e.g. `daytona-medium`) and loads env vars from `.env.sandbox`.
2. Your local `openclaw.json` is merged with built-in config and written to `~/.openclaw/openclaw.json` in the sandbox.
3. The OpenClaw gateway is started inside the sandbox on `OPENCLAW_PORT` via [process execution](https://www.daytona.io/docs/en/process-code-execution.md).
4. A signed [preview link](https://www.daytona.io/docs/en/preview.md) is generated and the token is appended as `?token=...`; this link is printed so you can open the Control UI.
5. On Ctrl+C, the sandbox is deleted unless `PERSIST_SANDBOX` is `true`.
### 4. Key Constants
You can change behavior by editing the constants in [`src/index.ts`](https://github.com/daytonaio/daytona/blob/main/guides/typescript/openclaw/src/index.ts):
| Constant | Default | Description |
|----------|---------|-------------|
| `PERSIST_SANDBOX` | true | When true, the sandbox is not deleted when the script exits |
| `MAKE_PUBLIC` | true | Allow anyone to access the sandbox instead of limiting to your Daytona organization |
| `OPENCLAW_PORT` | 18789 | OpenClaw Gateway and Control UI port |
| `SHOW_LOGS` | true | Stream OpenClaw stdout/stderr to the terminal |
**Key advantages:**
- Secure, isolated execution in a Daytona sandbox
- No device approval — token in URL and `allowInsecureAuth` skip pairing
- Control UI and channels accessible via the secret preview link
- Optional: keep the sandbox running after exit (`PERSIST_SANDBOX`)
Guides for running [OpenCode](https://opencode.ai/) with Daytona.
import { Image } from 'astro:assets'
import opencodePluginGif from '../../../../../assets/docs/images/opencode-plugin.gif'
This guide demonstrates how to run the [Daytona OpenCode plugin](https://www.npmjs.com/package/@daytonaio/opencode) which integrates Daytona sandboxes and OpenCode. When the plugin is active, all agent operations occur in secure sandboxes, with one sandbox per OpenCode session. The plugin also has the ability to sync changes between sandboxes and local Git branches.
### 1. Workflow Overview
When you run OpenCode with the Daytona plugin, sandboxes are created automatically inside OpenCode sessions. Operations such as running code, installing dependencies, and starting servers occur in the sandbox.
Sandboxes are preserved until you delete the OpenCode session. If a local Git repository is detected, the plugin syncs changes between the sandbox and branches with the `opencode/` prefix.
### 2. Project Setup
#### Add the Plugin
Add the Daytona plugin to your project by creating or editing `opencode.json` in the project directory:
```json
{
"$schema": "https://opencode.ai/config.json",
"plugin": ["@daytonaio/opencode"]
}
```
OpenCode downloads the plugin automatically when it starts. To install the plugin globally instead, edit `~/.config/opencode/opencode.json` and add the same `plugin` entry.
#### Configure Environment
This plugin requires a [Daytona account](https://www.daytona.io/) and [Daytona API key](https://app.daytona.io/dashboard/keys) to create sandboxes.
Set your API key:
```bash
export DAYTONA_API_KEY="your-api-key"
```
Or create a `.env` file in your project root:
```env
DAYTONA_API_KEY=your-api-key
```
#### Run OpenCode
:::note[Git required]
Ensure your project is a Git repository to enable syncing changes between the sandbox and your machine.
:::
Initialize Git if needed, then start OpenCode:
```bash
git init
opencode
```
You can now use OpenCode as usual. As you work, you will see notifications in OpenCode indicating sandboxes are being created and changes are being synced to local branches.
To confirm the plugin is working, type `pwd` in the chat and you should see a path like `/home/daytona/project`.
To view live logs from the plugin for debugging:
```bash
tail -f ~/.local/share/opencode/log/daytona.log
```
#### Version control
In your project directory, use Git to list and check out the branches OpenCode creates:
```bash
git branch
git checkout opencode/1
```
By default, new sessions start from the branch that was checked out when OpenCode was started. After this, synchronization only goes one way: from the sandbox to your local branch. To start working from a different branch, use git to check out that branch and start OpenCode again:
```bash
git checkout opencode/1
opencode
```
You can run as many OpenCode sessions in parallel as you want. Use Git to review and merge changes.
### 3. Understanding the Plugin Architecture
The Daytona plugin consists of several modules that provide custom tools, hooks for events, connections from sessions to sandboxes and system prompt transforms. These modules ensure every agent action runs in a [Daytona sandbox](https://www.daytona.io/docs/en/sandboxes.md) and that changes sync to local Git branches:
- **Custom tools:** Overrides bash, read, write, edit, etc., so they run in the sandbox.
- **System prompt transform:** Injects sandbox path and instructions into the agent's system prompt.
- **Event handlers:** Handles session lifecycle events including cleanup (deleting sandboxes) and idle auto-commit (syncing changes to local git branches).
- **Session management:** Manages the creation and deletion of sandboxes and the mapping of sessions to sandboxes.
#### Custom tools
The custom tools module registers overrides for OpenCode's built-in tools so that every file and process operation goes through the Daytona SDK. It receives the project `id` and `worktree` from the plugin context and returns a tool map:
```typescript
export async function customTools(ctx: PluginInput, sessionManager: DaytonaSessionManager) {
logger.info('OpenCode started with Daytona plugin')
const projectId = ctx.project.id
const worktree = ctx.project.worktree
return {
bash: bashTool(sessionManager, projectId, worktree, ctx),
// ... read, write, edit, multiedit, patch, ls, glob, grep, lsp, getPreviewURL
}
}
```
For example, the plugin implementation of the bash tool uses the Daytona SDK to run the command in the sandbox:
```typescript
async execute(args: { command: string; background?: boolean }, ctx: ToolContext) {
const sessionId = ctx.sessionID
const sandbox = await sessionManager.getSandbox(sessionId, projectId, worktree, pluginCtx)
if (args.background) {
// ... create or get exec session, then:
const result = await sandbox.process.executeSessionCommand(execSessionId, {
command: args.command,
runAsync: true,
})
return `Command started in background (cmdId: ${result.cmdId})`
} else {
const result = await sandbox.process.executeCommand(args.command, repoPath)
return `Exit code: ${result.exitCode}\n${result.result}`
}
}
```
All stateful tools (bash, read, write, edit, glob, grep, ls, lsp, multiedit, patch) are overridden the same way. The plugin also adds a custom tool for [preview links](https://www.daytona.io/docs/en/preview.md).
#### System prompt transform
The system prompt transform extends the system prompt to include instructions for the agent to work in the sandbox and use the background option for long-running commands:
```typescript
export async function systemPromptTransform(ctx: PluginInput, repoPath: string) {
return async (input: ExperimentalChatSystemTransformInput, output: ExperimentalChatSystemTransformOutput) => {
output.system.push(
[
'## Daytona Sandbox Integration',
'This session is integrated with a Daytona sandbox.',
`The main project repository is located at: ${repoPath}.`,
'Bash commands will run in this directory.',
'Put all projects in the project directory. Do NOT try to use the current working directory of the host system.',
"When executing long-running commands, use the 'background' option to run them asynchronously.",
'Before showing a preview URL, ensure the server is running in the sandbox on that port.',
].join('\n'),
)
}
}
```
#### Session events
The session events handler listens for OpenCode session lifecycle events and handles them appropriately. When you delete a session, the handler cleans up the corresponding sandbox. When a session becomes idle, it triggers auto-commit and sync:
```typescript
export async function eventHandlers(ctx: PluginInput, sessionManager: DaytonaSessionManager, repoPath: string) {
const projectId = ctx.project.id
const worktree = ctx.project.worktree
return async (args: any) => {
const event = args.event
if (event.type === EVENT_TYPE_SESSION_DELETED) {
const sessionId = (event as EventSessionDeleted).properties.info.id
await sessionManager.deleteSandbox(sessionId, projectId)
toast.show({ title: 'Session deleted', message: 'Sandbox deleted successfully.', variant: 'success' })
} else if (event.type === EVENT_TYPE_SESSION_IDLE) {
const sessionId = event.properties.sessionID
const sandbox = await sessionManager.getSandbox(sessionId, projectId, worktree, ctx)
const branchNumber = sessionManager.getBranchNumberForSandbox(projectId, sandbox.id)
if (!branchNumber) return
const sessionGit = new SessionGitManager(sandbox, repoPath, worktree, branchNumber)
await sessionGit.autoCommitAndPull(ctx)
}
}
}
```
#### File synchronization
While OpenCode is in use, the plugin uses Git to keep session sandboxes and your local Git repository in sync. This only occurs if a git repository is detected in the project directory. On plugin start:
1. The plugin looks for a Git repository in the local directory.
2. A parallel repository is created in the sandbox with a single `opencode` branch, mirroring your current local branch.
3. A `sandbox` remote is added to your local repo using an SSH connection to the sandbox.
4. Your current `HEAD` is pushed to `opencode`, and the sandbox repo is reset to that state.
5. On session idle, the plugin commits in the sandbox on `opencode`, then pulls into a local branch (`opencode/1`, `opencode/2`, etc.) which is unique to each sandbox. A notification is shown when the sync is complete.
For more information on how the sync is implemented, see the [SessionGitManager](https://github.com/daytonaio/daytona/blob/main/libs/opencode-plugin/.opencode/plugin/daytona/git/session-git-manager.ts) class.
:::caution
When the plugin syncs to local `opencode` branches, any local changes on those branches are overwritten.
:::
#### Session storage
The session manager stores which sandbox belongs to each project in JSON files (using the same base path as OpenCode via `xdg-basedir`).
- **macOS:** `~/.local/share/opencode/storage/daytona/[projectid].json`
- **Windows:** `%LOCALAPPDATA%\opencode\storage\daytona\[projectid].json`
Each file holds sandbox metadata for that project's sessions so that sandboxes are retained between OpenCode uses.
**Key advantages:**
- Secure, isolated execution: each OpenCode session runs in its own Daytona sandbox
- Sandboxes persist until you delete the OpenCode session
- Live [preview links](https://www.daytona.io/docs/en/preview.md) when a server starts in the sandbox
- Automatic git sync to local branches so you can review and merge agent changes
- No script to run: add the plugin and use OpenCode as usual
import { Image } from 'astro:assets'
import opencodeSdkSyncboard from '../../../../../assets/docs/images/opencode-sdk-syncboard.gif'
This guide walks you through running the [OpenCode](https://opencode.ai/) autonomous coding agent inside a secure Daytona sandbox. The OpenCode server runs fully isolated in the sandbox and the script connects to the server using the [OpenCode SDK](https://www.npmjs.com/package/@opencode-ai/sdk).
The agent can develop full-stack web apps, write code in any language, install dependencies, and run scripts. It can also start and manage dev servers, and generate [preview links](https://www.daytona.io/docs/en/preview.md) for live apps.
### 1. Workflow Overview
When you run the script, it creates a Daytona sandbox, installs OpenCode, and starts the OpenCode server inside the sandbox. You send prompts and see responses in your terminal. On exit, the sandbox is deleted.
```
$ npm run start
Creating sandbox...
Installing OpenCode in sandbox...
Preview: https://4096-0626a08c-08e7-4fbe-9799-d160bac66b08.daytonaproxy01.net
Press Ctrl+C at any time to exit.
User: Create a minimalist collaborative whiteboard app
Thinking...
🔨 ✓ Run: Check current directory structure
✓ 3 todos
📝 Add home/daytona/SPEC.md
✓ 2 todos
📝 Add home/daytona/index.html
✓ 1 todos
✓ home/daytona/SPEC.md
✓ https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500&family=Outfit:wght@400;500;700&display=swap (text/css; charset=utf-8)
✓ home/daytona/index.html
🔨 ✓ Run: List files in directory
🔨 ✓ Run: Start HTTP server for whiteboard
🔨 ✓ Run: Check if server is running
✓ 0 todos
Your minimalist collaborative whiteboard app is ready!
**Preview URL:** https://8080-0626a08c-08e7-4fbe-9799-d160bac66b08.daytonaproxy01.net
## SyncBoard - Features
**Drawing Tools:**
- Pencil (freehand drawing)
- Line, Rectangle, Ellipse (shape tools with preview)
- Eraser (removes intersecting strokes)
**Customization:**
- 6 vibrant color presets
- 3 stroke widths (thin/medium/thick)
- Keyboard shortcuts: `P` `L` `R` `E` `X` for tools, `1` `2` `3` for stroke widths
**Collaboration:**
- Simulated real-time collaboration with other users
- Unique user colors for each participant
- Auto-saves to localStorage every 2 seconds
**Actions:**
- Undo/Redo (stores 20 actions, Ctrl+Z / Ctrl+Shift+Z)
- Clear canvas (with confirmation dialog)
- Coordinates display in status bar
**Design:**
- Dark theme with coral/teal accents
- Dot grid background pattern
- Smooth animations and hover effects
- Responsive layout for mobile devices
User:
Cleaning up...
```
When your task involves running or previewing a web application, the agent can host the app and generate a [preview link](https://www.daytona.io/docs/en/preview.md) for you to inspect the live result:
You can continue interacting with your agent until you are finished. When you exit the program, the sandbox will be deleted automatically.
### 2. Project Setup
#### Clone the Repository
First, clone the Daytona [repository](https://github.com/daytonaio/daytona.git) and navigate to the OpenCode SDK example:
```bash
git clone https://github.com/daytonaio/daytona.git
cd daytona/guides/typescript/opencode/opencode-sdk
```
#### Configure Environment
Get your API key from the [Daytona Dashboard](https://app.daytona.io/dashboard/keys).
Copy `.env.example` to `.env` and add your key:
```bash
DAYTONA_API_KEY=your_daytona_key
```
#### Local Usage
:::note[Node.js Version]
Node.js 18 or newer is required to run this example. Please ensure your environment meets this requirement before proceeding.
:::
Install dependencies and run the example:
```bash
npm install
npm run start
```
The agent will start and wait for your prompt.
### 3. Understanding the Script
OpenCode uses a client-server model: The [server](https://opencode.ai/docs/server/) manages coding agents, sessions and configuration. Clients communicate with the server [over HTTP](https://opencode.ai/docs/server/#apis) to run prompts in sessions and receive streamed responses.
#### Initialization
On startup, the script:
1. Creates a new [Daytona sandbox](https://www.daytona.io/docs/en/sandboxes.md).
2. Installs OpenCode globally in the sandbox.
3. Starts the OpenCode server in the sandbox.
4. Gets the preview URL for the server and creates a client with that base URL.
5. Enters the readline loop to send prompts to the server and receive streamed responses.
6. On Ctrl+C, deletes the sandbox and exits.
#### OpenCode Server
The OpenCode server runs inside the sandbox and handles all agent work: LLM calls, tools (bash, write, etc.), and code execution. The script starts it with:
```ts
const envVar = injectEnvVar('OPENCODE_CONFIG_CONTENT', opencodeConfig)
const command = await sandbox.process.executeSessionCommand(sessionId, {
command: `${envVar} opencode serve --port ${PORT} --hostname ${HOSTNAME}`,
runAsync: true,
})
```
A custom configuration is injected which includes a system prompt. The system prompt tells the agent it runs in a sandbox, to use `/home/daytona` for file operations, and the preview URL pattern so it can provide correct preview links.
#### OpenCode Client
The client runs on your machine and talks to the server using the [OpenCode SDK](https://opencode.ai/docs/sdk/). `Session.create` sets up the SDK client and subscribes to the event stream so the client can show tool activity (e.g. “✓ Run: …”, “📝 Add …”) as the agent works:
```ts
const client = createOpencodeClient({ baseUrl })
const sessionRes = await client.session.create({ body: { title: 'Daytona query' } })
const sessionId = sessionRes.data?.id
if (!sessionId) throw new Error('Failed to create OpenCode session:' + sessionRes.error)
const events = await client.event.subscribe()
```
To send a prompt, the client calls `session.prompt` and processes events from the existing stream to show tool activity:
```ts
const promptPromise = this.client.session.prompt({
path: { id: this.sessionId },
body: { parts: [{ type: 'text', text: query } satisfies TextPartInput] },
})
for await (const event of takeUntil(this.events.stream, promptPromise)) {
printEvent(this.sessionId, event)
}
```
#### Main loop
When the server is ready, the script creates a session and runs a readline loop:
```ts
const session = await Session.create(baseUrl)
const rl = readline.createInterface({ input: process.stdin, output: process.stdout })
while (true) {
const query = await new Promise((resolve) => rl.question('User: ', resolve))
if (!query.trim()) continue
await session.runQuery(query)
}
```
The readline loop waits for user input, sends it to the agent, and prints the response.
**Key advantages:**
- Secure, isolated execution in Daytona sandboxes
- OpenCode SDK client in your terminal; server runs in the sandbox
- Support for 75+ LLM providers
- All agent code execution happens inside the sandbox
- Automatic preview link generation for deployed services
- Custom agent configuration for Daytona-specific workflows
import { Image } from 'astro:assets'
import opencodeResult from '../../../../../assets/docs/images/opencode-web-agent.gif'
This guide demonstrates how to run the [OpenCode](https://opencode.ai/) coding agent inside a Daytona sandbox environment using OpenCode's easy-to-use [web interface](https://opencode.ai/docs/web/).
The agent can develop web apps, write code in any language, install dependencies, and run scripts. It supports over 75 different LLM providers and can start dev servers with preview links for live apps.
---
### 1. Workflow Overview
When you launch the main script, a Daytona sandbox is created and OpenCode is installed inside it. OpenCode is configured with a custom Daytona-aware agent.
The script provides a preview link to access the web interface, where you can create, configure and interact with agent sessions:
```
$ npm run start
Creating sandbox...
Installing OpenCode...
Starting OpenCode web server...
Press Ctrl+C to stop.
▄
█▀▀█ █▀▀█ █▀▀█ █▀▀▄ █▀▀▀ █▀▀█ █▀▀█ █▀▀█
█░░█ █░░█ █▀▀▀ █░░█ █░░░ █░░█ █░░█ █▀▀▀
▀▀▀▀ █▀▀▀ ▀▀▀▀ ▀ ▀ ▀▀▀▀ ▀▀▀▀ ▀▀▀▀ ▀▀▀▀
Web interface: https://3000-1e0f775c-c01b-40e7-8c64-062fd3dadd75.proxy.daytona.works/
```
The agent can host web apps and provide you with a preview link using the [Daytona Preview Links](https://www.daytona.io/docs/en/preview-and-authentication.md) feature. When your task involves running or previewing a web application, the agent automatically reasons about this need, hosts the app, and generates a preview link for you to inspect the live result:
You can continue interacting with your agent until you are finished. When you exit the program, the sandbox will be deleted automatically.
### 2. Project Setup
#### Clone the Repository
First, clone the Daytona [repository](https://github.com/daytonaio/daytona.git) and navigate to the example directory:
```bash
git clone https://github.com/daytonaio/daytona.git
cd daytona/guides/typescript/opencode
```
#### Configure Environment
Get your API key from the [Daytona Dashboard](https://app.daytona.io/dashboard/keys).
Copy `.env.example` to `.env` and add your key:
```bash
DAYTONA_API_KEY=your_daytona_key
```
#### Local Usage
:::note[Node.js Version]
Node.js 18 or newer is required to run this example. Please ensure your environment meets this requirement before proceeding.
:::
Install dependencies:
```bash
npm install
```
Run the example:
```bash
npm run start
```
The OpenCode web interface will start and wait for you to open it in your browser.
### Models and API Providers
OpenCode works with [over 75 LLM providers](https://opencode.ai/docs/providers/), with a free provider selected by default. You can change the model or provider at any time using the menu below the prompt input in the web interface. If your chosen provider needs an API key, you’ll be prompted to enter it.
#### Persisting API Keys
To persist API keys between uses of the script, you can set them as environment variables when creating the Daytona sandbox.
For example, to use an Anthropic API key, modify the `daytona.create()` call in `src/index.ts` to include your desired API key:
```typescript
sandbox = await daytona.create({
envVars: {
ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY || '',
},
})
```
### 3. Understanding the Script
This example consists of a Node.js script that installs, configures and runs OpenCode inside a Daytona sandbox.
#### Initialization
On initialization, the main script:
1. Creates a new [Daytona sandbox](https://www.daytona.io/docs/en/sandboxes.md).
2. Installs OpenCode globally inside the sandbox using npm with [process execution](https://www.daytona.io/docs/en/process-code-execution.md#process-execution).
3. Creates and uploads a [custom agent configuration](https://opencode.ai/docs/agents/) with Daytona-specific system prompt.
4. Starts the OpenCode web server inside the sandbox on port 3000.
5. Substitutes the URL in OpenCode's output with a [Daytona preview link](https://www.daytona.io/docs/en/preview-and-authentication.md) for the web interface.
#### Main Script Code
The script creates a session and executes OpenCode as an asynchronous command, which allows it to stream output while keeping the process alive:
```typescript
const command = await sandbox.process.executeSessionCommand(sessionId, {
command: `${envVar} opencode web --port ${OPENCODE_PORT}`,
runAsync: true,
})
```
When OpenCode starts its web server, it prints a link to its web UI using a localhost address (e.g., `http://127.0.0.1:3000`). However, since the sandbox runs remotely, this localhost link is only accessible inside the sandbox itself. To solve this, the script parses OpenCode’s output, and replaces the URL with the corresponding Daytona preview link.
```typescript
const opencodePreviewLink = await sandbox.getPreviewLink(OPENCODE_PORT)
const replaceUrl = (text: string) =>
text.replace(
new RegExp(`http:\\/\\/127\\.0\\.0\\.1:${OPENCODE_PORT}`, 'g'),
opencodePreviewLink.url
)
```
#### OpenCode Agent Configuration
A custom system prompt is used to instruct the agent on how to use Daytona sandbox paths and preview links. This prompt is packaged into a JSON configuration string, which is passed to the sandbox as the `OPENCODE_CONFIG_CONTENT` environment variable:
```json
{
"$schema": "https://opencode.ai/config.json",
"default_agent": "daytona",
"agent": {
"daytona": {
"description": "Daytona sandbox-aware coding agent",
"mode": "primary",
"prompt": "You are running in a Daytona sandbox. Use the /home/daytona directory instead of /workspace for file operations. When running services on localhost, they will be accessible as: . When starting a server, always give the user the preview URL to access it. When starting a server, start it in the background with & so the command does not block further instructions."
}
}
}
```
The `` in the agent prompt is a template URL where `{PORT}` is a placeholder for the port to access on the Daytona sandbox. This template string is created by generating a [preview link](https://www.daytona.io/docs/en/preview-and-authentication.md) for a specific port number and then replacing the port number with `{PORT}`.
#### Clean up
When you press `Ctrl+C`, the script automatically cleans up by deleting the sandbox:
```typescript
process.once('SIGINT', async () => {
console.log('\nCleaning up...')
if (sandbox) await sandbox.delete()
process.exit(0)
})
```
**Key advantages:**
- Secure, isolated execution in Daytona sandboxes
- OpenCode Web interface accessible via browser
- Support for 75+ LLM providers
- All agent code execution happens inside the sandbox
- Automatic preview link generation for deployed services
- Custom agent configuration for Daytona-specific workflows
- Clean resource management with automatic sandbox cleanup
import { Image } from 'astro:assets'
import rewardsPlot from '../../../../../assets/docs/images/trl-grpo-rewards-plot.png'
This guide demonstrates how to use Daytona sandboxes to safely execute hundreds of code completions in parallel during reinforcement learning training.
We use [TRL](https://huggingface.co/docs/trl/)'s GRPOTrainer together with 500 Daytona sandboxes evaluating completions concurrently, in order to train the `Qwen3-1.7B-Base` model on some basic code-writing tasks.
---
### 1. Workflow Overview
This guide presents a simple, self-contained script that performs reinforcement learning training of `Qwen3-1.7B-Base`. In particular, we use **reinforcement learning with verifiable rewards**, with the reward being computed from the test pass rate of model-written functions.
The training loop consists of following steps:
1. **Generate**: The model produces many code completions for each prompt (e.g., 250 completions per prompt per step)
2. **Evaluate**: Each completion runs in its own Daytona sandbox against a test suite
3. **Reward**: Completions that pass more tests get higher rewards; errors or banned patterns get negative rewards
4. **Update**: GRPO reinforces completions that scored above their group average
The evaluation step happens in parallel across all 500 sandboxes. The sandboxes are spawned once at the start of the training and reused throughout it, and cleaned up after the training completes.
### 2. Setup
#### Clone the Repository
:::note[GPU Requirement]
This guide is written to run on a single 80GB VRAM GPU. If you want to run it on a GPU with less VRAM, you can decrease `per_device_train_batch_size` parameter, possibly increasing `gradient_accumulation_steps` proportionally if you wish to keep effective batch size at 500.
:::
Clone the [Daytona repository](https://github.com/daytonaio/daytona.git) and navigate to the example directory:
```bash
git clone https://github.com/daytonaio/daytona.git
cd daytona/guides/python/reinforcement-learning/trl
```
#### Create Virtual Environment
:::note[Python Version]
Python 3.10 or higher is required. A GPU with 80GB+ VRAM is recommended for training.
:::
```bash
python3 -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
```
#### Install Dependencies
```bash
pip install -e .
```
This installs:
- `daytona` - Daytona SDK for sandbox management
- `trl[vllm]` - TRL with vLLM integration for fast inference
- `datasets` - HuggingFace datasets library
- `python-dotenv` - Environment variable management
#### Configure Environment
Get your Daytona API key from the [Daytona Dashboard](https://app.daytona.io/dashboard/keys) and create a `.env` file:
```bash
DAYTONA_API_KEY=your_daytona_api_key
```
### 3. Understanding the Code
Let's walk through the key components of the training script.
#### Task Definitions
The script defines coding tasks as prompts with test cases. Note that the prompts are written in completion mode rather than QA mode because `Qwen3-1.7B-Base` is a base rather than an instruct model. Each task specifies what the model should generate and how to verify correctness:
```python
SORTING_PROMPT = """# I've been fiddling with different ways to sort numbers in Python.
# At first I just used sorted() and list.sort(), but then I decided to try
# my hand at writing some original sorting functions. And I succeeded!
# I don't call sorted(), list.sort(), heapq, or use any imports here - just plain
# Python and an original algorithm.
def sort_numbers(xs: list[int]) -> list[int]:
\"\"\"Sort a list of integers in ascending order.
Args:
xs: A list of integers to be sorted.
Returns:
A new list containing the same integers, sorted from smallest to largest.
\"\"\"
"""
TASKS = {
"sorting": {
"prompt": SORTING_PROMPT,
"func_name": "sort_numbers",
"banned_patterns": ["sorted(", ".sort(", "heapq", "import ", "__import__"],
"tests": [
"[]",
"[1, 3, 2]",
"[random.randint(-1000, 1000) for _ in range(200)]",
"[random.randint(-100, 100) for _ in range(1000)]",
"list(range(0, 100)) + list(range(200, 100, -1)) + list(range(200, 300))",
],
"reference": "sorted",
},
# Additional tasks can be added here...
}
```
Each task includes:
- **prompt**: The code context the model continues from
- **func_name**: The function name being implemented
- **banned_patterns**: Patterns that disqualify a completion (e.g., using built-in `sorted()`)
- **tests**: Test inputs to verify correctness
- **reference**: The reference implementation to compare against
#### How Prompts Become Completions
When the model receives the sorting prompt, it continues the text as if completing a Python file. A typical model output might look like:
```
if len(xs) <= 1:
return xs
pivot = xs[len(xs) // 2]
left = [x for x in xs if x < pivot]
middle = [x for x in xs if x == pivot]
right = [x for x in xs if x > pivot]
return sort_numbers(left) + middle + sort_numbers(right)
# Example usage:
print(sort_numbers([3, 1, 4, 1, 5, 9, 2, 6]))
```
Notice the model generates the indented function body, but may also add extra content after (comments, example usage, etc.). The `sanitize_completion` function extracts only the indented lines that form the function body:
```python
def sanitize_completion(text: str) -> str:
# Take lines until the first unindented line
lines = text.splitlines()
kept: List[str] = []
for line in lines:
if line and (not line.startswith(" ")):
break
kept.append(line)
return "\n".join(kept).rstrip()
```
After sanitization, the example above becomes just the function body:
```python
if len(xs) <= 1:
return xs
pivot = xs[len(xs) // 2]
left = [x for x in xs if x < pivot]
middle = [x for x in xs if x == pivot]
right = [x for x in xs if x > pivot]
return sort_numbers(left) + middle + sort_numbers(right)
```
#### Sandbox Pool Management
We create the sandbox pool upfront and reuse sandboxes throughout training:
```python
EFFECTIVE_BATCH_SIZE = 500
# We evaluate each completion concurrently, in its own sandbox,
# so we spawn EFFECTIVE_BATCH_SIZE number of sandboxes.
async def _create_sandbox_pool_async(
daytona: AsyncDaytona, n: int = 10
) -> List[AsyncSandbox]:
print(f"Creating {n} sandboxes...")
tasks = [daytona.create() for _ in range(n)]
sandboxes = await asyncio.gather(*tasks)
print(f"Successfully created all {len(sandboxes)} sandboxes")
return list(sandboxes)
async def _cleanup_sandbox_pool_async(sandbox_pool: List[AsyncSandbox]) -> None:
if not sandbox_pool:
return
print("Cleaning up sandboxes...")
tasks = [sandbox.delete() for sandbox in sandbox_pool]
results = await asyncio.gather(*tasks, return_exceptions=True)
for r in results:
if isinstance(r, Exception):
print(f" Sandbox delete error: {type(r).__name__}: {r}")
print("All sandboxes cleaned up")
```
The pool size (500) is chosen to match the total batch size (`per_device_train_batch_size * gradient_accumulation_steps`), ensuring every completion in a batch can be evaluated in parallel.
#### Code Evaluation
The main evaluation function ties everything together - it sanitizes the completion, checks for banned patterns, builds the test harness, executes it in a sandbox, and parses the results:
```python
async def evaluate_single_completion_async(
sandbox: AsyncSandbox,
raw_completion: str,
prompt: str,
) -> EvalResult:
task = PROMPT_TO_TASK[prompt]
num_task_tests = len(task["tests"])
body = sanitize_completion(raw_completion)
if not body.strip():
return _fail_result(num_task_tests)
if has_banned_pattern(body, task):
return _fail_result(num_task_tests)
code = build_test_harness(task, body)
try:
response = await sandbox.code_interpreter.run_code(
code, timeout=MAX_TIMEOUT_SECONDS
)
except DaytonaTimeoutError:
print(
f"Completion timed out after {MAX_TIMEOUT_SECONDS}s "
f"in sandbox {getattr(sandbox, 'id', '?')}"
)
return _fail_result(num_task_tests)
except Exception as e:
print(
f"Error evaluating completion in sandbox {getattr(sandbox, 'id', '?')}: "
f"{type(e).__name__}: {e}",
)
return _fail_result(num_task_tests)
if response.error is not None:
return _fail_result(num_task_tests)
raw_output = response.stdout.strip()
if not raw_output:
return _fail_result(num_task_tests)
last_line = raw_output.splitlines()[-1]
try:
results = json.loads(last_line)
except Exception:
return _fail_result(num_task_tests)
correct = results.get("results", [])
return {
"no_error": True,
"num_passed": sum(bool(x) for x in correct),
"num_tests": len(correct),
}
```
#### The Test Harness
The `build_test_harness` function combines the original prompt, the model's completion, and a test runner into Python code that ultimately executes on the sandbox:
```python
def build_test_harness(task: Dict[str, Any], function_body: str) -> str:
prompt = task["prompt"]
func_name = task["func_name"]
reference_function = task["reference"]
tests = task["tests"]
tests_tuple = ",\n ".join(tests)
return f"""{prompt}
{function_body}
import json
import random
random.seed(0)
def _kadane(xs):
max_sum = current = xs[0]
for x in xs[1:]:
current = max(x, current + x)
max_sum = max(max_sum, current)
return max_sum
def _run_tests():
tests = (
{tests_tuple}
)
results = []
for xs in tests:
try:
out = {func_name}(xs.copy())
expected = {reference_function}(xs.copy())
results.append(out == expected)
except Exception:
results.append(False)
print(json.dumps({{"results": results}}))
if __name__ == "__main__":
_run_tests()
"""
```
For the sorting task with a quicksort completion, the assembled code looks like:
```python
# I've been fiddling with different ways to sort numbers in Python...
def sort_numbers(xs: list[int]) -> list[int]:
"""Sort a list of integers in ascending order..."""
if len(xs) <= 1:
return xs
pivot = xs[len(xs) // 2]
left = [x for x in xs if x < pivot]
middle = [x for x in xs if x == pivot]
right = [x for x in xs if x > pivot]
return sort_numbers(left) + middle + sort_numbers(right)
import json
import random
random.seed(0)
def _run_tests():
tests = (
[],
[1, 3, 2],
[random.randint(-1000, 1000) for _ in range(200)],
# ... more tests
)
results = []
for xs in tests:
try:
out = sort_numbers(xs.copy())
expected = sorted(xs.copy())
results.append(out == expected)
except Exception:
results.append(False)
print(json.dumps({"results": results}))
if __name__ == "__main__":
_run_tests()
```
When executed in the sandbox, this prints JSON to stdout:
```json
{"results": [true, true, true, false, true]}
```
The evaluation function parses this JSON to count how many tests passed.
#### Banned Pattern Detection
Before running code in the sandbox, we check for banned patterns. This prevents the model from "cheating" by using built-in functions:
```python
def has_banned_pattern(text: str, task: Dict[str, Any]) -> bool:
banned = task.get("banned_patterns", [])
if not banned:
return False
lowered = text.lower()
return any(p.lower() in lowered for p in banned)
```
For the sorting task, banned patterns include `sorted(`, `.sort(`, `heapq`, and `import`. If the model generates `return sorted(xs)`, it gets a reward of -1.0 instead of being executed - we want the model to learn to write actual sorting algorithms, not to call built-in functions.
#### Parallel Batch Evaluation
The batch evaluator distributes completions across the sandbox pool:
```python
async def _evaluate_batch_async(
sandbox_pool: List[AsyncSandbox], completions: List[str], prompts: List[str]
) -> List[EvalResult]:
print(
f"Evaluating {len(completions)} completions in parallel across "
f"{len(sandbox_pool)} sandboxes..."
)
async def run_one(
i: int, sandbox: AsyncSandbox, completion: str, prompt: str
) -> EvalResult:
task = PROMPT_TO_TASK[prompt]
num_task_tests = len(task["tests"])
try:
stats = await evaluate_single_completion_async(sandbox, completion, prompt)
print(f" Completion {i + 1}/{len(completions)} done")
return stats
except Exception as e:
print(
f" Completion {i + 1}/{len(completions)} failed: "
f"{type(e).__name__}: {e}"
)
return _fail_result(num_task_tests)
tasks = [
run_one(i, sandbox_pool[i % len(sandbox_pool)], completion, prompt)
for i, (completion, prompt) in enumerate(zip(completions, prompts))
]
stats_list = await asyncio.gather(*tasks)
print(f" Done: {len(completions)}/{len(completions)} completions evaluated")
return stats_list
```
Each completion is assigned to a sandbox using round-robin distribution (`i % len(sandbox_pool)`), ensuring even load distribution.
#### Reward Function
The reward function receives the results from the sandboxes and computes the corresponding scalar reward.
```python
def reward_func(prompts, completions, **kwargs):
stats_list = run_async(
_evaluate_batch_async(sandbox_pool, completions, prompts)
)
rewards = []
for s in stats_list:
if not s["no_error"]:
rewards.append(-1.0)
elif s["num_tests"] == 0:
rewards.append(0.0)
else:
rewards.append(s["num_passed"] / s["num_tests"])
return rewards
```
The reward scheme:
- **-1.0**: Error, timeout, or banned pattern detected
- **0.0**: No tests were present (shouldn't happen with valid tasks)
- **0.0 to 1.0**: Fraction of tests passed
#### Bridging Sync and Async
TRL's `GRPOTrainer` expects a synchronous reward function, but the Daytona SDK uses async/await for parallel sandbox operations. We bridge these two worlds with a helper:
```python
def main():
# Create a dedicated event loop for async operations
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
def run_async(coro: Awaitable[Any]) -> Any:
"""Run async code from sync context."""
return loop.run_until_complete(coro)
# ... training code ...
def reward_func(prompts, completions, **kwargs):
# This sync function is called by TRL
# We use run_async to call our async evaluation
stats_list = run_async(
_evaluate_batch_async(sandbox_pool, completions, prompts)
)
# ... compute rewards ...
return rewards
```
This pattern lets us keep the async parallelism benefits of the Daytona SDK while working within TRL's synchronous training loop. The `run_async` helper blocks until all 500 parallel sandbox evaluations complete, then returns the results.
#### Training Configuration
The GRPO trainer is configured with these parameters:
```python
training_args = GRPOConfig(
output_dir="training_results",
per_device_train_batch_size=20,
# batch size chosen so the training runs comfortably on a single 80GB GPU,
# if running this on a GPU with less memory, reduce the batch size accordingly
gradient_accumulation_steps=25,
num_generations=EFFECTIVE_BATCH_SIZE // len(TASKS),
max_prompt_length=256,
max_completion_length=512,
learning_rate=8e-6,
num_train_epochs=1,
logging_steps=1,
report_to="none",
max_steps=8,
bf16=True,
use_vllm=True,
vllm_mode="colocate",
vllm_gpu_memory_utilization=0.15,
gradient_checkpointing=True,
loss_type="dapo",
beta=0.01,
)
```
Key settings explained:
**Batch size and sandbox pool alignment:**
```
per_device_train_batch_size (20) × gradient_accumulation_steps (25) = 500
```
This equals `EFFECTIVE_BATCH_SIZE`. Each training step generates exactly 500 completions, and we have exactly 500 sandboxes - so every completion evaluates in parallel with no waiting. If we had fewer sandboxes, some completions would queue up. If we had more, sandboxes would sit idle.
**vLLM colocate mode:**
```python
use_vllm=True,
vllm_mode="colocate",
vllm_gpu_memory_utilization=0.15,
```
This runs vLLM for fast inference on the same GPU as training. We use 15% of the GPU's memory for model generation, and the rest for training (optimizer states).
**Generation settings:**
- `num_generations=EFFECTIVE_BATCH_SIZE // len(TASKS)`: Generate 250 completions per prompt (500 / 2 tasks). With 2 prompts (sorting and max_subarray), that's 500 total per step
- `max_completion_length=512`: Limit completion length to prevent runaway generation
### 4. Running the Training
Start training with:
```bash
python train.py
```
You'll see output like:
```
Creating 500 sandboxes...
Successfully created all 500 sandboxes
Evaluating 500 completions in parallel across 500 sandboxes...
Completion 1/500 done
Completion 2/500 done
...
Done: 500/500 completions evaluated
```
After training completes, metrics are saved to `training_results/metrics.jsonl` and the model is saved as `training_results/checkpoint-8`.
### 5. Example Evaluation Walkthrough
Let's trace through what happens when evaluating a single completion:
**Step 1: Model generates a completion**
The model receives the sorting prompt and generates:
```
if len(xs) <= 1:
return xs
pivot = xs[0]
less = [x for x in xs[1:] if x <= pivot]
greater = [x for x in xs[1:] if x > pivot]
return sort_numbers(less) + [pivot] + sort_numbers(greater)
# Test
print(sort_numbers([3, 1, 2]))
```
**Step 2: Sanitization extracts the function body**
`sanitize_completion` keeps only the indented lines:
```python
if len(xs) <= 1:
return xs
pivot = xs[0]
less = [x for x in xs[1:] if x <= pivot]
greater = [x for x in xs[1:] if x > pivot]
return sort_numbers(less) + [pivot] + sort_numbers(greater)
```
**Step 3: Check for banned patterns**
`has_banned_pattern` scans for `sorted(`, `.sort(`, `heapq`, `import`. None found, so we proceed.
**Step 4: Build the test harness**
`build_test_harness` assembles the full script: prompt + completion + test runner. This becomes ~50 lines of executable Python.
**Step 5: Execute in sandbox**
```python
response = await sandbox.code_interpreter.run_code(code, timeout=1)
```
The sandbox runs the code and returns within the 1-second timeout.
**Step 6: Parse results**
The test runner printed:
```json
{"results": [true, true, true, true, true]}
```
We parse this from `response.stdout`:
```python
results = json.loads(response.stdout.strip().splitlines()[-1])
# {"results": [true, true, true, true, true]}
```
**Step 7: Compute reward**
All 5 tests passed:
```python
reward = 5 / 5 # = 1.0
```
This completion gets a perfect reward of 1.0, reinforcing the model to generate similar quicksort implementations.
### 6. Training Results
The plot below shows average rewards over training steps. At the start, the model is very rarely writing functions that meet the task specifications, and it is often writing code that either errors out or times out. Given our large effective batch size of 500, the model achieves near-perfect performance after only 8 steps.
### 7. Adding Custom Tasks
To add a new coding task, extend the `TASKS` dictionary:
```python
TASKS = {
"your_task": {
"prompt": "Your prompt here...",
"func_name": "function_name",
"banned_patterns": ["patterns", "to", "ban"],
"tests": [
"test_input_1",
"test_input_2",
],
"reference": "reference_function",
},
}
```
The reference function should be defined in the test harness that `build_test_harness` generates.
### 8. Configuration Options
| Parameter | Default | Description |
|-----------|---------|-------------|
| `EFFECTIVE_BATCH_SIZE` | 500 | Effective batch size, also equal to the number of parallel sandboxes |
| `MAX_TIMEOUT_SECONDS` | 1 | Timeout per code execution |
| `MODEL_NAME` | `Qwen/Qwen3-1.7B-Base` | Base model to train |
:::tip[Scaling Tips]
- Keep `per_device_train_batch_size * gradient_accumulation_steps` equal to `EFFECTIVE_BATCH_SIZE` for optimal parallelism
- Increase `MAX_TIMEOUT_SECONDS` for tasks with more (algorithmically) complex test cases
:::
---
**Key advantages of this approach:**
- **Massive parallelism**: 500 sandboxes evaluate completions simultaneously
- **Safe execution**: Generated code runs in isolated environments, protecting your system
- **Fast feedback**: vLLM + parallel evaluation minimizes training iteration time
- **Extensible**: Add new coding tasks by defining prompts and test cases
import { Image } from 'astro:assets'
import wealthTrajectories from '../../../../../assets/docs/images/wealth-trajectories.png'
[DSPy](https://dspy.ai/)'s RLM implements [recursive language models](https://arxiv.org/abs/2512.24601), a system where an LLM writes Python code through which it can pass parts of its context to LLM calls, leading to significantly enhanced long-context reasoning.
The generated code runs in a REPL, and in this guide we use and present `DaytonaInterpreter`, which plugs into DSPy as the code-execution backend so that all generated code runs inside an isolated Daytona cloud sandbox rather than on your machine.
---
### 1. Setup
#### Clone the Repository
Clone the [Daytona repository](https://github.com/daytonaio/daytona.git) and navigate to the example directory:
```bash
git clone https://github.com/daytonaio/daytona.git
cd daytona/guides/python/dspy-rlms
```
#### Create Virtual Environment
```bash
python3.10 -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
```
#### Install Dependencies
```bash
pip install -e .
```
This installs the DSPy framework and the Daytona SDK. To also run the included demo (which plots results with matplotlib), use
```bash
pip install -e ".[demo]"
```
#### Configure Environment
Create a `.env` file with your API keys:
```bash
cp .env.example .env
# Edit .env with your keys
```
The file needs two variables:
```bash
DAYTONA_API_KEY=your_daytona_api_key
OPENROUTER_API_KEY=your_openrouter_api_key # or OPENAI_API_KEY / ANTHROPIC_API_KEY
```
:::note
Get your Daytona API key from the [Daytona Dashboard](https://app.daytona.io/dashboard/keys). The LLM provider key depends on which model you configure in your code — the examples use OpenRouter.
:::
### 2. Basic Usage
The following example shows the basic setup — configure a model, create a `DaytonaInterpreter`, and pass it to an RLM. The generated code can call `llm_query()` to delegate semantic work back to the LLM:
```python
import dspy
from dotenv import load_dotenv
from daytona_interpreter import DaytonaInterpreter
load_dotenv()
lm = dspy.LM("openrouter/google/gemini-3-flash-preview")
dspy.configure(lm=lm)
interpreter = DaytonaInterpreter()
rlm = dspy.RLM(
signature="documents: list[str], question: str -> answer: str",
interpreter=interpreter,
verbose=True,
)
documents = [...] # your documents
result = rlm(documents=documents, question="Summarize the key findings across these documents.")
print(result.answer)
interpreter.shutdown()
```
Inside the sandbox, the RLM might loop over the documents, call `llm_query()` to summarize each one, then aggregate the results with Python before calling `SUBMIT(answer=...)`.
### 3. Workflow Overview
Each RLM call runs an iterative REPL loop. The LLM writes Python code, the code executes in a Daytona sandbox, and the output is fed back to the LLM for the next iteration. Crucially, the generated code can call `llm_query()` to invoke a sub-LLM call — this is how the LLM delegates semantic work (understanding, extraction, classification) to itself while keeping the orchestration logic in Python.
1. **Prompt** — RLM sends the task inputs and previous turns to the LLM
2. **Code** — The LLM responds with reasoning and a Python code snippet
3. **Execute** — The code runs inside a Daytona sandbox; any `llm_query()` calls are bridged back to the host LLM
4. **Repeat** — Steps 1–3 repeat until the code calls `SUBMIT()` or the iteration limit is reached
#### How Bridging Works
Step 3 above mentions that `llm_query()` calls are "bridged back to the host." Here's a diagram and an explanation of that process:
```
Host Process Daytona Sandbox
┌──────────────────────────────┐ ┌──────────────────────────────┐
│ DaytonaInterpreter │ │ Broker Server (Flask) │
│ │ │ │
│ • polls the broker for │ tool call, │ • accepts requests from │
│ pending requests │ e.g. llm_query │ the wrapper functions │
│ │◄───────────────│ │
│ • calls the LLM API │ │ • queues them for the host │
│ or runs tool functions │ result │ • returns results once the │
│ • posts results back │───────────────►│ host replies │
│ │ │ │
└──────────────────────────────┘ │ Generated Code │
│ │ • llm_query() │
▼ │ • llm_query_batched() │
LLM API │ • custom tool wrappers │
└──────────────────────────────┘
```
When `DaytonaInterpreter` starts, it launches a small Flask broker server inside the sandbox and injects wrapper functions (`llm_query`, `llm_query_batched`, and any custom tools you provide). These wrappers POST requests to the broker and block until a result arrives. On the host side, a polling loop picks up pending requests, executes them (e.g. calls the LLM API or runs your tool function), and posts the results back to the broker. From the generated code's perspective, the wrappers look and behave like ordinary Python functions.
Custom tools passed via the `tools` dict use the same mechanism, so that the host generates a matching wrapper inside the sandbox and bridges calls identically.
State persists across iterations: variables, imports, and function definitions all carry over.
#### Sub-LLM Calls
Two built-in functions are available inside the sandbox:
- **`llm_query(prompt)`** — send a single natural-language prompt to the LLM, get a string back
- **`llm_query_batched(prompts)`** — send multiple prompts concurrently, get a list of strings back
These execute on the host (they need LLM API access) and are bridged into the sandbox. From the generated code's perspective they are ordinary Python functions that take strings and return strings. This is what makes the pattern powerful: the LLM can write a `for` loop over 100 chapters, call `llm_query_batched()` to extract structured data from each one in parallel, then aggregate and use the results with additional Python code.
### 4. Example Walkthrough
The included `demo.py` shows a realistic use of sub-LLM calls: literary analysis of _The Count of Monte Cristo_ — a ~1,300-page novel with 117 chapters — tracking the wealth trajectory of five major characters. The RLM uses `llm_query_batched()` to process chapters in parallel batches, then aggregates the results with Python.
#### How the Demo Works
The script fetches the full novel text from Project Gutenberg, splits it into chapters, and passes them to an RLM configured with a typed signature:
```python
interpreter = DaytonaInterpreter()
rlm = dspy.RLM(
signature="chapters: list[str], task: str -> wealth_data: list[dict]",
interpreter=interpreter,
max_iterations=40,
max_llm_calls=500,
verbose=True,
)
chapters = fetch_chapters()
print(f"Fetched {len(chapters)} chapters")
TASK = (
"Analyze the economic trajectory of each major character across the novel. "
"For each chapter where a character's wealth status is mentioned or implied, "
"produce a dict with keys: chapter (int), character (str), wealth (int 1-10 "
"where 1=destitute and 10=richest in Paris), and event (str, brief description "
"of what changed). Track the following characters: Dantès, Danglars, Fernand/"
"Morcerf, Villefort, and Mercédès. You need to cover each chapter in the book."
)
result = rlm(chapters=chapters, task=TASK)
wealth_data = result.wealth_data
```
#### What the RLM Does
The RLM's generated code follows a pattern typical of sub-LLM workloads:
1. **Batch the input** — Split the 117 chapters into manageable groups
2. **Fan out with `llm_query_batched()`** — For each batch, send a prompt like _"Extract wealth events from these chapters as JSON"_ — the sub-LLM calls run concurrently on the host
3. **Parse and accumulate** — Each sub-call returns a string; the code parses the JSON and appends to a running list
4. **Iterate** — Repeat for the next batch; state (the accumulated list) persists across REPL iterations
5. **Submit** — Once all chapters are processed, call `SUBMIT(wealth_data=accumulated_results)`
This is the core RLM pattern: Python handles the data plumbing (batching, parsing, aggregating) while `llm_query_batched()` handles the parts that need language understanding (reading prose, identifying wealth events, rating severity).
#### Running the Demo
```bash
python demo.py
```
The script plots the results with matplotlib after the RLM finishes.
:::tip
The demo runs up to 40 iterations and 500 sub-LLM calls. Depending on the model and provider, a full run may take several minutes and consume significant API credits.
:::
#### Results
The output is a list of `{chapter, character, wealth, event}` dictionaries that the script plots as smoothed time series:
### 5. Conclusion
RLMs combine the LLM's language understanding with Python's ability to loop, branch, and aggregate — the generated code calls the LLM whenever it needs semantic reasoning and handles everything else with ordinary computation. `DaytonaInterpreter` makes this safe to run by executing all generated code in an isolated Daytona cloud sandbox:
- **Sub-LLM recursion** — `llm_query()` and `llm_query_batched()` are bridged from the sandbox to the host, letting generated code invoke the LLM for semantic tasks like extraction, classification, and summarisation
- **Isolation** — All generated code runs in a Daytona cloud sandbox, not on your machine
- **Persistent state** — Variables, imports, and definitions survive across REPL iterations, so the LLM can accumulate results across batches
Guides for building and running Recursive Language Models with Daytona.
This guide demonstrates how to build a recursive language model (RLM) agent system that uses Daytona sandboxes, based on the approach pioneered in [Recursive Language Models](https://arxiv.org/abs/2512.24601) (Zhang, Kraska, Khattab) and further explored by [Prime Intellect](https://www.primeintellect.ai/blog/rlm).
While the original paper and Prime Intellect's implementation focus on single-level recursion (depth=1), this guide extends the concept to **unlimited recursion depth** — agents can spawn sub-agents, which can spawn their own sub-agents, and so on. Each agent runs in its own isolated Daytona sandbox with a fresh clone of the target repository.
---
### 1. Workflow Overview
The system implements a recursive agent architecture where agents can delegate subtasks to child agents:
1. **Initialize**: Root agent receives a task and gets a Daytona sandbox with a fresh repository clone
2. **Iterate**: Agent runs a loop: LLM call → extract Python code → execute in REPL
3. **Delegate**: Code can call `rlm_query()` to spawn sub-agents, each with their own sandbox
4. **Aggregate**: Sub-agents return results; parent synthesizes findings and optionally runs more code
5. **Complete**: Root agent receives all sub-agent results, produces a git patch; all sandboxes are cleaned up
```
Root Agent (depth=0)
├── Sub-Agent A (depth=1)
│ ├── Sub-Agent A1 (depth=2)
│ └── Sub-Agent A2 (depth=2)
└── Sub-Agent B (depth=1)
├── Sub-Agent B1 (depth=2)
└── Sub-Agent B2 (depth=2)
```
Each agent runs in its own isolated Daytona sandbox with a fresh repository clone, enabling parallel exploration.
### 2. Setup
#### Clone the Repository
Clone the [Daytona repository](https://github.com/daytonaio/daytona.git) and navigate to the example directory:
```bash
git clone https://github.com/daytonaio/daytona.git
cd daytona/guides/python/recursive-language-models
```
#### Create Virtual Environment
```bash
python3.10 -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
```
#### Install Dependencies
```bash
pip install -e .
```
This installs:
- `daytona` - Daytona SDK for sandbox management
- `litellm` - Unified LLM interface for any provider
- `typer` - CLI framework
- `pyyaml` - Configuration parsing
#### Configure Environment
Get your Daytona API key from the [Daytona Dashboard](https://app.daytona.io/dashboard/keys) and create a `.env` file:
```bash
DAYTONA_API_KEY=your_daytona_api_key
LLM_API_KEY=your_llm_api_key
```
The `LLM_API_KEY` is used via [LiteLLM](https://docs.litellm.ai/), supporting OpenRouter, OpenAI, Anthropic, and other providers.
### 3. Running an Agent
With setup complete, let's run an agent. Here's an example that investigates TODO comments in scikit-learn:
```bash
python run.py https://github.com/scikit-learn/scikit-learn \
-p "Investigate TODO comments across this repository. Spawn sub-agents to explore different modules. Find the easiest TODO and fix it."
```
This spawns a root agent that explores the codebase, delegates to sub-agents for parallel investigation, and produces a git patch fixing the easiest TODO it finds. We'll walk through the results and trace the execution in detail later, but first, let's look at how the code works.
#### CLI Options
| Option | Description |
|--------|-------------|
| `repo` | GitHub repository URL (required) |
| `-p, --prompt` | Task prompt for the agent (required) |
| `-b, --branch` | Branch name (optional) |
| `--commit` | Specific commit SHA (optional) |
| `-c, --config` | Path to config file (default: `config.yaml`) |
| `-o, --output` | Output file for patch (default: stdout) |
### 4. Understanding the Code
Let's walk through the key components of the agent system.
#### Agent Execution Loop
Each agent runs an iteration loop that calls the LLM, extracts code blocks, and executes them. The core loop in `agent.py`:
```python
def _run_loop(self) -> None:
"""Run the main iteration loop."""
system_prompt = build_system_prompt(depth=self.depth)
messages = [{"role": "system", "content": system_prompt}]
execution_result = None
for iteration in range(self.config.rlm.max_iterations):
# Check global timeout
if self._is_timeout():
break
# Build user prompt with previous execution result
user_prompt = build_user_prompt(iteration, execution_result)
messages.append({"role": "user", "content": user_prompt})
# Get model completion
response = self.client.completion(messages)
messages.append({"role": "assistant", "content": response})
# Execute code blocks in REPL
repl_result = self.repl.execute_response(response)
# Check for final answer
if repl_result.final_answer is not None:
self._result = repl_result.final_answer
break
# Format result for next iteration
execution_result = format_execution_result(...)
```
Each iteration:
1. Builds a prompt with context from previous execution
2. Gets an LLM completion
3. Extracts and executes Python code blocks
4. Checks if the agent called `FINAL()` to submit results
5. Formats the output for the next iteration
#### Sub-Agent Spawning
When agent code calls `rlm_query()`, a new sub-agent is created with its own sandbox:
```python
def _handle_rlm_query(self, task: str) -> str:
"""Spawn a sub-agent for a specific task."""
# Check sandbox budget
if not self.sandbox_manager.budget.can_acquire():
return "Error: sandbox budget exhausted"
# Create sub-agent at depth + 1
sub_agent = RLMAgent(
client=self.client,
sandbox_manager=self.sandbox_manager,
config=self.config,
depth=self.depth + 1,
task=task,
# ... other params
)
# Run sub-agent (blocking)
result = sub_agent.run()
# Return result, truncated if necessary
return result.result or "No result"
```
For parallel spawning, `rlm_query_batched()` uses a thread pool:
```python
def _handle_rlm_query_batched(self, tasks: list[str]) -> list[str]:
"""Spawn multiple sub-agents in parallel."""
results = [""] * len(tasks)
with ThreadPoolExecutor(max_workers=10) as executor:
future_to_idx = {
executor.submit(self._handle_rlm_query, task): i
for i, task in enumerate(tasks)
}
for future in as_completed(future_to_idx):
idx = future_to_idx[future]
results[idx] = future.result()
return results
```
#### Agent Code Interface
Inside the REPL, agents have access to these functions:
| Function | Description |
|----------|-------------|
| `rlm_query(task)` | Spawn a single sub-agent, returns result string |
| `rlm_query_batched(tasks)` | Spawn multiple sub-agents in parallel |
| `FINAL(answer)` | Submit final result (root: triggers patch extraction) |
| `FINAL_VAR(var_name)` | Submit the value of a variable as result |
| `edit_file(path, old, new)` | Edit a file with syntax validation |
Example spawning pattern used by agents:
```python
# Spawn multiple sub-agents to explore different modules
results = rlm_query_batched([
"Search for TODO comments in sklearn/linear_model/ and assess difficulty",
"Search for TODO comments in sklearn/ensemble/ and assess difficulty",
"Search for TODO comments in sklearn/tree/ and assess difficulty",
])
for i, result in enumerate(results):
print(f"=== Sub-agent {i+1} findings ===")
print(result)
```
### 5. Example Walkthrough
Let's trace what happens when we run an agent on a popular machine learning library, scikit-learn:
```bash
python run.py https://github.com/scikit-learn/scikit-learn \
-p "Investigate TODO comments across this repository. Spawn sub-agents to explore different modules under sklearn/ in parallel. For each TODO found, assess how difficult it would be to fix (easy/medium/hard). After gathering results, pick the easiest TODO and fix it."
```
Note that there are about 400 lines in scikit-learn that contain the substring "# TODO".
**Step 1: Root agent explores and spawns depth-1 sub-agents**
The root agent (depth=0) examines the repository structure, identifies all sklearn modules, and spawns 25 sub-agents in parallel:
```python
# Define the subdirectories to investigate
subdirs = [
"cluster", "compose", "covariance", "cross_decomposition", "datasets",
"decomposition", "ensemble", "feature_extraction", "feature_selection",
"gaussian_process", "impute", "inspection", "linear_model", "manifold",
"metrics", "mixture", "model_selection", "neighbors", "neural_network",
"preprocessing", "semi_supervised", "svm", "tree", "utils"
]
# Create queries for sub-agents
queries = [
f"Search for 'TODO' comments in 'sklearn/{subdir}/'. For each TODO found, provide: "
f"1. The file path and line number. 2. The content of the TODO. 3. An assessment "
f"of how difficult it would be to fix (easy/medium/hard) with a brief justification."
for subdir in subdirs
]
results = rlm_query_batched(queries)
```
Each of these 25 sub-agents gets its own Daytona sandbox with a fresh clone of scikit-learn.
**Step 2: Depth-1 agents spawn depth-2 agents**
Some depth-1 agents decide their module is too large and spawn their own sub-agents. For example, the `sklearn/metrics/` agent spawned 3 depth-2 agents:
```python
# Inside the sklearn/metrics/ agent (depth=1)
# To efficiently handle the large number of TODOs, spawn sub-agents for sub-directories
tasks = [
"Identify and assess TODOs in 'sklearn/metrics/cluster/'. Provide file, line, content, and difficulty.",
"Identify and assess TODOs in 'sklearn/metrics/tests/'. Provide file, line, content, and difficulty.",
"Identify and assess TODOs in 'sklearn/metrics/_plot/' and its 'tests' sub-directory."
]
results = rlm_query_batched(tasks)
```
**Step 3: Results propagate back**
Each sub-agent returns findings via `FINAL()`. Results flow back up:
- Depth-2 → Depth-1: Detailed analysis of specific subdirectories
- Depth-1 → Root: Module-level summaries with difficulty ratings
**Step 4: Root agent synthesizes and acts**
The root agent reviews all findings, identifies the easiest TODO, and makes the fix.
**Step 5: Git patch produced**
```python
import subprocess
subprocess.run(['git', 'add', '-A'], cwd='/workspace')
result = subprocess.run(['git', 'diff', '--cached', 'HEAD'],
capture_output=True, text=True, cwd='/workspace')
FINAL(result.stdout)
```
#### Results
- Execution time: **316 seconds** (~5.3 minutes)
- Agents spawned: **40** (25 at depth 1, 15 at depth 2)
**Generated patch:**
```diff
diff --git a/sklearn/utils/_array_api.py b/sklearn/utils/_array_api.py
--- a/sklearn/utils/_array_api.py
+++ b/sklearn/utils/_array_api.py
@@ -19,8 +19,7 @@ from sklearn.externals.array_api_compat import numpy as np_compat
from sklearn.utils._dataframe import is_df_or_series
from sklearn.utils.fixes import parse_version
-# TODO: complete __all__
-__all__ = ["xpx"] # we import xpx here just to re-export it, need this to appease ruff
+__all__ = ['device', 'get_namespace', 'get_namespace_and_device', 'indexing_dtype', 'move_to', 'size', 'supported_float_dtypes', 'xpx', 'yield_namespace_device_dtype_combinations', 'yield_namespaces']
```
The agent found the easiest TODO (`# TODO: complete __all__` in `sklearn/utils/_array_api.py`) and completed the `__all__` list with all public symbols from the module.
### 6. Configuration
Configure the agent in `config.yaml`:
```yaml
# Model configuration - using LiteLLM format
model:
name: "openrouter/google/gemini-3-flash-preview"
# RLM configuration
rlm:
max_sandboxes: 50
max_iterations: 50
global_timeout: 3600
result_truncation_limit: 10000
```
| Parameter | Default | Description |
|-----------|---------|-------------|
| `model.name` | `openrouter/google/gemini-3-flash-preview` | LLM model in LiteLLM format |
| `rlm.max_sandboxes` | 50 | Maximum total sandboxes across entire rollout |
| `rlm.max_iterations` | 50 | Maximum iterations per agent |
| `rlm.global_timeout` | 3600 | Total timeout in seconds |
| `rlm.result_truncation_limit` | 10000 | Max chars in sub-agent results |
:::tip[Scaling Tips]
- Increase `max_sandboxes` for tasks requiring more parallel exploration
- The sandbox budget tracks total sandboxes created over the lifetime of the rollout
- Sub-agent sandboxes are deleted immediately after completion
:::
### 7. Viewing Results
Results are saved to the `results/` directory as JSON files. Use the built-in viewer:
```bash
python -m http.server 8000
# Open http://localhost:8000/viewer/
```
The viewer provides:
- Interactive tree visualization of the agent hierarchy
- Iteration details with code and output for each agent
- Statistics: agent count, max depth, total iterations
### 8. Conclusion
Current language models aren't specifically trained to leverage recursive delegation, so RLMs don't necessarily outperform single-agent approaches on benchmarks yet. However, the architecture demonstrates compelling properties for complex tasks.
In our scikit-learn example, 40 agents ran in parallel across the agent tree, each with its own isolated sandbox, completing the entire run in just over 5 minutes. This level of parallelism, where each agent can freely modify files, run tests, and explore without affecting others, would be difficult to achieve without per-agent sandboxes.
**Key advantages of this approach:**
- **Recursive decomposition**: Complex tasks naturally break into sub-tasks handled by specialized agents
- **Isolated execution**: Each agent gets a fresh sandbox, preventing interference
- **Parallel exploration**: `rlm_query_batched()` enables concurrent investigation
Daytona is an open-source, secure and elastic infrastructure for running AI-generated code. Daytona provides full composable computers — [sandboxes](https://www.daytona.io/docs/en/sandboxes.md) — that you can manage programmatically using the Daytona SDKs, [CLI](https://www.daytona.io/docs/en/tools/cli.md), and [API](https://www.daytona.io/docs/en/tools/api.md) to run and control code execution.
Daytona SDK is available for [Python](https://www.daytona.io/docs/en/python-sdk.md), [TypeScript](https://www.daytona.io/docs/en/typescript-sdk.md), [Ruby](https://www.daytona.io/docs/en/ruby-sdk.md) and [Go](https://www.daytona.io/docs/en/go-sdk.md) interfaces.
## 1. Create an account
Open the [Daytona Dashboard ↗](https://app.daytona.io/) to create your account. Daytona supports account creation using an email and password, or by connecting your Google or GitHub account.
## 2. Obtain an API key
Generate an API key from the [Daytona Dashboard ↗](https://app.daytona.io/dashboard/keys) or using the [Daytona API](https://www.daytona.io/docs/en/tools/api.md#daytona/tag/api-keys/POST/api-keys) to authenticate SDK requests and access Daytona services.
## 3. Install the SDK
Install the Daytona [Python](https://www.daytona.io/docs/python-sdk.md), [TypeScript](https://www.daytona.io/docs/typescript-sdk.md), [Ruby](https://www.daytona.io/docs/ruby-sdk.md) or [Go](https://www.daytona.io/docs/go-sdk.md) SDKs to interact with sandboxes from code.
```bash
pip install daytona
```
```bash
npm install @daytonaio/sdk
```
```bash
gem install daytona
```
```bash
go get github.com/daytonaio/daytona/libs/sdk-go
```
## 4. Create a Sandbox
Create a [sandbox](https://www.daytona.io/docs/en/sandboxes.md) to run your code securely in an isolated environment.
`main.py`
```python
# Import the Daytona SDK
from daytona import Daytona, DaytonaConfig
# Define the configuration
config = DaytonaConfig(api_key="YOUR_API_KEY") # Replace with your API key
# Initialize the Daytona client
daytona = Daytona(config)
# Create the Sandbox instance
sandbox = daytona.create()
```
`index.mts`
```typescript
// Import the Daytona SDK
import { Daytona } from '@daytonaio/sdk'
// Initialize the Daytona client
const daytona = new Daytona({ apiKey: 'YOUR_API_KEY' }) // Replace with your API key
// Create the Sandbox instance
const sandbox = await daytona.create()
```
`main.rb`
```ruby
require 'daytona'
# Initialize the Daytona client
config = Daytona::Config.new(api_key: 'YOUR_API_KEY') # Replace with your API key
# Create the Daytona client
daytona = Daytona::Daytona.new(config)
# Create the Sandbox instance
sandbox = daytona.create
```
`main.go`
```go
package main
import (
"context"
"fmt"
"github.com/daytonaio/daytona/libs/sdk-go/pkg/daytona"
"github.com/daytonaio/daytona/libs/sdk-go/pkg/types"
)
func main() {
config := &types.DaytonaConfig{
APIKey: "YOUR_API_KEY", // Replace with your API key
}
client, _ := daytona.NewClientWithConfig(config)
ctx := context.Background()
sandbox, _ := client.Create(ctx, nil)
fmt.Println(sandbox.ID)
}
```
```bash
curl https://app.daytona.io/api/sandbox \
--request POST \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer YOUR_API_KEY' \
--data '{}'
```
:::tip
Daytona supports multiple options to configure your environment: [in code](https://www.daytona.io/docs/en/configuration.md#configuration-in-code), [environment variables](https://www.daytona.io/docs/en/configuration.md#environment-variables), [.env file](https://www.daytona.io/docs/en/configuration.md#env-file), and [default values](https://www.daytona.io/docs/en/configuration.md#default-values).
:::
## 5. Write and run code
Create a program that runs code inside a sandbox. The following snippets are examples of "Hello World" programs that run securely inside a sandbox.
`main.py`
```python
# Import the Daytona SDK
from daytona import Daytona, DaytonaConfig
# Define the configuration
config = DaytonaConfig(api_key="YOUR_API_KEY") # Replace with your API key
# Initialize the Daytona client
daytona = Daytona(config)
# Create the Sandbox instance
sandbox = daytona.create()
# Run the code securely inside the Sandbox
response = sandbox.process.code_run('print("Hello World")')
# Check the response
if response.exit_code != 0:
print(f"Error: {response.exit_code} {response.result}")
else:
print(response.result)
# Clean up
sandbox.delete()
```
`index.mts`
```typescript
// Import the Daytona SDK
import { Daytona } from '@daytonaio/sdk'
// Initialize the Daytona client
const daytona = new Daytona({ apiKey: 'YOUR_API_KEY' }) // Replace with your API key
// Create the Sandbox instance
const sandbox = await daytona.create({
language: 'typescript',
})
// Run the code securely inside the Sandbox
const response = await sandbox.process.codeRun('console.log("Hello World")')
// Check the response
if (response.exitCode !== 0) {
console.error(`Error: ${response.exitCode} ${response.result}`)
} else {
console.log(response.result)
}
// Clean up
await sandbox.delete()
```
`main.rb`
```ruby
require 'daytona'
# Initialize the Daytona client
config = Daytona::Config.new(api_key: 'YOUR_API_KEY')
daytona = Daytona::Daytona.new(config)
# Create the Sandbox instance
sandbox = daytona.create
# Run the code securely inside the Sandbox
response = sandbox.process.code_run(code: 'print("Hello World")')
puts response.result
```
`main.go`
```go
// Import the Daytona SDK
package main
import (
"context"
"log"
"github.com/daytonaio/daytona/libs/sdk-go/pkg/daytona"
"github.com/daytonaio/daytona/libs/sdk-go/pkg/types"
)
func main() {
// Define the configuration
config := &types.DaytonaConfig{
APIKey: "YOUR_API_KEY", // Replace with your API key
}
// Initialize the Daytona client
client, err := daytona.NewClientWithConfig(config)
if err != nil {
log.Fatal(err)
}
ctx := context.Background()
// Create the Sandbox instance
params := types.SnapshotParams{
SandboxBaseParams: types.SandboxBaseParams{
Language: types.CodeLanguagePython,
},
}
sandbox, err := client.Create(ctx, params)
if err != nil {
log.Fatal(err)
}
// Run the code securely inside the Sandbox
result, err := sandbox.Process.ExecuteCommand(ctx, `echo "Hello World"`)
// Check the response
if err != nil {
log.Fatalf("Error: %v", err)
}
if result.ExitCode != 0 {
log.Printf("Error: %d %s", result.ExitCode, result.Result)
} else {
log.Println(result.Result)
}
// Clean up
sandbox.Delete(ctx)
}
```
## Summary
By following the steps above, you successfully create a Daytona account, obtain an API key, install the SDK, create a sandbox, write code, and run it securely in a sandbox.
## Next steps
Use the following resources to interact with sandboxes:
- Learn more about Daytona with the [Getting Started](https://www.daytona.io/docs/en/getting-started.md) guide
- Get started with [Python](https://www.daytona.io/docs/en/python-sdk.md), [TypeScript](https://www.daytona.io/docs/en/typescript-sdk.md), [Ruby](https://www.daytona.io/docs/en/ruby-sdk.md) or [Go](https://www.daytona.io/docs/en/go-sdk.md) **SDKs**
- Install the [CLI](https://www.daytona.io/docs/en/getting-started.md#cli) to manage sandboxes from the command line
- Use the [API](https://www.daytona.io/docs/en/tools/api.md) to manage sandboxes programmatically
- View [examples](https://www.daytona.io/docs/en/getting-started.md#examples) for common sandbox operations and best practices
- Explore [guides](https://www.daytona.io/docs/en/guides.md) to connect Daytona with [Claude](https://www.daytona.io/docs/en/guides/claude.md), [OpenCode](https://www.daytona.io/docs/en/guides/opencode/opencode-web-agent.md), [Codex](https://www.daytona.io/docs/en/guides/codex/codex-sdk-interactive-terminal-sandbox.md), [LangChain](https://www.daytona.io/docs/en/guides/langchain/langchain-data-analysis.md) and more
:::tip
For faster development with AI agents and assistants, use our LLMs context files. Copy the [llms-full.txt](https://www.daytona.io/docs/llms-full.txt.md) and [llms.txt](https://www.daytona.io/docs/llms.txt.md) files and include them in your projects or chat contexts.
:::
Daytona provides Language Server Protocol (LSP) support through sandbox instances. This enables advanced language features like code completion, diagnostics, and more.
## Create LSP servers
Daytona provides methods to create LSP servers. The `path_to_project` argument is relative to the current sandbox working directory when no leading `/` is used. The working directory is specified by WORKDIR when it is present in the Dockerfile, and otherwise falls back to the user's home directory.
```python
from daytona import Daytona, LspLanguageId
# Create Sandbox
daytona = Daytona()
sandbox = daytona.create()
# Create LSP server for Python
lsp_server = sandbox.create_lsp_server(
language_id=LspLanguageId.PYTHON,
path_to_project="workspace/project"
)
```
```typescript
import { Daytona, LspLanguageId } from '@daytonaio/sdk'
// Create sandbox
const daytona = new Daytona()
const sandbox = await daytona.create({
language: 'typescript',
})
// Create LSP server for TypeScript
const lspServer = await sandbox.createLspServer(
LspLanguageId.TYPESCRIPT,
'workspace/project'
)
```
```ruby
require 'daytona'
# Create Sandbox
daytona = Daytona::Daytona.new
sandbox = daytona.create
# Create LSP server for Python
lsp_server = sandbox.create_lsp_server(
language_id: Daytona::LspServer::Language::PYTHON,
path_to_project: 'workspace/project'
)
```
```go
// Create sandbox
client, err := daytona.NewClient()
if err != nil {
log.Fatal(err)
}
ctx := context.Background()
sandbox, err := client.Create(ctx, nil)
if err != nil {
log.Fatal(err)
}
// Get LSP service for Python
lsp := sandbox.Lsp(types.LspLanguagePython, "workspace/project")
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk/lsp-server.md), and [Go SDK](https://www.daytona.io/docs/en/go-sdk.md) references:
> [**create_lsp_server (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/sandbox.md#sandboxcreate_lsp_server)
>
> [**createLspServer (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/sandbox.md#createlspserver)
>
> [**create_lsp_server (Ruby SDK)**](https://www.daytona.io/docs/en/ruby-sdk/sandbox.md#create_lsp_server)
### Supported languages
The supported languages for creating LSP servers with Daytona are defined by the `LspLanguageId` enum:
| Enum Value | Description |
| ------------------------------ | -------------------------------------- |
| **`LspLanguageId.PYTHON`** | Python language server |
| **`LspLanguageId.TYPESCRIPT`** | TypeScript/JavaScript language server |
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk/sync/lsp-server.md#lsplanguageid) and [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk/lsp-server.md#lsplanguageid) references:
> [**LspLanguageId (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/lsp-server.md#lsplanguageid)
>
> [**LspLanguageId (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/lsp-server.md#lsplanguageid)
## Start LSP servers
Daytona provides methods to start LSP servers.
```python
lsp = sandbox.create_lsp_server("typescript", "workspace/project")
lsp.start() # Initialize the server
# Now ready for LSP operations
```
```typescript
const lsp = await sandbox.createLspServer('typescript', 'workspace/project')
await lsp.start() // Initialize the server
// Now ready for LSP operations
```
```ruby
lsp = sandbox.create_lsp_server(
language_id: Daytona::LspServer::Language::PYTHON,
path_to_project: 'workspace/project'
)
lsp.start # Initialize the server
# Now ready for LSP operations
```
```go
lsp := sandbox.Lsp(types.LspLanguagePython, "workspace/project")
err := lsp.Start(ctx) // Initialize the server
if err != nil {
log.Fatal(err)
}
// Now ready for LSP operations
```
```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/lsp/start' \
--request POST \
--header 'Content-Type: application/json' \
--data '{
"languageId": "",
"pathToProject": ""
}'
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk/lsp-server.md), [Go SDK](https://www.daytona.io/docs/en/go-sdk.md), and [API](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/lsp/) references:
> [**start (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/lsp-server.md#lspserverstart)
>
> [**start (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/lsp-server.md#start)
>
> [**start (Ruby SDK)**](https://www.daytona.io/docs/en/ruby-sdk/lsp-server.md#start)
>
> [**Start (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#LspServerService.Start)
>
> [**start (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/lsp/POST/lsp/start)
## Stop LSP servers
Daytona provides methods to stop LSP servers.
```python
# When done with LSP features
lsp.stop() # Clean up resources
```
```typescript
// When done with LSP features
await lsp.stop() // Clean up resources
```
```ruby
# When done with LSP features
lsp.stop # Clean up resources
```
```go
// When done with LSP features
err := lsp.Stop(ctx) // Clean up resources
if err != nil {
log.Fatal(err)
}
```
```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/lsp/stop' \
--request POST \
--header 'Content-Type: application/json' \
--data '{
"languageId": "",
"pathToProject": ""
}'
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk/lsp-server.md), [Go SDK](https://www.daytona.io/docs/en/go-sdk.md), and [API](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/lsp/) references:
> [**stop (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/lsp-server.md#lspserverstop)
>
> [**stop (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/lsp-server.md#stop)
>
> [**stop (Ruby SDK)**](https://www.daytona.io/docs/en/ruby-sdk/lsp-server.md#stop)
>
> [**Stop (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#LspServerService.Stop)
>
> [**stop (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/lsp/POST/lsp/stop)
## Code completions
Daytona provides methods to get code completions for a specific position in a file.
```python
completions = lsp_server.completions(
path="workspace/project/main.py",
position={"line": 10, "character": 15}
)
print(f"Completions: {completions}")
```
```typescript
const completions = await lspServer.completions('workspace/project/main.ts', {
line: 10,
character: 15,
})
console.log('Completions:', completions)
```
```ruby
completions = lsp_server.completions(
path: 'workspace/project/main.py',
position: { line: 10, character: 15 }
)
puts "Completions: #{completions}"
```
```go
completions, err := lsp.Completions(ctx, "workspace/project/main.py",
types.Position{Line: 10, Character: 15},
)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Completions: %v\n", completions)
```
```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/lsp/completions' \
--request POST \
--header 'Content-Type: application/json' \
--data '{
"context": {
"triggerCharacter": "",
"triggerKind": 1
},
"languageId": "",
"pathToProject": "",
"position": {
"character": 1,
"line": 1
},
"uri": ""
}'
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk/lsp-server.md), [Go SDK](https://www.daytona.io/docs/en/go-sdk.md), and [API](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/lsp/) references:
> [**completions (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/lsp-server.md#lspservercompletions)
>
> [**completions (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/lsp-server.md#completions)
>
> [**completions (Ruby SDK)**](https://www.daytona.io/docs/en/ruby-sdk/lsp-server.md#completions)
>
> [**Completions (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#LspServerService.Completions)
>
> [**completions (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/lsp/POST/lsp/completions)
## File notifications
Daytona provides methods to notify the LSP server when files are opened or closed. This enables features like diagnostics and completion tracking for the specified files.
### Open file
Notifies the language server that a file has been opened for editing.
```python
# Notify server that a file is open
lsp_server.did_open("workspace/project/main.py")
```
```typescript
// Notify server that a file is open
await lspServer.didOpen('workspace/project/main.ts')
```
```ruby
# Notify server that a file is open
lsp_server.did_open('workspace/project/main.py')
```
```go
// Notify server that a file is open
err := lsp.DidOpen(ctx, "workspace/project/main.py")
if err != nil {
log.Fatal(err)
}
```
```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/lsp/did-open' \
--request POST \
--header 'Content-Type: application/json' \
--data '{
"languageId": "",
"pathToProject": "",
"uri": ""
}'
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk/lsp-server.md), [Go SDK](https://www.daytona.io/docs/en/go-sdk.md), and [API](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/lsp/) references:
> [**did_open (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/lsp-server.md#lspserverdid_open)
>
> [**didOpen (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/lsp-server.md#didopen)
>
> [**did_open (Ruby SDK)**](https://www.daytona.io/docs/en/ruby-sdk/lsp-server.md#did_open)
>
> [**DidOpen (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#LspServerService.DidOpen)
>
> [**did_open (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/lsp/POST/lsp/did-open)
### Close file
Notifies the language server that a file has been closed. This allows the server to clean up resources associated with that file.
```python
# Notify server that a file is closed
lsp_server.did_close("workspace/project/main.py")
```
```typescript
// Notify server that a file is closed
await lspServer.didClose('workspace/project/main.ts')
```
```ruby
# Notify server that a file is closed
lsp_server.did_close('workspace/project/main.py')
```
```go
// Notify server that a file is closed
err := lsp.DidClose(ctx, "workspace/project/main.py")
if err != nil {
log.Fatal(err)
}
```
```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/lsp/did-close' \
--request POST \
--header 'Content-Type: application/json' \
--data '{
"languageId": "",
"pathToProject": "",
"uri": ""
}'
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk/lsp-server.md), [Go SDK](https://www.daytona.io/docs/en/go-sdk.md), and [API](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/lsp/) references:
> [**did_close (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/lsp-server.md#lspserverdid_close)
>
> [**didClose (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/lsp-server.md#didclose)
>
> [**did_close (Ruby SDK)**](https://www.daytona.io/docs/en/ruby-sdk/lsp-server.md#did_close)
>
> [**DidClose (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#LspServerService.DidClose)
>
> [**did_close (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/lsp/POST/lsp/did-close)
## Document symbols
Daytona provides methods to retrieve symbols (functions, classes, variables, etc.) from a document.
```python
symbols = lsp_server.document_symbols("workspace/project/main.py")
for symbol in symbols:
print(f"Symbol: {symbol.name}, Kind: {symbol.kind}")
```
```typescript
const symbols = await lspServer.documentSymbols('workspace/project/main.ts')
symbols.forEach((symbol) => {
console.log(`Symbol: ${symbol.name}, Kind: ${symbol.kind}`)
})
```
```ruby
symbols = lsp_server.document_symbols('workspace/project/main.py')
symbols.each do |symbol|
puts "Symbol: #{symbol.name}, Kind: #{symbol.kind}"
end
```
```go
symbols, err := lsp.DocumentSymbols(ctx, "workspace/project/main.py")
if err != nil {
log.Fatal(err)
}
for _, symbol := range symbols {
fmt.Printf("Symbol: %v\n", symbol)
}
```
```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/lsp/document-symbols?languageId=&pathToProject=&uri='
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk/lsp-server.md), [Go SDK](https://www.daytona.io/docs/en/go-sdk.md), and [API](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/lsp/) references:
> [**document_symbols (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/lsp-server.md#lspserverdocument_symbols)
>
> [**documentSymbols (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/lsp-server.md#documentsymbols)
>
> [**document_symbols (Ruby SDK)**](https://www.daytona.io/docs/en/ruby-sdk/lsp-server.md#document_symbols)
>
> [**DocumentSymbols (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#LspServerService.DocumentSymbols)
>
> [**document_symbols (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/lsp/GET/lsp/document-symbols)
## Sandbox symbols
Daytona provides methods to search for symbols across all files in the sandbox.
```python
symbols = lsp_server.sandbox_symbols("MyClass")
for symbol in symbols:
print(f"Found: {symbol.name} at {symbol.location}")
```
```typescript
const symbols = await lspServer.sandboxSymbols('MyClass')
symbols.forEach((symbol) => {
console.log(`Found: ${symbol.name} at ${symbol.location}`)
})
```
```ruby
symbols = lsp_server.sandbox_symbols('MyClass')
symbols.each do |symbol|
puts "Found: #{symbol.name} at #{symbol.location}"
end
```
```go
symbols, err := lsp.SandboxSymbols(ctx, "MyClass")
if err != nil {
log.Fatal(err)
}
for _, symbol := range symbols {
fmt.Printf("Found: %v\n", symbol)
}
```
```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/lsp/workspacesymbols?query=&languageId=&pathToProject='
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk/lsp-server.md), [Go SDK](https://www.daytona.io/docs/en/go-sdk.md), and [API](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/lsp) references:
> [**sandbox_symbols (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/lsp-server.md#lspserversandbox_symbols)
>
> [**sandboxSymbols (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/lsp-server.md#sandboxsymbols)
>
> [**sandbox_symbols (Ruby SDK)**](https://www.daytona.io/docs/en/ruby-sdk/lsp-server.md#sandbox_symbols)
>
> [**SandboxSymbols (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#LspServerService.SandboxSymbols)
>
> [**sandbox_symbols (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/lsp/GET/lsp/workspacesymbols)
Daytona enforces resource and requests limits to ensure fair usage and stability across all organizations.
[Daytona Limits ↗](https://app.daytona.io/dashboard/limits) provides an overview of your organization's resource limits and usage.
## Resources
Resources are shared across all running sandboxes. The number of sandboxes you can run at once depends on their individual usage.
Organizations are automatically placed into a tier based on verification status and have access to a compute pool consisting of:
- **Compute**: Total CPU cores available
- **Memory**: Total RAM available
- **Storage**: Total disk space available
Limits are applied to your organization's default region.
To unlock higher limits, complete the following steps:
| **Tier** | **Resources (vCPU / RAM / Storage)** | **Access Requirements** |
| ---------- | ----------------------------------------- | ---------------------------------------------------------------------------------------------------- |
| **Tier 1** | **`10`** / **`10GiB`** / **`30GiB`** | Email verified |
| **Tier 2** | **`100`** / **`200GiB`** / **`300GiB`** | Credit card linked, $25 top-up, [GitHub connected](https://www.daytona.io/docs/en/linked-accounts.md#how-to-link-an-account). |
| **Tier 3** | **`250`** / **`500GiB`** / **`2000GiB`** | Business email verified, $500 top-up. |
| **Tier 4** | **`500`** / **`1000GiB`** / **`5000GiB`** | $2000 top-up every 30 days. |
| **Custom** | Custom limits | Contact [support@daytona.io](mailto:support@daytona.io) |
Once you meet the criteria for a higher tier, upgrade your tier in the [Daytona Dashboard ↗](https://app.daytona.io/dashboard/limits).
### Resource usage
Daytona supports managing your resources by [changing the state](https://www.daytona.io/docs/sandboxes.md#sandbox-lifecycle) of your Sandboxes. The table below summarizes how each state affects resource usage:
| **State** | **vCPU** | **Memory** | **Storage** | **Description** |
| ------------ | -------- | ---------- | ----------- | --------------------------------------------- |
| **Running** | ✅ | ✅ | ✅ | Counts against all limits |
| **Stopped** | ❌ | ❌ | ✅ | Frees CPU & memory, but storage is still used |
| **Archived** | ❌ | ❌ | ❌ | Data moved to cold storage, no quota impact |
| **Deleted** | ❌ | ❌ | ❌ | All resources freed |
## Rate limits
Rate limits control how many API requests you can make within a specific time window.
These limits are applied based on your tier, authentication status, and the type of operation you're performing.
Rate limits for general authenticated requests are tracked per organization.
The following rate limits are applied for each tier:
- **General requests**
- **[Sandbox creation](#sandbox-creation)**
- **[Sandbox lifecycle](#sandbox-lifecycle-operations)**
| **Tier** | **General Requests (per min)** | **Sandbox Creation (per min)** | **Sandbox Lifecycle (per min)** |
| ---------- | ------------------------------ | ------------------------------ | ------------------------------- |
| **Tier 1** | 10,000 | 300 | 10,000 |
| **Tier 2** | 20,000 | 400 | 20,000 |
| **Tier 3** | 40,000 | 500 | 40,000 |
| **Tier 4** | 50,000 | 600 | 50,000 |
| **Custom** | Custom limits | Custom limits | Custom limits |
The general rate limit for authenticated API requests that don't fall under sandbox creation or lifecycle operations includes:
- **Listing sandboxes**
- **Getting sandbox details**
- **Retrieving sandbox regions**
- **Listing snapshots**
- **Managing volumes**
- **Viewing audit logs**
- and other read/management operations
When you exceed a rate limit, subsequent requests will fail with:
- **HTTP Status**: `429 Too Many Requests`
- **Error Response**: JSON body with rate limit details
- **Retry-After Header**: Time to wait before retrying (in seconds)
Understanding these limits helps you build robust applications that handle rate limiting gracefully and avoid service interruptions. For more information, see [best practices](#best-practices).
### Rate limit headers
Daytona includes rate limit information in API response headers. Header names include a suffix based on which rate limit is triggered (e.g., `-anonymous`, `-authenticated`, `-sandbox-create`, `-sandbox-lifecycle`):
| Header Pattern | Description |
| --------------------------------------- | ------------------------------------------------------------------------- |
| **`X-RateLimit-Limit-{throttler}`** | Maximum number of requests allowed in the time window |
| **`X-RateLimit-Remaining-{throttler}`** | Number of requests remaining in the current window |
| **`X-RateLimit-Reset-{throttler}`** | Time in seconds until the rate limit window resets |
| **`Retry-After-{throttler}`** | Time in seconds to wait before retrying (included when limit is exceeded) |
### Sandbox creation
This rate limit applies to all sandbox creation methods, including [creation from snapshots](https://www.daytona.io/docs/snapshots.md#create-snapshots), [declarative builds](https://www.daytona.io/docs/declarative-builder.md) and any other parameters passed to `daytona.create()` ([SDK](https://www.daytona.io/docs/getting-started.md#sdks)) or POST requests to `/api/sandbox` ([API](https://www.daytona.io/docs/getting-started.md#api)).
This independent limit prevents resource exhaustion while allowing you to perform lifecycle operations on existing sandboxes without restriction.
:::note
To create sandboxes at a higher rate for your use case, contact [support@daytona.io](mailto:support@daytona.io).
:::
### Sandbox lifecycle operations
This rate limit applies to lifecycle and state management operations on existing sandboxes:
- [**Starting** sandboxes](https://www.daytona.io/docs/tools/api.md#post-sandboxsandboxidornamestart) (`POST /api/sandbox/:id/start`)
- [**Stopping** sandboxes](https://www.daytona.io/docs/tools/api.md#post-sandboxsandboxidornamestop) (`POST /api/sandbox/:id/stop`)
- [**Deleting** sandboxes](https://www.daytona.io/docs/tools/api.md#delete-sandboxsandboxidorname) (`DELETE /api/sandbox/:id`)
- [**Archiving** sandboxes](https://www.daytona.io/docs/tools/api.md#post-sandboxsandboxidornamearchive) (`POST /api/sandbox/:id/archive`)
- and all corresponding SDK methods
These operations have a higher limit since they're often performed more frequently during development workflows.
### Rate limit errors
Daytona [Python](https://www.daytona.io/docs/python-sdk.md) or [TypeScript](https://www.daytona.io/docs/en/typescript-sdk.md) SDKs raise or throw a `DaytonaRateLimitError` exception (Python) or error (TypeScript) when you exceed a rate limit.
All errors include [**`headers`**](#rate-limit-headers) and [**`statusCode`**](#example-rate-limit-error-response) properties, allowing access to rate limit headers directly from the error object. Headers support case-insensitive access:
```typescript
try {
await daytona.create()
} catch (error) {
if (error instanceof DaytonaRateLimitError) {
console.log(error.headers?.get('x-ratelimit-remaining-sandbox-create'))
console.log(error.headers?.get('X-RateLimit-Remaining-Sandbox-Create')) // also works
}
}
```
```python
try:
daytona.create(snapshot="my-snapshot")
except DaytonaRateLimitError as e:
print(e.headers['x-ratelimit-remaining-sandbox-create'])
print(e.headers['X-RateLimit-Remaining-Sandbox-Create']) # also works
```
```ruby
begin
daytona.create
rescue Daytona::Sdk::Error => e
puts "Error: #{e.message}"
end
```
For more information, see the [Python SDK](https://www.daytona.io/docs/python-sdk/common/errors.md) and [TypeScript SDK](https://www.daytona.io/docs/typescript-sdk/errors.md) references.
> [**DaytonaRateLimitError (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/common/errors.md#daytonaratelimiteerror)
>
> [**DaytonaRateLimitError (TypeScript SDK)**](https://www.daytona.io/docs/python-sdk/common/errors.md#daytonaratelimiterror)
>
> [**DaytonaRateLimitError (Ruby SDK)**](https://www.daytona.io/docs/ruby-sdk/errors.md#daytonaratelimiteerror)
### Rate limit error response
The rate limit error response is a JSON object with the following properties:
- **`statusCode`**: The HTTP status code of the error
- **`message`**: The error message
- **`error`**: The error type
```json
{
"statusCode": 429,
"message": "Rate limit exceeded",
"error": "Too Many Requests"
}
```
## Tier upgrade
Unlock more resources and higher rate limits by completing verification steps. For more information, see the [Daytona Dashboard ↗](https://app.daytona.io/dashboard/limits).
:::note
For access to custom tier requirements or resources in other regions, please contact [sales@daytona.io](mailto:sales@daytona.io).
:::
## Best practices
To work effectively within rate limits, always handle `429` errors gracefully with proper retry logic. When you receive a rate limit error, implement exponential backoff—wait progressively longer between retries (1s, 2s, 4s, 8s, etc.) to avoid overwhelming the API.
The following snippet demonstrates how to create a sandbox with retry logic using the TypeScript SDK:
```typescript
async function createSandboxWithRetry() {
let retries = 0
const maxRetries = 5
while (retries < maxRetries) {
try {
return await daytona.create({ snapshot: 'my-snapshot' })
} catch (error) {
if (error instanceof DaytonaRateLimitError && retries < maxRetries - 1) {
// Use Retry-After header if available, otherwise exponential backoff
const retryAfter = error.headers?.get('retry-after-sandbox-create')
const delay = retryAfter
? parseInt(retryAfter) * 1000
: Math.pow(2, retries) * 1000
await new Promise(resolve => setTimeout(resolve, delay))
retries++
} else {
throw error
}
}
}
}
```
**Monitor [rate limit headers](#rate-limit-headers)** (e.g., `X-RateLimit-Remaining-{throttler}`, `X-RateLimit-Reset-{throttler}`) to track your consumption and implement proactive throttling before hitting limits. These headers are available on all error objects via the `headers` property.
**Cache API responses** that don't frequently change, such as [sandbox lists](https://www.daytona.io/docs/sandboxes.md#list-sandboxes) (when relatively static), [available regions](https://www.daytona.io/docs/regions.md), and [snapshot information](https://www.daytona.io/docs/snapshots.md). This reduces unnecessary API calls and helps you stay well within your limits.
**Batch and optimize operations** by creating multiple sandboxes in parallel (within rate limits) rather than sequentially. Consider reusing existing sandboxes when possible instead of creating new ones for every task.
**Efficiently manage sandbox lifecycle** to reduce API calls. [Archive sandboxes](https://www.daytona.io/docs/sandboxes.md#archive-sandboxes) instead of deleting and recreating them, stop sandboxes when not in use rather than deleting them, and leverage [auto-stop intervals](https://www.daytona.io/docs/sandboxes.md#auto-stop-interval) to automatically manage running sandboxes without manual intervention.
**Implement request queuing** to prevent bursts that exceed limits, and use [webhooks](https://www.daytona.io/docs/webhooks.md) instead of polling for state changes to avoid unnecessary API calls. Set up monitoring and alerts for `429` errors in your application logs so you can proactively address rate limiting issues before they impact your users.
Daytona supports linking user accounts from various identity providers. At the moment, the following providers are supported:
- Google
- GitHub
:::tip
GitHub account is one of the requirements to automatically [upgrade your organization to **Tier 2**](https://www.daytona.io/docs/en/limits.md#tiers--rate-limit-increases).
:::
## Link account
1. Navigate to [Daytona Dashboard ↗](https://app.daytona.io/dashboard/user/account-settings) account settings.
2. Click the **Link Account** button next to the provider you want to link.
3. Follow the prompts to link your account.
## Unlink account
1. Navigate to [Daytona Dashboard ↗](https://app.daytona.io/dashboard/user/account-settings) account settings.
2. Click the **Unlink** button next to the provider you want to unlink.
3. Follow the prompts to unlink your account.
Log streaming allows you to access and process logs as they are being produced, while the process is still running. When executing long-running processes in a sandbox, you often want to access and process their logs in **real-time**.
Real-time streaming is especially useful for **debugging**, **monitoring**, or integrating with **observability tools**.
- [**Log streaming**](#stream-logs-with-callbacks): stream logs as they are being produced, while the process is still running.
- [**Fetching log snapshot**](#retrieve-all-existing-logs): retrieve all logs up to a certain point.
This guide covers how to use log streaming with callbacks and fetching log snapshots in both asynchronous and synchronous modes.
:::note
Starting with version `0.27.0`, you can retrieve session command logs in two distinct streams: **stdout** and **stderr**.
:::
## Stream logs with callbacks
If your sandboxed process is part of a larger system and is expected to run for an extended period (or indefinitely),
you can process logs asynchronously **in the background**, while the rest of your system continues executing.
This is ideal for:
- Continuous monitoring
- Debugging long-running jobs
- Live log forwarding or visualizations
```python
import asyncio
from daytona import Daytona, SessionExecuteRequest
async def main():
daytona = Daytona()
sandbox = daytona.create()
session_id = "streaming-session"
sandbox.process.create_session(session_id)
command = sandbox.process.execute_session_command(
session_id,
SessionExecuteRequest(
command='for i in {1..5}; do echo "Step $i"; echo "Error $i" >&2; sleep 1; done',
var_async=True,
),
)
# Stream logs with separate callbacks
logs_task = asyncio.create_task(
sandbox.process.get_session_command_logs_async(
session_id,
command.cmd_id,
lambda stdout: print(f"[STDOUT]: {stdout}"),
lambda stderr: print(f"[STDERR]: {stderr}"),
)
)
print("Continuing execution while logs are streaming...")
await asyncio.sleep(3)
print("Other operations completed!")
# Wait for the logs to complete
await logs_task
sandbox.delete()
if __name__ == "__main__":
asyncio.run(main())
```
```typescript
import { Daytona, SessionExecuteRequest } from '@daytonaio/sdk'
async function main() {
const daytona = new Daytona()
const sandbox = await daytona.create()
const sessionId = "exec-session-1"
await sandbox.process.createSession(sessionId)
const command = await sandbox.process.executeSessionCommand(
sessionId,
{
command: 'for i in {1..5}; do echo "Step $i"; echo "Error $i" >&2; sleep 1; done',
runAsync: true,
},
)
// Stream logs with separate callbacks
const logsTask = sandbox.process.getSessionCommandLogs(
sessionId,
command.cmdId!,
(stdout) => console.log('[STDOUT]:', stdout),
(stderr) => console.log('[STDERR]:', stderr),
)
console.log('Continuing execution while logs are streaming...')
await new Promise((resolve) => setTimeout(resolve, 3000))
console.log('Other operations completed!')
// Wait for the logs to complete
await logsTask
await sandbox.delete()
}
main()
```
```ruby
require 'daytona'
daytona = Daytona::Daytona.new
sandbox = daytona.create
session_id = 'streaming-session'
sandbox.process.create_session(session_id)
command = sandbox.process.execute_session_command(
session_id,
Daytona::SessionExecuteRequest.new(
command: 'for i in {1..5}; do echo "Step $i"; echo "Error $i" >&2; sleep 1; done',
var_async: true
)
)
# Stream logs using a thread
log_thread = Thread.new do
sandbox.process.get_session_command_logs_stream(
session_id,
command.cmd_id,
on_stdout: ->(stdout) { puts "[STDOUT]: #{stdout}" },
on_stderr: ->(stderr) { puts "[STDERR]: #{stderr}" }
)
end
puts 'Continuing execution while logs are streaming...'
sleep(3)
puts 'Other operations completed!'
# Wait for the logs to complete
log_thread.join
daytona.delete(sandbox)
```
```go
package main
import (
"context"
"fmt"
"log"
"os"
"github.com/daytonaio/daytona/libs/sdk-go/pkg/daytona"
)
func main() {
client, _ := daytona.NewClient()
ctx := context.Background()
sandbox, _ := client.Create(ctx, nil)
sessionID := "streaming-session"
sandbox.Process.CreateSession(ctx, sessionID)
// Execute async command that outputs to stdout and stderr
cmd := `for i in 1 2 3 4 5; do echo "Step $i"; echo "Error $i" >&2; sleep 1; done`
cmdResult, _ := sandbox.Process.ExecuteSessionCommand(ctx, sessionID, cmd, true)
cmdID, _ := cmdResult["id"].(string)
// Create channels for stdout and stderr
stdout := make(chan string, 100)
stderr := make(chan string, 100)
// Stream logs in a goroutine
go func() {
err := sandbox.Process.GetSessionCommandLogsStream(ctx, sessionID, cmdID, stdout, stderr)
if err != nil {
log.Printf("Stream error: %v", err)
}
}()
fmt.Println("Continuing execution while logs are streaming...")
// Read from channels until both are closed
stdoutOpen, stderrOpen := true, true
for stdoutOpen || stderrOpen {
select {
case chunk, ok := <-stdout:
if !ok {
stdoutOpen = false
} else {
fmt.Fprintf(os.Stdout, "[STDOUT]: %s", chunk)
}
case chunk, ok := <-stderr:
if !ok {
stderrOpen = false
} else {
fmt.Fprintf(os.Stderr, "[STDERR]: %s", chunk)
}
}
}
fmt.Println("Streaming completed!")
sandbox.Delete(ctx)
}
```
```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/process/session/{sessionId}/command/{commandId}/logs'
```
For more information, see the [Python SDK](https://www.daytona.io/docs/python-sdk/sync/process.md), [TypeScript SDK](https://www.daytona.io/docs/typescript-sdk/process.md), [Ruby SDK](https://www.daytona.io/docs/ruby-sdk/process.md), [Go SDK](https://www.daytona.io/docs/go-sdk.md), and [API](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/process) references.
> [**get_session_command_logs_async (Python SDK)**](https://www.daytona.io/docs/python-sdk/sync/process.md#processget_session_command_logs_async)
>
> [**getSessionCommandLogs (TypeScript SDK)**](https://www.daytona.io/docs/typescript-sdk/process.md#getsessioncommandlogs)
>
> [**get_session_command_logs_async (Ruby SDK)**](https://www.daytona.io/docs/ruby-sdk/process.md#get_session_command_logs_async)
>
> [**GetSessionCommandLogsStream (Go SDK)**](https://www.daytona.io/docs/go-sdk/daytona.md#ProcessService.GetSessionCommandLogsStream)
>
> [**get session command logs (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/process/POST/process/session/{sessionId}/exec)
## Retrieve all existing logs
If the command has a predictable duration, or if you don't need to run it in the background but want to
periodically check all existing logs, you can use the following example to get the logs up to the current point in time.
```python
import time
from daytona import Daytona, SessionExecuteRequest
daytona = Daytona()
sandbox = daytona.create()
session_id = "exec-session-1"
sandbox.process.create_session(session_id)
# Execute a blocking command and wait for the result
command = sandbox.process.execute_session_command(
session_id, SessionExecuteRequest(command="echo 'Hello from stdout' && echo 'Hello from stderr' >&2")
)
print(f"[STDOUT]: {command.stdout}")
print(f"[STDERR]: {command.stderr}")
print(f"[OUTPUT]: {command.output}")
# Or execute command in the background and get the logs later
command = sandbox.process.execute_session_command(
session_id,
SessionExecuteRequest(
command='while true; do if (( RANDOM % 2 )); then echo "All good at $(date)"; else echo "Oops, an error at $(date)" >&2; fi; sleep 1; done',
run_async=True
)
)
time.sleep(5)
# Get the logs up to the current point in time
logs = sandbox.process.get_session_command_logs(session_id, command.cmd_id)
print(f"[STDOUT]: {logs.stdout}")
print(f"[STDERR]: {logs.stderr}")
print(f"[OUTPUT]: {logs.output}")
sandbox.delete()
```
```typescript
import { Daytona, SessionExecuteRequest } from '@daytonaio/sdk'
async function main() {
const daytona = new Daytona()
const sandbox = await daytona.create()
const sessionId = "exec-session-1"
await sandbox.process.createSession(sessionId)
// Execute a blocking command and wait for the result
const command = await sandbox.process.executeSessionCommand(
sessionId,
{
command: 'echo "Hello from stdout" && echo "Hello from stderr" >&2',
},
)
console.log(`[STDOUT]: ${command.stdout}`)
console.log(`[STDERR]: ${command.stderr}`)
console.log(`[OUTPUT]: ${command.output}`)
// Or execute command in the background and get the logs later
const command2 = await sandbox.process.executeSessionCommand(
sessionId,
{
command: 'while true; do if (( RANDOM % 2 )); then echo "All good at $(date)"; else echo "Oops, an error at $(date)" >&2; fi; sleep 1; done',
runAsync: true,
},
)
await new Promise((resolve) => setTimeout(resolve, 5000))
// Get the logs up to the current point in time
const logs = await sandbox.process.getSessionCommandLogs(sessionId, command2.cmdId!)
console.log(`[STDOUT]: ${logs.stdout}`)
console.log(`[STDERR]: ${logs.stderr}`)
console.log(`[OUTPUT]: ${logs.output}`)
await sandbox.delete()
}
main()
```
```ruby
require 'daytona'
daytona = Daytona::Daytona.new
sandbox = daytona.create
session_id = 'exec-session-1'
sandbox.process.create_session(session_id)
# Execute a blocking command and wait for the result
command = sandbox.process.execute_session_command(
session_id,
Daytona::SessionExecuteRequest.new(
command: 'echo "Hello from stdout" && echo "Hello from stderr" >&2'
)
)
puts "[STDOUT]: #{command.stdout}"
puts "[STDERR]: #{command.stderr}"
puts "[OUTPUT]: #{command.output}"
# Or execute command in the background and get the logs later
command = sandbox.process.execute_session_command(
session_id,
Daytona::SessionExecuteRequest.new(
command: 'while true; do if (( RANDOM % 2 )); then echo "All good at $(date)"; else echo "Oops, an error at $(date)" >&2; fi; sleep 1; done',
var_async: true
)
)
sleep(5)
# Get the logs up to the current point in time
logs = sandbox.process.get_session_command_logs(session_id, command.cmd_id)
puts "[STDOUT]: #{logs.stdout}"
puts "[STDERR]: #{logs.stderr}"
puts "[OUTPUT]: #{logs.output}"
daytona.delete(sandbox)
```
```go
package main
import (
"context"
"fmt"
"log"
"time"
"github.com/daytonaio/daytona/libs/sdk-go/pkg/daytona"
)
func main() {
client, _ := daytona.NewClient()
ctx := context.Background()
sandbox, _ := client.Create(ctx, nil)
sessionID := "exec-session-1"
sandbox.Process.CreateSession(ctx, sessionID)
// Execute a blocking command and wait for the result
cmd1, _ := sandbox.Process.ExecuteSessionCommand(ctx, sessionID,
`echo "Hello from stdout" && echo "Hello from stderr" >&2`, false)
if stdout, ok := cmd1["stdout"].(string); ok {
fmt.Printf("[STDOUT]: %s\n", stdout)
}
if stderr, ok := cmd1["stderr"].(string); ok {
fmt.Printf("[STDERR]: %s\n", stderr)
}
// Or execute command in the background and get the logs later
cmd := `counter=1; while (( counter <= 5 )); do echo "Count: $counter"; ((counter++)); sleep 1; done`
cmdResult, _ := sandbox.Process.ExecuteSessionCommand(ctx, sessionID, cmd, true)
cmdID, _ := cmdResult["id"].(string)
time.Sleep(5 * time.Second)
// Get the logs up to the current point in time
logs, err := sandbox.Process.GetSessionCommandLogs(ctx, sessionID, cmdID)
if err != nil {
log.Fatalf("Failed to get logs: %v", err)
}
if logContent, ok := logs["logs"].(string); ok {
fmt.Printf("[LOGS]: %s\n", logContent)
}
sandbox.Delete(ctx)
}
```
```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/process/session/{sessionId}/command/{commandId}/logs'
```
For more information, see the [Python SDK](https://www.daytona.io/docs/python-sdk/sync/process.md), [TypeScript SDK](https://www.daytona.io/docs/typescript-sdk/process.md), [Ruby SDK](https://www.daytona.io/docs/ruby-sdk/process.md), [Go SDK](https://www.daytona.io/docs/go-sdk.md), and [API](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/process) references.
> [**get_session_command_logs (Python SDK)**](https://www.daytona.io/docs/python-sdk/sync/process.md#processget_session_command_logs)
>
> [**getSessionCommandLogs (TypeScript SDK)**](https://www.daytona.io/docs/typescript-sdk/process.md#getsessioncommandlogs)
>
> [**get_session_command_logs (Ruby SDK)**](https://www.daytona.io/docs/ruby-sdk/process.md#get_session_command_logs)
>
> [**GetSessionCommandLogs (Go SDK)**](https://www.daytona.io/docs/go-sdk/daytona.md#ProcessService.GetSessionCommandLogs)
>
> [**get session command logs (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/process/POST/process/session/{sessionId}/exec)
Daytona Model Context Protocol (MCP) server enables AI agents to interact with [Daytona Sandboxes](https://www.daytona.io/docs/en/sandboxes.md) programmatically. This guide covers how to set up and use the MCP server with various AI agents.
## Install Daytona CLI
Install the Daytona CLI to manage the MCP server.
```bash
brew install daytonaio/cli/daytona
```
```bash
powershell -Command "irm https://get.daytona.io/windows | iex"
```
For more information, see the [CLI](https://www.daytona.io/docs/en/tools/cli.md) reference.
## Authenticate with Daytona
Authenticate with Daytona to enable MCP server access.
```bash
daytona login
```
For more information, see the [CLI](https://www.daytona.io/docs/en/tools/cli.md#daytona-login) reference:
> [**login (CLI)**](https://www.daytona.io/docs/en/tools/cli.md#daytona-login)
## Initialize MCP server
Daytona provides methods to initialize the MCP server with your preferred AI agent. Supported agents include Claude, Cursor, and Windsurf.
```bash
# Initialize with Claude
daytona mcp init claude
# Initialize with Cursor
daytona mcp init cursor
# Initialize with Windsurf
daytona mcp init windsurf
```
After initialization, open your AI agent application to begin using Daytona features.
For more information, see the [CLI](https://www.daytona.io/docs/en/tools/cli.md#daytona-mcp-init) reference:
> [**mcp init (CLI)**](https://www.daytona.io/docs/en/tools/cli.md#daytona-mcp-init)
## Configure MCP server
Daytona provides methods to generate MCP configuration for integration with other AI agents.
```bash
daytona mcp config
```
This command outputs a JSON configuration that you can copy into your agent's settings:
```json
{
"mcpServers": {
"daytona-mcp": {
"command": "daytona",
"args": ["mcp", "start"],
"env": {
"HOME": "${HOME}",
"PATH": "${HOME}:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/homebrew/bin"
},
"logFile": "${HOME}/Library/Logs/daytona/daytona-mcp-server.log"
}
}
}
```
:::note
For Windows users, add the following to the `env` field:
```json
"APPDATA": "${APPDATA}"
```
:::
For more information, see the [CLI](https://www.daytona.io/docs/en/tools/cli.md#daytona-mcp-config) reference:
> [**mcp config (CLI)**](https://www.daytona.io/docs/en/tools/cli.md#daytona-mcp-config)
## Start MCP server
Daytona provides methods to manually start the MCP server.
```bash
daytona mcp start
```
For more information, see the [CLI](https://www.daytona.io/docs/en/tools/cli.md#daytona-mcp-start) reference:
> [**mcp start (CLI)**](https://www.daytona.io/docs/en/tools/cli.md#daytona-mcp-start)
## Available tools
Daytona MCP server provides the following tools for interacting with Daytona Sandboxes:
- [Sandbox management](https://www.daytona.io/docs/en/sandboxes.md)
- [File system operations](https://www.daytona.io/docs/en/file-system-operations.md)
- [Git operations](https://www.daytona.io/docs/en/git-operations.md)
- [Process and code execution](https://www.daytona.io/docs/en/process-code-execution.md)
- [Computer use](https://www.daytona.io/docs/en/computer-use.md)
- [Preview](https://www.daytona.io/docs/en/preview.md)
## Troubleshooting
To troubleshoot issues with the Daytona MCP server, try the following:
- **Authentication issues**: run `daytona login` to refresh credentials
- **Connection errors**: verify MCP server configuration, check server status
- **Sandbox errors**: use `daytona list` to check sandbox status
If the issue persists, contact [support@daytona.io](mailto:support@daytona.io).
Daytona provides network egress limiting for sandboxes to control internet access. This feature can be automatically applied based on your [organization's limits](https://www.daytona.io/docs/en/limits.md) or manually configured for specific sandboxes.
## Tier-based network restrictions
Network limits are automatically applied to sandboxes based on your organization's billing tier. This provides secure and controlled internet access for development environments:
- **Tier 1 & Tier 2**: Network access is restricted and cannot be overridden at the sandbox level. Organization-level network restrictions take precedence over sandbox-level settings. Even with [`networkAllowList`](#create-sandboxes-with-network-restrictions) specified when creating a sandbox, the organization's network restrictions still apply
- **Tier 3 & Tier 4**: Full internet access is available by default, with the ability to configure custom network settings
> To learn more about organization tiers and limits, see [limits](https://www.daytona.io/docs/en/limits.md).
[Essential services](#essential-services) are available on all tiers and include services essential for development: package registries, container registries, Git repositories, CDN services, platform services, and system package managers.
## Create sandboxes with network restrictions
Daytona provides methods to control network access when [creating sandboxes](https://www.daytona.io/docs/en/sandboxes.md#create-sandboxes) by using the `networkAllowList` and `networkBlockAll` parameters:
```python
from daytona import CreateSandboxFromSnapshotParams, Daytona
daytona = Daytona()
# Allow access to specific IP addresses (Wikipedia, X/Twitter, private network)
sandbox = daytona.create(CreateSandboxFromSnapshotParams(
network_allow_list='208.80.154.232/32,199.16.156.103/32,192.168.1.0/24'
))
# Or block all network access
sandbox = daytona.create(CreateSandboxFromSnapshotParams(
network_block_all=True
))
```
```typescript
import { Daytona } from '@daytonaio/sdk'
const daytona = new Daytona()
// Allow access to specific IP addresses (Wikipedia, X/Twitter, private network)
const sandbox = await daytona.create({
networkAllowList: '208.80.154.232/32,199.16.156.103/32,192.168.1.0/24'
})
// Or block all network access
const sandbox = await daytona.create({
networkBlockAll: true
})
```
```ruby
require 'daytona'
daytona = Daytona::Daytona.new
# Allow access to specific IP addresses (Wikipedia, X/Twitter, private network)
sandbox = daytona.create(
Daytona::CreateSandboxFromSnapshotParams.new(
network_allow_list: '208.80.154.232/32,199.16.156.103/32,192.168.1.0/24'
)
)
# Or block all network access
sandbox = daytona.create(
Daytona::CreateSandboxFromSnapshotParams.new(
network_block_all: true
)
)
```
```go
package main
import (
"context"
"log"
"github.com/daytonaio/daytona/libs/sdk-go/pkg/daytona"
"github.com/daytonaio/daytona/libs/sdk-go/pkg/types"
)
func main() {
client, err := daytona.NewClient()
if err != nil {
log.Fatal(err)
}
ctx := context.Background()
// Allow access to specific IP addresses (Wikipedia, X/Twitter, private network)
allowList := "208.80.154.232/32,199.16.156.103/32,192.168.1.0/24"
sandbox, err := client.Create(ctx, types.SnapshotParams{
SandboxBaseParams: types.SandboxBaseParams{
NetworkAllowList: &allowList,
},
})
// Or block all network access
sandbox, err = client.Create(ctx, types.SnapshotParams{
SandboxBaseParams: types.SandboxBaseParams{
NetworkBlockAll: true,
},
})
}
```
```bash
# Allow access to specific IP addresses (Wikipedia, X/Twitter, private network)
curl 'https://app.daytona.io/api/sandbox' \
--request POST \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer YOUR_API_KEY' \
--data '{
"networkAllowList": "208.80.154.232/32,199.16.156.103/32,192.168.1.0/24"
}'
# Or block all network access
curl 'https://app.daytona.io/api/sandbox' \
--request POST \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer YOUR_API_KEY' \
--data '{
"networkBlockAll": true
}'
```
```bash
# Allow access to specific IP addresses (Wikipedia, X/Twitter, private network)
daytona create --network-allow-list '208.80.154.232/32,199.16.156.103/32,192.168.1.0/24'
# Or block all network access
daytona create --network-block-all
```
:::note
If both `networkBlockAll` and `networkAllowList` are specified, `networkBlockAll` takes precedence and all network access will be blocked, ignoring the allow list.
:::
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk/sync/daytona.md#createsandboxbaseparams), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk/daytona.md#createsandboxbaseparams), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk/sandbox.md#network_allow_list), [Go SDK](https://www.daytona.io/docs/en/go-sdk/types.md#SandboxBaseParams), [API](https://www.daytona.io/docs/en/tools/api.md#daytona/tag/sandbox/POST/sandbox), and [CLI](https://www.daytona.io/docs/en/tools/cli.md#daytona-create) references:
> [**network_allow_list (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/daytona.md#createsandboxbaseparams)
>
> [**network_block_all (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/daytona.md#createsandboxbaseparams)
>
> [**network_allow_list (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/daytona.md#createsandboxbaseparams)
>
> [**network_block_all (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/daytona.md#createsandboxbaseparams)
>
> [**network_allow_list (Ruby SDK)**](https://www.daytona.io/docs/en/ruby-sdk/sandbox.md#network_allow_list)
>
> [**network_block_all (Ruby SDK)**](https://www.daytona.io/docs/en/ruby-sdk/sandbox.md#network_allow_list)
>
> [**network_allow_list (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/types.md#SandboxBaseParams)
>
> [**network_block_all (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/types.md#SandboxBaseParams)
>
> [**networkAllowList (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona/tag/sandbox/POST/sandbox)
>
> [**networkBlockAll (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona/tag/sandbox/POST/sandbox)
>
> [**--network-allow-list (CLI)**](https://www.daytona.io/docs/en/tools/cli.md#daytona-create)
>
> [**--network-block-all (CLI)**](https://www.daytona.io/docs/en/tools/cli.md#daytona-create)
## Network allow list format
The network allow list is a comma-separated list of IPv4 CIDR blocks. Set your allowed networks using the `networkAllowList` parameter when [creating a sandbox](https://www.daytona.io/docs/en/sandboxes.md#create-sandboxes).
- **IPv4 only**: hostnames, domains, and IPv6 are not supported
- **CIDR required**: every entry must include a `/` prefix length integer in the range `0` to `32` (inclusive), for example: `/32`
- **CIDR format**: use standard CIDR notation (`A.B.C.D/N`). Do not include extra `/` segments
- **Max 10 entries**: the list cannot contain more than 10 comma-separated items
- **Whitespace is ignored**: entries are trimmed, so spaces around commas are ok
The following examples are valid:
- **Single IP**: `208.80.154.232/32` (Wikipedia)
- **Subnet**: `192.168.1.0/24` (Private network)
- **Multiple networks**: `208.80.154.232/32,199.16.156.103/32,10.0.0.0/8`
## Organization configuration
The network access policies for your organization are set automatically depending on your organization's limits tier and cannot be modified by organization administrators. These policies determine the default network behavior for all sandboxes in your organization.
## Test network access
To test network connectivity from your sandbox:
```bash
# Test HTTP connectivity to allowed addresses
curl -I https://208.80.154.232
# Test package manager access (allowed on all tiers)
apt update # For Ubuntu/Debian
npm ping # For Node.js
pip install --dry-run requests # For Python
```
## Security benefits
Network limits provide several security advantages:
- **Prevents data exfiltration** from sandboxes
- **Reduces attack surface** by limiting external connections
- **Complies with security policies** for development environments
- **Enables fine-grained control** over network access
:::caution
Enabling unrestricted network access may pose security risks when executing untrusted code. It is recommended to whitelist specific network addresses using `networkAllowList` or block all network access using `networkBlockAll` instead.
Test network connectivity before starting critical development work and consider upgrading your tier if you need access to many external services.
:::
## Essential services
Daytona provides a list of essential services that are available on all tiers and can be used for development.
:::note
This list is continuously updated. If you require access to additional essential development services, submit a request in the [sandbox network whitelist](https://github.com/daytonaio/sandbox-network-whitelist) repository or contact [support@daytona.io](mailto:support@daytona.io).
:::
### NPM registry and package managers
- **NPM Registry**: `registry.npmjs.org`, `registry.npmjs.com`, `nodejs.org`, `nodesource.com`, `npm.pkg.github.com`
- **Yarn Packages**: `yarnpkg.com`, `*.yarnpkg.com`, `yarn.npmjs.org`, `yarnpkg.netlify.com`
- **Bun**: `bun.sh`, `*.bun.sh`
### Git hosting and version control
- **GitHub**: `github.com`, `*.github.com`, `*.githubusercontent.com`, `ghcr.io`
- **GitLab**: `gitlab.com`, `*.gitlab.com`
- **Bitbucket**: `bitbucket.org`
- **Azure DevOps**: `dev.azure.com`, `*.dev.azure.com`, `login.microsoftonline.com`, `visualstudio.com`, `*.visualstudio.com`, `ssh.dev.azure.com`, `vs-ssh.visualstudio.com`
### Python package managers
- **PyPI**: `pypi.org`, `pypi.python.org`, `files.pythonhosted.org`, `bootstrap.pypa.io`, `astral.sh`
### Composer packages
- **Composer**: `*.packagist.org`, `packagist.com`
### Ubuntu/Debian package repositories
- **Ubuntu Repos**: `*.ubuntu.com`
- **Debian Repos**: `*.debian.org`, `cdn-fastly.deb.debian.org`
### CDN and content delivery
- **CDN Services**: `fastly.com`, `cloudflare.com`, `r2.cloudflarestorage.com`, `*.r2.cloudflarestorage.com`
- **JavaScript CDNs**: `unpkg.com`, `jsdelivr.net`
### AI/ML services
- **Anthropic**: `*.anthropic.com`, `claude.ai`, `platform.claude.com`
- **OpenAI**: `openai.com`, `*.openai.com`, `chatgpt.com`
- **Google AI**: `generativelanguage.googleapis.com`, `gemini.google.com`, `aistudio.google.com`, `ai.google.dev`, `models.dev`
- **Perplexity**: `api.perplexity.ai`
- **DeepSeek**: `api.deepseek.com`
- **Groq**: `api.groq.com`
- **Expo**: `api.expo.dev`
- **OpenRouter**: `openrouter.ai`
- **Qwen**: `chat.qwen.ai`, `dashscope.aliyuncs.com`, `dashscope-intl.aliyuncs.com`
- **Cursor**: `*.cursor.com`
- **OpenCode**: `opencode.ai`, `*.opencode.ai`
- **Other AI Services**: `api.letta.com`, `api.fireworks.ai`, `open.bigmodel.cn`, `*.z.ai`, `*.moonshot.ai`, `ai-gateway.vercel.sh`, `api.featherless.ai`
### Docker registries and container services
- **Docker Registries**: `docker.io`, `*.docker.io`, `*.docker.com`
- **Microsoft Container Registry**: `mcr.microsoft.com`
- **Kubernetes Registry**: `registry.k8s.io`
- **Google Container Registry**: `gcr.io`, `*.gcr.io`, `registry.cloud.google.com`
- **Quay**: `quay.io`, `quay-registry.s3.amazonaws.com`
### Maven repositories
- **Maven Repos**: `repo1.maven.org`, `repo.maven.apache.org`
### Google Fonts
- **Google Fonts**: `fonts.googleapis.com`, `fonts.gstatic.com`
### AWS S3 endpoints
- **US East**: `s3.us-east-1.amazonaws.com`, `s3.us-east-2.amazonaws.com`
- **US West**: `s3.us-west-1.amazonaws.com`, `s3.us-west-2.amazonaws.com`
- **EU**: `s3.eu-central-1.amazonaws.com`, `s3.eu-west-1.amazonaws.com`, `s3.eu-west-2.amazonaws.com`
### Google Cloud Storage
- **GCS**: `storage.googleapis.com`
### Daytona
- **Daytona**: `app.daytona.io`
### Developer tools and services
- **Convex**: `convex.dev`, `*.convex.dev`, `*.convex.cloud`, `*.convex.site`
- **Heroku**: `herokuapp.com`, `*.herokuapp.com`
- **Vercel**: `vercel.com`, `*.vercel.com`, `*.vercel.app`
- **Supabase**: `supabase.com`, `*.supabase.com`, `supabase.co`, `*.supabase.co`
- **Clerk**: `clerk.com`, `*.clerk.com`, `clerk.dev`, `*.clerk.dev`, `accounts.dev`, `*.accounts.dev`, `clerk.accounts.dev`, `*.clerk.accounts.dev`
- **WorkOS**: `workos.com`, `*.workos.com`, `authkit.app`, `*.authkit.app`
- **Inngest**: `inngest.com`, `*.inngest.com`
- **PostHog**: `posthog.com`, `*.posthog.com`
- **Sentry**: `sentry.io`, `*.sentry.io`, `sentry-cdn.com`, `*.sentry-cdn.com`
- **Linear**: `linear.app`, `*.linear.app`
- **Figma**: `figma.com`, `*.figma.com`, `*.figmafiles.com`
- **ClickUp**: `clickup.com`, `*.clickup.com`
- **Playwright**: `playwright.dev`, `cdn.playwright.dev`
### Messaging services
- **Telegram**: `api.telegram.org`
- **WhatsApp**: `web.whatsapp.com`, `*.whatsapp.net`
### LLM observability
- **Langfuse**: `*.langfuse.com`, `*.cloud.langfuse.com`
## Troubleshooting
If you encounter network access issues or need unrestricted network access:
1. Verify your [organization tier](https://www.daytona.io/docs/en/limits.md#tier-upgrade) in the [Daytona Dashboard ↗](https://app.daytona.io/dashboard/limits)
2. Verify your [network allow list](#network-allow-list-format) configuration
3. Contact [support@daytona.io](mailto:support@daytona.io) for assistance
Daytona provides organizations as a way to group resources and enable collaboration. Users can work individually in their personal organization or together in a collaborative organization.
Navigate to [Daytona Dashboard ↗](https://app.daytona.io/dashboard) to manage your organizations.
## Personal vs Collaborative organizations
Every Daytona user starts with a personal organization, ideal for solo use and experimentation. Collaborative organizations are created manually and designed for company-wide collaboration with shared access and controls.
| **Feature** | **Personal organization** | **Collaborative organization** |
| ------------------ | -------------------------------- | ---------------------------------------------- |
| **Creation** | Automatic on signup | Manually by a user |
| **Members** | Single user only | Multiple users (invite-based) |
| **Access Control** | No roles or permissions | Roles with granular resource-based assignments |
| **Billing** | Tied to individual user | Shared across team members |
| **Use Case** | Personal testing, small projects | Company/team development and production |
| **Quota Scope** | Per user | Shared across all members |
| **Deletable** | No | Yes (by Owner) |
Users can switch between their personal and collaborative organizations by using the dropdown in the [Daytona Dashboard ↗](https://app.daytona.io/dashboard) sidebar. Each organization has its own sandboxes, API keys, and resource quotas.
## Organization roles
Users within an organization can have one of two different roles:
1. **Owners** have full administrative access to the organization and its resources. Organization owners can perform administrative actions.
2. **Members** have no administrative access to the organization, while their access to organization resources is based on [**Assignments**](#available-assignments).
## Administrative actions
Organization owners can perform administrative actions such as:
- [Invite new users to the organization](#inviting-new-users)
- [Manage pending invitations](#managing-invitations)
- [Change role](#organization-roles) of a user in the Organization
- [Update assignments](#available-assignments) for organization members
- Remove user from the organization
- Inspect audit logs
- [Delete organization](#organization-settings)
## Available assignments
The list of available assignments includes:
| Assignment | Description |
| ----------------------------- | ------------------------------------------------------------------- |
| **`Viewer (required)`** | Grants read access to all resources in the organization |
| **`Developer`** | Grants the ability to create sandboxes and keys in the organization |
| **`Sandboxes Admin`** | Grants admin access to sandboxes in the organization |
| **`Snapshots Admin`** | Grants admin access to snapshots in the organization |
| **`Registries Admin`** | Grants admin access to registries in the organization |
| **`Volumes Admin`** | Grants admin access to volumes in the organization |
| **`Super Admin`** | Grants full access to all resources in the organization |
| **`Auditor`** | Grants access to audit logs in the organization |
| **`Infrastructure Admin`** | Grants admin access to infrastructure in the organization |
## Manage members
### Invite new users
As an organization **Owner**, to invite a new user to your organization:
1. Navigate to [Members ↗](https://app.daytona.io/dashboard/members)
2. Click the **Invite Member** button
3. Enter the email address of the user you want to invite
4. [Select a role](#organization-roles) for the new user. If you select the **`Member`** role, define their [assignments](#available-assignments)
### Remove users
As an organization **Owner**, to remove a user from your organization:
1. Navigate to [Members ↗](https://app.daytona.io/dashboard/members)
2. Click the **Remove** button next to the user you want to remove
3. Confirm the removal by clicking the **Remove** button
## Manage invitations
To view pending invitations to join other organizations, navigate to [Invitations ↗](https://app.daytona.io/dashboard/invitations) page by expanding the dropdown at the bottom of the sidebar.
Once a user accepts an invitation to join an organization, they get access to resource quotas assigned to that organization and they may proceed by issuing a new [API key](https://www.daytona.io/docs/en/api-keys.md) and creating sandboxes.
## Organization settings
The [Settings](https://app.daytona.io/dashboard/settings) subpage in the Dashboard allows you to view the Organization ID and Name and to delete the Organization if you don't need it anymore. This action is irreversible, so please proceed with caution. Personal Organizations are there by default and cannot be deleted.
This guide will walk you through running Daytona Open Source locally using Docker Compose.
The compose file can be found in the [docker](https://github.com/daytonaio/daytona/tree/main/docker) folder of the Daytona repository.
:::caution
- This setup is still in development and is **not safe to use in production**
- For a fully licensed stable version, [contact sales](https://www.daytona.io/contact)
:::
## Overview
The Docker Compose configuration includes all the necessary services to run Daytona:
- **API**: Main Daytona application server
- **Proxy**: Request proxy service
- **Runner**: Service that hosts the Daytona Runner
- **SSH Gateway**: Service that handles sandbox SSH access
- **Database**: PostgreSQL database for data persistence
- **Redis**: In-memory data store for caching and sessions
- **Dex**: OIDC authentication provider
- **Registry**: Docker image registry with web UI
- **MinIO**: S3-compatible object storage
- **MailDev**: Email testing service
- **Jaeger**: Distributed tracing
- **PgAdmin**: Database administration interface
## Quick Start
1. Clone the [Daytona repository](https://github.com/daytonaio/daytona)
2. [Install Docker and Docker Compose](https://docs.docker.com/get-docker/)
3. Run the following command (from the root of the Daytona repo) to start all services:
```bash
docker compose -f docker/docker-compose.yaml up -d
```
4. Access the services:
- Daytona Dashboard: http://localhost:3000
- Access Credentials: dev@daytona.io `password`
- Make sure that the default snapshot is active at http://localhost:3000/dashboard/snapshots
- PgAdmin: http://localhost:5050
- Registry UI: http://localhost:5100
- MinIO Console: http://localhost:9001 (minioadmin / minioadmin)
## DNS Setup for Proxy URLs
For local development, you need to resolve `*.proxy.localhost` domains to `127.0.0.1`:
```bash
./scripts/setup-proxy-dns.sh
```
This configures dnsmasq with `address=/proxy.localhost/127.0.0.1`.
**Without this setup**, SDK examples and direct proxy access won't work.
## Development Notes
- The setup uses shared networking for simplified service communication
- Database and storage data is persisted in Docker volumes
- The registry is configured to allow image deletion for testing
- Sandbox resource limits are disabled due to inability to partition cgroups in DinD environment where the sock is not mounted
## Additional Network Options
### HTTP Proxy
To configurate an outbound HTTP proxy for the Daytona services, you can set the following environment variables in the `docker-compose.yaml` file for each service that requires proxy access (the API service is the only that requires outbound access to pull images):
- `HTTP_PROXY`: URL of the HTTP proxy server
- `HTTPS_PROXY`: URL of the HTTPS proxy server
- `NO_PROXY`: Comma-separated list of hostnames or IP addresses that should bypass the proxy
The baseline configuration for the API service should be as follows:
```yaml
environment:
- HTTP_PROXY=
- HTTPS_PROXY=
- NO_PROXY=localhost,runner,dex,registry,minio,jaeger,otel-collector,
```
### Extra CA Certificates
To configure extra CA certificates (for example, paired with `DB_TLS` env vars), set the following environment variable in the API service:
```yaml
environment:
- NODE_EXTRA_CA_CERTS=/path/to/your/cert-bundle.pembundle
```
The provided file is a cert bundle. Meaning it can contain multiple CA certificates in PEM format.
## Environment Variables
You can customize the deployment by modifying environment variables in the `docker-compose.yaml` file.
Below is a full list of environment variables with their default values:
### API Service
| Variable | Type | Default Value | Description |
| ------------------------------------------ | ------- | ---------------------------------------------------- | ---------------------------------------------------------------------------------------------------- |
| `ENCRYPTION_KEY` | string | `supersecretkey` | Encryption key for sensitive data (User must override outside of Compose) |
| `ENCRYPTION_SALT` | string | `supersecretsalt` | Encryption salt for sensitive data (User must override outside of Compose) |
| `PORT` | number | `3000` | API service port |
| `DB_HOST` | string | `db` | PostgreSQL database hostname |
| `DB_PORT` | number | `5432` | PostgreSQL database port |
| `DB_USERNAME` | string | `user` | PostgreSQL database username |
| `DB_PASSWORD` | string | `pass` | PostgreSQL database password |
| `DB_DATABASE` | string | `daytona` | PostgreSQL database name |
| `DB_TLS_ENABLED` | boolean | `false` | Enable TLS for database connection |
| `DB_TLS_REJECT_UNAUTHORIZED` | boolean | `true` | Reject unauthorized TLS certificates |
| `REDIS_HOST` | string | `redis` | Redis server hostname |
| `REDIS_PORT` | number | `6379` | Redis server port |
| `OIDC_CLIENT_ID` | string | `daytona` | OIDC client identifier |
| `OIDC_ISSUER_BASE_URL` | string | `http://dex:5556/dex` | OIDC issuer base URL |
| `PUBLIC_OIDC_DOMAIN` | string | `http://localhost:5556/dex` | Public OIDC domain |
| `OIDC_AUDIENCE` | string | `daytona` | OIDC audience identifier |
| `OIDC_MANAGEMENT_API_ENABLED` | boolean | (empty) | Enable OIDC management API |
| `OIDC_MANAGEMENT_API_CLIENT_ID` | string | (empty) | OIDC management API client ID |
| `OIDC_MANAGEMENT_API_CLIENT_SECRET` | string | (empty) | OIDC management API client secret |
| `OIDC_MANAGEMENT_API_AUDIENCE` | string | (empty) | OIDC management API audience |
| `DEFAULT_SNAPSHOT` | string | `daytonaio/sandbox:0.4.3` | Default sandbox snapshot image |
| `DASHBOARD_URL` | string | `http://localhost:3000/dashboard` | Dashboard URL |
| `DASHBOARD_BASE_API_URL` | string | `http://localhost:3000` | Dashboard base API URL |
| `POSTHOG_API_KEY` | string | `phc_bYtEsdMDrNLydXPD4tufkBrHKgfO2zbycM30LOowYNv` | PostHog API key for analytics |
| `POSTHOG_HOST` | string | `https://d18ag4dodbta3l.cloudfront.net` | PostHog host URL |
| `POSTHOG_ENVIRONMENT` | string | `local` | PostHog environment identifier |
| `TRANSIENT_REGISTRY_URL` | string | `http://registry:6000` | Transient registry URL |
| `TRANSIENT_REGISTRY_ADMIN` | string | `admin` | Transient registry admin username |
| `TRANSIENT_REGISTRY_PASSWORD` | string | `password` | Transient registry admin password |
| `TRANSIENT_REGISTRY_PROJECT_ID` | string | `daytona` | Transient registry project ID |
| `INTERNAL_REGISTRY_URL` | string | `http://registry:6000` | Internal registry URL |
| `INTERNAL_REGISTRY_ADMIN` | string | `admin` | Internal registry admin username |
| `INTERNAL_REGISTRY_PASSWORD` | string | `password` | Internal registry admin password |
| `INTERNAL_REGISTRY_PROJECT_ID` | string | `daytona` | Internal registry project ID |
| `SMTP_HOST` | string | `maildev` | SMTP server hostname |
| `SMTP_PORT` | number | `1025` | SMTP server port |
| `SMTP_USER` | string | (empty) | SMTP username |
| `SMTP_PASSWORD` | string | (empty) | SMTP password |
| `SMTP_SECURE` | boolean | (empty) | Enable SMTP secure connection |
| `SMTP_EMAIL_FROM` | string | `"Daytona Team "` | SMTP sender email address |
| `S3_ENDPOINT` | string | `http://minio:9000` | S3-compatible storage endpoint |
| `S3_STS_ENDPOINT` | string | `http://minio:9000/minio/v1/assume-role` | S3 STS endpoint |
| `S3_REGION` | string | `us-east-1` | S3 region |
| `S3_ACCESS_KEY` | string | `minioadmin` | S3 access key |
| `S3_SECRET_KEY` | string | `minioadmin` | S3 secret key |
| `S3_DEFAULT_BUCKET` | string | `daytona` | S3 default bucket name |
| `S3_ACCOUNT_ID` | string | `/` | S3 account ID |
| `S3_ROLE_NAME` | string | `/` | S3 role name |
| `ENVIRONMENT` | string | `dev` | Application environment |
| `MAX_AUTO_ARCHIVE_INTERVAL` | number | `43200` | Maximum auto-archive interval (seconds) |
| `OTEL_ENABLED` | boolean | `true` | Enable OpenTelemetry tracing |
| `OTEL_COLLECTOR_URL` | string | `http://jaeger:4318/v1/traces` | OpenTelemetry collector URL |
| `MAINTENANCE_MODE` | boolean | `false` | Enable maintenance mode |
| `PROXY_DOMAIN` | string | `proxy.localhost:4000` | Proxy domain |
| `PROXY_PROTOCOL` | string | `http` | Proxy protocol |
| `PROXY_API_KEY` | string | `super_secret_key` | Proxy API key |
| `PROXY_TEMPLATE_URL` | string | `http://{{PORT}}-{{sandboxId}}.proxy.localhost:4000` | Proxy template URL pattern |
| `PROXY_TOOLBOX_BASE_URL` | string | `{PROXY_PROTOCOL}://{PROXY_DOMAIN}` | Proxy base URL for toolbox requests |
| `DEFAULT_RUNNER_DOMAIN` | string | `runner:3003` | Default runner domain |
| `DEFAULT_RUNNER_API_URL` | string | `http://runner:3003` | Default runner API URL |
| `DEFAULT_RUNNER_PROXY_URL` | string | `http://runner:3003` | Default runner proxy URL |
| `DEFAULT_RUNNER_API_KEY` | string | `secret_api_token` | Default runner API key |
| `DEFAULT_RUNNER_CPU` | number | `4` | Default runner CPU allocation |
| `DEFAULT_RUNNER_MEMORY` | number | `8` | Default runner memory allocation (GB) |
| `DEFAULT_RUNNER_DISK` | number | `50` | Default runner disk allocation (GB) |
| `DEFAULT_RUNNER_API_VERSION` | string | `0` | Default runner API version |
| `DEFAULT_ORG_QUOTA_TOTAL_CPU_QUOTA` | number | `10000` | Default organization total CPU quota |
| `DEFAULT_ORG_QUOTA_TOTAL_MEMORY_QUOTA` | number | `10000` | Default organization total memory quota |
| `DEFAULT_ORG_QUOTA_TOTAL_DISK_QUOTA` | number | `100000` | Default organization total disk quota |
| `DEFAULT_ORG_QUOTA_MAX_CPU_PER_SANDBOX` | number | `100` | Default organization max CPU per sandbox |
| `DEFAULT_ORG_QUOTA_MAX_MEMORY_PER_SANDBOX` | number | `100` | Default organization max memory per sandbox |
| `DEFAULT_ORG_QUOTA_MAX_DISK_PER_SANDBOX` | number | `1000` | Default organization max disk per sandbox |
| `DEFAULT_ORG_QUOTA_SNAPSHOT_QUOTA` | number | `1000` | Default organization snapshot quota |
| `DEFAULT_ORG_QUOTA_MAX_SNAPSHOT_SIZE` | number | `1000` | Default organization max snapshot size |
| `DEFAULT_ORG_QUOTA_VOLUME_QUOTA` | number | `10000` | Default organization volume quota |
| `SSH_GATEWAY_API_KEY` | string | `ssh_secret_api_token` | SSH gateway API key |
| `SSH_GATEWAY_COMMAND` | string | `ssh -p 2222 {{TOKEN}}@localhost` | SSH gateway command template |
| `SSH_GATEWAY_PUBLIC_KEY` | string | (Base64-encoded OpenSSH public key) | SSH gateway public key for authentication |
| `SSH_GATEWAY_URL` | string | `localhost:2222` | SSH gateway URL |
| `RUNNER_DECLARATIVE_BUILD_SCORE_THRESHOLD` | number | `10` | Runner declarative build score threshold |
| `RUNNER_AVAILABILITY_SCORE_THRESHOLD` | number | `10` | Runner availability score threshold |
| `RUNNER_HEALTH_TIMEOUT_SECONDS` | number | `3` | Runner health-check timeout in seconds |
| `RUNNER_START_SCORE_THRESHOLD` | number | `3` | Runner start score threshold |
| `RUN_MIGRATIONS` | boolean | `true` | Enable database migrations on startup |
| `ADMIN_API_KEY` | string | (empty) | Admin API key, auto-generated if empty, used only upon initial setup, not recommended for production |
| `ADMIN_TOTAL_CPU_QUOTA` | number | `0` | Admin total CPU quota, used only upon initial setup |
| `ADMIN_TOTAL_MEMORY_QUOTA` | number | `0` | Admin total memory quota, used only upon initial setup |
| `ADMIN_TOTAL_DISK_QUOTA` | number | `0` | Admin total disk quota, used only upon initial setup |
| `ADMIN_MAX_CPU_PER_SANDBOX` | number | `0` | Admin max CPU per sandbox, used only upon initial setup |
| `ADMIN_MAX_MEMORY_PER_SANDBOX` | number | `0` | Admin max memory per sandbox, used only upon initial setup |
| `ADMIN_MAX_DISK_PER_SANDBOX` | number | `0` | Admin max disk per sandbox, used only upon initial setup |
| `ADMIN_SNAPSHOT_QUOTA` | number | `100` | Admin snapshot quota, used only upon initial setup |
| `ADMIN_MAX_SNAPSHOT_SIZE` | number | `100` | Admin max snapshot size, used only upon initial setup |
| `ADMIN_VOLUME_QUOTA` | number | `0` | Admin volume quota, used only upon initial setup |
| `SKIP_USER_EMAIL_VERIFICATION` | boolean | `true` | Skip user email verification process |
| `RATE_LIMIT_ANONYMOUS_TTL` | number | (empty) | Anonymous rate limit time-to-live (seconds, empty - rate limit is disabled) |
| `RATE_LIMIT_ANONYMOUS_LIMIT` | number | (empty) | Anonymous rate limit (requests per TTL, empty - rate limit is disabled) |
| `RATE_LIMIT_AUTHENTICATED_TTL` | number | (empty) | Authenticated rate limit time-to-live (seconds, empty - rate limit is disabled) |
| `RATE_LIMIT_AUTHENTICATED_LIMIT` | number | (empty) | Authenticated rate limit (requests per TTL, empty - rate limit is disabled) |
| `RATE_LIMIT_SANDBOX_CREATE_TTL` | number | (empty) | Sandbox create rate limit time-to-live (seconds, empty - rate limit is disabled) |
| `RATE_LIMIT_SANDBOX_CREATE_LIMIT` | number | (empty) | Sandbox create rate limit (requests per TTL, empty - rate limit is disabled) |
| `RATE_LIMIT_SANDBOX_LIFECYCLE_TTL` | number | (empty) | Sandbox lifecycle rate limit time-to-live (seconds, empty - rate limit is disabled) |
| `RATE_LIMIT_SANDBOX_LIFECYCLE_LIMIT` | number | (empty) | Sandbox lifecycle rate limit (requests per TTL, empty - rate limit is disabled) |
| `RATE_LIMIT_FAILED_AUTH_TTL` | number | (empty) | Failed authentication rate limit time-to-live (seconds, empty - rate limit is disabled) |
| `RATE_LIMIT_FAILED_AUTH_LIMIT` | number | (empty) | Failed authentication rate limit (requests per TTL, empty - rate limit is disabled) |
| `DEFAULT_REGION_ID` | string | `us` | Default region ID |
| `DEFAULT_REGION_NAME` | string | `us` | Default region name |
| `DEFAULT_REGION_ENFORCE_QUOTAS` | boolean | `false` | Enable region-based resource limits for default region |
| `OTEL_COLLECTOR_API_KEY` | string | `otel_collector_api_key` | OpenTelemetry collector API key for authentication (only needed if otel collector is deployed) |
| `CLICKHOUSE_HOST` | string | (empty) | ClickHouse host for querying sandbox otel |
| `CLICKHOUSE_DATABASE` | string | `otel` | ClickHouse database for querying sandbox otel |
| `CLICKHOUSE_PORT` | number | `8123` | ClickHouse port |
| `CLICKHOUSE_USERNAME` | string | (empty) | ClickHouse username |
| `CLICKHOUSE_PASSWORD` | string | (empty) | ClickHouse password |
| `CLICKHOUSE_PROTOCOL` | string | `https` | ClickHouse protocol (e.g., `http` or `https`) |
| `SANDBOX_OTEL_ENDPOINT_URL` | string | (empty) | OpenTelemetry endpoint URL for sandbox traces |
| `HEALTH_CHECK_API_KEY` | string | `supersecretkey` | Authentication key for the readiness health-check route. |
| `NOTIFICATION_GATEWAY_DISABLED` | boolean | `false` | Disable notification gateway service |
### Runner
| Variable | Type | Default Value | Description |
| --------------------------------------- | ------- | --------------------------------- | ----------------------------------------------------- |
| `DAYTONA_API_URL` | string | `http://api:3000/api` | Daytona API URL |
| `DAYTONA_RUNNER_TOKEN` | string | `secret_api_token` | Runner API authentication token |
| `VERSION` | string | `0.0.1` | Runner service version |
| `OTEL_LOGGING_ENABLED` | boolean | `false` | Runner OpenTelemetry logging enabled |
| `OTEL_TRACING_ENABLED` | boolean | `false` | Runner OpenTelemetry tracing enabled |
| `OTEL_EXPORTER_OTLP_ENDPOINT` | string | (empty) | Runner OpenTelemetry OTLP exporter endpoint |
| `OTEL_EXPORTER_OTLP_HEADERS` | string | (empty) | Runner OpenTelemetry OTLP exporter headers |
| `ENVIRONMENT` | string | `development` | Application environment |
| `API_PORT` | number | `3003` | Runner API service port |
| `LOG_FILE_PATH` | string | `/home/daytona/runner/runner.log` | Path to runner log file |
| `RESOURCE_LIMITS_DISABLED` | boolean | `true` | Disable resource limits for sandboxes |
| `AWS_ENDPOINT_URL` | string | `http://minio:9000` | AWS S3-compatible storage endpoint |
| `AWS_REGION` | string | `us-east-1` | AWS region |
| `AWS_ACCESS_KEY_ID` | string | `minioadmin` | AWS access key ID |
| `AWS_SECRET_ACCESS_KEY` | string | `minioadmin` | AWS secret access key |
| `AWS_DEFAULT_BUCKET` | string | `daytona` | AWS default bucket name |
| `DAEMON_START_TIMEOUT_SEC` | number | `60` | Daemon start timeout in seconds |
| `SANDBOX_START_TIMEOUT_SEC` | number | `30` | Sandbox start timeout in seconds |
| `USE_SNAPSHOT_ENTRYPOINT` | boolean | `false` | Use snapshot entrypoint for sandbox |
| `RUNNER_DOMAIN` | string | (none) | Runner domain name (hostname for runner URLs) |
| `VOLUME_CLEANUP_INTERVAL` | number | `30s` | Volume cleanup interval in seconds (minimum: 10s) |
| `COLLECTOR_WINDOW_SIZE` | number | `60` | Metrics collector window size (number of samples) |
| `CPU_USAGE_SNAPSHOT_INTERVAL` | string | `5s` | CPU usage snapshot interval duration (minimum: 1s) |
| `ALLOCATED_RESOURCES_SNAPSHOT_INTERVAL` | string | `5s` | Allocated resources snapshot interval (minimum: 1s) |
| `POLL_TIMEOUT` | string | `30s` | Poller service timeout duration (e.g., `30s`, `1m`) |
| `POLL_LIMIT` | number | `10` | Maximum poll attempts per request (min: 1, max: 100) |
| `HEALTHCHECK_INTERVAL` | string | `30s` | Interval between health checks (minimum: 10s) |
| `HEALTHCHECK_TIMEOUT` | string | `10s` | Health check timeout duration |
| `API_VERSION` | number | `2` | Runner API version (default: 2) |
| `SNAPSHOT_ERROR_CACHE_RETENTION` | string | `10m` | Snapshot error cache retention duration (minimum: 5m) |
### SSH Gateway
| Variable | Type | Default Value | Description |
| ------------------ | ------ | ------------------------------------ | -------------------------- |
| `API_URL` | string | `http://api:3000/api` | Daytona API URL |
| `API_KEY` | string | `ssh_secret_api_token` | API authentication key |
| `SSH_PRIVATE_KEY` | string | (Base64-encoded OpenSSH private key) | SSH private key for auth |
| `SSH_HOST_KEY` | string | (Base64-encoded OpenSSH host key) | SSH host key for server |
| `SSH_GATEWAY_PORT` | number | `2222` | SSH gateway listening port |
### Proxy
| Variable | Type | Default Value | Description |
| ------------------------- | ------- | --------------------------- | ------------------------------- |
| `DAYTONA_API_URL` | string | `http://api:3000/api` | Daytona API URL |
| `PROXY_PORT` | number | `4000` | Proxy service port |
| `PROXY_API_KEY` | string | `super_secret_key` | Proxy API authentication key |
| `PROXY_PROTOCOL` | string | `http` | Proxy protocol (http or https) |
| `COOKIE_DOMAIN` | string | `$PROXY_DOMAIN` | Cookie domain for proxy cookies |
| `OIDC_CLIENT_ID` | string | `daytona` | OIDC client identifier |
| `OIDC_CLIENT_SECRET` | string | (empty) | OIDC client secret |
| `OIDC_DOMAIN` | string | `http://dex:5556/dex` | OIDC domain |
| `OIDC_PUBLIC_DOMAIN` | string | `http://localhost:5556/dex` | OIDC public domain |
| `OIDC_AUDIENCE` | string | `daytona` | OIDC audience identifier |
| `REDIS_HOST` | string | `redis` | Redis server hostname |
| `REDIS_PORT` | number | `6379` | Redis server port |
| `TOOLBOX_ONLY_MODE` | boolean | `false` | Allow only toolbox requests |
| `PREVIEW_WARNING_ENABLED` | boolean | `false` | Enable browser preview warning |
| `SHUTDOWN_TIMEOUT_SEC` | number | `3600` | Shutdown timeout in seconds |
## [OPTIONAL] Configure Auth0 for Authentication
The default compose setup uses a local Dex OIDC provider for authentication. However, you can configure Auth0 as an alternative OIDC provider by following these steps:
### Step 1: Create Your Auth0 Tenant
Begin by navigating to https://auth0.com/signup and start the signup process. Choose your account type based on your use case - select `Company` for business applications or `Personal` for individual projects.\
On the "Let's get setup" page, you'll need to enter your application name such as `My Daytona` and select `Single Page Application (SPA)` as the application type. For authentication methods, you can start with `Email and Password` since additional social providers like Google, GitHub, or Facebook can be added later. Once you've configured these settings, click `Create Application` in the bottom right corner.
### Step 2: Configure Your Single Page Application
Navigate to `Applications` > `Applications` in the left sidebar and select the application you just created. Click the `Settings` tab and scroll down to find the `Application URIs` section where you'll configure the callback and origin URLs.
In the `Allowed Callback URIs` field, add the following URLs:
```
http://localhost:3000
http://localhost:3000/api/oauth2-redirect.html
http://localhost:4000/callback
http://proxy.localhost:4000/callback
```
For `Allowed Logout URIs`, add:
```
http://localhost:3000
```
And for `Allowed Web Origins`, add:
```
http://localhost:3000
```
Remember to click `Save Changes` at the bottom of the page to apply these configurations.
### Step 3: Create Machine-to-Machine Application
You'll need a Machine-to-Machine application to interact with Auth0's Management API. Go to `Applications` > `Applications` and click `Create Application`. Choose `Machine to Machine Applications` as the type and provide a descriptive name like `My Management API M2M`.
After creating the application, navigate to the `APIs` tab within your new M2M application. Find and authorize the `Auth0 Management API` by clicking the toggle or authorize button.\
Once authorized, click the dropdown arrow next to the Management API to configure permissions. Grant the following permissions to your M2M application:
```
read:users
update:users
read:connections
create:guardian_enrollment_tickets
read:connections_options
```
Click `Save` to apply these permission changes.
### Step 4: Set Up Custom API
Your Daytona application will need a custom API to handle authentication and authorization. Navigate to `Applications` > `APIs` in the left sidebar and click `Create API`. Enter a descriptive name such as `My Daytona API` and provide an identifier like `my-daytona-api`. The identifier should be a unique string that will be used in your application configuration.\
After creating the API, go to the `Permissions` tab to define the scopes your application will use. Add each of the following permissions with their corresponding descriptions:
| Permission | Description |
| --------------------------- | ---------------------------------------- |
| `read:node` | Get workspace node info |
| `create:node` | Create new workspace node record |
| `create:user` | Create user account |
| `read:users` | Get all user accounts |
| `regenerate-key-pair:users` | Regenerate user SSH key-pair |
| `read:workspaces` | Read workspaces (user scope) |
| `create:registry` | Create a new docker registry auth record |
| `read:registries` | Get all docker registry records |
| `read:registry` | Get docker registry record |
| `write:registry` | Create or update docker registry record |
### Step 5: Configure Environment Variables
Once you've completed all the Auth0 setup steps, you'll need to configure environment variables in your Daytona deployment. These variables connect your application to the Auth0 services you've just configured.
#### Finding Your Configuration Values
You can find the necessary values in the Auth0 dashboard. For your SPA application settings, go to `Applications` > `Applications`, select your SPA app, and click the `Settings` tab. For your M2M application, follow the same path but select your Machine-to-Machine app instead. Custom API settings are located under `Applications` > `APIs`, then select your custom API and go to `Settings`.
#### API Service Configuration
Configure the following environment variables for your API service:
```bash
OIDC_CLIENT_ID=your_spa_app_client_id
OIDC_ISSUER_BASE_URL=your_spa_app_domain
OIDC_AUDIENCE=your_custom_api_identifier
OIDC_MANAGEMENT_API_ENABLED=true
OIDC_MANAGEMENT_API_CLIENT_ID=your_m2m_app_client_id
OIDC_MANAGEMENT_API_CLIENT_SECRET=your_m2m_app_client_secret
OIDC_MANAGEMENT_API_AUDIENCE=your_auth0_managment_api_identifier
```
#### Proxy Service Configuration
For your proxy service, configure these environment variables:
```bash
OIDC_CLIENT_ID=your_spa_app_client_id
OIDC_CLIENT_SECRET=
OIDC_DOMAIN=your_spa_app_domain
OIDC_AUDIENCE=your_custom_api_identifier (with trailing slash)
```
Note that `OIDC_CLIENT_SECRET` should remain empty for your proxy environment.
Daytona provides an interactive environment ("Playground") for creating sandboxes, running SDK operations, and exploring Daytona features directly from your browser.
- **Interactive sandbox creation**: configure and create sandboxes with custom resources
- **Code snippet generation**: automatically generate SDK code samples based on the values configured in the [management](#management) section
- [Web terminal](https://www.daytona.io/docs/en/web-terminal.md): run commands directly in your sandbox through a built-in web terminal
- [VNC access](https://www.daytona.io/docs/en/vnc-access.md): interact with GUI applications using [Computer Use](https://www.daytona.io/docs/en/computer-use.md) features
## Access from Dashboard
Navigate to [Daytona Dashboard ↗](https://app.daytona.io/dashboard/playground) to access the playground.
Playground consists of three tabs: [Sandbox](#sandbox), [Terminal](#terminal), and [VNC](#vnc). All three tabs operate on the same active sandbox.
## Sandbox
The sandbox tab provides an interactive interface to configure sandboxes and perform SDK operations. The left panel contains configurable parameters organized into collapsible sections. The right panel displays auto-generated code snippets that you can inspect, copy, and run.
### Management
The management section contains the parameters used to configure a sandbox. You can edit these parameters to customize your sandbox and its resources.
- [sandbox language](https://www.daytona.io/docs/en/sandboxes.md#multiple-runtime-support): select a programming language runtime for the sandbox
- [sandbox resources](https://www.daytona.io/docs/en/sandboxes.md#resources): configure resources allocated to the sandbox
- [sandbox lifecycle](https://www.daytona.io/docs/en/sandboxes.md#sandbox-lifecycle): set the sandbox lifecycle policies
:::note
In the management section, sandboxes are only created when you explicitly click **Run**, replacing any existing playground sandbox. In the [Terminal](#terminal) or [VNC](#vnc) tabs, if there are no active sandboxes, the playground automatically creates one using the configured parameters.
:::
### File system
The file system section provides operations to manage files and directories in the sandbox. You can modify files and directories in the sandbox using the following operations:
- **Create a new directory**: set the directory location and its permissions
- **List files and directories**: set the directory location
- **Delete files**: set the file location and delete directory checkbox
For more information, see [file system operations](https://www.daytona.io/docs/en/file-system-operations.md).
### Git operations
The Git operations section provides operations to manage Git repositories in the sandbox. You can clone, get repository status, and list branches using the following operations:
- **Clone a Git repository**: set the repository URL, destination, branch, commit ID, and credentials
- **Get repository status**: retrieve the repository status
- **List branches**: retrieve the list of branches in the repository
For more information, see [Git operations](https://www.daytona.io/docs/en/git-operations.md).
### Process and code execution
The process and code execution section provides operations to run code snippets and shell commands directly in the sandbox. Shell commands are fixed, while code snippets change automatically based on the selected [sandbox language](https://www.daytona.io/docs/en/sandboxes.md#multiple-runtime-support) parameter.
For more information, see [process and code execution](https://www.daytona.io/docs/en/process-code-execution.md).
## Terminal
The terminal tab provides a web-based terminal connected to the sandbox. This gives you direct command-line access to the sandbox environment for running commands, viewing files, and debugging.
The terminal runs on port `22222` and remains active as long as the sandbox is running. If the sandbox stops due to inactivity, start it again to restore terminal access.
:::note
Terminal access is restricted to authenticated members of your [organization](https://www.daytona.io/docs/en/organizations.md).
:::
For more information, see [web terminal](https://www.daytona.io/docs/en/web-terminal.md).
## VNC
The VNC tab provides graphical desktop access to the sandbox, enabling you to interact with GUI applications and test [Computer Use](https://www.daytona.io/docs/en/computer-use.md) features. The left panel contains interaction controls organized into sections. The right panel displays the desktop view.
For more information, see [VNC access](https://www.daytona.io/docs/en/vnc-access.md).
### Display
The display section provides options to inspect the sandbox desktop environment.
- **Get display information**: retrieve information about the available displays
- **List open windows**: retrieve a list of currently open windows
For more information, see [display operations](https://www.daytona.io/docs/en/computer-use.md#display-operations).
### Keyboard
The keyboard section provides options to send keyboard input to the sandbox.
- **Press a hotkey combination**: send a hotkey combination to the sandbox
- **Press a key**: press a key with optional modifiers
- **Type text**: type text into the active window
For more information, see [keyboard operations](https://www.daytona.io/docs/en/computer-use.md#keyboard-operations).
### Mouse
The mouse section provides options to control mouse input in the sandbox.
- **Click**: click at a specified position
- **Drag**: drag from one position to another
- **Move**: move the cursor to a specified position
- **Get cursor position**: retrieve the current cursor position
For more information, see [mouse operations](https://www.daytona.io/docs/en/computer-use.md#mouse-operations).
### Screenshot
The screenshot section provides options to capture screenshots of the sandbox desktop.
- **Take a screenshot**: select format, scale, and quality, show cursor, and capture the entire screen or specific regions
For more information, see [screenshot operations](https://www.daytona.io/docs/en/computer-use.md#screenshot-operations).
## Related
- [Web Terminal](https://www.daytona.io/docs/en/web-terminal.md): browser-based terminal access for sandboxes
- [VNC Access](https://www.daytona.io/docs/en/vnc-access.md): graphical desktop access for sandboxes
- [Computer Use](https://www.daytona.io/docs/en/computer-use.md): programmatic desktop automation
- [File System Operations](https://www.daytona.io/docs/en/file-system-operations.md): manage files and directories in sandboxes
- [Git Operations](https://www.daytona.io/docs/en/git-operations.md): manage Git repositories in sandboxes
- [Process & Code Execution](https://www.daytona.io/docs/en/process-code-execution.md): execute commands and run code in sandboxes
Daytona provides preview URLs for accessing services running in your sandboxes. Any process listening for HTTP traffic on ports `3000` - `9999` can be previewed through a generated URL.
Daytona supports two types of preview URLs, each with a different authentication mechanism:
- [Standard preview URL](#standard-preview-url) uses the sandbox ID in the URL and requires a token sent via header
- [Signed preview URL](#signed-preview-url) embeds the authentication token directly in the URL, requiring no headers
## Authentication
If a sandbox has its `public` property set to `true`, preview links are publicly accessible without authentication. Otherwise, authentication is required. The authentication mechanism depends on the preview URL type.
:::note
Standard and signed preview tokens are not interchangeable. The token from `get_preview_link()` must be sent via the `x-daytona-preview-token` header. The token from `create_signed_preview_url()` is embedded in the URL itself: it cannot be used as a header value, and vice versa.
:::
## Standard preview URL
The standard preview URL includes your sandbox ID in the URL and provides a separate token for authentication via the `x-daytona-preview-token` request header.
URL structure: `https://{port}-{sandboxId}.{daytonaProxyDomain}`
The token resets automatically when the sandbox restarts. Any previously issued standard preview tokens become invalid. Call the `get_preview_link()` method again after starting the sandbox to obtain a fresh token. Use standard preview URLs for programmatic access and API integrations where you control the HTTP headers.
```python
preview_info = sandbox.get_preview_link(3000)
print(f"URL: {preview_info.url}")
print(f"Token: {preview_info.token}")
# Use with requests
import requests
response = requests.get(
preview_info.url,
headers={"x-daytona-preview-token": preview_info.token}
)
```
```typescript
const previewInfo = await sandbox.getPreviewLink(3000);
console.log(`URL: ${previewInfo.url}`);
console.log(`Token: ${previewInfo.token}`);
// Use with fetch
const response = await fetch(previewInfo.url, {
headers: { 'x-daytona-preview-token': previewInfo.token }
});
```
```ruby
preview_info = sandbox.preview_url(3000)
puts "Preview link url: #{preview_info.url}"
puts "Preview link token: #{preview_info.token}"
```
```go
preview, err := sandbox.GetPreviewLink(ctx, 3000)
if err != nil {
log.Fatal(err)
}
fmt.Printf("URL: %s\n", preview.URL)
fmt.Printf("Token: %s\n", preview.Token)
```
```bash
curl 'https://app.daytona.io/api/sandbox/{sandboxId}/ports/3000/preview-url' \
--header 'Authorization: Bearer '
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk/sync/sandbox.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk/sandbox.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk/sandbox.md), [Go SDK](https://www.daytona.io/docs/en/go-sdk/daytona.md), and [API](https://www.daytona.io/docs/en/tools/api.md#daytona/tag/sandbox) references:
> [**get_preview_link (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/sandbox.md#sandboxget_preview_link)
>
> [**getPreviewLink (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/sandbox.md#getpreviewlink)
>
> [**preview_url (Ruby SDK)**](https://www.daytona.io/docs/en/ruby-sdk/sandbox.md#preview_url)
>
> [**GetPreviewLink (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#Sandbox.GetPreviewLink)
>
> [**Get Port Preview URL (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona/tag/sandbox/GET/sandbox/{sandboxIdOrName}/ports/{port}/preview-url)
### Authentication
Authenticate by sending the token in the `x-daytona-preview-token` header:
```bash
curl -H "x-daytona-preview-token: vg5c0ylmcimr8b_v1ne0u6mdnvit6gc0" \
https://3000-sandbox-123456.proxy.daytona.work
```
## Signed preview URL
The signed preview URL embeds the authentication token directly in the URL, eliminating the need for separate headers. You can set a custom expiry time for the token (defaults to 60 seconds). The token persists across sandbox restarts until it expires. Tokens can be revoked manually before expiry if needed.
:::tip
Always set the `expires_in_seconds` parameter explicitly. The default of 60 seconds is short due to security considerations. Most use cases should use at least 3600 (1 hour).
:::
URL structure: `https://{port}-{token}.{daytonaProxyDomain}`
Use signed preview URLs when sharing links with users who cannot set custom headers, embedding previews in iframes or emails, or creating time-limited shareable links.
```python
# Create a signed preview URL that expires in 3600 seconds (1 hour)
signed_url = sandbox.create_signed_preview_url(3000, expires_in_seconds=3600)
print(f"URL: {signed_url.url}") # Token is embedded in the URL
print(f"Token: {signed_url.token}") # Can be used to revoke access
# Use directly - no headers needed
import requests
response = requests.get(signed_url.url)
# Revoke the token before expiry if needed
sandbox.expire_signed_preview_url(3000, signed_url.token)
```
```typescript
// Create a signed preview URL that expires in 3600 seconds (1 hour)
const signedUrl = await sandbox.getSignedPreviewUrl(3000, 3600);
console.log(`URL: ${signedUrl.url}`); // Token is embedded in the URL
console.log(`Token: ${signedUrl.token}`); // Can be used to revoke access
// Use directly - no headers needed
const response = await fetch(signedUrl.url);
// Revoke the token before expiry if needed
await sandbox.expireSignedPreviewUrl(3000, signedUrl.token);
```
```ruby
# Create a signed preview URL that expires in 3600 seconds (1 hour)
signed_url = sandbox.create_signed_preview_url(3000, 3600)
puts "URL: #{signed_url.url}"
puts "Token: #{signed_url.token}"
```
```bash
daytona preview-url --port 3000 --expires 3600
```
```bash
curl 'https://app.daytona.io/api/sandbox/{sandboxId}/ports/3000/signed-preview-url?expiresInSeconds=3600' \
--header 'Authorization: Bearer '
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk/sync/sandbox.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk/sandbox.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk/sandbox.md), and [API](https://www.daytona.io/docs/en/tools/api.md#daytona/tag/sandbox) references:
> [**create_signed_preview_url (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/sandbox.md#sandboxcreate_signed_preview_url)
>
> [**getSignedPreviewUrl (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/sandbox.md#getsignedpreviewurl)
>
> [**create_signed_preview_url (Ruby SDK)**](https://www.daytona.io/docs/en/ruby-sdk/sandbox.md#create_signed_preview_url)
>
> [**Get Signed Preview URL (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona/tag/sandbox/GET/sandbox/{sandboxIdOrName}/ports/{port}/signed-preview-url)
### Authentication
The token is embedded in the URL itself, so no additional headers are required:
```bash
curl https://3000-.proxy.daytona.work
```
:::tip
Port `22222` is used by the [web terminal](https://www.daytona.io/docs/en/web-terminal.md) to access the terminal using preview URLs.
:::
## Warning page
When opening a preview link in a browser for the first time, Daytona displays a warning page. This warning informs users about potential risks of visiting the preview URL and only appears when loading the link in a browser.
To skip the warning page:
- Send the `X-Daytona-Skip-Preview-Warning: true` header
- Upgrade to [Tier 3](https://www.daytona.io/docs/en/limits.md)
- Deploy a [custom preview proxy](https://www.daytona.io/docs/en/custom-domain-authentication.md)
Daytona provides process and code execution capabilities through the `process` module in sandboxes.
## Code execution
Daytona provides methods to execute code in sandboxes. You can run code snippets in multiple languages with support for both stateless execution and stateful interpretation with persistent contexts.
:::note
Stateless execution inherits the sandbox language that you choose at [sandbox creation](https://www.daytona.io/docs/en/sandboxes.md#create-sandboxes) time. The stateful interpreter supports only Python.
:::
### Run code (stateless)
Daytona provides methods to run code snippets in sandboxes using stateless execution. Each invocation starts from a clean interpreter, making it ideal for independent code snippets.
```python
# Run Python code
response = sandbox.process.code_run('''
def greet(name):
return f"Hello, {name}!"
print(greet("Daytona"))
''')
print(response.result)
```
```typescript
// Run TypeScript code
let response = await sandbox.process.codeRun(`
function greet(name: string): string {
return \`Hello, \${name}!\`;
}
console.log(greet("Daytona"));
`);
console.log(response.result);
// Run code with argv and environment variables
response = await sandbox.process.codeRun(
`
console.log(\`Hello, \${process.argv[2]}!\`);
console.log(\`FOO: \${process.env.FOO}\`);
`,
{
argv: ["Daytona"],
env: { FOO: "BAR" }
}
);
console.log(response.result);
// Run code with timeout (5 seconds)
response = await sandbox.process.codeRun(
'setTimeout(() => console.log("Done"), 2000);',
undefined,
5
);
console.log(response.result);
```
```ruby
# Run Python code
response = sandbox.process.code_run(code: <<~PYTHON)
def greet(name):
return f"Hello, {name}!"
print(greet("Daytona"))
PYTHON
puts response.result
```
```go
// Run code using shell command execution
// Note: For stateless code execution in Go, use ExecuteCommand with the appropriate interpreter
result, err := sandbox.Process.ExecuteCommand(ctx, `python3 -c '
def greet(name):
return f"Hello, {name}!"
print(greet("Daytona"))
'`)
if err != nil {
log.Fatal(err)
}
fmt.Println(result.Result)
// Run code with environment variables
result, err = sandbox.Process.ExecuteCommand(ctx, `python3 -c 'import os; print(f"FOO: {os.environ.get(\"FOO\")}")'`,
options.WithCommandEnv(map[string]string{"FOO": "BAR"}),
)
if err != nil {
log.Fatal(err)
}
fmt.Println(result.Result)
// Run code with timeout
result, err = sandbox.Process.ExecuteCommand(ctx, `python3 -c 'import time; time.sleep(2); print("Done")'`,
options.WithExecuteTimeout(5*time.Second),
)
if err != nil {
log.Fatal(err)
}
fmt.Println(result.Result)
```
```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/process/code-run' \
--request POST \
--header 'Content-Type: application/json' \
--data '{
"code": "def greet(name):\n return f\"Hello, {name}!\"\n\nprint(greet(\"Daytona\"))",
"env": {
"FOO": "BAR"
},
"timeout": 5000
}'
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk.md), [Go SDK](https://www.daytona.io/docs/en/go-sdk.md), and [API](https://www.daytona.io/docs/en/tools/api.md) references:
> [**code_run (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/process.md#processcode_run)
>
> [**codeRun (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/process.md#coderun)
>
> [**code_run (Ruby SDK)**](https://www.daytona.io/docs/en/ruby-sdk/process.md#code_run)
>
> [**ExecuteCommand (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#ProcessService.ExecuteCommand)
>
> [**execute command (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/process/POST/process/execute)
### Run code (stateful)
Daytona provides methods to run code with persistent state using the code interpreter. You can maintain variables and imports between calls, create isolated contexts, and control environment variables.
```python
from daytona import Daytona, OutputMessage
def handle_stdout(message: OutputMessage):
print(f"[STDOUT] {message.output}")
daytona = Daytona()
sandbox = daytona.create()
# Shared default context
result = sandbox.code_interpreter.run_code(
"counter = 1\nprint(f'Counter initialized at {counter}')",
on_stdout=handle_stdout,
)
# Isolated context
ctx = sandbox.code_interpreter.create_context()
try:
sandbox.code_interpreter.run_code(
"value = 'stored in ctx'",
context=ctx,
)
sandbox.code_interpreter.run_code(
"print(value)",
context=ctx,
on_stdout=handle_stdout,
)
finally:
sandbox.code_interpreter.delete_context(ctx)
```
```typescript
import { Daytona } from '@daytonaio/sdk'
const daytona = new Daytona()
async function main() {
const sandbox = await daytona.create()
// Shared default context
await sandbox.codeInterpreter.runCode(
`
counter = 1
print(f'Counter initialized at {counter}')
`,
{ onStdout: (msg) => process.stdout.write(`[STDOUT] ${msg.output}`)},
)
// Isolated context
const ctx = await sandbox.codeInterpreter.createContext()
try {
await sandbox.codeInterpreter.runCode(
`value = 'stored in ctx'`,
{ context: ctx },
)
await sandbox.codeInterpreter.runCode(
`print(value)`,
{ context: ctx, onStdout: (msg) => process.stdout.write(`[STDOUT] ${msg.output}`) },
)
} finally {
await sandbox.codeInterpreter.deleteContext(ctx)
}
}
main()
```
```ruby
# Ruby SDK uses process.code_run for code execution
# Stateful contexts are managed through the code interpreter API
require 'daytona'
daytona = Daytona::Daytona.new
sandbox = daytona.create
# Run code (stateless in Ruby SDK)
response = sandbox.process.code_run(code: <<~PYTHON)
counter = 1
print(f'Counter initialized at {counter}')
PYTHON
puts response.result
```
```go
// Create a code interpreter context
ctxInfo, err := sandbox.CodeInterpreter.CreateContext(ctx, nil)
if err != nil {
log.Fatal(err)
}
contextID := ctxInfo["id"].(string)
// Run code in the context
channels, err := sandbox.CodeInterpreter.RunCode(ctx,
"counter = 1\nprint(f'Counter initialized at {counter}')",
options.WithCustomContext(contextID),
)
if err != nil {
log.Fatal(err)
}
// Read output
for msg := range channels.Stdout {
fmt.Printf("[STDOUT] %s\n", msg.Text)
}
// Clean up context
err = sandbox.CodeInterpreter.DeleteContext(ctx, contextID)
if err != nil {
log.Fatal(err)
}
```
```bash
# Create context
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/process/interpreter/context' \
--request POST \
--header 'Content-Type: application/json' \
--data '{}'
# Run code in context (WebSocket endpoint)
# Connect via WebSocket to:
# wss://proxy.app.daytona.io/toolbox/{sandboxId}/process/interpreter/execute
# Send JSON message:
# {
# "code": "counter = 1\nprint(f\"Counter initialized at {counter}\")",
# "contextId": "your-context-id"
# }
# Delete context
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/process/interpreter/context/{contextId}' \
--request DELETE
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk.md), [Go SDK](https://www.daytona.io/docs/en/go-sdk.md), and [API](https://www.daytona.io/docs/en/tools/api.md) references:
> [**run_code (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/code-interpreter.md#codeinterpreterrun_code)
>
> [**create_context (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/code-interpreter.md#codeinterpretercreate_context)
>
> [**delete_context (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/code-interpreter.md#codeinterpreterdelete_context)
>
> [**runCode (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/code-interpreter.md#runcode)
>
> [**createContext (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/code-interpreter.md#createcontext)
>
> [**deleteContext (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/code-interpreter.md#deletecontext)
>
> [**code_run (Ruby SDK)**](https://www.daytona.io/docs/en/ruby-sdk/process.md#code_run)
>
> [**RunCode (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#CodeInterpreterService.RunCode)
>
> [**CreateContext (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#CodeInterpreterService.CreateContext)
>
> [**DeleteContext (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#CodeInterpreterService.DeleteContext)
>
> [**code interpreter (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/interpreter)
## Command execution
Daytona provides methods to execute shell commands in sandboxes. You can run commands with working directory, timeout, and environment variable options.
The working directory defaults to the sandbox working directory. It uses the WORKDIR specified in the Dockerfile if present, or falls back to the user's home directory if not (e.g., `workspace/repo` implies `/home/daytona/workspace/repo`). You can override it with an absolute path by starting the path with `/`.
### Execute commands
Daytona provides methods to execute shell commands in sandboxes by providing the command string and optional parameters for working directory, timeout, and environment variables. You can also use the `daytona exec` CLI command for quick command execution.
```python
# Execute any shell command
response = sandbox.process.exec("ls -la")
print(response.result)
# Setting a working directory and a timeout
response = sandbox.process.exec("sleep 3", cwd="workspace/src", timeout=5)
print(response.result)
# Passing environment variables
response = sandbox.process.exec("echo $CUSTOM_SECRET", env={
"CUSTOM_SECRET": "DAYTONA"
}
)
print(response.result)
```
```typescript
// Execute any shell command
const response = await sandbox.process.executeCommand("ls -la");
console.log(response.result);
// Setting a working directory and a timeout
const response2 = await sandbox.process.executeCommand("sleep 3", "workspace/src", undefined, 5);
console.log(response2.result);
// Passing environment variables
const response3 = await sandbox.process.executeCommand("echo $CUSTOM_SECRET", ".", {
"CUSTOM_SECRET": "DAYTONA"
}
);
console.log(response3.result);
```
```ruby
# Execute any shell command
response = sandbox.process.exec(command: 'ls -la')
puts response.result
# Setting a working directory and a timeout
response = sandbox.process.exec(command: 'sleep 3', cwd: 'workspace/src', timeout: 5)
puts response.result
# Passing environment variables
response = sandbox.process.exec(
command: 'echo $CUSTOM_SECRET',
env: { 'CUSTOM_SECRET' => 'DAYTONA' }
)
puts response.result
```
```go
// Execute any shell command
response, err := sandbox.Process.ExecuteCommand(ctx, "ls -la")
if err != nil {
log.Fatal(err)
}
fmt.Println(response.Result)
// Setting a working directory and a timeout
response, err = sandbox.Process.ExecuteCommand(ctx, "sleep 3",
options.WithCwd("workspace/src"),
options.WithExecuteTimeout(5*time.Second),
)
if err != nil {
log.Fatal(err)
}
fmt.Println(response.Result)
// Passing environment variables
response, err = sandbox.Process.ExecuteCommand(ctx, "echo $CUSTOM_SECRET",
options.WithCommandEnv(map[string]string{"CUSTOM_SECRET": "DAYTONA"}),
)
if err != nil {
log.Fatal(err)
}
fmt.Println(response.Result)
```
```bash
# Execute any shell command
daytona exec my-sandbox -- ls -la
# Setting a working directory and a timeout
daytona exec my-sandbox --cwd workspace/src --timeout 5 -- sleep 3
# Passing environment variables (use shell syntax)
daytona exec my-sandbox -- sh -c 'CUSTOM_SECRET=DAYTONA echo $CUSTOM_SECRET'
```
```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/process/execute' \
--request POST \
--header 'Content-Type: application/json' \
--data '{
"command": "ls -la",
"cwd": "workspace",
"timeout": 5
}'
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk.md), [Go SDK](https://www.daytona.io/docs/en/go-sdk.md), [CLI](https://www.daytona.io/docs/en/tools/cli.md), and [API](https://www.daytona.io/docs/en/tools/api.md) references:
> [**exec (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/process.md#processexec)
>
> [**executeCommand (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/process.md#executecommand)
>
> [**exec (Ruby SDK)**](https://www.daytona.io/docs/en/ruby-sdk/process.md#exec)
>
> [**ExecuteCommand (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#ProcessService.ExecuteCommand)
>
> [**daytona exec (CLI)**](https://www.daytona.io/docs/en/tools/cli.md#daytona-exec)
>
> [**execute command (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/process/POST/process/execute)
## Session operations
Daytona provides methods to manage background process sessions in sandboxes. You can create sessions, execute commands, monitor status, and manage long-running processes.
### Get session status
Daytona provides methods to get session status and list all sessions in a sandbox by providing the session ID.
```python
# Check session's executed commands
session = sandbox.process.get_session(session_id)
print(f"Session {session_id}:")
for command in session.commands:
print(f"Command: {command.command}, Exit Code: {command.exit_code}")
# List all running sessions
sessions = sandbox.process.list_sessions()
for session in sessions:
print(f"Session: {session.session_id}, Commands: {session.commands}")
```
```typescript
// Check session's executed commands
const session = await sandbox.process.getSession(sessionId);
console.log(`Session ${sessionId}:`);
for (const command of session.commands) {
console.log(`Command: ${command.command}, Exit Code: ${command.exitCode}`);
}
// List all running sessions
const sessions = await sandbox.process.listSessions();
for (const session of sessions) {
console.log(`Session: ${session.sessionId}, Commands: ${session.commands}`);
}
```
```ruby
# Check session's executed commands
session = sandbox.process.get_session(session_id)
puts "Session #{session_id}:"
session.commands.each do |command|
puts "Command: #{command.command}, Exit Code: #{command.exit_code}"
end
# List all running sessions
sessions = sandbox.process.list_sessions
sessions.each do |session|
puts "Session: #{session.session_id}, Commands: #{session.commands}"
end
```
```go
// Check session's executed commands
session, err := sandbox.Process.GetSession(ctx, sessionID)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Session %s:\n", sessionID)
commands := session["commands"].([]any)
for _, cmd := range commands {
cmdMap := cmd.(map[string]any)
fmt.Printf("Command: %s, Exit Code: %v\n", cmdMap["command"], cmdMap["exitCode"])
}
// List all running sessions
sessions, err := sandbox.Process.ListSessions(ctx)
if err != nil {
log.Fatal(err)
}
for _, sess := range sessions {
fmt.Printf("Session: %s, Commands: %v\n", sess["sessionId"], sess["commands"])
}
```
```bash
# Get session info
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/process/session/{sessionId}'
# List all sessions
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/process/session'
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk.md), [Go SDK](https://www.daytona.io/docs/en/go-sdk.md), and [API](https://www.daytona.io/docs/en/tools/api.md) references:
> [**get_session (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/process.md#processget_session)
>
> [**list_sessions (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/process.md#processlist_sessions)
>
> [**getSession (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/process.md#getsession)
>
> [**listSessions (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/process.md#listsessions)
>
> [**get_session (Ruby SDK)**](https://www.daytona.io/docs/en/ruby-sdk/process.md#get_session)
>
> [**list_sessions (Ruby SDK)**](https://www.daytona.io/docs/en/ruby-sdk/process.md#list_sessions)
>
> [**GetSession (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#ProcessService.GetSession)
>
> [**ListSessions (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#ProcessService.ListSessions)
>
> [**get session (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/process/GET/process/session/{sessionId})
>
> [**list sessions (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/process/GET/process/session)
### Execute interactive commands
Daytona provides methods to execute interactive commands in sessions. You can send input to running commands that expect user interaction, such as confirmations or interactive tools like database CLIs and package managers.
```python
session_id = "interactive-session"
sandbox.process.create_session(session_id)
# Execute command that requires confirmation
command = sandbox.process.execute_session_command(
session_id,
SessionExecuteRequest(
command='pip uninstall requests',
run_async=True,
),
)
# Stream logs asynchronously
logs_task = asyncio.create_task(
sandbox.process.get_session_command_logs_async(
session_id,
command.cmd_id,
lambda log: print(f"[STDOUT]: {log}"),
lambda log: print(f"[STDERR]: {log}"),
)
)
await asyncio.sleep(1)
# Send input to the command
sandbox.process.send_session_command_input(session_id, command.cmd_id, "y")
# Wait for logs to complete
await logs_task
```
```typescript
const sessionId = 'interactive-session'
await sandbox.process.createSession(sessionId)
// Execute command that requires confirmation
const command = await sandbox.process.executeSessionCommand(sessionId, {
command: 'pip uninstall requests',
runAsync: true,
})
// Stream logs asynchronously
const logPromise = sandbox.process.getSessionCommandLogs(
sessionId,
command.cmdId!,
(stdout) => console.log('[STDOUT]:', stdout),
(stderr) => console.log('[STDERR]:', stderr),
)
await new Promise((resolve) => setTimeout(resolve, 1000))
// Send input to the command
await sandbox.process.sendSessionCommandInput(sessionId, command.cmdId!, 'y')
// Wait for logs to complete
await logPromise
```
```ruby
session_id = "interactive-session"
sandbox.process.create_session(session_id)
# Execute command that requires confirmation
interactive_command = sandbox.process.execute_session_command(
session_id: session_id,
req: Daytona::SessionExecuteRequest.new(
command: 'pip uninstall requests',
run_async: true
)
)
# Wait a moment for the command to start
sleep 1
# Send input to the command
sandbox.process.send_session_command_input(
session_id: session_id,
command_id: interactive_command.cmd_id,
data: "y"
)
# Get logs for the interactive command asynchronously
sandbox.process.get_session_command_logs_async(
session_id: session_id,
command_id: interactive_command.cmd_id,
on_stdout: ->(log) { puts "[STDOUT]: #{log}" },
on_stderr: ->(log) { puts "[STDERR]: #{log}" }
)
```
```go
sessionID := "interactive-session"
err := sandbox.Process.CreateSession(ctx, sessionID)
if err != nil {
log.Fatal(err)
}
// Execute command that requires confirmation
result, err := sandbox.Process.ExecuteSessionCommand(ctx, sessionID, "pip uninstall requests", true)
if err != nil {
log.Fatal(err)
}
cmdID := result["cmdId"].(string)
// Stream logs asynchronously
stdout := make(chan string)
stderr := make(chan string)
go func() {
err := sandbox.Process.GetSessionCommandLogsStream(ctx, sessionID, cmdID, stdout, stderr)
if err != nil {
log.Println("Log stream error:", err)
}
}()
time.Sleep(1 * time.Second)
// Note: SendSessionCommandInput is not available in Go SDK
// Use the API endpoint directly for sending input
// Read logs
for msg := range stdout {
fmt.Printf("[STDOUT]: %s\n", msg)
}
```
```bash
# Create session
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/process/session' \
--request POST \
--header 'Content-Type: application/json' \
--data '{"sessionId": "interactive-session"}'
# Execute session command
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/process/session/{sessionId}/exec' \
--request POST \
--header 'Content-Type: application/json' \
--data '{
"command": "pip uninstall requests",
"runAsync": true
}'
# Send input to command
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/process/session/{sessionId}/command/{commandId}/input' \
--request POST \
--header 'Content-Type: application/json' \
--data '{
"data": "y"
}'
# Get command logs
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/process/session/{sessionId}/command/{commandId}/logs'
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk.md), [Go SDK](https://www.daytona.io/docs/en/go-sdk.md), and [API](https://www.daytona.io/docs/en/tools/api.md) references:
> [**create_session (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/process.md#processcreate_session)
>
> [**execute_session_command (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/process.md#processexecute_session_command)
>
> [**send_session_command_input (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/process.md#processsend_session_command_input)
>
> [**get_session_command_logs_async (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/process.md#processget_session_command_logs_async)
>
> [**createSession (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/process.md#createsession)
>
> [**executeSessionCommand (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/process.md#executesessioncommand)
>
> [**sendSessionCommandInput (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/process.md#sendsessioncommandinput)
>
> [**getSessionCommandLogs (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/process.md#getsessioncommandlogs)
>
> [**create_session (Ruby SDK)**](https://www.daytona.io/docs/en/ruby-sdk/process.md#create_session)
>
> [**execute_session_command (Ruby SDK)**](https://www.daytona.io/docs/en/ruby-sdk/process.md#execute_session_command)
>
> [**send_session_command_input (Ruby SDK)**](https://www.daytona.io/docs/en/ruby-sdk/process.md#send_session_command_input)
>
> [**CreateSession (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#ProcessService.CreateSession)
>
> [**ExecuteSessionCommand (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#ProcessService.ExecuteSessionCommand)
>
> [**GetSessionCommandLogsStream (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#ProcessService.GetSessionCommandLogsStream)
>
> [**create session (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/process/POST/process/session)
>
> [**execute session command (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/process/POST/process/session/{sessionId}/exec)
## Resource management
Daytona provides methods to manage session resources. You should use sessions for long-running operations, clean up sessions after execution, and handle exceptions properly.
```python
# Python - Clean up session
session_id = "long-running-cmd"
try:
sandbox.process.create_session(session_id)
session = sandbox.process.get_session(session_id)
# Do work...
finally:
sandbox.process.delete_session(session.session_id)
```
```typescript
// TypeScript - Clean up session
const sessionId = "long-running-cmd";
try {
await sandbox.process.createSession(sessionId);
const session = await sandbox.process.getSession(sessionId);
// Do work...
} finally {
await sandbox.process.deleteSession(session.sessionId);
}
```
```ruby
# Ruby - Clean up session
session_id = 'long-running-cmd'
begin
sandbox.process.create_session(session_id)
session = sandbox.process.get_session(session_id)
# Do work...
ensure
sandbox.process.delete_session(session.session_id)
end
```
```go
// Go - Clean up session
sessionID := "long-running-cmd"
err := sandbox.Process.CreateSession(ctx, sessionID)
if err != nil {
log.Fatal(err)
}
defer sandbox.Process.DeleteSession(ctx, sessionID)
session, err := sandbox.Process.GetSession(ctx, sessionID)
if err != nil {
log.Fatal(err)
}
// Do work...
```
```bash
# Create session
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/process/session' \
--request POST \
--header 'Content-Type: application/json' \
--data '{"sessionId": "long-running-cmd"}'
# Delete session when done
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/process/session/{sessionId}' \
--request DELETE
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk.md), [Go SDK](https://www.daytona.io/docs/en/go-sdk.md), and [API](https://www.daytona.io/docs/en/tools/api.md) references:
> [**create_session (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/process.md#processcreate_session)
>
> [**delete_session (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/process.md#processdelete_session)
>
> [**createSession (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/process.md#createsession)
>
> [**deleteSession (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/process.md#deletesession)
>
> [**create_session (Ruby SDK)**](https://www.daytona.io/docs/en/ruby-sdk/process.md#create_session)
>
> [**delete_session (Ruby SDK)**](https://www.daytona.io/docs/en/ruby-sdk/process.md#delete_session)
>
> [**CreateSession (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#ProcessService.CreateSession)
>
> [**DeleteSession (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#ProcessService.DeleteSession)
>
> [**create session (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/process/POST/process/session)
>
> [**delete session (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/process/DELETE/process/session/{sessionId})
## Error handling
Daytona provides methods to handle errors when executing processes. You should handle process exceptions properly, log error details for debugging, and use try-catch blocks for error handling.
```python
from daytona import DaytonaError
try:
response = sandbox.process.code_run("invalid python code")
if response.exit_code != 0:
print(f"Exit code: {response.exit_code}")
print(f"Error output: {response.result}")
except DaytonaError as e:
print(f"Execution failed: {e}")
```
```typescript
import { DaytonaError } from '@daytonaio/sdk'
try {
const response = await sandbox.process.codeRun("invalid typescript code");
if (response.exitCode !== 0) {
console.error("Exit code:", response.exitCode);
console.error("Error output:", response.result);
}
} catch (e) {
if (e instanceof DaytonaError) {
console.error("Execution failed:", e);
}
}
```
```ruby
begin
response = sandbox.process.code_run(code: 'invalid python code')
if response.exit_code != 0
puts "Exit code: #{response.exit_code}"
puts "Error output: #{response.result}"
end
rescue StandardError => e
puts "Execution failed: #{e}"
end
```
```go
result, err := sandbox.Process.ExecuteCommand(ctx, "python3 -c 'invalid python code'")
if err != nil {
fmt.Println("Execution failed:", err)
}
if result != nil && result.ExitCode != 0 {
fmt.Println("Exit code:", result.ExitCode)
fmt.Println("Error output:", result.Result)
}
```
```bash
# API responses include exitCode field for error handling
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/process/execute' \
--request POST \
--header 'Content-Type: application/json' \
--data '{
"command": "python3 -c \"invalid python code\""
}'
# Response includes:
# {
# "result": "",
# "exitCode": 1
# }
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk.md), and [Go SDK](https://www.daytona.io/docs/en/go-sdk.md) references.
## Common issues
Daytona provides solutions for troubleshooting common issues related to process and code execution.
| **Issue** | **Solutions** |
| ------------------------ | --------------------------------------------------------------------------------------------------------------- |
| Process execution failed | • Check command syntax • Verify required dependencies • Ensure sufficient permissions |
| Process timeout | • Adjust timeout settings • Optimize long-running operations • Consider using background processes |
| Resource limits | • Monitor process memory usage • Handle process cleanup properly • Use appropriate resource constraints |
Daytona provides powerful pseudo terminal (PTY) capabilities through the `process` module in sandboxes. PTY sessions allow you to create interactive terminal sessions that can execute commands, handle user input, and manage terminal operations.
A PTY (Pseudo Terminal) is a virtual terminal interface that allows programs to interact with a shell as if they were connected to a real terminal. PTY sessions in Daytona enable:
- **Interactive Development**: REPLs, debuggers, and development tools
- **Build Processes**: Running and monitoring compilation, testing, or deployment
- **System Administration**: Remote server management and configuration
- **User Interfaces**: Terminal-based applications requiring user interaction
## Create PTY session
Daytona provides methods to create an interactive terminal session that can execute commands and handle user input.
```python
from daytona.common.pty import PtySize
pty_handle = sandbox.process.create_pty_session(
id="my-session",
cwd="/workspace",
envs={"TERM": "xterm-256color"},
pty_size=PtySize(cols=120, rows=30)
)
```
```typescript
// Create a PTY session with custom configuration
const ptyHandle = await sandbox.process.createPty({
id: 'my-interactive-session',
cwd: '/workspace',
envs: { TERM: 'xterm-256color', LANG: 'en_US.UTF-8' },
cols: 120,
rows: 30,
onData: (data) => {
// Handle terminal output
const text = new TextDecoder().decode(data)
process.stdout.write(text)
},
})
// Wait for connection to be established
await ptyHandle.waitForConnection()
// Send commands to the terminal
await ptyHandle.sendInput('ls -la\n')
await ptyHandle.sendInput('echo "Hello, PTY!"\n')
await ptyHandle.sendInput('exit\n')
// Wait for completion and get result
const result = await ptyHandle.wait()
console.log(`PTY session completed with exit code: ${result.exitCode}`)
// Clean up
await ptyHandle.disconnect()
```
```ruby
pty_size = Daytona::PtySize.new(rows: 30, cols: 120)
pty_handle = sandbox.process.create_pty_session(
id: 'my-interactive-session',
cwd: '/workspace',
envs: { 'TERM' => 'xterm-256color' },
pty_size: pty_size
)
# Use the PTY session
pty_handle.send_input("ls -la\n")
pty_handle.send_input("echo 'Hello, PTY!'\n")
pty_handle.send_input("exit\n")
# Handle output
pty_handle.each { |data| print data }
puts "PTY session completed with exit code: #{pty_handle.exit_code}"
```
```go
// Create a PTY session with custom configuration
handle, err := sandbox.Process.CreatePty(ctx, "my-interactive-session",
options.WithCreatePtySize(types.PtySize{Cols: 120, Rows: 30}),
options.WithCreatePtyEnv(map[string]string{"TERM": "xterm-256color"}),
)
if err != nil {
log.Fatal(err)
}
defer handle.Disconnect()
// Wait for connection to be established
if err := handle.WaitForConnection(ctx); err != nil {
log.Fatal(err)
}
// Send commands to the terminal
handle.SendInput([]byte("ls -la\n"))
handle.SendInput([]byte("echo 'Hello, PTY!'\n"))
handle.SendInput([]byte("exit\n"))
// Read output from channel
for data := range handle.DataChan() {
fmt.Print(string(data))
}
// Wait for completion and get result
result, err := handle.Wait(ctx)
if err != nil {
log.Fatal(err)
}
fmt.Printf("PTY session completed with exit code: %d\n", *result.ExitCode)
```
```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/process/pty' \
--request POST \
--header 'Content-Type: application/json' \
--data '{
"cols": 1,
"cwd": "",
"envs": {
"additionalProperty": ""
},
"id": "",
"lazyStart": true,
"rows": 1
}'
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk/sync/process.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk/process.md#createpty), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk/process.md), [Go SDK](https://www.daytona.io/docs/en/go-sdk/daytona.md#type-processservice), and [API](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/process) references:
> [**create_pty_session (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/process.md#processcreate_pty_session)
>
> [**createPty (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/process.md#createpty)
>
> [**create_pty_session (Ruby SDK)**](https://www.daytona.io/docs/en/ruby-sdk/process.md#create_pty_session)
>
> [**CreatePty (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#ProcessService.CreatePty)
>
> [**Create PTY session (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/process/POST/process/pty)
## Connect to PTY session
Daytona provides methods to establish a connection to an existing PTY session, enabling interaction with a previously created terminal.
```python
pty_handle = sandbox.process.connect_pty_session("my-session")
```
```typescript
// Connect to an existing PTY session
const handle = await sandbox.process.connectPty('my-session', {
onData: (data) => {
// Handle terminal output
const text = new TextDecoder().decode(data)
process.stdout.write(text)
},
})
// Wait for connection to be established
await handle.waitForConnection()
// Send commands to the existing session
await handle.sendInput('pwd\n')
await handle.sendInput('ls -la\n')
await handle.sendInput('exit\n')
// Wait for completion
const result = await handle.wait()
console.log(`Session exited with code: ${result.exitCode}`)
// Clean up
await handle.disconnect()
```
```ruby
# Connect to an existing PTY session
pty_handle = sandbox.process.connect_pty_session('my-session')
pty_handle.send_input("echo 'Hello World'\n")
pty_handle.send_input("exit\n")
# Handle output
pty_handle.each { |data| print data }
puts "Session exited with code: #{pty_handle.exit_code}"
```
```go
// Connect to an existing PTY session
handle, err := sandbox.Process.ConnectPty(ctx, "my-session")
if err != nil {
log.Fatal(err)
}
defer handle.Disconnect()
// Wait for connection to be established
if err := handle.WaitForConnection(ctx); err != nil {
log.Fatal(err)
}
// Send commands to the existing session
handle.SendInput([]byte("pwd\n"))
handle.SendInput([]byte("ls -la\n"))
handle.SendInput([]byte("exit\n"))
// Read output
for data := range handle.DataChan() {
fmt.Print(string(data))
}
// Wait for completion
result, err := handle.Wait(ctx)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Session exited with code: %d\n", *result.ExitCode)
```
```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/process/pty/{sessionId}/connect'
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk/sync/process.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk/process.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk/process.md), [Go SDK](https://www.daytona.io/docs/en/go-sdk/daytona.md#type-processservice), and [API](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/process) references:
> [**connect_pty_session (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/process.md#processconnect_pty_session)
>
> [**connectPty (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/process.md#connectpty)
>
> [**connect_pty_session (Ruby SDK)**](https://www.daytona.io/docs/en/ruby-sdk/process.md#connect_pty_session)
>
> [**ConnectPty (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#ProcessService.ConnectPty)
>
> [**Connect to PTY session (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/process/GET/process/pty/{sessionId}/connect)
## List PTY sessions
Daytona provides methods to list PTY sessions, allowing you to retrieve information about all PTY sessions, both active and inactive, that have been created in the sandbox.
```python
# List all PTY sessions
sessions = sandbox.process.list_pty_sessions()
for session in sessions:
print(f"Session ID: {session.id}")
print(f"Active: {session.active}")
print(f"Created: {session.created_at}")
```
```typescript
// List all PTY sessions
const sessions = await sandbox.process.listPtySessions()
for (const session of sessions) {
console.log(`Session ID: ${session.id}`)
console.log(`Active: ${session.active}`)
console.log(`Created: ${session.createdAt}`)
console.log('---')
}
```
```ruby
# List all PTY sessions
sessions = sandbox.process.list_pty_sessions
sessions.each do |session|
puts "Session ID: #{session.id}"
puts "Active: #{session.active}"
puts "Terminal Size: #{session.cols}x#{session.rows}"
puts '---'
end
```
```go
// List all PTY sessions
sessions, err := sandbox.Process.ListPtySessions(ctx)
if err != nil {
log.Fatal(err)
}
for _, session := range sessions {
fmt.Printf("Session ID: %s\n", session.Id)
fmt.Printf("Active: %t\n", session.Active)
fmt.Printf("Terminal Size: %dx%d\n", session.Cols, session.Rows)
fmt.Println("---")
}
```
```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/process/pty'
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk/sync/process.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk/process.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk/process.md), [Go SDK](https://www.daytona.io/docs/en/go-sdk/daytona.md#type-processservice), and [API](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/process) references:
> [**list_pty_sessions (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/process.md#processlist_pty_sessions)
>
> [**listPtySessions (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/process.md#listptysessions)
>
> [**list_pty_sessions (Ruby SDK)**](https://www.daytona.io/docs/en/ruby-sdk/process.md#list_pty_sessions)
>
> [**ListPtySessions (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#ProcessService.ListPtySessions)
>
> [**List PTY sessions (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/process/GET/process/pty)
## Get PTY session info
Daytona provides methods to get information about a specific PTY session, allowing you to retrieve comprehensive information about a specific PTY session including its current state, configuration, and metadata.
```python
# Get details about a specific PTY session
session_info = sandbox.process.get_pty_session_info("my-session")
print(f"Session ID: {session_info.id}")
print(f"Active: {session_info.active}")
print(f"Working Directory: {session_info.cwd}")
print(f"Terminal Size: {session_info.cols}x{session_info.rows}")
```
```typescript
// Get details about a specific PTY session
const session = await sandbox.process.getPtySessionInfo('my-session')
console.log(`Session ID: ${session.id}`)
console.log(`Active: ${session.active}`)
console.log(`Working Directory: ${session.cwd}`)
console.log(`Terminal Size: ${session.cols}x${session.rows}`)
if (session.processId) {
console.log(`Process ID: ${session.processId}`)
}
```
```ruby
# Get details about a specific PTY session
session_info = sandbox.process.get_pty_session_info('my-session')
puts "Session ID: #{session_info.id}"
puts "Active: #{session_info.active}"
puts "Working Directory: #{session_info.cwd}"
puts "Terminal Size: #{session_info.cols}x#{session_info.rows}"
```
```go
// Get details about a specific PTY session
session, err := sandbox.Process.GetPtySessionInfo(ctx, "my-session")
if err != nil {
log.Fatal(err)
}
fmt.Printf("Session ID: %s\n", session.Id)
fmt.Printf("Active: %t\n", session.Active)
fmt.Printf("Working Directory: %s\n", session.Cwd)
fmt.Printf("Terminal Size: %dx%d\n", session.Cols, session.Rows)
if session.ProcessId != nil {
fmt.Printf("Process ID: %d\n", *session.ProcessId)
}
```
```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/process/session/{sessionId}'
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk/sync/process.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk/process.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk/process.md), [Go SDK](https://www.daytona.io/docs/en/go-sdk/daytona.md#type-processservice), and [API](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/process) references:
> [**get_pty_session_info (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/process.md#processget_pty_session_info)
>
> [**getPtySessionInfo (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/process.md#getptysessioninfo)
>
> [**get_pty_session_info (Ruby SDK)**](https://www.daytona.io/docs/en/ruby-sdk/process.md#get_pty_session_info)
>
> [**GetPtySessionInfo (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#ProcessService.GetPtySessionInfo)
>
> [**Get PTY session info (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/process/GET/process/session/{sessionId})
## Kill PTY session
Daytona provides methods to kill a PTY session, allowing you to forcefully terminate a PTY session and cleans up all associated resources.
```python
# Kill a specific PTY session
sandbox.process.kill_pty_session("my-session")
# Verify the session no longer exists
pty_sessions = sandbox.process.list_pty_sessions()
for pty_session in pty_sessions:
print(f"PTY session: {pty_session.id}")
```
```typescript
// Kill a specific PTY session
await sandbox.process.killPtySession('my-session')
// Verify the session is no longer active
try {
const info = await sandbox.process.getPtySessionInfo('my-session')
console.log(`Session still exists but active: ${info.active}`)
} catch (error) {
console.log('Session has been completely removed')
}
```
```ruby
# Delete a specific PTY session
sandbox.process.delete_pty_session('my-session')
# Verify the session no longer exists
sessions = sandbox.process.list_pty_sessions
sessions.each do |session|
puts "PTY session: #{session.id}"
end
```
```go
// Kill a specific PTY session
err := sandbox.Process.KillPtySession(ctx, "my-session")
if err != nil {
log.Fatal(err)
}
// Verify the session is no longer active
sessions, err := sandbox.Process.ListPtySessions(ctx)
if err != nil {
log.Fatal(err)
}
for _, session := range sessions {
fmt.Printf("PTY session: %s\n", session.Id)
}
```
```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/process/session/{sessionId}' \
--request DELETE
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk/sync/process.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk/process.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk/process.md#delete_pty_session), [Go SDK](https://www.daytona.io/docs/en/go-sdk/daytona.md#type-processservice), and [API](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/process) references:
> [**kill_pty_session (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/process.md#processkill_pty_session)
>
> [**killPtySession (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/process.md#killptysession)
>
> [**delete_pty_session (Ruby SDK)**](https://www.daytona.io/docs/en/ruby-sdk/process.md#delete_pty_session)
>
> [**KillPtySession (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#ProcessService.KillPtySession)
>
> [**Kill PTY session (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/process/DELETE/process/session/{sessionId})
## Resize PTY session
Daytona provides methods to resize a PTY session, allowing you to change the terminal dimensions of an active PTY session. This sends a SIGWINCH signal to the shell process, allowing terminal applications to adapt to the new size.
```python
from daytona.common.pty import PtySize
# Resize a PTY session to a larger terminal
new_size = PtySize(rows=40, cols=150)
updated_info = sandbox.process.resize_pty_session("my-session", new_size)
print(f"Terminal resized to {updated_info.cols}x{updated_info.rows}")
# You can also use the PtyHandle's resize method
pty_handle.resize(new_size)
```
```typescript
// Resize a PTY session to a larger terminal
const updatedInfo = await sandbox.process.resizePtySession('my-session', 150, 40)
console.log(`Terminal resized to ${updatedInfo.cols}x${updatedInfo.rows}`)
// You can also use the PtyHandle's resize method
await ptyHandle.resize(150, 40) // cols, rows
```
```ruby
# Resize a PTY session to a larger terminal
pty_size = Daytona::PtySize.new(rows: 40, cols: 150)
session_info = sandbox.process.resize_pty_session('my-session', pty_size)
puts "Terminal resized to #{session_info.cols}x#{session_info.rows}"
```
```go
// Resize a PTY session to a larger terminal
updatedInfo, err := sandbox.Process.ResizePtySession(ctx, "my-session", types.PtySize{
Cols: 150,
Rows: 40,
})
if err != nil {
log.Fatal(err)
}
fmt.Printf("Terminal resized to %dx%d\n", updatedInfo.Cols, updatedInfo.Rows)
// You can also use the PtyHandle's Resize method
info, err := handle.Resize(ctx, 150, 40)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Terminal resized to %dx%d\n", info.Cols, info.Rows)
```
```bash
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/process/pty/{sessionId}/resize' \
--request POST \
--header 'Content-Type: application/json' \
--data '{
"cols": 1,
"rows": 1
}'
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk/sync/process.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk/process.md#resizeptysession), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk/process.md), [Go SDK](https://www.daytona.io/docs/en/go-sdk/daytona.md#type-processservice), and [API](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/process) references:
> [**resize_pty_session (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/process.md#processresize_pty_session)
>
> [**resizePtySession (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/process.md#resizeptysession)
>
> [**resize_pty_session (Ruby SDK)**](https://www.daytona.io/docs/en/ruby-sdk/process.md#resize_pty_session)
>
> [**ResizePtySession (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#ProcessService.ResizePtySession)
>
> [**Resize PTY session (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox/tag/process/POST/process/pty/{sessionId}/resize)
## Interactive commands
Daytona provides methods to handle interactive commands with PTY sessions, allowing you to handle interactive commands that require user input and can be resized during execution.
```python
import time
from daytona import Daytona, Sandbox
from daytona.common.pty import PtySize
def handle_pty_data(data: bytes):
text = data.decode("utf-8", errors="replace")
print(text, end="")
# Create PTY session
pty_handle = sandbox.process.create_pty_session(
id="interactive-session",
pty_size=PtySize(cols=300, rows=100)
)
# Send interactive command
pty_handle.send_input('printf "Are you accepting the terms and conditions? (y/n): " && read confirm && if [ "$confirm" = "y" ]; then echo "You accepted"; else echo "You did not accept"; fi\n')
time.sleep(1)
pty_handle.send_input("y\n")
# Resize terminal
pty_session_info = pty_handle.resize(PtySize(cols=210, rows=110))
print(f"PTY session resized to {pty_session_info.cols}x{pty_session_info.rows}")
# Exit the session
pty_handle.send_input('exit\n')
# Handle output using iterator
for data in pty_handle:
handle_pty_data(data)
print(f"Session completed with exit code: {pty_handle.exit_code}")
```
```typescript
import { Daytona, Sandbox } from '@daytonaio/sdk'
// Create PTY session
const ptyHandle = await sandbox.process.createPty({
id: 'interactive-session',
cols: 300,
rows: 100,
onData: data => {
const text = new TextDecoder().decode(data)
process.stdout.write(text)
},
})
await ptyHandle.waitForConnection()
// Send interactive command
await ptyHandle.sendInput(
'printf "Are you accepting the terms and conditions? (y/n): " && read confirm && if [ "$confirm" = "y" ]; then echo "You accepted"; else echo "You did not accept"; fi\n'
)
await new Promise(resolve => setTimeout(resolve, 1000))
await ptyHandle.sendInput('y\n')
// Resize terminal
const ptySessionInfo = await sandbox.process.resizePtySession(
'interactive-session',
210,
110
)
console.log(
`\nPTY session resized to ${ptySessionInfo.cols}x${ptySessionInfo.rows}`
)
// Exit the session
await ptyHandle.sendInput('exit\n')
// Wait for completion
const result = await ptyHandle.wait()
console.log(`Session completed with exit code: ${result.exitCode}`)
```
```ruby
require 'daytona'
# Create PTY session
pty_handle = sandbox.process.create_pty_session(
id: 'interactive-session',
pty_size: Daytona::PtySize.new(cols: 300, rows: 100)
)
# Handle output in a separate thread
thread = Thread.new do
pty_handle.each { |data| print data }
end
# Send interactive command
pty_handle.send_input('printf "Are you accepting the terms and conditions? (y/n): " && read confirm && if [ "$confirm" = "y" ]; then echo "You accepted"; else echo "You did not accept"; fi' + "\n")
sleep(1)
pty_handle.send_input("y\n")
# Resize terminal
pty_handle.resize(Daytona::PtySize.new(cols: 210, rows: 110))
puts "\nPTY session resized"
# Exit the session
pty_handle.send_input("exit\n")
# Wait for the thread to finish
thread.join
puts "Session completed with exit code: #{pty_handle.exit_code}"
```
```go
// Create PTY session
handle, err := sandbox.Process.CreatePty(ctx, "interactive-session",
options.WithCreatePtySize(types.PtySize{Cols: 300, Rows: 100}),
)
if err != nil {
log.Fatal(err)
}
defer handle.Disconnect()
if err := handle.WaitForConnection(ctx); err != nil {
log.Fatal(err)
}
// Handle output in a goroutine
go func() {
for data := range handle.DataChan() {
fmt.Print(string(data))
}
}()
// Send interactive command
handle.SendInput([]byte(`printf "Are you accepting the terms and conditions? (y/n): " && read confirm && if [ "$confirm" = "y" ]; then echo "You accepted"; else echo "You did not accept"; fi` + "\n"))
time.Sleep(1 * time.Second)
handle.SendInput([]byte("y\n"))
// Resize terminal
info, err := handle.Resize(ctx, 210, 110)
if err != nil {
log.Fatal(err)
}
fmt.Printf("\nPTY session resized to %dx%d\n", info.Cols, info.Rows)
// Exit the session
handle.SendInput([]byte("exit\n"))
// Wait for completion
result, err := handle.Wait(ctx)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Session completed with exit code: %d\n", *result.ExitCode)
```
## Long-running processes
Daytona provides methods to manage long-running processes with PTY sessions, allowing you to manage long-running processes that need to be monitored or terminated.
```python
import time
import threading
from daytona import Daytona, Sandbox
from daytona.common.pty import PtySize
def handle_pty_data(data: bytes):
text = data.decode("utf-8", errors="replace")
print(text, end="")
# Create PTY session
pty_handle = sandbox.process.create_pty_session(
id="long-running-session",
pty_size=PtySize(cols=120, rows=30)
)
# Start a long-running process
pty_handle.send_input('while true; do echo "Running... $(date)"; sleep 1; done\n')
# Using thread and wait() method to handle PTY output
thread = threading.Thread(target=pty_handle.wait, args=(handle_pty_data, 10))
thread.start()
time.sleep(3) # Let it run for a bit
print("Killing long-running process...")
pty_handle.kill()
thread.join()
print(f"\nProcess terminated with exit code: {pty_handle.exit_code}")
if pty_handle.error:
print(f"Termination reason: {pty_handle.error}")
```
```typescript
import { Daytona, Sandbox } from '@daytonaio/sdk'
// Create PTY session
const ptyHandle = await sandbox.process.createPty({
id: 'long-running-session',
cols: 120,
rows: 30,
onData: (data) => {
const text = new TextDecoder().decode(data)
process.stdout.write(text)
},
})
await ptyHandle.waitForConnection()
// Start a long-running process
await ptyHandle.sendInput('while true; do echo "Running... $(date)"; sleep 1; done\n')
await new Promise(resolve => setTimeout(resolve, 3000)) // Let it run for a bit
console.log('Killing long-running process...')
await ptyHandle.kill()
// Wait for termination
const result = await ptyHandle.wait()
console.log(`\nProcess terminated with exit code: ${result.exitCode}`)
if (result.error) {
console.log(`Termination reason: ${result.error}`)
}
```
```ruby
require 'daytona'
# Create PTY session
pty_handle = sandbox.process.create_pty_session(
id: 'long-running-session',
pty_size: Daytona::PtySize.new(cols: 120, rows: 30)
)
# Handle output in a separate thread
thread = Thread.new do
pty_handle.each { |data| print data }
end
# Start a long-running process
pty_handle.send_input("while true; do echo \"Running... $(date)\"; sleep 1; done\n")
sleep(3) # Let it run for a bit
puts "Killing long-running process..."
pty_handle.kill
thread.join
puts "\nProcess terminated with exit code: #{pty_handle.exit_code}"
puts "Termination reason: #{pty_handle.error}" if pty_handle.error
```
```go
// Create PTY session
handle, err := sandbox.Process.CreatePty(ctx, "long-running-session",
options.WithCreatePtySize(types.PtySize{Cols: 120, Rows: 30}),
)
if err != nil {
log.Fatal(err)
}
defer handle.Disconnect()
if err := handle.WaitForConnection(ctx); err != nil {
log.Fatal(err)
}
// Handle output in a goroutine
go func() {
for data := range handle.DataChan() {
fmt.Print(string(data))
}
}()
// Start a long-running process
handle.SendInput([]byte(`while true; do echo "Running... $(date)"; sleep 1; done` + "\n"))
time.Sleep(3 * time.Second) // Let it run for a bit
fmt.Println("Killing long-running process...")
if err := handle.Kill(ctx); err != nil {
log.Fatal(err)
}
// Wait for termination
result, err := handle.Wait(ctx)
if err != nil {
log.Fatal(err)
}
fmt.Printf("\nProcess terminated with exit code: %d\n", *result.ExitCode)
if result.Error != nil {
fmt.Printf("Termination reason: %s\n", *result.Error)
}
```
## Resource management
Daytona provides methods to manage resource leaks with PTY sessions, allowing you to always clean up PTY sessions to prevent resource leaks.
```python
# Python: Use try/finally
pty_handle = None
try:
pty_handle = sandbox.process.create_pty_session(id="session", pty_size=PtySize(cols=120, rows=30))
# Do work...
finally:
if pty_handle:
pty_handle.kill()
```
```typescript
// TypeScript: Use try/finally
let ptyHandle
try {
ptyHandle = await sandbox.process.createPty({
id: 'session',
cols: 120,
rows: 30,
})
// Do work...
} finally {
if (ptyHandle) await ptyHandle.kill()
}
```
```ruby
# Ruby: Use begin/ensure
pty_handle = nil
begin
pty_handle = sandbox.process.create_pty_session(
id: 'session',
pty_size: Daytona::PtySize.new(cols: 120, rows: 30)
)
# Do work...
ensure
pty_handle&.kill
end
```
```go
// Go: Use defer for cleanup
handle, err := sandbox.Process.CreatePty(ctx, "session",
options.WithCreatePtySize(types.PtySize{Cols: 120, Rows: 30}),
)
if err != nil {
log.Fatal(err)
}
defer handle.Disconnect()
// Do work...
// Or use Kill to terminate the process
defer handle.Kill(ctx)
```
## PtyHandle methods
Daytona provides methods to interact with PTY sessions, allowing you to send input, resize the terminal, wait for completion, and manage the WebSocket connection to a PTY session.
### Send input
Daytona provides methods to send input to a PTY session, allowing you to send input data (keystrokes or commands) to the PTY session.
```python
# Send a command
pty_handle.send_input("ls -la\n")
# Send user input
pty_handle.send_input("y\n")
```
```typescript
// Send a command
await ptyHandle.sendInput('ls -la\n')
// Send raw bytes
await ptyHandle.sendInput(new Uint8Array([3])) // Ctrl+C
```
```ruby
# Send a command
pty_handle.send_input("ls -la\n")
# Send user input
pty_handle.send_input("y\n")
```
```go
// Send a command
handle.SendInput([]byte("ls -la\n"))
// Send Ctrl+C
handle.SendInput([]byte{0x03})
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk.md), and [Go SDK](https://www.daytona.io/docs/en/go-sdk/daytona.md#type-processservice) references:
> [**sendInput (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/pty-handle.md#sendinput)
>
> [**SendInput (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#PtyHandle.SendInput)
### Wait for completion
Daytona provides methods to wait for a PTY process to exit and return the result, allowing you to wait for a PTY process to exit and return the result.
```python
# Wait with a callback for output data
def handle_data(data: bytes):
print(data.decode("utf-8", errors="replace"), end="")
result = pty_handle.wait(on_data=handle_data, timeout=30)
print(f"Exit code: {result.exit_code}")
```
```typescript
// Wait for process to complete
const result = await ptyHandle.wait()
if (result.exitCode === 0) {
console.log('Process completed successfully')
} else {
console.log(`Process failed with code: ${result.exitCode}`)
if (result.error) {
console.log(`Error: ${result.error}`)
}
}
```
```ruby
# Wait by iterating over output (blocks until PTY session ends)
pty_handle.each { |data| print data }
if pty_handle.exit_code == 0
puts 'Process completed successfully'
else
puts "Process failed with code: #{pty_handle.exit_code}"
puts "Error: #{pty_handle.error}" if pty_handle.error
end
```
```go
// Wait for process to complete
result, err := handle.Wait(ctx)
if err != nil {
log.Fatal(err)
}
if result.ExitCode != nil && *result.ExitCode == 0 {
fmt.Println("Process completed successfully")
} else {
fmt.Printf("Process failed with code: %d\n", *result.ExitCode)
if result.Error != nil {
fmt.Printf("Error: %s\n", *result.Error)
}
}
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk.md), and [Go SDK](https://www.daytona.io/docs/en/go-sdk/daytona.md#type-processservice) references:
> [**wait (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/pty-handle.md#wait)
>
> [**Wait (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#PtyHandle.Wait)
### Wait for connection
Daytona provides methods to wait for the WebSocket connection to be established before sending input, allowing you to wait for the WebSocket connection to be established before sending input.
```python
# Python handles connection internally during creation
# No explicit wait needed
```
```typescript
// Wait for connection to be established
await ptyHandle.waitForConnection()
// Now safe to send input
await ptyHandle.sendInput('echo "Connected!"\n')
```
```ruby
# Ruby handles connection internally during creation
# No explicit wait needed - can send input immediately after creation
pty_handle.send_input("echo 'Connected!'\n")
```
```go
// Wait for connection to be established
if err := handle.WaitForConnection(ctx); err != nil {
log.Fatal(err)
}
// Now safe to send input
handle.SendInput([]byte("echo 'Connected!'\n"))
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk.md), and [Go SDK](https://www.daytona.io/docs/en/go-sdk/daytona.md#type-processservice) references:
> [**waitForConnection (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/pty-handle.md#waitforconnection)
>
> [**WaitForConnection (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#PtyHandle.WaitForConnection)
### Kill PTY process
Daytona provides methods to kill a PTY process and terminate the session from the handle.
```python
pty_handle.kill()
```
```typescript
// Kill a long-running process
await ptyHandle.kill()
// Wait to confirm termination
const result = await ptyHandle.wait()
console.log(`Process terminated with exit code: ${result.exitCode}`)
```
```ruby
# Kill a long-running process
pty_handle.kill
puts "Process terminated with exit code: #{pty_handle.exit_code}"
```
```go
// Kill a long-running process
if err := handle.Kill(ctx); err != nil {
log.Fatal(err)
}
// Wait to confirm termination
result, err := handle.Wait(ctx)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Process terminated with exit code: %d\n", *result.ExitCode)
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk.md), and [Go SDK](https://www.daytona.io/docs/en/go-sdk/daytona.md#type-processservice) references:
> [**kill (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/pty-handle.md#kill)
>
> [**Kill (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#PtyHandle.Kill)
### Resize from handle
Daytona provides methods to resize the PTY terminal dimensions directly from the handle.
```python
from daytona.common.pty import PtySize
pty_handle.resize(PtySize(cols=120, rows=30))
```
```typescript
// Resize to 120x30
await ptyHandle.resize(120, 30)
```
```ruby
# Resize to 120x30
pty_handle.resize(Daytona::PtySize.new(cols: 120, rows: 30))
```
```go
// Resize to 120x30
info, err := handle.Resize(ctx, 120, 30)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Resized to %dx%d\n", info.Cols, info.Rows)
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk.md), and [Go SDK](https://www.daytona.io/docs/en/go-sdk/daytona.md#type-processservice) references:
> [**resize (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/pty-handle.md#resize)
>
> [**Resize (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#PtyHandle.Resize)
### Disconnect
Daytona provides methods to disconnect from a PTY session and clean up resources without killing the process.
```python
# Python: Use kill() to terminate, or let the handle go out of scope
```
```typescript
// Always clean up when done
try {
// ... use PTY session
} finally {
await ptyHandle.disconnect()
}
```
```ruby
# Ruby: Use begin/ensure or kill the session
begin
# ... use PTY session
ensure
pty_handle.kill
end
```
```go
// Always clean up when done using defer
handle, err := sandbox.Process.CreatePty(ctx, "session")
if err != nil {
log.Fatal(err)
}
defer handle.Disconnect()
// ... use PTY session
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk.md), and [Go SDK](https://www.daytona.io/docs/en/go-sdk/daytona.md#type-processservice) references:
> [**disconnect (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/pty-handle.md#disconnect)
>
> [**Disconnect (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#PtyHandle.Disconnect)
### Check connection status
Daytona provides methods to check if a PTY session is still connected.
```python
# Python: Check by attempting operations or using session info
session_info = sandbox.process.get_pty_session_info("my-session")
print(f"Session active: {session_info.active}")
```
```typescript
if (ptyHandle.isConnected()) {
console.log('PTY session is active')
}
```
```ruby
# Ruby: Check by using session info
session_info = sandbox.process.get_pty_session_info('my-session')
puts 'PTY session is active' if session_info.active
```
```go
if handle.IsConnected() {
fmt.Println("PTY session is active")
}
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk.md), and [Go SDK](https://www.daytona.io/docs/en/go-sdk/daytona.md#type-processservice) references:
> [**isConnected (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/pty-handle.md#isconnected)
>
> [**IsConnected (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#PtyHandle.IsConnected)
### Exit code and error
Daytona provides methods to access the exit code and error message after a PTY process terminates.
```python
# After iteration or wait completes
print(f"Exit code: {pty_handle.exit_code}")
if pty_handle.error:
print(f"Error: {pty_handle.error}")
```
```typescript
// Access via getters after process terminates
console.log(`Exit code: ${ptyHandle.exitCode}`)
if (ptyHandle.error) {
console.log(`Error: ${ptyHandle.error}`)
}
```
```ruby
# Access after process terminates
puts "Exit code: #{pty_handle.exit_code}"
puts "Error: #{pty_handle.error}" if pty_handle.error
```
```go
// Access via methods after process terminates
if exitCode := handle.ExitCode(); exitCode != nil {
fmt.Printf("Exit code: %d\n", *exitCode)
}
if errMsg := handle.Error(); errMsg != nil {
fmt.Printf("Error: %s\n", *errMsg)
}
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk.md), and [Go SDK](https://www.daytona.io/docs/en/go-sdk/daytona.md#type-processservice) references:
> [**exitCode (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/pty-handle.md#exitcode)
>
> [**error (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/pty-handle.md#error)
>
> [**ExitCode (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#PtyHandle.ExitCode)
>
> [**Error (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#PtyHandle.Error)
### Iterate over output (Python)
Daytona provides methods to iterate over a PTY handle to receive output data.
```python
# Iterate over PTY output
for data in pty_handle:
text = data.decode("utf-8", errors="replace")
print(text, end="")
print(f"Session ended with exit code: {pty_handle.exit_code}")
```
```typescript
// TypeScript uses the onData callback instead
const ptyHandle = await sandbox.process.createPty({
id: 'my-session',
onData: (data) => {
const text = new TextDecoder().decode(data)
process.stdout.write(text)
},
})
```
```ruby
# Iterate over PTY output
pty_handle.each do |data|
print data
end
puts "Session ended with exit code: #{pty_handle.exit_code}"
```
```go
// Go uses a channel to receive output data
for data := range handle.DataChan() {
fmt.Print(string(data))
}
// Or use as io.Reader
io.Copy(os.Stdout, handle)
fmt.Printf("Session ended with exit code: %d\n", *handle.ExitCode())
```
## Error handling
Daytona provides methods to monitor exit codes and handle errors appropriately with PTY sessions.
```python
# Python: Check exit codes
result = pty_handle.wait()
if result.exit_code != 0:
print(f"Command failed: {result.exit_code}")
print(f"Error: {result.error}")
```
```typescript
// TypeScript: Check exit codes
const result = await ptyHandle.wait()
if (result.exitCode !== 0) {
console.log(`Command failed: ${result.exitCode}`)
console.log(`Error: ${result.error}`)
}
```
```ruby
# Ruby: Check exit codes
# The handle blocks until the PTY session completes
pty_handle.each { |data| print data }
if pty_handle.exit_code != 0
puts "Command failed: #{pty_handle.exit_code}"
puts "Error: #{pty_handle.error}"
end
```
```go
// Go: Check exit codes
result, err := handle.Wait(ctx)
if err != nil {
log.Fatal(err)
}
if result.ExitCode != nil && *result.ExitCode != 0 {
fmt.Printf("Command failed: %d\n", *result.ExitCode)
if result.Error != nil {
fmt.Printf("Error: %s\n", *result.Error)
}
}
```
## Troubleshooting
- **Connection issues**: verify sandbox status, network connectivity, and proper session IDs
- **Performance issues**: use appropriate terminal dimensions and efficient data handlers
- **Process management**: use explicit `kill()` calls and proper timeout handling for long-running processes
## AsyncCodeInterpreter
```python
class AsyncCodeInterpreter()
```
Handles code interpretation and execution within a Sandbox. Currently supports only Python.
This class provides methods to execute code in isolated interpreter contexts,
manage contexts, and stream execution output via callbacks. If subsequent code executions
are performed in the same context, the variables, imports, and functions defined in
the previous execution will be available.
For other languages, use the `code_run` method from the `AsyncProcess` interface,
or execute the appropriate command directly in the sandbox terminal.
#### AsyncCodeInterpreter.\_\_init\_\_
```python
def __init__(api_client: InterpreterApi)
```
Initialize a new AsyncCodeInterpreter instance.
**Arguments**:
- `api_client` - API client for interpreter operations.
#### AsyncCodeInterpreter.run\_code
```python
@intercept_errors(message_prefix="Failed to run code: ")
async def run_code(code: str,
*,
context: InterpreterContext | None = None,
on_stdout: OutputHandler[OutputMessage] | None = None,
on_stderr: OutputHandler[OutputMessage] | None = None,
on_error: OutputHandler[ExecutionError] | None = None,
envs: dict[str, str] | None = None,
timeout: int | None = None) -> ExecutionResult
```
Execute Python code in the sandbox.
By default, code runs in the default shared context which persists variables,
imports, and functions across executions. To run in an isolated context,
create a new context with `create_context()` and pass it as `context` argument.
**Arguments**:
- `code` _str_ - Code to execute.
- `context` _InterpreterContext | None_ - Context to run code in. If not provided, uses default context.
- `on_stdout` _OutputHandler[OutputMessage] | None_ - Callback for stdout messages.
- `on_stderr` _OutputHandler[OutputMessage] | None_ - Callback for stderr messages.
- `on_error` _OutputHandler[ExecutionError] | None_ - Callback for execution errors
(e.g., syntax errors, runtime errors).
- `envs` _dict[str, str] | None_ - Environment variables for this execution.
- `timeout` _int | None_ - Timeout in seconds. 0 means no timeout. Default is 10 minutes.
**Returns**:
- `ExecutionResult` - Result object containing stdout, stderr and error if any.
**Raises**:
- `DaytonaTimeoutError` - If execution times out.
- `DaytonaError` - If execution fails due to communication or other SDK errors.
**Examples**:
```python
def handle_stdout(msg: OutputMessage):
print(f"STDOUT: {msg.output}", end="")
def handle_stderr(msg: OutputMessage):
print(f"STDERR: {msg.output}", end="")
def handle_error(err: ExecutionError):
print(f"ERROR: {err.name}: {err.value}")
code = '''
import sys
import time
for i in range(5):
print(i)
time.sleep(1)
sys.stderr.write("Counting done!")
'''
result = await sandbox.code_interpreter.run_code(
code=code,
on_stdout=handle_stdout,
on_stderr=handle_stderr,
on_error=handle_error,
timeout=10
)
```
#### AsyncCodeInterpreter.create\_context
```python
@intercept_errors(message_prefix="Failed to create interpreter context: ")
async def create_context(cwd: str | None = None) -> InterpreterContext
```
Create a new isolated interpreter context.
Contexts provide isolated execution environments with their own global namespace.
Variables, imports, and functions defined in one context don't affect others.
**Arguments**:
- `cwd` _str | None_ - Working directory for the context. If not specified, uses sandbox working directory.
**Returns**:
- `InterpreterContext` - The created context with its ID and metadata.
**Raises**:
- `DaytonaError` - If context creation fails.
**Examples**:
```python
# Create isolated context
ctx = await sandbox.code_interpreter.create_context()
# Execute code in this context
await sandbox.code_interpreter.run_code("x = 100", context=ctx)
# Variable only exists in this context
result = await sandbox.code_interpreter.run_code("print(x)", context=ctx) # OK
# Won't see the variable in default context
result = await sandbox.code_interpreter.run_code("print(x)") # NameError
# Clean up
await sandbox.code_interpreter.delete_context(ctx)
```
#### AsyncCodeInterpreter.list\_contexts
```python
@intercept_errors(message_prefix="Failed to list interpreter contexts: ")
async def list_contexts() -> list[InterpreterContext]
```
List all user-created interpreter contexts.
The default context is not included in this list. Only contexts created
via `create_context()` are returned.
**Returns**:
- `list[InterpreterContext]` - List of context objects.
**Raises**:
- `DaytonaError` - If listing fails.
**Examples**:
```python
contexts = await sandbox.code_interpreter.list_contexts()
for ctx in contexts:
print(f"Context {ctx.id}: {ctx.language} at {ctx.cwd}")
```
#### AsyncCodeInterpreter.delete\_context
```python
@intercept_errors(message_prefix="Failed to delete interpreter context: ")
async def delete_context(context: InterpreterContext) -> None
```
Delete an interpreter context and shut down all associated processes.
This permanently removes the context and all its state (variables, imports, etc.).
The default context cannot be deleted.
**Arguments**:
- `context` _InterpreterContext_ - Context to delete.
**Raises**:
- `DaytonaError` - If deletion fails or context not found.
**Examples**:
```python
ctx = await sandbox.code_interpreter.create_context()
# ... use context ...
await sandbox.code_interpreter.delete_context(ctx)
```
## OutputMessage
```python
class OutputMessage(BaseModel)
```
Represents stdout or stderr output from code execution.
**Attributes**:
- `output` - The output content.
## ExecutionError
```python
class ExecutionError(BaseModel)
```
Represents an error that occurred during code execution.
**Attributes**:
- `name` - The error type/class name (e.g., "ValueError", "SyntaxError").
- `value` - The error value.
- `traceback` - Full traceback of the error.
## ExecutionResult
```python
class ExecutionResult(BaseModel)
```
Result of code execution.
**Attributes**:
- `stdout` - Standard output from the code execution.
- `stderr` - Standard error output from the code execution.
- `error` - Error details if execution failed, None otherwise.
## AsyncComputerUse
```python
class AsyncComputerUse()
```
Computer Use functionality for interacting with the desktop environment.
Provides access to mouse, keyboard, screenshot, display, and recording operations
for automating desktop interactions within a sandbox.
**Attributes**:
- `mouse` _AsyncMouse_ - Mouse operations interface.
- `keyboard` _AsyncKeyboard_ - Keyboard operations interface.
- `screenshot` _AsyncScreenshot_ - Screenshot operations interface.
- `display` _AsyncDisplay_ - Display operations interface.
- `recording` _AsyncRecordingService_ - Screen recording operations interface.
#### AsyncComputerUse.start
```python
@intercept_errors(message_prefix="Failed to start computer use: ")
@with_instrumentation()
async def start() -> ComputerUseStartResponse
```
Starts all computer use processes (Xvfb, xfce4, x11vnc, novnc).
**Returns**:
- `ComputerUseStartResponse` - Computer use start response.
**Example**:
```python
result = await sandbox.computer_use.start()
print("Computer use processes started:", result.message)
```
#### AsyncComputerUse.stop
```python
@intercept_errors(message_prefix="Failed to stop computer use: ")
@with_instrumentation()
async def stop() -> ComputerUseStopResponse
```
Stops all computer use processes.
**Returns**:
- `ComputerUseStopResponse` - Computer use stop response.
**Example**:
```python
result = await sandbox.computer_use.stop()
print("Computer use processes stopped:", result.message)
```
#### AsyncComputerUse.get\_status
```python
@intercept_errors(message_prefix="Failed to get computer use status: ")
@with_instrumentation()
async def get_status() -> ComputerUseStatusResponse
```
Gets the status of all computer use processes.
**Returns**:
- `ComputerUseStatusResponse` - Status information about all VNC desktop processes.
**Example**:
```python
response = await sandbox.computer_use.get_status()
print("Computer use status:", response.status)
```
#### AsyncComputerUse.get\_process\_status
```python
@intercept_errors(message_prefix="Failed to get process status: ")
@with_instrumentation()
async def get_process_status(process_name: str) -> ProcessStatusResponse
```
Gets the status of a specific VNC process.
**Arguments**:
- `process_name` _str_ - Name of the process to check.
**Returns**:
- `ProcessStatusResponse` - Status information about the specific process.
**Example**:
```python
xvfb_status = await sandbox.computer_use.get_process_status("xvfb")
no_vnc_status = await sandbox.computer_use.get_process_status("novnc")
```
#### AsyncComputerUse.restart\_process
```python
@intercept_errors(message_prefix="Failed to restart process: ")
@with_instrumentation()
async def restart_process(process_name: str) -> ProcessRestartResponse
```
Restarts a specific VNC process.
**Arguments**:
- `process_name` _str_ - Name of the process to restart.
**Returns**:
- `ProcessRestartResponse` - Process restart response.
**Example**:
```python
result = await sandbox.computer_use.restart_process("xfce4")
print("XFCE4 process restarted:", result.message)
```
#### AsyncComputerUse.get\_process\_logs
```python
@intercept_errors(message_prefix="Failed to get process logs: ")
@with_instrumentation()
async def get_process_logs(process_name: str) -> ProcessLogsResponse
```
Gets logs for a specific VNC process.
**Arguments**:
- `process_name` _str_ - Name of the process to get logs for.
**Returns**:
- `ProcessLogsResponse` - Process logs.
**Example**:
```python
logs = await sandbox.computer_use.get_process_logs("novnc")
print("NoVNC logs:", logs)
```
#### AsyncComputerUse.get\_process\_errors
```python
@intercept_errors(message_prefix="Failed to get process errors: ")
@with_instrumentation()
async def get_process_errors(process_name: str) -> ProcessErrorsResponse
```
Gets error logs for a specific VNC process.
**Arguments**:
- `process_name` _str_ - Name of the process to get error logs for.
**Returns**:
- `ProcessErrorsResponse` - Process error logs.
**Example**:
```python
errors = await sandbox.computer_use.get_process_errors("x11vnc")
print("X11VNC errors:", errors)
```
## AsyncMouse
```python
class AsyncMouse()
```
Mouse operations for computer use functionality.
#### AsyncMouse.get\_position
```python
@intercept_errors(message_prefix="Failed to get mouse position: ")
@with_instrumentation()
async def get_position() -> MousePositionResponse
```
Gets the current mouse cursor position.
**Returns**:
- `MousePositionResponse` - Current mouse position with x and y coordinates.
**Example**:
```python
position = await sandbox.computer_use.mouse.get_position()
print(f"Mouse is at: {position.x}, {position.y}")
```
#### AsyncMouse.move
```python
@intercept_errors(message_prefix="Failed to move mouse: ")
@with_instrumentation()
async def move(x: int, y: int) -> MousePositionResponse
```
Moves the mouse cursor to the specified coordinates.
**Arguments**:
- `x` _int_ - The x coordinate to move to.
- `y` _int_ - The y coordinate to move to.
**Returns**:
- `MousePositionResponse` - Position after move.
**Example**:
```python
result = await sandbox.computer_use.mouse.move(100, 200)
print(f"Mouse moved to: {result.x}, {result.y}")
```
#### AsyncMouse.click
```python
@intercept_errors(message_prefix="Failed to click mouse: ")
@with_instrumentation()
async def click(x: int,
y: int,
button: str = "left",
double: bool = False) -> MouseClickResponse
```
Clicks the mouse at the specified coordinates.
**Arguments**:
- `x` _int_ - The x coordinate to click at.
- `y` _int_ - The y coordinate to click at.
- `button` _str_ - The mouse button to click ('left', 'right', 'middle').
- `double` _bool_ - Whether to perform a double-click.
**Returns**:
- `MouseClickResponse` - Click operation result.
**Example**:
```python
# Single left click
result = await sandbox.computer_use.mouse.click(100, 200)
# Double click
double_click = await sandbox.computer_use.mouse.click(100, 200, "left", True)
# Right click
right_click = await sandbox.computer_use.mouse.click(100, 200, "right")
```
#### AsyncMouse.drag
```python
@intercept_errors(message_prefix="Failed to drag mouse: ")
@with_instrumentation()
async def drag(start_x: int,
start_y: int,
end_x: int,
end_y: int,
button: str = "left") -> MouseDragResponse
```
Drags the mouse from start coordinates to end coordinates.
**Arguments**:
- `start_x` _int_ - The starting x coordinate.
- `start_y` _int_ - The starting y coordinate.
- `end_x` _int_ - The ending x coordinate.
- `end_y` _int_ - The ending y coordinate.
- `button` _str_ - The mouse button to use for dragging.
**Returns**:
- `MouseDragResponse` - Drag operation result.
**Example**:
```python
result = await sandbox.computer_use.mouse.drag(50, 50, 150, 150)
print(f"Dragged from {result.from_x},{result.from_y} to {result.to_x},{result.to_y}")
```
#### AsyncMouse.scroll
```python
@intercept_errors(message_prefix="Failed to scroll mouse: ")
@with_instrumentation()
async def scroll(x: int, y: int, direction: str, amount: int = 1) -> bool
```
Scrolls the mouse wheel at the specified coordinates.
**Arguments**:
- `x` _int_ - The x coordinate to scroll at.
- `y` _int_ - The y coordinate to scroll at.
- `direction` _str_ - The direction to scroll ('up' or 'down').
- `amount` _int_ - The amount to scroll.
**Returns**:
- `bool` - Whether the scroll operation was successful.
**Example**:
```python
# Scroll up
scroll_up = await sandbox.computer_use.mouse.scroll(100, 200, "up", 3)
# Scroll down
scroll_down = await sandbox.computer_use.mouse.scroll(100, 200, "down", 5)
```
## AsyncKeyboard
```python
class AsyncKeyboard()
```
Keyboard operations for computer use functionality.
#### AsyncKeyboard.type
```python
@intercept_errors(message_prefix="Failed to type text: ")
@with_instrumentation()
async def type(text: str, delay: int | None = None) -> None
```
Types the specified text.
**Arguments**:
- `text` _str_ - The text to type.
- `delay` _int_ - Delay between characters in milliseconds.
**Raises**:
- `DaytonaError` - If the type operation fails.
**Example**:
```python
try:
await sandbox.computer_use.keyboard.type("Hello, World!")
print(f"Operation success")
except Exception as e:
print(f"Operation failed: {e}")
# With delay between characters
try:
await sandbox.computer_use.keyboard.type("Slow typing", 100)
print(f"Operation success")
except Exception as e:
print(f"Operation failed: {e}")
```
#### AsyncKeyboard.press
```python
@intercept_errors(message_prefix="Failed to press key: ")
@with_instrumentation()
async def press(key: str, modifiers: list[str] | None = None) -> None
```
Presses a key with optional modifiers.
**Arguments**:
- `key` _str_ - The key to press (e.g., 'Enter', 'Escape', 'Tab', 'a', 'A').
- `modifiers` _list[str]_ - Modifier keys ('ctrl', 'alt', 'meta', 'shift').
**Raises**:
- `DaytonaError` - If the press operation fails.
**Example**:
```python
# Press Enter
try:
await sandbox.computer_use.keyboard.press("Return")
print(f"Operation success")
except Exception as e:
print(f"Operation failed: {e}")
# Press Ctrl+C
try:
await sandbox.computer_use.keyboard.press("c", ["ctrl"])
print(f"Operation success")
# Press Ctrl+Shift+T
try:
await sandbox.computer_use.keyboard.press("t", ["ctrl", "shift"])
print(f"Operation success")
except Exception as e:
print(f"Operation failed: {e}")
```
#### AsyncKeyboard.hotkey
```python
@intercept_errors(message_prefix="Failed to press hotkey: ")
@with_instrumentation()
async def hotkey(keys: str) -> None
```
Presses a hotkey combination.
**Arguments**:
- `keys` _str_ - The hotkey combination (e.g., 'ctrl+c', 'alt+tab', 'cmd+shift+t').
**Raises**:
- `DaytonaError` - If the hotkey operation fails.
**Example**:
```python
# Copy
try:
await sandbox.computer_use.keyboard.hotkey("ctrl+c")
print(f"Operation success")
except Exception as e:
print(f"Operation failed: {e}")
# Paste
try:
await sandbox.computer_use.keyboard.hotkey("ctrl+v")
print(f"Operation success")
except Exception as e:
print(f"Operation failed: {e}")
# Alt+Tab
try:
await sandbox.computer_use.keyboard.hotkey("alt+tab")
print(f"Operation success")
except Exception as e:
print(f"Operation failed: {e}")
```
## AsyncScreenshot
```python
class AsyncScreenshot()
```
Screenshot operations for computer use functionality.
#### AsyncScreenshot.take\_full\_screen
```python
@intercept_errors(message_prefix="Failed to take screenshot: ")
@with_instrumentation()
async def take_full_screen(show_cursor: bool = False) -> ScreenshotResponse
```
Takes a screenshot of the entire screen.
**Arguments**:
- `show_cursor` _bool_ - Whether to show the cursor in the screenshot.
**Returns**:
- `ScreenshotResponse` - Screenshot data with base64 encoded image.
**Example**:
```python
screenshot = await sandbox.computer_use.screenshot.take_full_screen()
print(f"Screenshot size: {screenshot.width}x{screenshot.height}")
# With cursor visible
with_cursor = await sandbox.computer_use.screenshot.take_full_screen(True)
```
#### AsyncScreenshot.take\_region
```python
@intercept_errors(message_prefix="Failed to take region screenshot: ")
@with_instrumentation()
async def take_region(region: ScreenshotRegion,
show_cursor: bool = False) -> ScreenshotResponse
```
Takes a screenshot of a specific region.
**Arguments**:
- `region` _ScreenshotRegion_ - The region to capture.
- `show_cursor` _bool_ - Whether to show the cursor in the screenshot.
**Returns**:
- `ScreenshotResponse` - Screenshot data with base64 encoded image.
**Example**:
```python
region = ScreenshotRegion(x=100, y=100, width=300, height=200)
screenshot = await sandbox.computer_use.screenshot.take_region(region)
print(f"Captured region: {screenshot.region.width}x{screenshot.region.height}")
```
#### AsyncScreenshot.take\_compressed
```python
@intercept_errors(message_prefix="Failed to take compressed screenshot: ")
@with_instrumentation()
async def take_compressed(
options: ScreenshotOptions | None = None) -> ScreenshotResponse
```
Takes a compressed screenshot of the entire screen.
**Arguments**:
- `options` _ScreenshotOptions | None_ - Compression and display options.
**Returns**:
- `ScreenshotResponse` - Compressed screenshot data.
**Example**:
```python
# Default compression
screenshot = await sandbox.computer_use.screenshot.take_compressed()
# High quality JPEG
jpeg = await sandbox.computer_use.screenshot.take_compressed(
ScreenshotOptions(format="jpeg", quality=95, show_cursor=True)
)
# Scaled down PNG
scaled = await sandbox.computer_use.screenshot.take_compressed(
ScreenshotOptions(format="png", scale=0.5)
)
```
#### AsyncScreenshot.take\_compressed\_region
```python
@intercept_errors(
message_prefix="Failed to take compressed region screenshot: ")
@with_instrumentation()
async def take_compressed_region(
region: ScreenshotRegion,
options: ScreenshotOptions | None = None) -> ScreenshotResponse
```
Takes a compressed screenshot of a specific region.
**Arguments**:
- `region` _ScreenshotRegion_ - The region to capture.
- `options` _ScreenshotOptions | None_ - Compression and display options.
**Returns**:
- `ScreenshotResponse` - Compressed screenshot data.
**Example**:
```python
region = ScreenshotRegion(x=0, y=0, width=800, height=600)
screenshot = await sandbox.computer_use.screenshot.take_compressed_region(
region,
ScreenshotOptions(format="webp", quality=80, show_cursor=True)
)
print(f"Compressed size: {screenshot.size_bytes} bytes")
```
## AsyncDisplay
```python
class AsyncDisplay()
```
Display operations for computer use functionality.
#### AsyncDisplay.get\_info
```python
@intercept_errors(message_prefix="Failed to get display info: ")
@with_instrumentation()
async def get_info() -> DisplayInfoResponse
```
Gets information about the displays.
**Returns**:
- `DisplayInfoResponse` - Display information including primary display and all available displays.
**Example**:
```python
info = await sandbox.computer_use.display.get_info()
print(f"Primary display: {info.primary_display.width}x{info.primary_display.height}")
print(f"Total displays: {info.total_displays}")
for i, display in enumerate(info.displays):
print(f"Display {i}: {display.width}x{display.height} at {display.x},{display.y}")
```
#### AsyncDisplay.get\_windows
```python
@intercept_errors(message_prefix="Failed to get windows: ")
@with_instrumentation()
async def get_windows() -> WindowsResponse
```
Gets the list of open windows.
**Returns**:
- `WindowsResponse` - List of open windows with their IDs and titles.
**Example**:
```python
windows = await sandbox.computer_use.display.get_windows()
print(f"Found {windows.count} open windows:")
for window in windows.windows:
print(f"- {window.title} (ID: {window.id})")
```
## AsyncRecordingService
```python
class AsyncRecordingService()
```
Recording operations for computer use functionality.
#### AsyncRecordingService.start
```python
@intercept_errors(message_prefix="Failed to start recording: ")
@with_instrumentation()
async def start(label: str | None = None) -> Recording
```
Starts a new screen recording session.
**Arguments**:
- `label` _str | None_ - Optional custom label for the recording.
**Returns**:
- `Recording` - Recording start response.
**Example**:
```python
# Start a recording with a label
recording = await sandbox.computer_use.recording.start("my-test-recording")
print(f"Recording started: {recording.id}")
print(f"File: {recording.file_path}")
```
#### AsyncRecordingService.stop
```python
@intercept_errors(message_prefix="Failed to stop recording: ")
@with_instrumentation()
async def stop(recording_id: str) -> Recording
```
Stops an active screen recording session.
**Arguments**:
- `recording_id` _str_ - The ID of the recording to stop.
**Returns**:
- `Recording` - Recording stop response.
**Example**:
```python
result = await sandbox.computer_use.recording.stop(recording.id)
print(f"Recording stopped: {result.duration_seconds} seconds")
print(f"Saved to: {result.file_path}")
```
#### AsyncRecordingService.list
```python
@intercept_errors(message_prefix="Failed to list recordings: ")
@with_instrumentation()
async def list() -> ListRecordingsResponse
```
Lists all recordings (active and completed).
**Returns**:
- `ListRecordingsResponse` - List of all recordings.
**Example**:
```python
recordings = await sandbox.computer_use.recording.list()
print(f"Found {len(recordings.recordings)} recordings")
for rec in recordings.recordings:
print(f"- {rec.file_name}: {rec.status}")
```
#### AsyncRecordingService.get
```python
@intercept_errors(message_prefix="Failed to get recording: ")
@with_instrumentation()
async def get(recording_id: str) -> Recording
```
Gets details of a specific recording by ID.
**Arguments**:
- `recording_id` _str_ - The ID of the recording to retrieve.
**Returns**:
- `Recording` - Recording details.
**Example**:
```python
recording = await sandbox.computer_use.recording.get(recording_id)
print(f"Recording: {recording.file_name}")
print(f"Status: {recording.status}")
print(f"Duration: {recording.duration_seconds} seconds")
```
#### AsyncRecordingService.delete
```python
@intercept_errors(message_prefix="Failed to delete recording: ")
@with_instrumentation()
async def delete(recording_id: str) -> None
```
Deletes a recording by ID.
**Arguments**:
- `recording_id` _str_ - The ID of the recording to delete.
**Example**:
```python
await sandbox.computer_use.recording.delete(recording_id)
print("Recording deleted")
```
#### AsyncRecordingService.download
```python
@intercept_errors(message_prefix="Failed to download recording: ")
@with_instrumentation()
async def download(recording_id: str, local_path: str) -> None
```
Downloads a recording file from the Sandbox and saves it to a local file.
The file is streamed directly to disk without loading the entire content into memory.
**Arguments**:
- `recording_id` _str_ - The ID of the recording to download.
- `local_path` _str_ - Path to save the recording file locally.
**Example**:
```python
# Download recording to file
await sandbox.computer_use.recording.download(recording_id, "local_recording.mp4")
print("Recording downloaded")
```
## ScreenshotRegion
```python
class ScreenshotRegion(BaseModel)
```
Region coordinates for screenshot operations.
**Attributes**:
- `x` _int_ - X coordinate of the region.
- `y` _int_ - Y coordinate of the region.
- `width` _int_ - Width of the region.
- `height` _int_ - Height of the region.
## ScreenshotOptions
```python
class ScreenshotOptions(BaseModel)
```
Options for screenshot compression and display.
**Attributes**:
- `show_cursor` _bool | None_ - Whether to show the cursor in the screenshot.
- `fmt` _str | None_ - Image format (e.g., 'png', 'jpeg', 'webp').
- `quality` _int | None_ - Compression quality (0-100).
- `scale` _float | None_ - Scale factor for the screenshot.
## AsyncDaytona
```python
class AsyncDaytona()
```
Main class for interacting with the Daytona API.
This class provides asynchronous methods to create, manage, and interact with Daytona Sandboxes.
It can be initialized either with explicit configuration or using environment variables.
**Attributes**:
- `volume` _AsyncVolumeService_ - Service for managing volumes.
- `snapshot` _AsyncSnapshotService_ - Service for managing snapshots.
**Example**:
Using environment variables:
```python
async with AsyncDaytona() as daytona: # Uses DAYTONA_API_KEY, DAYTONA_API_URL
sandbox = await daytona.create()
```
Using explicit configuration:
```python
config = DaytonaConfig(
api_key="your-api-key",
api_url="https://your-api.com",
target="us"
)
try:
daytona = AsyncDaytona(config)
sandbox = await daytona.create()
finally:
await daytona.close()
```
Using OpenTelemetry tracing:
```python
config = DaytonaConfig(
api_key="your-api-key",
experimental={"otelEnabled": True}
)
async with AsyncDaytona(config) as daytona:
sandbox = await daytona.create()
# All SDK operations will be traced
# OpenTelemetry traces are flushed on close
```
#### AsyncDaytona.\_\_init\_\_
```python
def __init__(config: DaytonaConfig | None = None)
```
Initializes Daytona instance with optional configuration.
If no config is provided, reads from environment variables:
- `DAYTONA_API_KEY`: Required API key for authentication
- `DAYTONA_API_URL`: Required api URL
- `DAYTONA_TARGET`: Optional target environment (if not provided, default region for the organization is used)
**Arguments**:
- `config` _DaytonaConfig | None_ - Object containing api_key, api_url, and target.
**Raises**:
- `DaytonaError` - If API key is not provided either through config or environment variables
**Example**:
```python
from daytona import Daytona, DaytonaConfig
# Using environment variables
daytona1 = AsyncDaytona()
await daytona1.close()
# Using explicit configuration
config = DaytonaConfig(
api_key="your-api-key",
api_url="https://your-api.com",
target="us"
)
daytona2 = AsyncDaytona(config)
await daytona2.close()
```
#### AsyncDaytona.\_\_aenter\_\_
```python
async def __aenter__()
```
Async context manager entry.
#### AsyncDaytona.\_\_aexit\_\_
```python
async def __aexit__(exc_type: type[BaseException] | None = None,
exc_value: BaseException | None = None,
traceback: TracebackType | None = None)
```
Async context manager exit - ensures proper cleanup.
#### AsyncDaytona.close
```python
async def close()
```
Close the HTTP session and clean up resources.
This method should be called when you're done using the AsyncDaytona instance
to properly close the underlying HTTP sessions and avoid resource leaks.
**Example**:
```python
daytona = AsyncDaytona()
try:
sandbox = await daytona.create()
# ... use sandbox ...
finally:
await daytona.close()
```
Or better yet, use as async context manager:
```python
async with AsyncDaytona() as daytona:
sandbox = await daytona.create()
# ... use sandbox ...
# Automatically closed
```
#### AsyncDaytona.create
```python
@overload
async def create(params: CreateSandboxFromSnapshotParams | None = None,
*,
timeout: float = 60) -> AsyncSandbox
```
Creates Sandboxes from specified or default snapshot. You can specify various parameters,
including language, image, environment variables, and volumes.
**Arguments**:
- `params` _CreateSandboxFromSnapshotParams | None_ - Parameters for Sandbox creation. If not provided,
defaults to default Daytona snapshot and Python language.
- `timeout` _float_ - Timeout (in seconds) for sandbox creation. 0 means no timeout.
Default is 60 seconds.
**Returns**:
- `Sandbox` - The created Sandbox instance.
**Raises**:
- `DaytonaError` - If timeout, auto_stop_interval or auto_archive_interval is negative;
If sandbox fails to start or times out
**Example**:
Create a default Python Sandbox:
```python
sandbox = await daytona.create()
```
Create a custom Sandbox:
```python
params = CreateSandboxFromSnapshotParams(
language="python",
snapshot="my-snapshot-id",
env_vars={"DEBUG": "true"},
auto_stop_interval=0,
auto_archive_interval=60,
auto_delete_interval=120
)
sandbox = await daytona.create(params, timeout=40)
```
#### AsyncDaytona.create
```python
@overload
async def create(
params: CreateSandboxFromImageParams | None = None,
*,
timeout: float = 60,
on_snapshot_create_logs: Callable[[str], None] | None = None
) -> AsyncSandbox
```
Creates Sandboxes from specified image available on some registry or declarative Daytona Image.
You can specify various parameters, including resources, language, image, environment variables,
and volumes. Daytona creates snapshot from provided image and uses it to create Sandbox.
**Arguments**:
- `params` _CreateSandboxFromImageParams | None_ - Parameters for Sandbox creation from image.
- `timeout` _float_ - Timeout (in seconds) for sandbox creation. 0 means no timeout.
Default is 60 seconds.
- `on_snapshot_create_logs` _Callable[[str], None] | None_ - This callback function
handles snapshot creation logs.
**Returns**:
- `Sandbox` - The created Sandbox instance.
**Raises**:
- `DaytonaError` - If timeout, auto_stop_interval or auto_archive_interval is negative;
If sandbox fails to start or times out
**Example**:
Create a default Python Sandbox from image:
```python
sandbox = await daytona.create(CreateSandboxFromImageParams(image="debian:12.9"))
```
Create a custom Sandbox from declarative Image definition:
```python
declarative_image = (
Image.base("alpine:3.18")
.pipInstall(["numpy", "pandas"])
.env({"MY_ENV_VAR": "My Environment Variable"})
)
params = CreateSandboxFromImageParams(
language="python",
image=declarative_image,
env_vars={"DEBUG": "true"},
resources=Resources(cpu=2, memory=4),
auto_stop_interval=0,
auto_archive_interval=60,
auto_delete_interval=120
)
sandbox = await daytona.create(
params,
timeout=40,
on_snapshot_create_logs=lambda chunk: print(chunk, end=""),
)
```
#### AsyncDaytona.delete
```python
@with_instrumentation()
async def delete(sandbox: AsyncSandbox, timeout: float = 60) -> None
```
Deletes a Sandbox.
**Arguments**:
- `sandbox` _Sandbox_ - The Sandbox instance to delete.
- `timeout` _float_ - Timeout (in seconds) for sandbox deletion. 0 means no timeout.
Default is 60 seconds.
**Raises**:
- `DaytonaError` - If sandbox fails to delete or times out
**Example**:
```python
sandbox = await daytona.create()
# ... use sandbox ...
await daytona.delete(sandbox) # Clean up when done
```
#### AsyncDaytona.get
```python
@intercept_errors(message_prefix="Failed to get sandbox: ")
@with_instrumentation()
async def get(sandbox_id_or_name: str) -> AsyncSandbox
```
Gets a Sandbox by its ID or name.
**Arguments**:
- `sandbox_id_or_name` _str_ - The ID or name of the Sandbox to retrieve.
**Returns**:
- `Sandbox` - The Sandbox instance.
**Raises**:
- `DaytonaError` - If sandbox_id_or_name is not provided.
**Example**:
```python
sandbox = await daytona.get("my-sandbox-id-or-name")
print(sandbox.state)
```
#### AsyncDaytona.list
```python
@intercept_errors(message_prefix="Failed to list sandboxes: ")
@with_instrumentation()
async def list(labels: dict[str, str] | None = None,
page: int | None = None,
limit: int | None = None) -> AsyncPaginatedSandboxes
```
Returns paginated list of Sandboxes filtered by labels.
**Arguments**:
- `labels` _dict[str, str] | None_ - Labels to filter Sandboxes.
- `page` _int | None_ - Page number for pagination (starting from 1).
- `limit` _int | None_ - Maximum number of items per page.
**Returns**:
- `AsyncPaginatedSandboxes` - Paginated list of Sandbox instances that match the labels.
**Example**:
```python
result = await daytona.list(labels={"my-label": "my-value"}, page=2, limit=10)
for sandbox in result.items:
print(f"{sandbox.id}: {sandbox.state}")
```
#### AsyncDaytona.start
```python
@with_instrumentation()
async def start(sandbox: AsyncSandbox, timeout: float = 60) -> None
```
Starts a Sandbox and waits for it to be ready.
**Arguments**:
- `sandbox` _Sandbox_ - The Sandbox to start.
- `timeout` _float_ - Optional timeout in seconds to wait for the Sandbox to start.
0 means no timeout. Default is 60 seconds.
**Raises**:
- `DaytonaError` - If timeout is negative; If Sandbox fails to start or times out
#### AsyncDaytona.stop
```python
@with_instrumentation()
async def stop(sandbox: AsyncSandbox, timeout: float = 60) -> None
```
Stops a Sandbox and waits for it to be stopped.
**Arguments**:
- `sandbox` _Sandbox_ - The sandbox to stop
- `timeout` _float_ - Optional timeout (in seconds) for sandbox stop.
0 means no timeout. Default is 60 seconds.
**Raises**:
- `DaytonaError` - If timeout is negative; If Sandbox fails to stop or times out
## CodeLanguage
```python
class CodeLanguage(str, Enum)
```
Programming languages supported by Daytona
**Enum Members**:
- `PYTHON` ("python")
- `TYPESCRIPT` ("typescript")
- `JAVASCRIPT` ("javascript")
## DaytonaConfig
```python
class DaytonaConfig(BaseModel)
```
Configuration options for initializing the Daytona client.
**Attributes**:
- `api_key` _str | None_ - API key for authentication with the Daytona API. If not set, it must be provided
via the environment variable `DAYTONA_API_KEY`, or a JWT token must be provided instead.
- `jwt_token` _str | None_ - JWT token for authentication with the Daytona API. If not set, it must be provided
via the environment variable `DAYTONA_JWT_TOKEN`, or an API key must be provided instead.
- `organization_id` _str | None_ - Organization ID used for JWT-based authentication. Required if a JWT token
is provided, and must be set either here or in the environment variable `DAYTONA_ORGANIZATION_ID`.
- `api_url` _str | None_ - URL of the Daytona API. Defaults to `'https://app.daytona.io/api'` if not set
here or in the environment variable `DAYTONA_API_URL`.
- `server_url` _str | None_ - Deprecated. Use `api_url` instead. This property will be removed
in a future version.
- `target` _str | None_ - Target runner location for the Sandbox. Default region for the organization is used
if not set here or in the environment variable `DAYTONA_TARGET`.
- `_experimental` _dict[str, any] | None_ - Configuration for experimental features.
**Example**:
```python
config = DaytonaConfig(api_key="your-api-key")
```
```python
config = DaytonaConfig(jwt_token="your-jwt-token", organization_id="your-organization-id")
```
## CreateSandboxBaseParams
```python
class CreateSandboxBaseParams(BaseModel)
```
Base parameters for creating a new Sandbox.
**Attributes**:
- `name` _str | None_ - Name of the Sandbox.
- `language` _CodeLanguage | CodeLanguageLiteral | None_ - Programming language for the Sandbox.
Defaults to "python".
- `os_user` _str | None_ - OS user for the Sandbox.
- `env_vars` _dict[str, str] | None_ - Environment variables to set in the Sandbox.
- `labels` _dict[str, str] | None_ - Custom labels for the Sandbox.
- `public` _bool | None_ - Whether the Sandbox should be public.
- `timeout` _float | None_ - Timeout in seconds for Sandbox to be created and started.
- `auto_stop_interval` _int | None_ - Interval in minutes after which Sandbox will
automatically stop if no Sandbox event occurs during that time. Default is 15 minutes.
0 means no auto-stop.
- `auto_archive_interval` _int | None_ - Interval in minutes after which a continuously stopped Sandbox will
automatically archive. Default is 7 days.
0 means the maximum interval will be used.
- `auto_delete_interval` _int | None_ - Interval in minutes after which a continuously stopped Sandbox will
automatically be deleted. By default, auto-delete is disabled.
Negative value means disabled, 0 means delete immediately upon stopping.
- `volumes` _list[VolumeMount] | None_ - List of volumes mounts to attach to the Sandbox.
- `network_block_all` _bool | None_ - Whether to block all network access for the Sandbox.
- `network_allow_list` _str | None_ - Comma-separated list of allowed CIDR network addresses for the Sandbox.
- `ephemeral` _bool | None_ - Whether the Sandbox should be ephemeral.
If True, auto_delete_interval will be set to 0.
## CreateSandboxFromImageParams
```python
class CreateSandboxFromImageParams(CreateSandboxBaseParams)
```
Parameters for creating a new Sandbox from an image.
**Attributes**:
- `image` _str | Image_ - Custom Docker image to use for the Sandbox. If an Image object is provided,
the image will be dynamically built.
- `resources` _Resources | None_ - Resource configuration for the Sandbox. If not provided, sandbox will
have default resources.
## CreateSandboxFromSnapshotParams
```python
class CreateSandboxFromSnapshotParams(CreateSandboxBaseParams)
```
Parameters for creating a new Sandbox from a snapshot.
**Attributes**:
- `snapshot` _str | None_ - Name of the snapshot to use for the Sandbox.
## AsyncFileSystem
```python
class AsyncFileSystem()
```
Provides file system operations within a Sandbox.
This class implements a high-level interface to file system operations that can
be performed within a Daytona Sandbox.
#### AsyncFileSystem.\_\_init\_\_
```python
def __init__(api_client: FileSystemApi)
```
Initializes a new FileSystem instance.
**Arguments**:
- `api_client` _FileSystemApi_ - API client for Sandbox file system operations.
#### AsyncFileSystem.create\_folder
```python
@intercept_errors(message_prefix="Failed to create folder: ")
@with_instrumentation()
async def create_folder(path: str, mode: str) -> None
```
Creates a new directory in the Sandbox at the specified path with the given
permissions.
**Arguments**:
- `path` _str_ - Path where the folder should be created. Relative paths are resolved based
on the sandbox working directory.
- `mode` _str_ - Folder permissions in octal format (e.g., "755" for rwxr-xr-x).
**Example**:
```python
# Create a directory with standard permissions
await sandbox.fs.create_folder("workspace/data", "755")
# Create a private directory
await sandbox.fs.create_folder("workspace/secrets", "700")
```
#### AsyncFileSystem.delete\_file
```python
@intercept_errors(message_prefix="Failed to delete file: ")
@with_instrumentation()
async def delete_file(path: str, recursive: bool = False) -> None
```
Deletes a file from the Sandbox.
**Arguments**:
- `path` _str_ - Path to the file to delete. Relative paths are resolved based on the sandbox working directory.
- `recursive` _bool_ - If the file is a directory, this must be true to delete it.
**Example**:
```python
# Delete a file
await sandbox.fs.delete_file("workspace/data/old_file.txt")
```
#### AsyncFileSystem.download\_file
```python
@overload
async def download_file(remote_path: str, timeout: int = 30 * 60) -> bytes
```
Downloads a file from the Sandbox. Returns the file contents as a bytes object.
This method is useful when you want to load the file into memory without saving it to disk.
It can only be used for smaller files.
**Arguments**:
- `remote_path` _str_ - Path to the file in the Sandbox. Relative paths are resolved based
on the sandbox working directory.
- `timeout` _int_ - Timeout for the download operation in seconds. 0 means no timeout. Default is 30 minutes.
**Returns**:
- `bytes` - The file contents as a bytes object.
**Example**:
```python
# Download and save a file locally
content = await sandbox.fs.download_file("workspace/data/file.txt")
with open("local_copy.txt", "wb") as f:
f.write(content)
# Download and process text content
content = await sandbox.fs.download_file("workspace/data/config.json")
config = json.loads(content.decode('utf-8'))
```
#### AsyncFileSystem.download\_file
```python
@overload
async def download_file(remote_path: str,
local_path: str,
timeout: int = 30 * 60) -> None
```
Downloads a file from the Sandbox and saves it to a local file using stream.
This method is useful when you want to download larger files that may not fit into memory.
**Arguments**:
- `remote_path` _str_ - Path to the file in the Sandbox. Relative paths are resolved based
on the sandbox working directory.
- `local_path` _str_ - Path to save the file locally.
- `timeout` _int_ - Timeout for the download operation in seconds. 0 means no timeout. Default is 30 minutes.
**Example**:
```python
local_path = "local_copy.txt"
await sandbox.fs.download_file("tmp/large_file.txt", local_path)
size_mb = os.path.getsize(local_path) / 1024 / 1024
print(f"Size of the downloaded file {local_path}: {size_mb} MB")
```
#### AsyncFileSystem.download\_files
```python
@intercept_errors(message_prefix="Failed to download files: ")
@with_instrumentation()
async def download_files(files: list[FileDownloadRequest],
timeout: int = 30 * 60) -> list[FileDownloadResponse]
```
Downloads multiple files from the Sandbox. If the files already exist locally, they will be overwritten.
**Arguments**:
- `files` _list[FileDownloadRequest]_ - List of files to download.
- `timeout` _int_ - Timeout for the download operation in seconds. 0 means no timeout. Default is 30 minutes.
**Returns**:
- `list[FileDownloadResponse]` - List of download results.
**Raises**:
- `Exception` - Only if the request itself fails (network issues, invalid request/response, etc.). Individual
file download errors are returned in the `FileDownloadResponse.error` field.
**Example**:
```python
# Download multiple files
results = await sandbox.fs.download_files([
FileDownloadRequest(source="tmp/data.json"),
FileDownloadRequest(source="tmp/config.json", destination="local_config.json")
])
for result in results:
if result.error:
print(f"Error downloading {result.source}: {result.error}")
elif result.result:
print(f"Downloaded {result.source} to {result.result}")
```
#### AsyncFileSystem.find\_files
```python
@intercept_errors(message_prefix="Failed to find files: ")
@with_instrumentation()
async def find_files(path: str, pattern: str) -> list[Match]
```
Searches for files containing a pattern, similar to
the grep command.
**Arguments**:
- `path` _str_ - Path to the file or directory to search. If the path is a directory,
the search will be performed recursively. Relative paths are resolved based
on the sandbox working directory.
- `pattern` _str_ - Search pattern to match against file contents.
**Returns**:
- `list[Match]` - List of matches found in files. Each Match object includes:
- file: Path to the file containing the match
- line: The line number where the match was found
- content: The matching line content
**Example**:
```python
# Search for TODOs in Python files
matches = await sandbox.fs.find_files("workspace/src", "TODO:")
for match in matches:
print(f"{match.file}:{match.line}: {match.content.strip()}")
```
#### AsyncFileSystem.get\_file\_info
```python
@intercept_errors(message_prefix="Failed to get file info: ")
@with_instrumentation()
async def get_file_info(path: str) -> FileInfo
```
Gets detailed information about a file or directory, including its
size, permissions, and timestamps.
**Arguments**:
- `path` _str_ - Path to the file or directory. Relative paths are resolved based
on the sandbox working directory.
**Returns**:
- `FileInfo` - Detailed file information including:
- name: File name
- is_dir: Whether the path is a directory
- size: File size in bytes
- mode: File permissions
- mod_time: Last modification timestamp
- permissions: File permissions in octal format
- owner: File owner
- group: File group
**Example**:
```python
# Get file metadata
info = await sandbox.fs.get_file_info("workspace/data/file.txt")
print(f"Size: {info.size} bytes")
print(f"Modified: {info.mod_time}")
print(f"Mode: {info.mode}")
# Check if path is a directory
info = await sandbox.fs.get_file_info("workspace/data")
if info.is_dir:
print("Path is a directory")
```
#### AsyncFileSystem.list\_files
```python
@intercept_errors(message_prefix="Failed to list files: ")
@with_instrumentation()
async def list_files(path: str) -> list[FileInfo]
```
Lists files and directories in a given path and returns their information, similar to the ls -l command.
**Arguments**:
- `path` _str_ - Path to the directory to list contents from. Relative paths are resolved
based on the sandbox working directory.
**Returns**:
- `list[FileInfo]` - List of file and directory information. Each FileInfo
object includes the same fields as described in get_file_info().
**Example**:
```python
# List directory contents
files = await sandbox.fs.list_files("workspace/data")
# Print files and their sizes
for file in files:
if not file.is_dir:
print(f"{file.name}: {file.size} bytes")
# List only directories
dirs = [f for f in files if f.is_dir]
print("Subdirectories:", ", ".join(d.name for d in dirs))
```
#### AsyncFileSystem.move\_files
```python
@intercept_errors(message_prefix="Failed to move files: ")
@with_instrumentation()
async def move_files(source: str, destination: str) -> None
```
Moves or renames a file or directory. The parent directory of the destination must exist.
**Arguments**:
- `source` _str_ - Path to the source file or directory. Relative paths are resolved
based on the sandbox working directory.
- `destination` _str_ - Path to the destination. Relative paths are resolved based on
the sandbox working directory.
**Example**:
```python
# Rename a file
await sandbox.fs.move_files(
"workspace/data/old_name.txt",
"workspace/data/new_name.txt"
)
# Move a file to a different directory
await sandbox.fs.move_files(
"workspace/data/file.txt",
"workspace/archive/file.txt"
)
# Move a directory
await sandbox.fs.move_files(
"workspace/old_dir",
"workspace/new_dir"
)
```
#### AsyncFileSystem.replace\_in\_files
```python
@intercept_errors(message_prefix="Failed to replace in files: ")
@with_instrumentation()
async def replace_in_files(files: list[str], pattern: str,
new_value: str) -> list[ReplaceResult]
```
Performs search and replace operations across multiple files.
**Arguments**:
- `files` _list[str]_ - List of file paths to perform replacements in. Relative paths are
resolved based on the sandbox working directory.
- `pattern` _str_ - Pattern to search for.
- `new_value` _str_ - Text to replace matches with.
**Returns**:
- `list[ReplaceResult]` - List of results indicating replacements made in
each file. Each ReplaceResult includes:
- file: Path to the modified file
- success: Whether the operation was successful
- error: Error message if the operation failed
**Example**:
```python
# Replace in specific files
results = await sandbox.fs.replace_in_files(
files=["workspace/src/file1.py", "workspace/src/file2.py"],
pattern="old_function",
new_value="new_function"
)
# Print results
for result in results:
if result.success:
print(f"{result.file}: {result.success}")
else:
print(f"{result.file}: {result.error}")
```
#### AsyncFileSystem.search\_files
```python
@intercept_errors(message_prefix="Failed to search files: ")
@with_instrumentation()
async def search_files(path: str, pattern: str) -> SearchFilesResponse
```
Searches for files and directories whose names match the
specified pattern. The pattern can be a simple string or a glob pattern.
**Arguments**:
- `path` _str_ - Path to the root directory to start search from. Relative paths are resolved
based on the sandbox working directory.
- `pattern` _str_ - Pattern to match against file names. Supports glob
patterns (e.g., "*.py" for Python files).
**Returns**:
- `SearchFilesResponse` - Search results containing:
- files: List of matching file and directory paths
**Example**:
```python
# Find all Python files
result = await sandbox.fs.search_files("workspace", "*.py")
for file in result.files:
print(file)
# Find files with specific prefix
result = await sandbox.fs.search_files("workspace/data", "test_*")
print(f"Found {len(result.files)} test files")
```
#### AsyncFileSystem.set\_file\_permissions
```python
@intercept_errors(message_prefix="Failed to set file permissions: ")
@with_instrumentation()
async def set_file_permissions(path: str,
mode: str | None = None,
owner: str | None = None,
group: str | None = None) -> None
```
Sets permissions and ownership for a file or directory. Any of the parameters can be None
to leave that attribute unchanged.
**Arguments**:
- `path` _str_ - Path to the file or directory. Relative paths are resolved based on
the sandbox working directory.
- `mode` _str | None_ - File mode/permissions in octal format
(e.g., "644" for rw-r--r--).
- `owner` _str | None_ - User owner of the file.
- `group` _str | None_ - Group owner of the file.
**Example**:
```python
# Make a file executable
await sandbox.fs.set_file_permissions(
path="workspace/scripts/run.sh",
mode="755" # rwxr-xr-x
)
# Change file owner
await sandbox.fs.set_file_permissions(
path="workspace/data/file.txt",
owner="daytona",
group="daytona"
)
```
#### AsyncFileSystem.upload\_file
```python
@overload
async def upload_file(file: bytes,
remote_path: str,
timeout: int = 30 * 60) -> None
```
Uploads a file to the specified path in the Sandbox. If a file already exists at
the destination path, it will be overwritten. This method is useful when you want to upload
small files that fit into memory.
**Arguments**:
- `file` _bytes_ - File contents as a bytes object.
- `remote_path` _str_ - Path to the destination file. Relative paths are resolved based on
the sandbox working directory.
- `timeout` _int_ - Timeout for the upload operation in seconds. 0 means no timeout. Default is 30 minutes.
**Example**:
```python
# Upload a text file
content = b"Hello, World!"
await sandbox.fs.upload_file(content, "tmp/hello.txt")
# Upload a local file
with open("local_file.txt", "rb") as f:
content = f.read()
await sandbox.fs.upload_file(content, "tmp/file.txt")
# Upload binary data
import json
data = {"key": "value"}
content = json.dumps(data).encode('utf-8')
await sandbox.fs.upload_file(content, "tmp/config.json")
```
#### AsyncFileSystem.upload\_file
```python
@overload
async def upload_file(local_path: str,
remote_path: str,
timeout: int = 30 * 60) -> None
```
Uploads a file from the local file system to the specified path in the Sandbox.
If a file already exists at the destination path, it will be overwritten. This method uses
streaming to upload the file, so it is useful when you want to upload larger files that may
not fit into memory.
**Arguments**:
- `local_path` _str_ - Path to the local file to upload.
- `remote_path` _str_ - Path to the destination file in the Sandbox. Relative paths are
resolved based on the sandbox working directory.
- `timeout` _int_ - Timeout for the upload operation in seconds. 0 means no timeout. Default is 30 minutes.
**Example**:
```python
await sandbox.fs.upload_file("local_file.txt", "tmp/large_file.txt")
```
#### AsyncFileSystem.upload\_files
```python
@intercept_errors(message_prefix="Failed to upload files: ")
@with_instrumentation()
async def upload_files(files: list[FileUpload],
timeout: int = 30 * 60) -> None
```
Uploads multiple files to the Sandbox. If files already exist at the destination paths,
they will be overwritten.
**Arguments**:
- `files` _list[FileUpload]_ - List of files to upload.
- `timeout` _int_ - Timeout for the upload operation in seconds. 0 means no timeout. Default is 30 minutes.
**Example**:
```python
# Upload multiple text files
files = [
FileUpload(
source=b"Content of file 1",
destination="/tmp/file1.txt"
),
FileUpload(
source="workspace/data/file2.txt",
destination="/tmp/file2.txt"
),
FileUpload(
source=b'{"key": "value"}',
destination="/tmp/config.json"
)
]
await sandbox.fs.upload_files(files)
```
## FileUpload
```python
@dataclass
class FileUpload()
```
Represents a file to be uploaded to the Sandbox.
**Attributes**:
- `source` _bytes | str_ - File contents as a bytes object or a local file path. If a bytes object is provided,
make sure it fits into memory, otherwise use the local file path which content will be streamed to the Sandbox.
- `destination` _str_ - Absolute destination path in the Sandbox. Relative paths are resolved based on
the sandbox working directory.
## FileDownloadRequest
```python
@dataclass
class FileDownloadRequest()
```
Represents a request to download a single file from the Sandbox.
**Attributes**:
- `source` _str_ - Source path in the Sandbox. Relative paths are resolved based on the user's
root directory.
- `destination` _str | None_ - Destination path in the local filesystem where the file content will be
streamed to. If not provided, the file will be downloaded in the bytes buffer
(might cause memory issues if the file is large).
## FileDownloadResponse
```python
@dataclass
class FileDownloadResponse()
```
Represents the response to a single file download request.
**Attributes**:
- `source` _str_ - The original source path requested for download.
- `result` _str | bytes | None_ - The download result - file path (if destination provided in the request)
or bytes content (if no destination in the request), None if failed or no data received.
- `error` _str | None_ - Error message if the download failed, None if successful.
## AsyncGit
```python
class AsyncGit()
```
Provides Git operations within a Sandbox.
**Example**:
```python
# Clone a repository
await sandbox.git.clone(
url="https://github.com/user/repo.git",
path="workspace/repo"
)
# Check repository status
status = await sandbox.git.status("workspace/repo")
print(f"Modified files: {status.modified}")
# Stage and commit changes
await sandbox.git.add("workspace/repo", ["file.txt"])
await sandbox.git.commit(
path="workspace/repo",
message="Update file",
author="John Doe",
email="john@example.com"
)
```
#### AsyncGit.\_\_init\_\_
```python
def __init__(api_client: GitApi)
```
Initializes a new Git handler instance.
**Arguments**:
- `api_client` _GitApi_ - API client for Sandbox Git operations.
#### AsyncGit.add
```python
@intercept_errors(message_prefix="Failed to add files: ")
@with_instrumentation()
async def add(path: str, files: list[str]) -> None
```
Stages the specified files for the next commit, similar to
running 'git add' on the command line.
**Arguments**:
- `path` _str_ - Path to the Git repository root. Relative paths are resolved based on
the sandbox working directory.
- `files` _list[str]_ - List of file paths or directories to stage, relative to the repository root.
**Example**:
```python
# Stage a single file
await sandbox.git.add("workspace/repo", ["file.txt"])
# Stage multiple files
await sandbox.git.add("workspace/repo", [
"src/main.py",
"tests/test_main.py",
"README.md"
])
```
#### AsyncGit.branches
```python
@intercept_errors(message_prefix="Failed to list branches: ")
@with_instrumentation()
async def branches(path: str) -> ListBranchResponse
```
Lists branches in the repository.
**Arguments**:
- `path` _str_ - Path to the Git repository root. Relative paths are resolved based on
the sandbox working directory.
**Returns**:
- `ListBranchResponse` - List of branches in the repository.
**Example**:
```python
response = await sandbox.git.branches("workspace/repo")
print(f"Branches: {response.branches}")
```
#### AsyncGit.clone
```python
@intercept_errors(message_prefix="Failed to clone repository: ")
@with_instrumentation()
async def clone(url: str,
path: str,
branch: str | None = None,
commit_id: str | None = None,
username: str | None = None,
password: str | None = None) -> None
```
Clones a Git repository into the specified path. It supports
cloning specific branches or commits, and can authenticate with the remote
repository if credentials are provided.
**Arguments**:
- `url` _str_ - Repository URL to clone from.
- `path` _str_ - Path where the repository should be cloned. Relative paths are resolved
based on the sandbox working directory.
- `branch` _str | None_ - Specific branch to clone. If not specified,
clones the default branch.
- `commit_id` _str | None_ - Specific commit to clone. If specified,
the repository will be left in a detached HEAD state at this commit.
- `username` _str | None_ - Git username for authentication.
- `password` _str | None_ - Git password or token for authentication.
**Example**:
```python
# Clone the default branch
await sandbox.git.clone(
url="https://github.com/user/repo.git",
path="workspace/repo"
)
# Clone a specific branch with authentication
await sandbox.git.clone(
url="https://github.com/user/private-repo.git",
path="workspace/private",
branch="develop",
username="user",
password="token"
)
# Clone a specific commit
await sandbox.git.clone(
url="https://github.com/user/repo.git",
path="workspace/repo-old",
commit_id="abc123"
)
```
#### AsyncGit.commit
```python
@intercept_errors(message_prefix="Failed to commit changes: ")
@with_instrumentation()
async def commit(path: str,
message: str,
author: str,
email: str,
allow_empty: bool = False) -> GitCommitResponse
```
Creates a new commit with the staged changes. Make sure to stage
changes using the add() method before committing.
**Arguments**:
- `path` _str_ - Path to the Git repository root. Relative paths are resolved based on
the sandbox working directory.
- `message` _str_ - Commit message describing the changes.
- `author` _str_ - Name of the commit author.
- `email` _str_ - Email address of the commit author.
- `allow_empty` _bool_ - Allow creating an empty commit when no changes are staged. Defaults to False.
**Example**:
```python
# Stage and commit changes
await sandbox.git.add("workspace/repo", ["README.md"])
await sandbox.git.commit(
path="workspace/repo",
message="Update documentation",
author="John Doe",
email="john@example.com",
allow_empty=True
)
```
#### AsyncGit.push
```python
@intercept_errors(message_prefix="Failed to push changes: ")
@with_instrumentation()
async def push(path: str,
username: str | None = None,
password: str | None = None) -> None
```
Pushes all local commits on the current branch to the remote
repository. If the remote repository requires authentication, provide
username and password/token.
**Arguments**:
- `path` _str_ - Path to the Git repository root. Relative paths are resolved based on
the sandbox working directory.
- `username` _str | None_ - Git username for authentication.
- `password` _str | None_ - Git password or token for authentication.
**Example**:
```python
# Push without authentication (for public repos or SSH)
await sandbox.git.push("workspace/repo")
# Push with authentication
await sandbox.git.push(
path="workspace/repo",
username="user",
password="github_token"
)
```
#### AsyncGit.pull
```python
@intercept_errors(message_prefix="Failed to pull changes: ")
@with_instrumentation()
async def pull(path: str,
username: str | None = None,
password: str | None = None) -> None
```
Pulls changes from the remote repository. If the remote repository requires authentication,
provide username and password/token.
**Arguments**:
- `path` _str_ - Path to the Git repository root. Relative paths are resolved based on
the sandbox working directory.
- `username` _str | None_ - Git username for authentication.
- `password` _str | None_ - Git password or token for authentication.
**Example**:
```python
# Pull without authentication
await sandbox.git.pull("workspace/repo")
# Pull with authentication
await sandbox.git.pull(
path="workspace/repo",
username="user",
password="github_token"
)
```
#### AsyncGit.status
```python
@intercept_errors(message_prefix="Failed to get status: ")
@with_instrumentation()
async def status(path: str) -> GitStatus
```
Gets the current Git repository status.
**Arguments**:
- `path` _str_ - Path to the Git repository root. Relative paths are resolved based on
the sandbox working directory.
**Returns**:
- `GitStatus` - Repository status information including:
- current_branch: Current branch name
- file_status: List of file statuses
- ahead: Number of local commits not pushed to remote
- behind: Number of remote commits not pulled locally
- branch_published: Whether the branch has been published to the remote repository
**Example**:
```python
status = await sandbox.git.status("workspace/repo")
print(f"On branch: {status.current_branch}")
print(f"Commits ahead: {status.ahead}")
print(f"Commits behind: {status.behind}")
```
#### AsyncGit.checkout\_branch
```python
@intercept_errors(message_prefix="Failed to checkout branch: ")
@with_instrumentation()
async def checkout_branch(path: str, branch: str) -> None
```
Checkout branch in the repository.
**Arguments**:
- `path` _str_ - Path to the Git repository root. Relative paths are resolved based on
the sandbox working directory.
- `branch` _str_ - Name of the branch to checkout
**Example**:
```python
# Checkout a branch
await sandbox.git.checkout_branch("workspace/repo", "feature-branch")
```
#### AsyncGit.create\_branch
```python
@intercept_errors(message_prefix="Failed to create branch: ")
@with_instrumentation()
async def create_branch(path: str, name: str) -> None
```
Create branch in the repository.
**Arguments**:
- `path` _str_ - Path to the Git repository root. Relative paths are resolved based on
the sandbox working directory.
- `name` _str_ - Name of the new branch to create
**Example**:
```python
# Create a new branch
await sandbox.git.create_branch("workspace/repo", "new-feature")
```
#### AsyncGit.delete\_branch
```python
@intercept_errors(message_prefix="Failed to delete branch: ")
@with_instrumentation()
async def delete_branch(path: str, name: str) -> None
```
Delete branch in the repository.
**Arguments**:
- `path` _str_ - Path to the Git repository root. Relative paths are resolved based on
the sandbox working directory.
- `name` _str_ - Name of the branch to delete
**Example**:
```python
# Delete a branch
await sandbox.git.delete_branch("workspace/repo", "old-feature")
```
## GitCommitResponse
```python
class GitCommitResponse()
```
Response from the git commit.
**Attributes**:
- `sha` _str_ - The SHA of the commit
## AsyncLspServer
```python
class AsyncLspServer()
```
Provides Language Server Protocol functionality for code intelligence to provide
IDE-like features such as code completion, symbol search, and more.
#### AsyncLspServer.\_\_init\_\_
```python
def __init__(language_id: LspLanguageId | LspLanguageIdLiteral,
path_to_project: str, api_client: LspApi)
```
Initializes a new LSP server instance.
**Arguments**:
- `language_id` _LspLanguageId | LspLanguageIdLiteral_ - The language server type
(e.g., LspLanguageId.TYPESCRIPT).
- `path_to_project` _str_ - Absolute path to the project root directory.
- `api_client` _LspApi_ - API client for Sandbox operations.
#### AsyncLspServer.start
```python
@intercept_errors(message_prefix="Failed to start LSP server: ")
@with_instrumentation()
async def start() -> None
```
Starts the language server.
This method must be called before using any other LSP functionality.
It initializes the language server for the specified language and project.
**Example**:
```python
lsp = sandbox.create_lsp_server("typescript", "workspace/project")
await lsp.start() # Initialize the server
# Now ready for LSP operations
```
#### AsyncLspServer.stop
```python
@intercept_errors(message_prefix="Failed to stop LSP server: ")
@with_instrumentation()
async def stop() -> None
```
Stops the language server.
This method should be called when the LSP server is no longer needed to
free up system resources.
**Example**:
```python
# When done with LSP features
await lsp.stop() # Clean up resources
```
#### AsyncLspServer.did\_open
```python
@intercept_errors(message_prefix="Failed to open file: ")
@with_instrumentation()
async def did_open(path: str) -> None
```
Notifies the language server that a file has been opened.
This method should be called when a file is opened in the editor to enable
language features like diagnostics and completions for that file. The server
will begin tracking the file's contents and providing language features.
**Arguments**:
- `path` _str_ - Path to the opened file. Relative paths are resolved based on the project path
set in the LSP server constructor.
**Example**:
```python
# When opening a file for editing
await lsp.did_open("workspace/project/src/index.ts")
# Now can get completions, symbols, etc. for this file
```
#### AsyncLspServer.did\_close
```python
@intercept_errors(message_prefix="Failed to close file: ")
@with_instrumentation()
async def did_close(path: str) -> None
```
Notify the language server that a file has been closed.
This method should be called when a file is closed in the editor to allow
the language server to clean up any resources associated with that file.
**Arguments**:
- `path` _str_ - Path to the closed file. Relative paths are resolved based on the project path
set in the LSP server constructor.
**Example**:
```python
# When done editing a file
await lsp.did_close("workspace/project/src/index.ts")
```
#### AsyncLspServer.document\_symbols
```python
@intercept_errors(message_prefix="Failed to get symbols from document: ")
@with_instrumentation()
async def document_symbols(path: str) -> list[LspSymbol]
```
Gets symbol information (functions, classes, variables, etc.) from a document.
**Arguments**:
- `path` _str_ - Path to the file to get symbols from. Relative paths are resolved based on the project path
set in the LSP server constructor.
**Returns**:
- `list[LspSymbol]` - List of symbols in the document. Each symbol includes:
- name: The symbol's name
- kind: The symbol's kind (function, class, variable, etc.)
- location: The location of the symbol in the file
**Example**:
```python
# Get all symbols in a file
symbols = await lsp.document_symbols("workspace/project/src/index.ts")
for symbol in symbols:
print(f"{symbol.kind} {symbol.name}: {symbol.location}")
```
#### AsyncLspServer.workspace\_symbols
```python
@deprecated(
reason=
"Method is deprecated. Use `sandbox_symbols` instead. This method will be removed in a future version."
)
@with_instrumentation()
async def workspace_symbols(query: str) -> list[LspSymbol]
```
Searches for symbols matching the query string across all files
in the Sandbox.
**Arguments**:
- `query` _str_ - Search query to match against symbol names.
**Returns**:
- `list[LspSymbol]` - List of matching symbols from all files.
#### AsyncLspServer.sandbox\_symbols
```python
@intercept_errors(message_prefix="Failed to get symbols from sandbox: ")
@with_instrumentation()
async def sandbox_symbols(query: str) -> list[LspSymbol]
```
Searches for symbols matching the query string across all files
in the Sandbox.
**Arguments**:
- `query` _str_ - Search query to match against symbol names.
**Returns**:
- `list[LspSymbol]` - List of matching symbols from all files. Each symbol
includes:
- name: The symbol's name
- kind: The symbol's kind (function, class, variable, etc.)
- location: The location of the symbol in the file
**Example**:
```python
# Search for all symbols containing "User"
symbols = await lsp.sandbox_symbols("User")
for symbol in symbols:
print(f"{symbol.name} in {symbol.location}")
```
#### AsyncLspServer.completions
```python
@intercept_errors(message_prefix="Failed to get completions: ")
@with_instrumentation()
async def completions(path: str,
position: LspCompletionPosition) -> CompletionList
```
Gets completion suggestions at a position in a file.
**Arguments**:
- `path` _str_ - Path to the file. Relative paths are resolved based on the project path
set in the LSP server constructor.
- `position` _LspCompletionPosition_ - Cursor position to get completions for.
**Returns**:
- `CompletionList` - List of completion suggestions. The list includes:
- isIncomplete: Whether more items might be available
- items: List of completion items, each containing:
- label: The text to insert
- kind: The kind of completion
- detail: Additional details about the item
- documentation: Documentation for the item
- sortText: Text used to sort the item in the list
- filterText: Text used to filter the item
- insertText: The actual text to insert (if different from label)
**Example**:
```python
# Get completions at a specific position
pos = LspCompletionPosition(line=10, character=15)
completions = await lsp.completions("workspace/project/src/index.ts", pos)
for item in completions.items:
print(f"{item.label} ({item.kind}): {item.detail}")
```
## LspLanguageId
```python
class LspLanguageId(str, Enum)
```
Language IDs for Language Server Protocol (LSP).
**Enum Members**:
- `PYTHON` ("python")
- `TYPESCRIPT` ("typescript")
- `JAVASCRIPT` ("javascript")
## LspCompletionPosition
```python
@dataclass
class LspCompletionPosition()
```
Represents a zero-based completion position in a text document,
specified by line number and character offset.
**Attributes**:
- `line` _int_ - Zero-based line number in the document.
- `character` _int_ - Zero-based character offset on the line.
## AsyncObjectStorage
```python
class AsyncObjectStorage()
```
AsyncObjectStorage class for interacting with object storage services.
**Attributes**:
- `endpoint_url` _str_ - The endpoint URL for the object storage service.
- `aws_access_key_id` _str_ - The access key ID for the object storage service.
- `aws_secret_access_key` _str_ - The secret access key for the object storage service.
- `aws_session_token` _str_ - The session token for the object storage service. Used for temporary credentials.
- `bucket_name` _str_ - The name of the bucket to use. Defaults to "daytona-volume-builds".
#### AsyncObjectStorage.upload
```python
@with_instrumentation()
async def upload(path: str,
organization_id: str,
archive_base_path: str | None = None) -> str
```
Uploads a file to the object storage service.
**Arguments**:
- `path` _str_ - The path to the file to upload.
- `organization_id` _str_ - The organization ID to use.
- `archive_base_path` _str_ - The base path to use for the archive.
**Returns**:
- `str` - The hash of the uploaded file.
## AsyncProcess
```python
class AsyncProcess()
```
Handles process and code execution within a Sandbox.
#### AsyncProcess.\_\_init\_\_
```python
def __init__(code_toolbox: SandboxCodeToolbox, api_client: ProcessApi)
```
Initialize a new Process instance.
**Arguments**:
- `code_toolbox` _SandboxCodeToolbox_ - Language-specific code execution toolbox.
- `api_client` _ProcessApi_ - API client for process operations.
#### AsyncProcess.exec
```python
@intercept_errors(message_prefix="Failed to execute command: ")
@with_instrumentation()
async def exec(command: str,
cwd: str | None = None,
env: dict[str, str] | None = None,
timeout: int | None = None) -> ExecuteResponse
```
Execute a shell command in the Sandbox.
**Arguments**:
- `command` _str_ - Shell command to execute.
- `cwd` _str | None_ - Working directory for command execution. If not
specified, uses the sandbox working directory.
- `env` _dict[str, str] | None_ - Environment variables to set for the command.
- `timeout` _int | None_ - Maximum time in seconds to wait for the command
to complete. 0 means wait indefinitely.
**Returns**:
- `ExecuteResponse` - Command execution results containing:
- exit_code: The command's exit status
- result: Standard output from the command
- artifacts: ExecutionArtifacts object containing `stdout` (same as result)
and `charts` (matplotlib charts metadata)
**Example**:
```python
# Simple command
response = await sandbox.process.exec("echo 'Hello'")
print(response.artifacts.stdout) # Prints: Hello
# Command with working directory
result = await sandbox.process.exec("ls", cwd="workspace/src")
# Command with timeout
result = await sandbox.process.exec("sleep 10", timeout=5)
```
#### AsyncProcess.code\_run
```python
@with_instrumentation()
async def code_run(code: str,
params: CodeRunParams | None = None,
timeout: int | None = None) -> ExecuteResponse
```
Executes code in the Sandbox using the appropriate language runtime.
**Arguments**:
- `code` _str_ - Code to execute.
- `params` _CodeRunParams | None_ - Parameters for code execution.
- `timeout` _int | None_ - Maximum time in seconds to wait for the code
to complete. 0 means wait indefinitely.
**Returns**:
- `ExecuteResponse` - Code execution result containing:
- exit_code: The execution's exit status
- result: Standard output from the code
- artifacts: ExecutionArtifacts object containing `stdout` (same as result)
and `charts` (matplotlib charts metadata)
**Example**:
```python
# Run Python code
response = await sandbox.process.code_run('''
x = 10
y = 20
print(f"Sum: {x + y}")
''')
print(response.artifacts.stdout) # Prints: Sum: 30
```
Matplotlib charts are automatically detected and returned in the `charts` field
of the `ExecutionArtifacts` object.
```python
code = '''
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 10, 30)
y = np.sin(x)
plt.figure(figsize=(8, 5))
plt.plot(x, y, 'b-', linewidth=2)
plt.title('Line Chart')
plt.xlabel('X-axis (seconds)')
plt.ylabel('Y-axis (amplitude)')
plt.grid(True)
plt.show()
'''
response = await sandbox.process.code_run(code)
chart = response.artifacts.charts[0]
print(f"Type: {chart.type}")
print(f"Title: {chart.title}")
if chart.type == ChartType.LINE and isinstance(chart, LineChart):
print(f"X Label: {chart.x_label}")
print(f"Y Label: {chart.y_label}")
print(f"X Ticks: {chart.x_ticks}")
print(f"X Tick Labels: {chart.x_tick_labels}")
print(f"X Scale: {chart.x_scale}")
print(f"Y Ticks: {chart.y_ticks}")
print(f"Y Tick Labels: {chart.y_tick_labels}")
print(f"Y Scale: {chart.y_scale}")
print("Elements:")
for element in chart.elements:
print(f"Label: {element.label}")
print(f"Points: {element.points}")
```
#### AsyncProcess.create\_session
```python
@intercept_errors(message_prefix="Failed to create session: ")
@with_instrumentation()
async def create_session(session_id: str) -> None
```
Creates a new long-running background session in the Sandbox.
Sessions are background processes that maintain state between commands, making them ideal for
scenarios requiring multiple related commands or persistent environment setup. You can run
long-running commands and monitor process status.
**Arguments**:
- `session_id` _str_ - Unique identifier for the new session.
**Example**:
```python
# Create a new session
session_id = "my-session"
await sandbox.process.create_session(session_id)
session = await sandbox.process.get_session(session_id)
# Do work...
await sandbox.process.delete_session(session_id)
```
#### AsyncProcess.get\_session
```python
@intercept_errors(message_prefix="Failed to get session: ")
async def get_session(session_id: str) -> Session
```
Gets a session in the Sandbox.
**Arguments**:
- `session_id` _str_ - Unique identifier of the session to retrieve.
**Returns**:
- `Session` - Session information including:
- session_id: The session's unique identifier
- commands: List of commands executed in the session
**Example**:
```python
session = await sandbox.process.get_session("my-session")
for cmd in session.commands:
print(f"Command: {cmd.command}")
```
#### AsyncProcess.get\_entrypoint\_session
```python
@intercept_errors(message_prefix="Failed to get sandbox entrypoint session: ")
async def get_entrypoint_session() -> Session
```
Gets the sandbox entrypoint session.
**Returns**:
- `Session` - Entrypoint session information including:
- session_id: The entrypoint session's unique identifier
- commands: List of commands executed in the entrypoint session
**Example**:
```python
session = await sandbox.process.get_entrypoint_session()
for cmd in session.commands:
print(f"Command: {cmd.command}")
```
#### AsyncProcess.get\_session\_command
```python
@intercept_errors(message_prefix="Failed to get session command: ")
@with_instrumentation()
async def get_session_command(session_id: str, command_id: str) -> Command
```
Gets information about a specific command executed in a session.
**Arguments**:
- `session_id` _str_ - Unique identifier of the session.
- `command_id` _str_ - Unique identifier of the command.
**Returns**:
- `Command` - Command information including:
- id: The command's unique identifier
- command: The executed command string
- exit_code: Command's exit status (if completed)
**Example**:
```python
cmd = await sandbox.process.get_session_command("my-session", "cmd-123")
if cmd.exit_code == 0:
print(f"Command {cmd.command} completed successfully")
```
#### AsyncProcess.execute\_session\_command
```python
@intercept_errors(message_prefix="Failed to execute session command: ")
@with_instrumentation()
async def execute_session_command(
session_id: str,
req: SessionExecuteRequest,
timeout: int | None = None) -> SessionExecuteResponse
```
Executes a command in the session.
**Arguments**:
- `session_id` _str_ - Unique identifier of the session to use.
- `req` _SessionExecuteRequest_ - Command execution request containing:
- command: The command to execute
- run_async: Whether to execute asynchronously
**Returns**:
- `SessionExecuteResponse` - Command execution results containing:
- cmd_id: Unique identifier for the executed command
- output: Combined command output (stdout and stderr) (if synchronous execution)
- stdout: Standard output from the command
- stderr: Standard error from the command
- exit_code: Command exit status (if synchronous execution)
**Example**:
```python
# Execute commands in sequence, maintaining state
session_id = "my-session"
# Change directory
req = SessionExecuteRequest(command="cd /workspace")
await sandbox.process.execute_session_command(session_id, req)
# Create a file
req = SessionExecuteRequest(command="echo 'Hello' > test.txt")
await sandbox.process.execute_session_command(session_id, req)
# Read the file
req = SessionExecuteRequest(command="cat test.txt")
result = await sandbox.process.execute_session_command(session_id, req)
print(f"Command stdout: {result.stdout}")
print(f"Command stderr: {result.stderr}")
```
#### AsyncProcess.get\_session\_command\_logs
```python
@intercept_errors(message_prefix="Failed to get session command logs: ")
@with_instrumentation()
async def get_session_command_logs(
session_id: str, command_id: str) -> SessionCommandLogsResponse
```
Get the logs for a command executed in a session.
**Arguments**:
- `session_id` _str_ - Unique identifier of the session.
- `command_id` _str_ - Unique identifier of the command.
**Returns**:
- `SessionCommandLogsResponse` - Command logs including:
- output: Combined command output (stdout and stderr)
- stdout: Standard output from the command
- stderr: Standard error from the command
**Example**:
```python
logs = await sandbox.process.get_session_command_logs(
"my-session",
"cmd-123"
)
print(f"Command stdout: {logs.stdout}")
print(f"Command stderr: {logs.stderr}")
```
#### AsyncProcess.get\_session\_command\_logs\_async
```python
@intercept_errors(message_prefix="Failed to get session command logs: ")
async def get_session_command_logs_async(
session_id: str, command_id: str, on_stdout: OutputHandler[str],
on_stderr: OutputHandler[str]) -> None
```
Asynchronously retrieves and processes the logs for a command executed in a session as they become available.
Accepts both sync and async callbacks. Async callbacks are awaited.
Blocking synchronous operations inside callbacks may cause WebSocket
disconnections — use async callbacks and async libraries to avoid this.
**Arguments**:
- `session_id` _str_ - Unique identifier of the session.
- `command_id` _str_ - Unique identifier of the command.
- `on_stdout` _OutputHandler[str]_ - Callback function to handle stdout log chunks as they arrive.
- `on_stderr` _OutputHandler[str]_ - Callback function to handle stderr log chunks as they arrive.
**Example**:
```python
await sandbox.process.get_session_command_logs_async(
"my-session",
"cmd-123",
lambda log: print(f"[STDOUT]: {log}"),
lambda log: print(f"[STDERR]: {log}"),
)
```
#### AsyncProcess.get\_entrypoint\_logs
```python
@intercept_errors(message_prefix="Failed to get entrypoint logs: ")
@with_instrumentation()
async def get_entrypoint_logs() -> SessionCommandLogsResponse
```
Get the logs for the entrypoint session.
**Returns**:
- `SessionCommandLogsResponse` - Command logs including:
- output: Combined command output (stdout and stderr)
- stdout: Standard output from the command
- stderr: Standard error from the command
**Example**:
```python
logs = await sandbox.process.get_entrypoint_logs()
print(f"Command stdout: {logs.stdout}")
print(f"Command stderr: {logs.stderr}")
```
#### AsyncProcess.get\_entrypoint\_logs\_async
```python
@intercept_errors(message_prefix="Failed to get entrypoint logs: ")
async def get_entrypoint_logs_async(on_stdout: OutputHandler[str],
on_stderr: OutputHandler[str]) -> None
```
Asynchronously retrieves and processes the logs for the entrypoint session as they become available.
**Arguments**:
on_stdout OutputHandler[str]: Callback function to handle stdout log chunks as they arrive.
on_stderr OutputHandler[str]: Callback function to handle stderr log chunks as they arrive.
**Example**:
```python
await sandbox.process.get_entrypoint_logs_async(
lambda log: print(f"[STDOUT]: {log}"),
lambda log: print(f"[STDERR]: {log}"),
)
```
#### AsyncProcess.send\_session\_command\_input
```python
@intercept_errors(message_prefix="Failed to send session command input: ")
async def send_session_command_input(session_id: str, command_id: str,
data: str) -> None
```
Sends input data to a command executed in a session.
**Arguments**:
- `session_id` _str_ - Unique identifier of the session.
- `command_id` _str_ - Unique identifier of the command.
- `data` _str_ - Input data to send.
#### AsyncProcess.list\_sessions
```python
@intercept_errors(message_prefix="Failed to list sessions: ")
@with_instrumentation()
async def list_sessions() -> list[Session]
```
Lists all sessions in the Sandbox.
**Returns**:
- `list[Session]` - List of all sessions in the Sandbox.
**Example**:
```python
sessions = await sandbox.process.list_sessions()
for session in sessions:
print(f"Session {session.session_id}:")
print(f" Commands: {len(session.commands)}")
```
#### AsyncProcess.delete\_session
```python
@intercept_errors(message_prefix="Failed to delete session: ")
@with_instrumentation()
async def delete_session(session_id: str) -> None
```
Terminates and removes a session from the Sandbox, cleaning up any resources
associated with it.
**Arguments**:
- `session_id` _str_ - Unique identifier of the session to delete.
**Example**:
```python
# Create and use a session
await sandbox.process.create_session("temp-session")
# ... use the session ...
# Clean up when done
await sandbox.process.delete_session("temp-session")
```
#### AsyncProcess.create\_pty\_session
```python
@intercept_errors(message_prefix="Failed to create PTY session: ")
@with_instrumentation()
async def create_pty_session(
id: str,
on_data: Callable[[bytes], None] | Callable[[bytes], Awaitable[None]],
cwd: str | None = None,
envs: dict[str, str] | None = None,
pty_size: PtySize | None = None) -> AsyncPtyHandle
```
Creates a new PTY (pseudo-terminal) session in the Sandbox.
Creates an interactive terminal session that can execute commands and handle user input.
The PTY session behaves like a real terminal, supporting features like command history.
**Arguments**:
- `id` - Unique identifier for the PTY session. Must be unique within the Sandbox.
on_data (Callable[[bytes], None] | Callable[[bytes], Awaitable[None]]):
Callback function to handle PTY output data.
- `cwd` - Working directory for the PTY session. Defaults to the sandbox's working directory.
- `env` - Environment variables to set in the PTY session. These will be merged with
the Sandbox's default environment variables.
- `pty_size` - Terminal size configuration. Defaults to 80x24 if not specified.
**Returns**:
- `AsyncPtyHandle` - Handle for managing the created PTY session. Use this to send input,
receive output, resize the terminal, and manage the session lifecycle.
**Raises**:
- `DaytonaError` - If the PTY session creation fails or the session ID is already in use.
#### AsyncProcess.connect\_pty\_session
```python
@intercept_errors(message_prefix="Failed to connect PTY session: ")
@with_instrumentation()
async def connect_pty_session(
session_id: str,
on_data: Callable[[bytes], None] | Callable[[bytes], Awaitable[None]]
) -> AsyncPtyHandle
```
Connects to an existing PTY session in the Sandbox.
Establishes a WebSocket connection to an existing PTY session, allowing you to
interact with a previously created terminal session.
**Arguments**:
- `session_id` - Unique identifier of the PTY session to connect to.
**Returns**:
- `AsyncPtyHandle` - Handle for managing the connected PTY session.
**Raises**:
- `DaytonaError` - If the PTY session doesn't exist or connection fails.
#### AsyncProcess.list\_pty\_sessions
```python
@intercept_errors(message_prefix="Failed to list PTY sessions: ")
@with_instrumentation()
async def list_pty_sessions() -> list[PtySessionInfo]
```
Lists all PTY sessions in the Sandbox.
Retrieves information about all PTY sessions in this Sandbox.
**Returns**:
- `list[PtySessionInfo]` - List of PTY session information objects containing
details about each session's state, creation time, and configuration.
**Example**:
```python
# List all PTY sessions
sessions = await sandbox.process.list_pty_sessions()
for session in sessions:
print(f"Session ID: {session.id}")
print(f"Active: {session.active}")
print(f"Created: {session.created_at}")
```
#### AsyncProcess.get\_pty\_session\_info
```python
@intercept_errors(message_prefix="Failed to get PTY session info: ")
@with_instrumentation()
async def get_pty_session_info(session_id: str) -> PtySessionInfo
```
Gets detailed information about a specific PTY session.
Retrieves comprehensive information about a PTY session including its current state,
configuration, and metadata.
**Arguments**:
- `session_id` - Unique identifier of the PTY session to retrieve information for.
**Returns**:
- `PtySessionInfo` - Detailed information about the PTY session including ID, state,
creation time, working directory, environment variables, and more.
**Raises**:
- `DaytonaError` - If the PTY session doesn't exist.
**Example**:
```python
# Get details about a specific PTY session
session_info = await sandbox.process.get_pty_session_info("my-session")
print(f"Session ID: {session_info.id}")
print(f"Active: {session_info.active}")
print(f"Working Directory: {session_info.cwd}")
print(f"Terminal Size: {session_info.cols}x{session_info.rows}")
```
#### AsyncProcess.kill\_pty\_session
```python
@intercept_errors(message_prefix="Failed to kill PTY session: ")
@with_instrumentation()
async def kill_pty_session(session_id: str) -> None
```
Kills a PTY session and terminates its associated process.
Forcefully terminates the PTY session and cleans up all associated resources.
This will close any active connections and kill the underlying shell process.
This operation is irreversible. Any unsaved work in the terminal session will be lost.
**Arguments**:
- `session_id` - Unique identifier of the PTY session to kill.
**Raises**:
- `DaytonaError` - If the PTY session doesn't exist or cannot be killed.
**Example**:
```python
# Kill a specific PTY session
await sandbox.process.kill_pty_session("my-session")
# Verify the session no longer exists
pty_sessions = await sandbox.process.list_pty_sessions()
for pty_session in pty_sessions:
print(f"PTY session: {pty_session.id}")
```
#### AsyncProcess.resize\_pty\_session
```python
@intercept_errors(message_prefix="Failed to resize PTY session: ")
@with_instrumentation()
async def resize_pty_session(session_id: str,
pty_size: PtySize) -> PtySessionInfo
```
Resizes a PTY session's terminal dimensions.
Changes the terminal size of an active PTY session. This is useful when the
client terminal is resized or when you need to adjust the display for different
output requirements.
**Arguments**:
- `session_id` - Unique identifier of the PTY session to resize.
- `pty_size` - New terminal dimensions containing the desired columns and rows.
**Returns**:
- `PtySessionInfo` - Updated session information reflecting the new terminal size.
**Raises**:
- `DaytonaError` - If the PTY session doesn't exist or resize operation fails.
**Example**:
```python
from daytona.common.pty import PtySize
# Resize a PTY session to a larger terminal
new_size = PtySize(rows=40, cols=150)
updated_info = await sandbox.process.resize_pty_session("my-session", new_size)
print(f"Terminal resized to {updated_info.cols}x{updated_info.rows}")
# You can also use the AsyncPtyHandle's resize method
await pty_handle.resize(new_size)
```
## CodeRunParams
```python
@dataclass
class CodeRunParams()
```
Parameters for code execution.
**Attributes**:
- `argv` _list[str] | None_ - Command line arguments
- `env` _dict[str, str] | None_ - Environment variables
## SessionExecuteRequest
```python
class SessionExecuteRequest(ApiSessionExecuteRequest,
AsyncApiSessionExecuteRequest)
```
Contains the request for executing a command in a session.
**Attributes**:
- `command` _str_ - The command to execute.
- `run_async` _bool | None_ - Whether to execute the command asynchronously.
- `var_async` _bool | None_ - Deprecated. Use `run_async` instead.
- `suppress_input_echo` _bool | None_ - Whether to suppress input echo. Default is `False`.
## ExecutionArtifacts
```python
@dataclass
class ExecutionArtifacts()
```
Artifacts from the command execution.
**Attributes**:
- `stdout` _str_ - Standard output from the command, same as `result` in `ExecuteResponse`
- `charts` _list[Chart] | None_ - List of chart metadata from matplotlib
## ExecuteResponse
```python
class ExecuteResponse(BaseModel)
```
Response from the command execution.
**Attributes**:
- `exit_code` _int_ - The exit code from the command execution
- `result` _str_ - The output from the command execution
- `artifacts` _ExecutionArtifacts | None_ - Artifacts from the command execution
## SessionExecuteResponse
```python
class SessionExecuteResponse(ApiSessionExecuteResponse)
```
Response from the session command execution.
**Attributes**:
- `cmd_id` _str_ - The ID of the executed command
- `stdout` _str | None_ - The stdout from the command execution
- `stderr` _str | None_ - The stderr from the command execution
- `output` _str_ - The output from the command execution
- `exit_code` _int_ - The exit code from the command execution
## SessionCommandLogsResponse
```python
@dataclass
class SessionCommandLogsResponse()
```
Response from the command logs.
**Attributes**:
- `output` _str | None_ - The combined output from the command
- `stdout` _str | None_ - The stdout from the command
- `stderr` _str | None_ - The stderr from the command
#### parse\_session\_command\_logs
```python
def parse_session_command_logs(data: bytes) -> SessionCommandLogsResponse
```
Parse combined stdout/stderr output into separate streams.
**Arguments**:
- `data` - Combined log bytes with STDOUT_PREFIX and STDERR_PREFIX markers
**Returns**:
SessionCommandLogsResponse with separated stdout and stderr
#### demux\_log
```python
def demux_log(data: bytes) -> tuple[bytes, bytes]
```
Demultiplex combined stdout/stderr log data.
**Arguments**:
- `data` - Combined log bytes with STDOUT_PREFIX and STDERR_PREFIX markers
**Returns**:
Tuple of (stdout_bytes, stderr_bytes)
##### OutputHandler
```python
OutputHandler = Union[
Callable[[T], None],
Callable[[T], Awaitable[None]],
]
```
Callback type that accepts both sync and async handlers.
Blocking synchronous operations inside handlers may cause WebSocket disconnections.
## AsyncSandbox
```python
class AsyncSandbox(SandboxDto)
```
Represents a Daytona Sandbox.
**Attributes**:
- `fs` _AsyncFileSystem_ - File system operations interface.
- `git` _AsyncGit_ - Git operations interface.
- `process` _AsyncProcess_ - Process execution interface.
- `computer_use` _AsyncComputerUse_ - Computer use operations interface for desktop automation.
- `code_interpreter` _AsyncCodeInterpreter_ - Stateful interpreter interface for executing code.
Currently supports only Python. For other languages, use the `process.code_run` interface.
- `id` _str_ - Unique identifier for the Sandbox.
- `name` _str_ - Name of the Sandbox.
- `organization_id` _str_ - Organization ID of the Sandbox.
- `snapshot` _str_ - Daytona snapshot used to create the Sandbox.
- `user` _str_ - OS user running in the Sandbox.
- `env` _dict[str, str]_ - Environment variables set in the Sandbox.
- `labels` _dict[str, str]_ - Custom labels attached to the Sandbox.
- `public` _bool_ - Whether the Sandbox is publicly accessible.
- `target` _str_ - Target location of the runner where the Sandbox runs.
- `cpu` _int_ - Number of CPUs allocated to the Sandbox.
- `gpu` _int_ - Number of GPUs allocated to the Sandbox.
- `memory` _int_ - Amount of memory allocated to the Sandbox in GiB.
- `disk` _int_ - Amount of disk space allocated to the Sandbox in GiB.
- `state` _SandboxState_ - Current state of the Sandbox (e.g., "started", "stopped").
- `error_reason` _str_ - Error message if Sandbox is in error state.
- `recoverable` _bool_ - Whether the Sandbox error is recoverable.
- `backup_state` _SandboxBackupStateEnum_ - Current state of Sandbox backup.
- `backup_created_at` _str_ - When the backup was created.
- `auto_stop_interval` _int_ - Auto-stop interval in minutes.
- `auto_archive_interval` _int_ - Auto-archive interval in minutes.
- `auto_delete_interval` _int_ - Auto-delete interval in minutes.
- `volumes` _list[str]_ - Volumes attached to the Sandbox.
- `build_info` _str_ - Build information for the Sandbox if it was created from dynamic build.
- `created_at` _str_ - When the Sandbox was created.
- `updated_at` _str_ - When the Sandbox was last updated.
- `network_block_all` _bool_ - Whether to block all network access for the Sandbox.
- `network_allow_list` _str_ - Comma-separated list of allowed CIDR network addresses for the Sandbox.
#### AsyncSandbox.\_\_init\_\_
```python
def __init__(sandbox_dto: SandboxDto, toolbox_api: ApiClient,
sandbox_api: SandboxApi, code_toolbox: SandboxCodeToolbox)
```
Initialize a new Sandbox instance.
**Arguments**:
- `sandbox_dto` _SandboxDto_ - The sandbox data from the API.
- `toolbox_api` _ApiClient_ - API client for toolbox operations.
- `sandbox_api` _SandboxApi_ - API client for Sandbox operations.
- `code_toolbox` _SandboxCodeToolbox_ - Language-specific toolbox implementation.
#### AsyncSandbox.refresh\_data
```python
@intercept_errors(message_prefix="Failed to refresh sandbox data: ")
@with_instrumentation()
async def refresh_data() -> None
```
Refreshes the Sandbox data from the API.
**Example**:
```python
await sandbox.refresh_data()
print(f"Sandbox {sandbox.id}:")
print(f"State: {sandbox.state}")
print(f"Resources: {sandbox.cpu} CPU, {sandbox.memory} GiB RAM")
```
#### AsyncSandbox.get\_user\_home\_dir
```python
@intercept_errors(message_prefix="Failed to get user home directory: ")
@with_instrumentation()
async def get_user_home_dir() -> str
```
Gets the user's home directory path inside the Sandbox.
**Returns**:
- `str` - The absolute path to the user's home directory inside the Sandbox.
**Example**:
```python
user_home_dir = await sandbox.get_user_home_dir()
print(f"Sandbox user home: {user_home_dir}")
```
#### AsyncSandbox.get\_work\_dir
```python
@intercept_errors(message_prefix="Failed to get working directory path: ")
@with_instrumentation()
async def get_work_dir() -> str
```
Gets the working directory path inside the Sandbox.
**Returns**:
- `str` - The absolute path to the Sandbox working directory. Uses the WORKDIR specified in
the Dockerfile if present, or falling back to the user's home directory if not.
**Example**:
```python
work_dir = await sandbox.get_work_dir()
print(f"Sandbox working directory: {work_dir}")
```
#### AsyncSandbox.create\_lsp\_server
```python
@with_instrumentation()
def create_lsp_server(language_id: LspLanguageId | LspLanguageIdLiteral,
path_to_project: str) -> AsyncLspServer
```
Creates a new Language Server Protocol (LSP) server instance.
The LSP server provides language-specific features like code completion,
diagnostics, and more.
**Arguments**:
- `language_id` _LspLanguageId | LspLanguageIdLiteral_ - The language server type (e.g., LspLanguageId.PYTHON).
- `path_to_project` _str_ - Path to the project root directory. Relative paths are resolved
based on the sandbox working directory.
**Returns**:
- `LspServer` - A new LSP server instance configured for the specified language.
**Example**:
```python
lsp = sandbox.create_lsp_server("python", "workspace/project")
```
#### AsyncSandbox.set\_labels
```python
@intercept_errors(message_prefix="Failed to set labels: ")
@with_instrumentation()
async def set_labels(labels: dict[str, str]) -> dict[str, str]
```
Sets labels for the Sandbox.
Labels are key-value pairs that can be used to organize and identify Sandboxes.
**Arguments**:
- `labels` _dict[str, str]_ - Dictionary of key-value pairs representing Sandbox labels.
**Returns**:
dict[str, str]: Dictionary containing the updated Sandbox labels.
**Example**:
```python
new_labels = sandbox.set_labels({
"project": "my-project",
"environment": "development",
"team": "backend"
})
print(f"Updated labels: {new_labels}")
```
#### AsyncSandbox.start
```python
@intercept_errors(message_prefix="Failed to start sandbox: ")
@with_timeout()
@with_instrumentation()
async def start(timeout: float | None = 60)
```
Starts the Sandbox and waits for it to be ready.
**Arguments**:
- `timeout` _float | None_ - Maximum time to wait in seconds. 0 means no timeout. Default is 60 seconds.
**Raises**:
- `DaytonaError` - If timeout is negative. If sandbox fails to start or times out.
**Example**:
```python
sandbox = daytona.get("my-sandbox-id")
sandbox.start(timeout=40) # Wait up to 40 seconds
print("Sandbox started successfully")
```
#### AsyncSandbox.recover
```python
@intercept_errors(message_prefix="Failed to recover sandbox: ")
@with_timeout()
async def recover(timeout: float | None = 60)
```
Recovers the Sandbox from a recoverable error and waits for it to be ready.
**Arguments**:
- `timeout` _float | None_ - Maximum time to wait in seconds. 0 means no timeout. Default is 60 seconds.
**Raises**:
- `DaytonaError` - If timeout is negative. If sandbox fails to recover or times out.
**Example**:
```python
sandbox = daytona.get("my-sandbox-id")
await sandbox.recover(timeout=40) # Wait up to 40 seconds
print("Sandbox recovered successfully")
```
#### AsyncSandbox.stop
```python
@intercept_errors(message_prefix="Failed to stop sandbox: ")
@with_timeout()
@with_instrumentation()
async def stop(timeout: float | None = 60)
```
Stops the Sandbox and waits for it to be fully stopped.
**Arguments**:
- `timeout` _float | None_ - Maximum time to wait in seconds. 0 means no timeout. Default is 60 seconds.
**Raises**:
- `DaytonaError` - If timeout is negative; If sandbox fails to stop or times out
**Example**:
```python
sandbox = daytona.get("my-sandbox-id")
sandbox.stop()
print("Sandbox stopped successfully")
```
#### AsyncSandbox.delete
```python
@intercept_errors(message_prefix="Failed to remove sandbox: ")
@with_instrumentation()
async def delete(timeout: float | None = 60) -> None
```
Deletes the Sandbox.
**Arguments**:
- `timeout` _float | None_ - Timeout (in seconds) for sandbox deletion. 0 means no timeout.
Default is 60 seconds.
#### AsyncSandbox.wait\_for\_sandbox\_start
```python
@intercept_errors(
message_prefix="Failure during waiting for sandbox to start: ")
@with_timeout()
@with_instrumentation()
async def wait_for_sandbox_start(timeout: float | None = 60) -> None
```
Waits for the Sandbox to reach the 'started' state. Polls the Sandbox status until it
reaches the 'started' state, encounters an error or times out.
**Arguments**:
- `timeout` _float | None_ - Maximum time to wait in seconds. 0 means no timeout. Default is 60 seconds.
**Raises**:
- `DaytonaError` - If timeout is negative; If Sandbox fails to start or times out
#### AsyncSandbox.wait\_for\_sandbox\_stop
```python
@intercept_errors(
message_prefix="Failure during waiting for sandbox to stop: ")
@with_timeout()
@with_instrumentation()
async def wait_for_sandbox_stop(timeout: float | None = 60) -> None
```
Waits for the Sandbox to reach the 'stopped' state. Polls the Sandbox status until it
reaches the 'stopped' state, encounters an error or times out. It will wait up to 60 seconds
for the Sandbox to stop.
Treats destroyed as stopped to cover ephemeral sandboxes that are automatically deleted after stopping.
**Arguments**:
- `timeout` _float | None_ - Maximum time to wait in seconds. 0 means no timeout. Default is 60 seconds.
**Raises**:
- `DaytonaError` - If timeout is negative. If Sandbox fails to stop or times out.
#### AsyncSandbox.set\_autostop\_interval
```python
@intercept_errors(message_prefix="Failed to set auto-stop interval: ")
@with_instrumentation()
async def set_autostop_interval(interval: int) -> None
```
Sets the auto-stop interval for the Sandbox.
The Sandbox will automatically stop after being idle (no new events) for the specified interval.
Events include any state changes or interactions with the Sandbox through the SDK.
Interactions using Sandbox Previews are not included.
**Arguments**:
- `interval` _int_ - Number of minutes of inactivity before auto-stopping.
Set to 0 to disable auto-stop. Defaults to 15.
**Raises**:
- `DaytonaError` - If interval is negative
**Example**:
```python
# Auto-stop after 1 hour
sandbox.set_autostop_interval(60)
# Or disable auto-stop
sandbox.set_autostop_interval(0)
```
#### AsyncSandbox.set\_auto\_archive\_interval
```python
@intercept_errors(message_prefix="Failed to set auto-archive interval: ")
@with_instrumentation()
async def set_auto_archive_interval(interval: int) -> None
```
Sets the auto-archive interval for the Sandbox.
The Sandbox will automatically archive after being continuously stopped for the specified interval.
**Arguments**:
- `interval` _int_ - Number of minutes after which a continuously stopped Sandbox will be auto-archived.
Set to 0 for the maximum interval. Default is 7 days.
**Raises**:
- `DaytonaError` - If interval is negative
**Example**:
```python
# Auto-archive after 1 hour
sandbox.set_auto_archive_interval(60)
# Or use the maximum interval
sandbox.set_auto_archive_interval(0)
```
#### AsyncSandbox.set\_auto\_delete\_interval
```python
@intercept_errors(message_prefix="Failed to set auto-delete interval: ")
@with_instrumentation()
async def set_auto_delete_interval(interval: int) -> None
```
Sets the auto-delete interval for the Sandbox.
The Sandbox will automatically delete after being continuously stopped for the specified interval.
**Arguments**:
- `interval` _int_ - Number of minutes after which a continuously stopped Sandbox will be auto-deleted.
Set to negative value to disable auto-delete. Set to 0 to delete immediately upon stopping.
By default, auto-delete is disabled.
**Example**:
```python
# Auto-delete after 1 hour
sandbox.set_auto_delete_interval(60)
# Or delete immediately upon stopping
sandbox.set_auto_delete_interval(0)
# Or disable auto-delete
sandbox.set_auto_delete_interval(-1)
```
#### AsyncSandbox.get\_preview\_link
```python
@intercept_errors(message_prefix="Failed to get preview link: ")
@with_instrumentation()
async def get_preview_link(port: int) -> PortPreviewUrl
```
Retrieves the preview link for the sandbox at the specified port. If the port is closed,
it will be opened automatically. For private sandboxes, a token is included to grant access
to the URL.
**Arguments**:
- `port` _int_ - The port to open the preview link on.
**Returns**:
- `PortPreviewUrl` - The response object for the preview link, which includes the `url`
and the `token` (to access private sandboxes).
**Example**:
```python
preview_link = sandbox.get_preview_link(3000)
print(f"Preview URL: {preview_link.url}")
print(f"Token: {preview_link.token}")
```
#### AsyncSandbox.create\_signed\_preview\_url
```python
@intercept_errors(message_prefix="Failed to create signed preview url: ")
async def create_signed_preview_url(
port: int,
expires_in_seconds: int | None = None) -> SignedPortPreviewUrl
```
Creates a signed preview URL for the sandbox at the specified port.
**Arguments**:
- `port` _int_ - The port to open the preview link on.
- `expires_in_seconds` _int | None_ - The number of seconds the signed preview
url will be valid for. Defaults to 60 seconds.
**Returns**:
- `SignedPortPreviewUrl` - The response object for the signed preview url.
#### AsyncSandbox.expire\_signed\_preview\_url
```python
@intercept_errors(message_prefix="Failed to expire signed preview url: ")
async def expire_signed_preview_url(port: int, token: str) -> None
```
Expires a signed preview URL for the sandbox at the specified port.
**Arguments**:
- `port` _int_ - The port to expire the signed preview url on.
- `token` _str_ - The token to expire the signed preview url on.
#### AsyncSandbox.archive
```python
@intercept_errors(message_prefix="Failed to archive sandbox: ")
@with_instrumentation()
async def archive() -> None
```
Archives the sandbox, making it inactive and preserving its state. When sandboxes are
archived, the entire filesystem state is moved to cost-effective object storage, making it
possible to keep sandboxes available for an extended period. The tradeoff between archived
and stopped states is that starting an archived sandbox takes more time, depending on its size.
Sandbox must be stopped before archiving.
#### AsyncSandbox.resize
```python
@intercept_errors(message_prefix="Failed to resize sandbox: ")
@with_timeout()
@with_instrumentation()
async def resize(resources: Resources, timeout: float | None = 60) -> None
```
Resizes the Sandbox resources.
Changes the CPU, memory, or disk allocation for the Sandbox. Hot resize (on running
sandbox) only allows CPU/memory increases. Disk resize requires a stopped sandbox.
**Arguments**:
- `resources` _Resources_ - New resource configuration. Only specified fields will be updated.
- cpu: Number of CPU cores (minimum: 1). For hot resize, can only be increased.
- memory: Memory in GiB (minimum: 1). For hot resize, can only be increased.
- disk: Disk space in GiB (can only be increased, requires stopped sandbox).
- `timeout` _Optional[float]_ - Timeout (in seconds) for the resize operation. 0 means no timeout.
Default is 60 seconds.
**Raises**:
- `DaytonaError` - If hot resize constraints are violated (CPU/memory decrease on running sandbox).
- `DaytonaError` - If disk resize attempted on running sandbox.
- `DaytonaError` - If disk size decrease is attempted.
- `DaytonaError` - If resize operation times out.
- `DaytonaError` - If no resource changes are specified.
**Example**:
```python
# Increase CPU/memory on running sandbox (hot resize)
await sandbox.resize(Resources(cpu=4, memory=8))
# Change disk (sandbox must be stopped)
await sandbox.stop()
await sandbox.resize(Resources(cpu=2, memory=4, disk=30))
```
#### AsyncSandbox.wait\_for\_resize\_complete
```python
@intercept_errors(
message_prefix="Failure during waiting for resize to complete: ")
@with_timeout()
@with_instrumentation()
async def wait_for_resize_complete(timeout: float | None = 60) -> None
```
Waits for the Sandbox resize operation to complete. Polls the Sandbox status until
the state is no longer 'resizing'.
**Arguments**:
- `timeout` _Optional[float]_ - Maximum time to wait in seconds. 0 means no timeout. Default is 60 seconds.
**Raises**:
- `DaytonaError` - If timeout is negative. If resize operation times out.
#### AsyncSandbox.create\_ssh\_access
```python
@intercept_errors(message_prefix="Failed to create SSH access: ")
@with_instrumentation()
async def create_ssh_access(
expires_in_minutes: int | None = None) -> SshAccessDto
```
Creates an SSH access token for the sandbox.
**Arguments**:
- `expires_in_minutes` _int | None_ - The number of minutes the SSH access token will be valid for.
#### AsyncSandbox.revoke\_ssh\_access
```python
@intercept_errors(message_prefix="Failed to revoke SSH access: ")
@with_instrumentation()
async def revoke_ssh_access(token: str) -> None
```
Revokes an SSH access token for the sandbox.
**Arguments**:
- `token` _str_ - The token to revoke.
#### AsyncSandbox.validate\_ssh\_access
```python
@intercept_errors(message_prefix="Failed to validate SSH access: ")
@with_instrumentation()
async def validate_ssh_access(token: str) -> SshAccessValidationDto
```
Validates an SSH access token for the sandbox.
**Arguments**:
- `token` _str_ - The token to validate.
#### AsyncSandbox.refresh\_activity
```python
@intercept_errors(message_prefix="Failed to refresh sandbox activity: ")
async def refresh_activity() -> None
```
Refreshes the sandbox activity to reset the timer for automated lifecycle management actions.
This method updates the sandbox's last activity timestamp without changing its state.
It is useful for keeping long-running sessions alive while there is still user activity.
**Example**:
```python
await sandbox.refresh_activity()
```
## AsyncPaginatedSandboxes
```python
class AsyncPaginatedSandboxes(PaginatedSandboxesDto)
```
Represents a paginated list of Daytona Sandboxes.
**Attributes**:
- `items` _list[AsyncSandbox]_ - List of Sandbox instances in the current page.
- `total` _int_ - Total number of Sandboxes across all pages.
- `page` _int_ - Current page number.
- `total_pages` _int_ - Total number of pages available.
##### items: `list[AsyncSandbox]`
```python
items = None
```
pyright: ignore[reportIncompatibleVariableOverride]
## Resources
```python
@dataclass
class Resources()
```
Resources configuration for Sandbox.
**Attributes**:
- `cpu` _int | None_ - Number of CPU cores to allocate.
- `memory` _int | None_ - Amount of memory in GiB to allocate.
- `disk` _int | None_ - Amount of disk space in GiB to allocate.
- `gpu` _int | None_ - Number of GPUs to allocate.
**Example**:
```python
resources = Resources(
cpu=2,
memory=4, # 4GiB RAM
disk=20, # 20GiB disk
gpu=1
)
params = CreateSandboxFromImageParams(
image=Image.debian_slim("3.12"),
language="python",
resources=resources
)
```
## Snapshot
```python
class Snapshot(SyncSnapshotDto)
```
Represents a Daytona Snapshot which is a pre-configured sandbox.
**Attributes**:
- `id` _str_ - Unique identifier for the Snapshot.
- `organization_id` _str | None_ - Organization ID of the Snapshot.
- `general` _bool_ - Whether the Snapshot is general.
- `name` _str_ - Name of the Snapshot.
- `image_name` _str_ - Name of the Image of the Snapshot.
- `state` _str_ - State of the Snapshot.
- `size` _float | int | None_ - Size of the Snapshot.
- `entrypoint` _list[str] | None_ - Entrypoint of the Snapshot.
- `cpu` _float | int_ - CPU of the Snapshot.
- `gpu` _float | int_ - GPU of the Snapshot.
- `mem` _float | int_ - Memory of the Snapshot in GiB.
- `disk` _float | int_ - Disk of the Snapshot in GiB.
- `error_reason` _str | None_ - Error reason of the Snapshot.
- `created_at` _str_ - Timestamp when the Snapshot was created.
- `updated_at` _str_ - Timestamp when the Snapshot was last updated.
- `last_used_at` _str_ - Timestamp when the Snapshot was last used.
## AsyncSnapshotService
```python
class AsyncSnapshotService()
```
Service for managing Daytona Snapshots. Can be used to list, get, create and delete Snapshots.
#### AsyncSnapshotService.list
```python
@intercept_errors(message_prefix="Failed to list snapshots: ")
@with_instrumentation()
async def list(page: int | None = None,
limit: int | None = None) -> PaginatedSnapshots
```
Returns paginated list of Snapshots.
**Arguments**:
- `page` _int | None_ - Page number for pagination (starting from 1).
- `limit` _int | None_ - Maximum number of items per page.
**Returns**:
- `PaginatedSnapshots` - Paginated list of Snapshots.
**Example**:
```python
async with AsyncDaytona() as daytona:
result = await daytona.snapshot.list(page=2, limit=10)
for snapshot in result.items:
print(f"{snapshot.name} ({snapshot.image_name})")
```
#### AsyncSnapshotService.delete
```python
@intercept_errors(message_prefix="Failed to delete snapshot: ")
@with_instrumentation()
async def delete(snapshot: Snapshot) -> None
```
Delete a Snapshot.
**Arguments**:
- `snapshot` _Snapshot_ - Snapshot to delete.
**Example**:
```python
async with AsyncDaytona() as daytona:
snapshot = await daytona.snapshot.get("test-snapshot")
await daytona.snapshot.delete(snapshot)
print("Snapshot deleted")
```
#### AsyncSnapshotService.get
```python
@intercept_errors(message_prefix="Failed to get snapshot: ")
@with_instrumentation()
async def get(name: str) -> Snapshot
```
Get a Snapshot by name.
**Arguments**:
- `name` _str_ - Name of the Snapshot to get.
**Returns**:
- `Snapshot` - The Snapshot object.
**Example**:
```python
async with AsyncDaytona() as daytona:
snapshot = await daytona.snapshot.get("test-snapshot-name")
print(f"{snapshot.name} ({snapshot.image_name})")
```
#### AsyncSnapshotService.create
```python
@intercept_errors(message_prefix="Failed to create snapshot: ")
@with_timeout()
@with_instrumentation()
async def create(params: CreateSnapshotParams,
*,
on_logs: Callable[[str], None] | None = None,
timeout: float | None = 0) -> Snapshot
```
Creates and registers a new snapshot from the given Image definition.
**Arguments**:
- `params` _CreateSnapshotParams_ - Parameters for snapshot creation.
- `on_logs` _Callable[[str], None]_ - This callback function handles snapshot creation logs.
- `timeout` _float | None_ - Default is no timeout. Timeout in seconds (0 means no timeout).
**Example**:
```python
image = Image.debianSlim('3.12').pipInstall('numpy')
daytona.snapshot.create(
CreateSnapshotParams(name='my-snapshot', image=image),
on_logs=lambda chunk: print(chunk, end=""),
)
```
#### AsyncSnapshotService.activate
```python
@with_instrumentation()
async def activate(snapshot: Snapshot) -> Snapshot
```
Activate a snapshot.
**Arguments**:
- `snapshot` _Snapshot_ - The Snapshot instance.
**Returns**:
- `Snapshot` - The activated Snapshot instance.
#### AsyncSnapshotService.process\_image\_context
```python
@staticmethod
@with_instrumentation()
async def process_image_context(object_storage_api: ObjectStorageApi,
image: Image) -> list[str]
```
Processes the image context by uploading it to object storage.
**Arguments**:
- `image` _Image_ - The Image instance.
**Returns**:
- `List[str]` - List of context hashes stored in object storage.
## PaginatedSnapshots
```python
class PaginatedSnapshots(PaginatedSnapshotsDto)
```
Represents a paginated list of Daytona Snapshots.
**Attributes**:
- `items` _list[Snapshot]_ - List of Snapshot instances in the current page.
- `total` _int_ - Total number of Snapshots across all pages.
- `page` _int_ - Current page number.
- `total_pages` _int_ - Total number of pages available.
## CreateSnapshotParams
```python
class CreateSnapshotParams(BaseModel)
```
Parameters for creating a new snapshot.
**Attributes**:
- `name` _str_ - Name of the snapshot.
- `image` _str | Image_ - Image of the snapshot. If a string is provided,
it should be available on some registry. If an Image instance is provided,
it will be used to create a new image in Daytona.
- `resources` _Resources | None_ - Resources of the snapshot.
- `entrypoint` _list[str] | None_ - Entrypoint of the snapshot.
- `region_id` _str | None_ - ID of the region where the snapshot will be available.
Defaults to organization default region if not specified.
## Volume
```python
class Volume(VolumeDto)
```
Represents a Daytona Volume which is a shared storage volume for Sandboxes.
**Attributes**:
- `id` _str_ - Unique identifier for the Volume.
- `name` _str_ - Name of the Volume.
- `organization_id` _str_ - Organization ID of the Volume.
- `state` _str_ - State of the Volume.
- `created_at` _str_ - Date and time when the Volume was created.
- `updated_at` _str_ - Date and time when the Volume was last updated.
- `last_used_at` _str_ - Date and time when the Volume was last used.
## AsyncVolumeService
```python
class AsyncVolumeService()
```
Service for managing Daytona Volumes. Can be used to list, get, create and delete Volumes.
#### AsyncVolumeService.list
```python
async def list() -> list[Volume]
```
List all Volumes.
**Returns**:
- `list[Volume]` - List of all Volumes.
**Example**:
```python
async with AsyncDaytona() as daytona:
volumes = await daytona.volume.list()
for volume in volumes:
print(f"{volume.name} ({volume.id})")
```
#### AsyncVolumeService.get
```python
@with_instrumentation()
async def get(name: str, create: bool = False) -> Volume
```
Get a Volume by name.
**Arguments**:
- `name` _str_ - Name of the Volume to get.
- `create` _bool_ - If True, create a new Volume if it doesn't exist.
**Returns**:
- `Volume` - The Volume object.
**Example**:
```python
async with AsyncDaytona() as daytona:
volume = await daytona.volume.get("test-volume-name", create=True)
print(f"{volume.name} ({volume.id})")
```
#### AsyncVolumeService.create
```python
@with_instrumentation()
async def create(name: str) -> Volume
```
Create a new Volume.
**Arguments**:
- `name` _str_ - Name of the Volume to create.
**Returns**:
- `Volume` - The Volume object.
**Example**:
```python
async with AsyncDaytona() as daytona:
volume = await daytona.volume.create("test-volume")
print(f"{volume.name} ({volume.id}); state: {volume.state}")
```
#### AsyncVolumeService.delete
```python
@with_instrumentation()
async def delete(volume: Volume) -> None
```
Delete a Volume.
**Arguments**:
- `volume` _Volume_ - Volume to delete.
**Example**:
```python
async with AsyncDaytona() as daytona:
volume = await daytona.volume.get("test-volume")
await daytona.volume.delete(volume)
print("Volume deleted")
```
## VolumeMount
```python
class VolumeMount(ApiVolumeMount, AsyncApiVolumeMount)
```
Represents a Volume mount configuration for a Sandbox.
**Attributes**:
- `volume_id` _str_ - ID of the volume to mount.
- `mount_path` _str_ - Path where the volume will be mounted in the sandbox.
- `subpath` _str | None_ - Optional S3 subpath/prefix within the volume to mount.
When specified, only this prefix will be accessible. When omitted,
the entire volume is mounted.
## Chart
```python
class Chart(BaseModel)
```
Represents a chart with metadata from matplotlib.
**Attributes**:
- `type` _ChartType_ - The type of chart
- `title` _str_ - The title of the chart
- `elements` _list[Any]_ - The elements of the chart
- `png` _str | None_ - The PNG representation of the chart encoded in base64
#### Chart.to\_dict
```python
def to_dict() -> dict[str, Any]
```
Return the metadata dictionary used to create the chart.
## ChartType
```python
class ChartType(str, Enum)
```
Chart types
**Enum Members**:
- `LINE` ("line")
- `SCATTER` ("scatter")
- `BAR` ("bar")
- `PIE` ("pie")
- `BOX_AND_WHISKER` ("box_and_whisker")
- `COMPOSITE_CHART` ("composite_chart")
- `UNKNOWN` ("unknown")
## Chart2D
```python
class Chart2D(Chart)
```
Represents a 2D chart with metadata.
**Attributes**:
- `x_label` _str | None_ - The label of the x-axis
- `y_label` _str | None_ - The label of the y-axis
## PointData
```python
class PointData(BaseModel)
```
Represents a point in a 2D chart.
**Attributes**:
- `label` _str_ - The label of the point
- `points` _list[tuple[str | float, str | float]]_ - The points of the chart
## PointChart
```python
class PointChart(Chart2D)
```
Represents a point chart with metadata.
**Attributes**:
- `x_ticks` _list[str | float]_ - The ticks of the x-axis
- `x_tick_labels` _list[str]_ - The labels of the x-axis
- `x_scale` _str_ - The scale of the x-axis
- `y_ticks` _list[str | float]_ - The ticks of the y-axis
- `y_tick_labels` _list[str]_ - The labels of the y-axis
- `y_scale` _str_ - The scale of the y-axis
- `elements` _list[PointData]_ - The points of the chart
## LineChart
```python
class LineChart(PointChart)
```
Represents a line chart with metadata.
**Attributes**:
- `type` _ChartType_ - The type of chart
## ScatterChart
```python
class ScatterChart(PointChart)
```
Represents a scatter chart with metadata.
**Attributes**:
- `type` _ChartType_ - The type of chart
## BarData
```python
class BarData(BaseModel)
```
Represents a bar in a bar chart.
**Attributes**:
- `label` _str_ - The label of the bar
- `group` _str_ - The group of the bar
- `value` _str_ - The value of the bar
## BarChart
```python
class BarChart(Chart2D)
```
Represents a bar chart with metadata.
**Attributes**:
- `type` _ChartType_ - The type of chart
- `elements` _list[BarData]_ - The bars of the chart
## PieData
```python
class PieData(BaseModel)
```
Represents a pie slice in a pie chart.
**Attributes**:
- `label` _str_ - The label of the pie slice
- `angle` _float_ - The angle of the pie slice
- `radius` _float_ - The radius of the pie slice
- `autopct` _str | float_ - The autopct value of the pie slice
## PieChart
```python
class PieChart(Chart)
```
Represents a pie chart with metadata.
**Attributes**:
- `type` _ChartType_ - The type of chart
- `elements` _list[PieData]_ - The pie slices of the chart
## BoxAndWhiskerData
```python
class BoxAndWhiskerData(BaseModel)
```
Represents a box and whisker in a box and whisker chart.
**Attributes**:
- `label` _str_ - The label of the box and whisker
- `min` _float_ - The minimum value of the box and whisker
- `first_quartile` _float_ - The first quartile of the box and whisker
- `median` _float_ - The median of the box and whisker
- `third_quartile` _float_ - The third quartile of the box and whisker
- `max` _float_ - The maximum value of the box and whisker
- `outliers` _list[float]_ - The outliers of the box and whisker
## BoxAndWhiskerChart
```python
class BoxAndWhiskerChart(Chart2D)
```
Represents a box and whisker chart with metadata.
**Attributes**:
- `type` _ChartType_ - The type of chart
- `elements` _list[BoxAndWhiskerData]_ - The box and whiskers of the chart
## CompositeChart
```python
class CompositeChart(Chart)
```
Represents a composite chart with metadata. A composite chart is a chart
that contains multiple charts (subplots).
**Attributes**:
- `type` _ChartType_ - The type of chart
- `elements` _list[Chart]_ - The charts (subplots) of the composite chart
## DaytonaError
```python
class DaytonaError(Exception)
```
Base error for Daytona SDK.
**Attributes**:
- `message` _str_ - Error message
- `status_code` _int | None_ - HTTP status code if available
- `headers` _dict[str, Any]_ - Response headers
#### DaytonaError.\_\_init\_\_
```python
def __init__(message: str,
status_code: int | None = None,
headers: Mapping[str, Any] | None = None)
```
Initialize Daytona error.
**Arguments**:
- `message` _str_ - Error message
- `status_code` _int | None_ - HTTP status code if available
- `headers` _Mapping[str, Any] | None_ - Response headers if available
## DaytonaNotFoundError
```python
class DaytonaNotFoundError(DaytonaError)
```
Error for when a resource is not found.
## DaytonaRateLimitError
```python
class DaytonaRateLimitError(DaytonaError)
```
Error for when rate limit is exceeded.
## DaytonaTimeoutError
```python
class DaytonaTimeoutError(DaytonaError)
```
Error for when a timeout occurs.
## Image
```python
class Image(BaseModel)
```
Represents an image definition for a Daytona sandbox.
Do not construct this class directly. Instead use one of its static factory methods,
such as `Image.base()`, `Image.debian_slim()`, or `Image.from_dockerfile()`.
#### Image.dockerfile
```python
def dockerfile() -> str
```
Returns a generated Dockerfile for the image.
#### Image.pip\_install
```python
def pip_install(*packages: str | list[str],
find_links: list[str] | None = None,
index_url: str | None = None,
extra_index_urls: list[str] | None = None,
pre: bool = False,
extra_options: str = "") -> "Image"
```
Adds commands to install packages using pip.
**Arguments**:
- `*packages` - The packages to install.
- `find_links` - list[str] | None: The find-links to use.
- `index_url` - str | None: The index URL to use.
- `extra_index_urls` - list[str] | None: The extra index URLs to use.
- `pre` - bool = False: Whether to install pre-release packages.
- `extra_options` - str = "": Additional options to pass to pip. Given string is passed
directly to the pip install command.
**Returns**:
- `Image` - The image with the pip install commands added.
**Example**:
```python
image = Image.debian_slim("3.12").pip_install("requests", "pandas")
```
#### Image.pip\_install\_from\_requirements
```python
def pip_install_from_requirements(requirements_txt: str,
find_links: list[str] | None = None,
index_url: str | None = None,
extra_index_urls: list[str] | None = None,
pre: bool = False,
extra_options: str = "") -> "Image"
```
Installs dependencies from a requirements.txt file.
**Arguments**:
- `requirements_txt` - str: The path to the requirements.txt file.
- `find_links` - list[str] | None: The find-links to use.
- `index_url` - str | None: The index URL to use.
- `extra_index_urls` - list[str] | None: The extra index URLs to use.
- `pre` - bool = False: Whether to install pre-release packages.
- `extra_options` - str = "": Additional options to pass to pip.
**Returns**:
- `Image` - The image with the pip install commands added.
**Example**:
```python
image = Image.debian_slim("3.12").pip_install_from_requirements("requirements.txt")
```
#### Image.pip\_install\_from\_pyproject
```python
def pip_install_from_pyproject(pyproject_toml: str,
optional_dependencies: list[str],
find_links: str | None = None,
index_url: str | None = None,
extra_index_url: str | None = None,
pre: bool = False,
extra_options: str = "") -> "Image"
```
Installs dependencies from a pyproject.toml file.
**Arguments**:
- `pyproject_toml` - str: The path to the pyproject.toml file.
- `optional_dependencies` - list[str] = []: The optional dependencies to install from the pyproject.toml file.
- `find_links` - str | None = None: The find-links to use.
- `index_url` - str | None = None: The index URL to use.
- `extra_index_url` - str | None = None: The extra index URL to use.
- `pre` - bool = False: Whether to install pre-release packages.
- `extra_options` - str = "": Additional options to pass to pip. Given string is passed
directly to the pip install command.
**Returns**:
- `Image` - The image with the pip install commands added.
**Example**:
```python
image = Image.debian_slim("3.12") .pip_install_from_pyproject("pyproject.toml", optional_dependencies=["dev"])
```
#### Image.add\_local\_file
```python
def add_local_file(local_path: str | Path, remote_path: str) -> "Image"
```
Adds a local file to the image.
**Arguments**:
- `local_path` - str | Path: The path to the local file.
- `remote_path` - str: The path to the file in the image.
**Returns**:
- `Image` - The image with the local file added.
**Example**:
```python
image = Image.debian_slim("3.12").add_local_file("package.json", "/home/daytona/package.json")
```
#### Image.add\_local\_dir
```python
def add_local_dir(local_path: str | Path, remote_path: str) -> "Image"
```
Adds a local directory to the image.
**Arguments**:
- `local_path` - str | Path: The path to the local directory.
- `remote_path` - str: The path to the directory in the image.
**Returns**:
- `Image` - The image with the local directory added.
**Example**:
```python
image = Image.debian_slim("3.12").add_local_dir("src", "/home/daytona/src")
```
#### Image.run\_commands
```python
def run_commands(*commands: str | list[str]) -> "Image"
```
Runs commands in the image.
**Arguments**:
- `*commands` - The commands to run.
**Returns**:
- `Image` - The image with the commands added.
**Example**:
```python
image = Image.debian_slim("3.12").run_commands(
'echo "Hello, world!"',
['bash', '-c', 'echo Hello, world, again!']
)
```
#### Image.env
```python
def env(env_vars: dict[str, str]) -> "Image"
```
Sets environment variables in the image.
**Arguments**:
- `env_vars` - dict[str, str]: The environment variables to set.
**Returns**:
- `Image` - The image with the environment variables added.
**Example**:
```python
image = Image.debian_slim("3.12").env({"PROJECT_ROOT": "/home/daytona"})
```
#### Image.workdir
```python
def workdir(path: str | Path) -> "Image"
```
Sets the working directory in the image.
**Arguments**:
- `path` - str | Path: The path to the working directory.
**Returns**:
- `Image` - The image with the working directory added.
**Example**:
```python
image = Image.debian_slim("3.12").workdir("/home/daytona")
```
#### Image.entrypoint
```python
def entrypoint(entrypoint_commands: list[str]) -> "Image"
```
Sets the entrypoint for the image.
**Arguments**:
- `entrypoint_commands` - list[str]: The commands to set as the entrypoint.
**Returns**:
- `Image` - The image with the entrypoint added.
**Example**:
```python
image = Image.debian_slim("3.12").entrypoint(["/bin/bash"])
```
#### Image.cmd
```python
def cmd(cmd: list[str]) -> "Image"
```
Sets the default command for the image.
**Arguments**:
- `cmd` - list[str]: The commands to set as the default command.
**Returns**:
- `Image` - The image with the default command added.
**Example**:
```python
image = Image.debian_slim("3.12").cmd(["/bin/bash"])
```
#### Image.dockerfile\_commands
```python
def dockerfile_commands(dockerfile_commands: list[str],
context_dir: Path | str | None = None) -> "Image"
```
Adds arbitrary Dockerfile-like commands to the image.
**Arguments**:
- `*dockerfile_commands` - The commands to add to the Dockerfile.
- `context_dir` - Path | str | None: The path to the context directory.
**Returns**:
- `Image` - The image with the Dockerfile commands added.
**Example**:
```python
image = Image.debian_slim("3.12").dockerfile_commands(["RUN echo 'Hello, world!'"])
```
#### Image.from\_dockerfile
```python
@staticmethod
def from_dockerfile(path: str | Path) -> "Image"
```
Creates an Image from an existing Dockerfile.
**Arguments**:
- `path` - str | Path: The path to the Dockerfile.
**Returns**:
- `Image` - The image with the Dockerfile added.
**Example**:
```python
image = Image.from_dockerfile("Dockerfile")
```
#### Image.base
```python
@staticmethod
def base(image: str) -> "Image"
```
Creates an Image from an existing base image.
**Arguments**:
- `image` - str: The base image to use.
**Returns**:
- `Image` - The image with the base image added.
**Example**:
```python
image = Image.base("python:3.12-slim-bookworm")
```
#### Image.debian\_slim
```python
@staticmethod
def debian_slim(
python_version: SupportedPythonSeries | None = None) -> "Image"
```
Creates a Debian slim image based on the official Python Docker image.
**Arguments**:
- `python_version` - SupportedPythonSeries | None: The Python version to use.
**Returns**:
- `Image` - The image with the Debian slim image added.
**Example**:
```python
image = Image.debian_slim("3.12")
```
## Context
```python
class Context(BaseModel)
```
Context for an image.
**Attributes**:
- `source_path` _str_ - The path to the source file or directory.
- `archive_path` _str | None_ - The path inside the archive file in object storage.
The Daytona Python SDK provides a robust interface for programmatically interacting with Daytona Sandboxes.
## Installation
Install the Daytona Python SDK using pip:
```bash
pip install daytona
```
Or using poetry:
```bash
poetry add daytona
```
## Getting Started
### Create a Sandbox
Create a Daytona Sandbox to run your code securely in an isolated environment. The following snippet is an example "Hello World" program that runs securely inside a Daytona Sandbox.
```python
from daytona import Daytona
def main():
# Initialize the SDK (uses environment variables by default)
daytona = Daytona()
# Create a new sandbox
sandbox = daytona.create()
# Execute a command
response = sandbox.process.exec("echo 'Hello, World!'")
print(response.result)
if __name__ == "__main__":
main()
```
```python
import asyncio
from daytona import AsyncDaytona
async def main():
# Initialize the SDK (uses environment variables by default)
async with AsyncDaytona() as daytona:
# Create a new sandbox
sandbox = await daytona.create()
# Execute a command
response = await sandbox.process.exec("echo 'Hello, World!'")
print(response.result)
if __name__ == "__main__":
asyncio.run(main())
```
## Configuration
The Daytona SDK can be configured using environment variables or by passing options to the constructor:
```python
from daytona import Daytona, DaytonaConfig
# Using environment variables (DAYTONA_API_KEY, DAYTONA_API_URL, DAYTONA_TARGET)
daytona = Daytona()
# Using explicit configuration
config = DaytonaConfig(
api_key="YOUR_API_KEY",
api_url="https://app.daytona.io/api",
target="us"
)
daytona = Daytona(config)
```
```python
import asyncio
from daytona import AsyncDaytona, DaytonaConfig
async def main():
try:
# Using environment variables (DAYTONA_API_KEY, DAYTONA_API_URL, DAYTONA_TARGET)
daytona = AsyncDaytona()
# Your async code here
pass
finally:
await daytona.close()
# Using explicit configuration
config = DaytonaConfig(
api_key="YOUR_API_KEY",
api_url="https://app.daytona.io/api",
target="us"
)
async with AsyncDaytona(config) as daytona:
# Your code here
pass
if __name__ == "__main__":
asyncio.run(main())
```
For more information on configuring the Daytona SDK, see [configuration](https://www.daytona.io/docs/en/configuration.md).
## CodeInterpreter
```python
class CodeInterpreter()
```
Handles code interpretation and execution within a Sandbox. Currently supports only Python.
This class provides methods to execute code in isolated interpreter contexts,
manage contexts, and stream execution output via callbacks. If subsequent code executions
are performed in the same context, the variables, imports, and functions defined in
the previous execution will be available.
For other languages, use the `code_run` method from the `Process` interface,
or execute the appropriate command directly in the sandbox terminal.
#### CodeInterpreter.\_\_init\_\_
```python
def __init__(api_client: InterpreterApi)
```
Initialize a new CodeInterpreter instance.
**Arguments**:
- `api_client` - API client for interpreter operations.
#### CodeInterpreter.run\_code
```python
@intercept_errors(message_prefix="Failed to run code: ")
def run_code(code: str,
*,
context: InterpreterContext | None = None,
on_stdout: OutputHandler[OutputMessage] | None = None,
on_stderr: OutputHandler[OutputMessage] | None = None,
on_error: OutputHandler[ExecutionError] | None = None,
envs: dict[str, str] | None = None,
timeout: int | None = None) -> ExecutionResult
```
Execute Python code in the sandbox.
By default, code runs in the default shared context which persists variables,
imports, and functions across executions. To run in an isolated context,
create a new context with `create_context()` and pass it as `context` argument.
**Arguments**:
- `code` _str_ - Code to execute.
- `context` _InterpreterContext | None_ - Context to run code in. If not provided, uses default context.
- `on_stdout` _OutputHandler[OutputMessage] | None_ - Callback for stdout messages.
- `on_stderr` _OutputHandler[OutputMessage] | None_ - Callback for stderr messages.
- `on_error` _OutputHandler[ExecutionError] | None_ - Callback for execution errors
(e.g., syntax errors, runtime errors).
- `envs` _dict[str, str] | None_ - Environment variables for this execution.
- `timeout` _int | None_ - Timeout in seconds. 0 means no timeout. Default is 10 minutes.
**Returns**:
- `ExecutionResult` - Result object containing stdout, stderr and error if any.
**Raises**:
- `DaytonaTimeoutError` - If execution times out.
- `DaytonaError` - If execution fails due to communication or other SDK errors.
**Examples**:
```python
def handle_stdout(msg: OutputMessage):
print(f"STDOUT: {msg.output}", end="")
def handle_stderr(msg: OutputMessage):
print(f"STDERR: {msg.output}", end="")
def handle_error(err: ExecutionError):
print(f"ERROR: {err.name}: {err.value}")
code = '''
import sys
import time
for i in range(5):
print(i)
time.sleep(1)
sys.stderr.write("Counting done!")
'''
result = sandbox.code_interpreter.run_code(
code=code,
on_stdout=handle_stdout,
on_stderr=handle_stderr,
on_error=handle_error,
timeout=10
)
```
#### CodeInterpreter.create\_context
```python
@intercept_errors(message_prefix="Failed to create interpreter context: ")
def create_context(cwd: str | None = None) -> InterpreterContext
```
Create a new isolated interpreter context.
Contexts provide isolated execution environments with their own global namespace.
Variables, imports, and functions defined in one context don't affect others.
**Arguments**:
- `cwd` _str | None_ - Working directory for the context. If not specified, uses sandbox working directory.
**Returns**:
- `InterpreterContext` - The created context with its ID and metadata.
**Raises**:
- `DaytonaError` - If context creation fails.
**Examples**:
```python
# Create isolated context
ctx = sandbox.code_interpreter.create_context()
# Execute code in this context
sandbox.code_interpreter.run_code("x = 100", context=ctx)
# Variable only exists in this context
result = sandbox.code_interpreter.run_code("print(x)", context=ctx) # OK
# Won't see the variable in default context
result = sandbox.code_interpreter.run_code("print(x)") # NameError
# Clean up
sandbox.code_interpreter.delete_context(ctx)
```
#### CodeInterpreter.list\_contexts
```python
@intercept_errors(message_prefix="Failed to list interpreter contexts: ")
def list_contexts() -> list[InterpreterContext]
```
List all user-created interpreter contexts.
The default context is not included in this list. Only contexts created
via `create_context()` are returned.
**Returns**:
- `list[InterpreterContext]` - List of context objects.
**Raises**:
- `DaytonaError` - If listing fails.
**Examples**:
```python
contexts = sandbox.code_interpreter.list_contexts()
for ctx in contexts:
print(f"Context {ctx.id}: {ctx.language} at {ctx.cwd}")
```
#### CodeInterpreter.delete\_context
```python
@intercept_errors(message_prefix="Failed to delete interpreter context: ")
def delete_context(context: InterpreterContext) -> None
```
Delete an interpreter context and shut down all associated processes.
This permanently removes the context and all its state (variables, imports, etc.).
The default context cannot be deleted.
**Arguments**:
- `context` _InterpreterContext_ - Context to delete.
**Raises**:
- `DaytonaError` - If deletion fails or context not found.
**Examples**:
```python
ctx = sandbox.code_interpreter.create_context()
# ... use context ...
sandbox.code_interpreter.delete_context(ctx)
```
## OutputMessage
```python
class OutputMessage(BaseModel)
```
Represents stdout or stderr output from code execution.
**Attributes**:
- `output` - The output content.
## ExecutionError
```python
class ExecutionError(BaseModel)
```
Represents an error that occurred during code execution.
**Attributes**:
- `name` - The error type/class name (e.g., "ValueError", "SyntaxError").
- `value` - The error value.
- `traceback` - Full traceback of the error.
## ExecutionResult
```python
class ExecutionResult(BaseModel)
```
Result of code execution.
**Attributes**:
- `stdout` - Standard output from the code execution.
- `stderr` - Standard error output from the code execution.
- `error` - Error details if execution failed, None otherwise.
## ComputerUse
```python
class ComputerUse()
```
Computer Use functionality for interacting with the desktop environment.
Provides access to mouse, keyboard, screenshot, display, and recording operations
for automating desktop interactions within a sandbox.
**Attributes**:
- `mouse` _Mouse_ - Mouse operations interface.
- `keyboard` _Keyboard_ - Keyboard operations interface.
- `screenshot` _Screenshot_ - Screenshot operations interface.
- `display` _Display_ - Display operations interface.
- `recording` _RecordingService_ - Screen recording operations interface.
#### ComputerUse.start
```python
@intercept_errors(message_prefix="Failed to start computer use: ")
@with_instrumentation()
def start() -> ComputerUseStartResponse
```
Starts all computer use processes (Xvfb, xfce4, x11vnc, novnc).
**Returns**:
- `ComputerUseStartResponse` - Computer use start response.
**Example**:
```python
result = sandbox.computer_use.start()
print("Computer use processes started:", result.message)
```
#### ComputerUse.stop
```python
@intercept_errors(message_prefix="Failed to stop computer use: ")
@with_instrumentation()
def stop() -> ComputerUseStopResponse
```
Stops all computer use processes.
**Returns**:
- `ComputerUseStopResponse` - Computer use stop response.
**Example**:
```python
result = sandbox.computer_use.stop()
print("Computer use processes stopped:", result.message)
```
#### ComputerUse.get\_status
```python
@intercept_errors(message_prefix="Failed to get computer use status: ")
@with_instrumentation()
def get_status() -> ComputerUseStatusResponse
```
Gets the status of all computer use processes.
**Returns**:
- `ComputerUseStatusResponse` - Status information about all VNC desktop processes.
**Example**:
```python
response = sandbox.computer_use.get_status()
print("Computer use status:", response.status)
```
#### ComputerUse.get\_process\_status
```python
@intercept_errors(message_prefix="Failed to get process status: ")
@with_instrumentation()
def get_process_status(process_name: str) -> ProcessStatusResponse
```
Gets the status of a specific VNC process.
**Arguments**:
- `process_name` _str_ - Name of the process to check.
**Returns**:
- `ProcessStatusResponse` - Status information about the specific process.
**Example**:
```python
xvfb_status = sandbox.computer_use.get_process_status("xvfb")
no_vnc_status = sandbox.computer_use.get_process_status("novnc")
```
#### ComputerUse.restart\_process
```python
@intercept_errors(message_prefix="Failed to restart process: ")
@with_instrumentation()
def restart_process(process_name: str) -> ProcessRestartResponse
```
Restarts a specific VNC process.
**Arguments**:
- `process_name` _str_ - Name of the process to restart.
**Returns**:
- `ProcessRestartResponse` - Process restart response.
**Example**:
```python
result = sandbox.computer_use.restart_process("xfce4")
print("XFCE4 process restarted:", result.message)
```
#### ComputerUse.get\_process\_logs
```python
@intercept_errors(message_prefix="Failed to get process logs: ")
@with_instrumentation()
def get_process_logs(process_name: str) -> ProcessLogsResponse
```
Gets logs for a specific VNC process.
**Arguments**:
- `process_name` _str_ - Name of the process to get logs for.
**Returns**:
- `ProcessLogsResponse` - Process logs.
**Example**:
```python
logs = sandbox.computer_use.get_process_logs("novnc")
print("NoVNC logs:", logs)
```
#### ComputerUse.get\_process\_errors
```python
@intercept_errors(message_prefix="Failed to get process errors: ")
@with_instrumentation()
def get_process_errors(process_name: str) -> ProcessErrorsResponse
```
Gets error logs for a specific VNC process.
**Arguments**:
- `process_name` _str_ - Name of the process to get error logs for.
**Returns**:
- `ProcessErrorsResponse` - Process error logs.
**Example**:
```python
errors = sandbox.computer_use.get_process_errors("x11vnc")
print("X11VNC errors:", errors)
```
## Mouse
```python
class Mouse()
```
Mouse operations for computer use functionality.
#### Mouse.get\_position
```python
@intercept_errors(message_prefix="Failed to get mouse position: ")
@with_instrumentation()
def get_position() -> MousePositionResponse
```
Gets the current mouse cursor position.
**Returns**:
- `MousePositionResponse` - Current mouse position with x and y coordinates.
**Example**:
```python
position = sandbox.computer_use.mouse.get_position()
print(f"Mouse is at: {position.x}, {position.y}")
```
#### Mouse.move
```python
@intercept_errors(message_prefix="Failed to move mouse: ")
@with_instrumentation()
def move(x: int, y: int) -> MousePositionResponse
```
Moves the mouse cursor to the specified coordinates.
**Arguments**:
- `x` _int_ - The x coordinate to move to.
- `y` _int_ - The y coordinate to move to.
**Returns**:
- `MousePositionResponse` - Position after move.
**Example**:
```python
result = sandbox.computer_use.mouse.move(100, 200)
print(f"Mouse moved to: {result.x}, {result.y}")
```
#### Mouse.click
```python
@intercept_errors(message_prefix="Failed to click mouse: ")
@with_instrumentation()
def click(x: int,
y: int,
button: str = "left",
double: bool = False) -> MouseClickResponse
```
Clicks the mouse at the specified coordinates.
**Arguments**:
- `x` _int_ - The x coordinate to click at.
- `y` _int_ - The y coordinate to click at.
- `button` _str_ - The mouse button to click ('left', 'right', 'middle').
- `double` _bool_ - Whether to perform a double-click.
**Returns**:
- `MouseClickResponse` - Click operation result.
**Example**:
```python
# Single left click
result = sandbox.computer_use.mouse.click(100, 200)
# Double click
double_click = sandbox.computer_use.mouse.click(100, 200, "left", True)
# Right click
right_click = sandbox.computer_use.mouse.click(100, 200, "right")
```
#### Mouse.drag
```python
@intercept_errors(message_prefix="Failed to drag mouse: ")
@with_instrumentation()
def drag(start_x: int,
start_y: int,
end_x: int,
end_y: int,
button: str = "left") -> MouseDragResponse
```
Drags the mouse from start coordinates to end coordinates.
**Arguments**:
- `start_x` _int_ - The starting x coordinate.
- `start_y` _int_ - The starting y coordinate.
- `end_x` _int_ - The ending x coordinate.
- `end_y` _int_ - The ending y coordinate.
- `button` _str_ - The mouse button to use for dragging.
**Returns**:
- `MouseDragResponse` - Drag operation result.
**Example**:
```python
result = sandbox.computer_use.mouse.drag(50, 50, 150, 150)
print(f"Dragged from {result.from_x},{result.from_y} to {result.to_x},{result.to_y}")
```
#### Mouse.scroll
```python
@intercept_errors(message_prefix="Failed to scroll mouse: ")
@with_instrumentation()
def scroll(x: int, y: int, direction: str, amount: int = 1) -> bool
```
Scrolls the mouse wheel at the specified coordinates.
**Arguments**:
- `x` _int_ - The x coordinate to scroll at.
- `y` _int_ - The y coordinate to scroll at.
- `direction` _str_ - The direction to scroll ('up' or 'down').
- `amount` _int_ - The amount to scroll.
**Returns**:
- `bool` - Whether the scroll operation was successful.
**Example**:
```python
# Scroll up
scroll_up = sandbox.computer_use.mouse.scroll(100, 200, "up", 3)
# Scroll down
scroll_down = sandbox.computer_use.mouse.scroll(100, 200, "down", 5)
```
## Keyboard
```python
class Keyboard()
```
Keyboard operations for computer use functionality.
#### Keyboard.type
```python
@intercept_errors(message_prefix="Failed to type text: ")
@with_instrumentation()
def type(text: str, delay: int | None = None) -> None
```
Types the specified text.
**Arguments**:
- `text` _str_ - The text to type.
- `delay` _int_ - Delay between characters in milliseconds.
**Raises**:
- `DaytonaError` - If the type operation fails.
**Example**:
```python
try:
sandbox.computer_use.keyboard.type("Hello, World!")
print(f"Operation success")
except Exception as e:
print(f"Operation failed: {e}")
# With delay between characters
try:
sandbox.computer_use.keyboard.type("Slow typing", 100)
print(f"Operation success")
except Exception as e:
print(f"Operation failed: {e}")
```
#### Keyboard.press
```python
@intercept_errors(message_prefix="Failed to press key: ")
@with_instrumentation()
def press(key: str, modifiers: list[str] | None = None) -> None
```
Presses a key with optional modifiers.
**Arguments**:
- `key` _str_ - The key to press (e.g., 'Enter', 'Escape', 'Tab', 'a', 'A').
- `modifiers` _list[str]_ - Modifier keys ('ctrl', 'alt', 'meta', 'shift').
**Raises**:
- `DaytonaError` - If the press operation fails.
**Example**:
```python
# Press Enter
try:
sandbox.computer_use.keyboard.press("Return")
print(f"Operation success")
except Exception as e:
print(f"Operation failed: {e}")
# Press Ctrl+C
try:
sandbox.computer_use.keyboard.press("c", ["ctrl"])
print(f"Operation success")
# Press Ctrl+Shift+T
try:
sandbox.computer_use.keyboard.press("t", ["ctrl", "shift"])
print(f"Operation success")
except Exception as e:
print(f"Operation failed: {e}")
```
#### Keyboard.hotkey
```python
@intercept_errors(message_prefix="Failed to press hotkey: ")
@with_instrumentation()
def hotkey(keys: str) -> None
```
Presses a hotkey combination.
**Arguments**:
- `keys` _str_ - The hotkey combination (e.g., 'ctrl+c', 'alt+tab', 'cmd+shift+t').
**Raises**:
- `DaytonaError` - If the hotkey operation fails.
**Example**:
```python
# Copy
try:
sandbox.computer_use.keyboard.hotkey("ctrl+c")
print(f"Operation success")
except Exception as e:
print(f"Operation failed: {e}")
# Paste
try:
sandbox.computer_use.keyboard.hotkey("ctrl+v")
print(f"Operation success")
except Exception as e:
print(f"Operation failed: {e}")
# Alt+Tab
try:
sandbox.computer_use.keyboard.hotkey("alt+tab")
print(f"Operation success")
except Exception as e:
print(f"Operation failed: {e}")
```
## Screenshot
```python
class Screenshot()
```
Screenshot operations for computer use functionality.
#### Screenshot.take\_full\_screen
```python
@intercept_errors(message_prefix="Failed to take screenshot: ")
@with_instrumentation()
def take_full_screen(show_cursor: bool = False) -> ScreenshotResponse
```
Takes a screenshot of the entire screen.
**Arguments**:
- `show_cursor` _bool_ - Whether to show the cursor in the screenshot.
**Returns**:
- `ScreenshotResponse` - Screenshot data with base64 encoded image.
**Example**:
```python
screenshot = sandbox.computer_use.screenshot.take_full_screen()
print(f"Screenshot size: {screenshot.width}x{screenshot.height}")
# With cursor visible
with_cursor = sandbox.computer_use.screenshot.take_full_screen(True)
```
#### Screenshot.take\_region
```python
@intercept_errors(message_prefix="Failed to take region screenshot: ")
@with_instrumentation()
def take_region(region: ScreenshotRegion,
show_cursor: bool = False) -> ScreenshotResponse
```
Takes a screenshot of a specific region.
**Arguments**:
- `region` _ScreenshotRegion_ - The region to capture.
- `show_cursor` _bool_ - Whether to show the cursor in the screenshot.
**Returns**:
- `ScreenshotResponse` - Screenshot data with base64 encoded image.
**Example**:
```python
region = ScreenshotRegion(x=100, y=100, width=300, height=200)
screenshot = sandbox.computer_use.screenshot.take_region(region)
print(f"Captured region: {screenshot.region.width}x{screenshot.region.height}")
```
#### Screenshot.take\_compressed
```python
@intercept_errors(message_prefix="Failed to take compressed screenshot: ")
@with_instrumentation()
def take_compressed(
options: ScreenshotOptions | None = None) -> ScreenshotResponse
```
Takes a compressed screenshot of the entire screen.
**Arguments**:
- `options` _ScreenshotOptions | None_ - Compression and display options.
**Returns**:
- `ScreenshotResponse` - Compressed screenshot data.
**Example**:
```python
# Default compression
screenshot = sandbox.computer_use.screenshot.take_compressed()
# High quality JPEG
jpeg = sandbox.computer_use.screenshot.take_compressed(
ScreenshotOptions(format="jpeg", quality=95, show_cursor=True)
)
# Scaled down PNG
scaled = sandbox.computer_use.screenshot.take_compressed(
ScreenshotOptions(format="png", scale=0.5)
)
```
#### Screenshot.take\_compressed\_region
```python
@intercept_errors(
message_prefix="Failed to take compressed region screenshot: ")
@with_instrumentation()
def take_compressed_region(
region: ScreenshotRegion,
options: ScreenshotOptions | None = None) -> ScreenshotResponse
```
Takes a compressed screenshot of a specific region.
**Arguments**:
- `region` _ScreenshotRegion_ - The region to capture.
- `options` _ScreenshotOptions | None_ - Compression and display options.
**Returns**:
- `ScreenshotResponse` - Compressed screenshot data.
**Example**:
```python
region = ScreenshotRegion(x=0, y=0, width=800, height=600)
screenshot = sandbox.computer_use.screenshot.take_compressed_region(
region,
ScreenshotOptions(format="webp", quality=80, show_cursor=True)
)
print(f"Compressed size: {screenshot.size_bytes} bytes")
```
## Display
```python
class Display()
```
Display operations for computer use functionality.
#### Display.get\_info
```python
@intercept_errors(message_prefix="Failed to get display info: ")
@with_instrumentation()
def get_info() -> DisplayInfoResponse
```
Gets information about the displays.
**Returns**:
- `DisplayInfoResponse` - Display information including primary display and all available displays.
**Example**:
```python
info = sandbox.computer_use.display.get_info()
print(f"Primary display: {info.primary_display.width}x{info.primary_display.height}")
print(f"Total displays: {info.total_displays}")
for i, display in enumerate(info.displays):
print(f"Display {i}: {display.width}x{display.height} at {display.x},{display.y}")
```
#### Display.get\_windows
```python
@intercept_errors(message_prefix="Failed to get windows: ")
@with_instrumentation()
def get_windows() -> WindowsResponse
```
Gets the list of open windows.
**Returns**:
- `WindowsResponse` - List of open windows with their IDs and titles.
**Example**:
```python
windows = sandbox.computer_use.display.get_windows()
print(f"Found {windows.count} open windows:")
for window in windows.windows:
print(f"- {window.title} (ID: {window.id})")
```
## RecordingService
```python
class RecordingService()
```
Recording operations for computer use functionality.
#### RecordingService.start
```python
@intercept_errors(message_prefix="Failed to start recording: ")
@with_instrumentation()
def start(label: str | None = None) -> Recording
```
Starts a new screen recording session.
**Arguments**:
- `label` _str | None_ - Optional custom label for the recording.
**Returns**:
- `Recording` - Recording start response.
**Example**:
```python
# Start a recording with a label
recording = sandbox.computer_use.recording.start("my-test-recording")
print(f"Recording started: {recording.id}")
print(f"File: {recording.file_path}")
```
#### RecordingService.stop
```python
@intercept_errors(message_prefix="Failed to stop recording: ")
@with_instrumentation()
def stop(recording_id: str) -> Recording
```
Stops an active screen recording session.
**Arguments**:
- `recording_id` _str_ - The ID of the recording to stop.
**Returns**:
- `Recording` - Recording stop response.
**Example**:
```python
result = sandbox.computer_use.recording.stop(recording.id)
print(f"Recording stopped: {result.duration_seconds} seconds")
print(f"Saved to: {result.file_path}")
```
#### RecordingService.list
```python
@intercept_errors(message_prefix="Failed to list recordings: ")
@with_instrumentation()
def list() -> ListRecordingsResponse
```
Lists all recordings (active and completed).
**Returns**:
- `ListRecordingsResponse` - List of all recordings.
**Example**:
```python
recordings = sandbox.computer_use.recording.list()
print(f"Found {len(recordings.recordings)} recordings")
for rec in recordings.recordings:
print(f"- {rec.file_name}: {rec.status}")
```
#### RecordingService.get
```python
@intercept_errors(message_prefix="Failed to get recording: ")
@with_instrumentation()
def get(recording_id: str) -> Recording
```
Gets details of a specific recording by ID.
**Arguments**:
- `recording_id` _str_ - The ID of the recording to retrieve.
**Returns**:
- `Recording` - Recording details.
**Example**:
```python
recording = sandbox.computer_use.recording.get(recording_id)
print(f"Recording: {recording.file_name}")
print(f"Status: {recording.status}")
print(f"Duration: {recording.duration_seconds} seconds")
```
#### RecordingService.delete
```python
@intercept_errors(message_prefix="Failed to delete recording: ")
@with_instrumentation()
def delete(recording_id: str) -> None
```
Deletes a recording by ID.
**Arguments**:
- `recording_id` _str_ - The ID of the recording to delete.
**Example**:
```python
sandbox.computer_use.recording.delete(recording_id)
print("Recording deleted")
```
#### RecordingService.download
```python
@intercept_errors(message_prefix="Failed to download recording: ")
@with_instrumentation()
def download(recording_id: str, local_path: str) -> None
```
Downloads a recording file from the Sandbox and saves it to a local file.
The file is streamed directly to disk without loading the entire content into memory.
**Arguments**:
- `recording_id` _str_ - The ID of the recording to download.
- `local_path` _str_ - Path to save the recording file locally.
**Example**:
```python
# Download recording to file
sandbox.computer_use.recording.download(recording_id, "local_recording.mp4")
print("Recording downloaded")
```
## ScreenshotRegion
```python
class ScreenshotRegion(BaseModel)
```
Region coordinates for screenshot operations.
**Attributes**:
- `x` _int_ - X coordinate of the region.
- `y` _int_ - Y coordinate of the region.
- `width` _int_ - Width of the region.
- `height` _int_ - Height of the region.
## ScreenshotOptions
```python
class ScreenshotOptions(BaseModel)
```
Options for screenshot compression and display.
**Attributes**:
- `show_cursor` _bool | None_ - Whether to show the cursor in the screenshot.
- `fmt` _str | None_ - Image format (e.g., 'png', 'jpeg', 'webp').
- `quality` _int | None_ - Compression quality (0-100).
- `scale` _float | None_ - Scale factor for the screenshot.
## Daytona
```python
class Daytona()
```
Main class for interacting with the Daytona API.
This class provides methods to create, manage, and interact with Daytona Sandboxes.
It can be initialized either with explicit configuration or using environment variables.
**Attributes**:
- `volume` _VolumeService_ - Service for managing volumes.
- `snapshot` _SnapshotService_ - Service for managing snapshots.
**Example**:
Using environment variables:
```python
daytona = Daytona() # Uses DAYTONA_API_KEY, DAYTONA_API_URL
sandbox = daytona.create()
```
Using explicit configuration:
```python
config = DaytonaConfig(
api_key="your-api-key",
api_url="https://your-api.com",
target="us"
)
daytona = Daytona(config)
sandbox = daytona.create()
```
Using OpenTelemetry tracing:
```python
config = DaytonaConfig(
api_key="your-api-key",
experimental={"otelEnabled": True} # Enable OpenTelemetry tracing through experimental config
)
async with Daytona(config) as daytona:
sandbox = daytona.create()
# All SDK operations will be traced
# OpenTelemetry traces are flushed on close
```
#### Daytona.\_\_init\_\_
```python
def __init__(config: DaytonaConfig | None = None)
```
Initializes Daytona instance with optional configuration.
If no config is provided, reads from environment variables:
- `DAYTONA_API_KEY`: Required API key for authentication
- `DAYTONA_API_URL`: Required api URL
- `DAYTONA_TARGET`: Optional target environment (if not provided, default region for the organization is used)
**Arguments**:
- `config` _DaytonaConfig | None_ - Object containing api_key, api_url, and target.
**Raises**:
- `DaytonaError` - If API key is not provided either through config or environment variables
**Example**:
```python
from daytona import Daytona, DaytonaConfig
# Using environment variables
daytona1 = Daytona()
# Using explicit configuration
config = DaytonaConfig(
api_key="your-api-key",
api_url="https://your-api.com",
target="us"
)
daytona2 = Daytona(config)
```
#### Daytona.create
```python
@overload
def create(params: CreateSandboxFromSnapshotParams | None = None,
*,
timeout: float = 60) -> Sandbox
```
Creates Sandboxes from specified or default snapshot. You can specify various parameters,
including language, image, environment variables, and volumes.
**Arguments**:
- `params` _CreateSandboxFromSnapshotParams | None_ - Parameters for Sandbox creation. If not provided,
defaults to default Daytona snapshot and Python language.
- `timeout` _float_ - Timeout (in seconds) for sandbox creation. 0 means no timeout.
Default is 60 seconds.
**Returns**:
- `Sandbox` - The created Sandbox instance.
**Raises**:
- `DaytonaError` - If timeout, auto_stop_interval or auto_archive_interval is negative;
If sandbox fails to start or times out
**Example**:
Create a default Python Sandbox:
```python
sandbox = daytona.create()
```
Create a custom Sandbox:
```python
params = CreateSandboxFromSnapshotParams(
language="python",
snapshot="my-snapshot-id",
env_vars={"DEBUG": "true"},
auto_stop_interval=0,
auto_archive_interval=60,
auto_delete_interval=120
)
sandbox = daytona.create(params, timeout=40)
```
#### Daytona.create
```python
@overload
def create(
params: CreateSandboxFromImageParams | None = None,
*,
timeout: float = 60,
on_snapshot_create_logs: Callable[[str], None] | None = None
) -> Sandbox
```
Creates Sandboxes from specified image available on some registry or declarative Daytona Image.
You can specify various parameters, including resources, language, image, environment variables,
and volumes. Daytona creates snapshot from provided image and uses it to create Sandbox.
**Arguments**:
- `params` _CreateSandboxFromImageParams | None_ - Parameters for Sandbox creation from image.
- `timeout` _float_ - Timeout (in seconds) for sandbox creation. 0 means no timeout.
Default is 60 seconds.
- `on_snapshot_create_logs` _Callable[[str], None] | None_ - This callback function
handles snapshot creation logs.
**Returns**:
- `Sandbox` - The created Sandbox instance.
**Raises**:
- `DaytonaError` - If timeout, auto_stop_interval or auto_archive_interval is negative;
If sandbox fails to start or times out
**Example**:
Create a default Python Sandbox from image:
```python
sandbox = daytona.create(CreateSandboxFromImageParams(image="debian:12.9"))
```
Create a custom Sandbox from declarative Image definition:
```python
declarative_image = (
Image.base("alpine:3.18")
.pipInstall(["numpy", "pandas"])
.env({"MY_ENV_VAR": "My Environment Variable"})
)
params = CreateSandboxFromImageParams(
language="python",
image=declarative_image,
env_vars={"DEBUG": "true"},
resources=Resources(cpu=2, memory=4),
auto_stop_interval=0,
auto_archive_interval=60,
auto_delete_interval=120
)
sandbox = daytona.create(
params,
timeout=40,
on_snapshot_create_logs=lambda chunk: print(chunk, end=""),
)
```
#### Daytona.delete
```python
@with_instrumentation()
def delete(sandbox: Sandbox, timeout: float = 60) -> None
```
Deletes a Sandbox.
**Arguments**:
- `sandbox` _Sandbox_ - The Sandbox instance to delete.
- `timeout` _float_ - Timeout (in seconds) for sandbox deletion. 0 means no timeout.
Default is 60 seconds.
**Raises**:
- `DaytonaError` - If sandbox fails to delete or times out
**Example**:
```python
sandbox = daytona.create()
# ... use sandbox ...
daytona.delete(sandbox) # Clean up when done
```
#### Daytona.get
```python
@intercept_errors(message_prefix="Failed to get sandbox: ")
@with_instrumentation()
def get(sandbox_id_or_name: str) -> Sandbox
```
Gets a Sandbox by its ID or name.
**Arguments**:
- `sandbox_id_or_name` _str_ - The ID or name of the Sandbox to retrieve.
**Returns**:
- `Sandbox` - The Sandbox instance.
**Raises**:
- `DaytonaError` - If sandbox_id_or_name is not provided.
**Example**:
```python
sandbox = daytona.get("my-sandbox-id-or-name")
print(sandbox.state)
```
#### Daytona.list
```python
@intercept_errors(message_prefix="Failed to list sandboxes: ")
@with_instrumentation()
def list(labels: dict[str, str] | None = None,
page: int | None = None,
limit: int | None = None) -> PaginatedSandboxes
```
Returns paginated list of Sandboxes filtered by labels.
**Arguments**:
- `labels` _dict[str, str] | None_ - Labels to filter Sandboxes.
- `page` _int | None_ - Page number for pagination (starting from 1).
- `limit` _int | None_ - Maximum number of items per page.
**Returns**:
- `PaginatedSandboxes` - Paginated list of Sandbox instances that match the labels.
**Example**:
```python
result = daytona.list(labels={"my-label": "my-value"}, page=2, limit=10)
for sandbox in result.items:
print(f"{sandbox.id}: {sandbox.state}")
```
#### Daytona.start
```python
@with_instrumentation()
def start(sandbox: Sandbox, timeout: float = 60) -> None
```
Starts a Sandbox and waits for it to be ready.
**Arguments**:
- `sandbox` _Sandbox_ - The Sandbox to start.
- `timeout` _float_ - Optional timeout in seconds to wait for the Sandbox to start.
0 means no timeout. Default is 60 seconds.
**Raises**:
- `DaytonaError` - If timeout is negative; If Sandbox fails to start or times out
#### Daytona.stop
```python
@with_instrumentation()
def stop(sandbox: Sandbox, timeout: float = 60) -> None
```
Stops a Sandbox and waits for it to be stopped.
**Arguments**:
- `sandbox` _Sandbox_ - The sandbox to stop
- `timeout` _float_ - Optional timeout (in seconds) for sandbox stop.
0 means no timeout. Default is 60 seconds.
**Raises**:
- `DaytonaError` - If timeout is negative; If Sandbox fails to stop or times out
## CodeLanguage
```python
class CodeLanguage(str, Enum)
```
Programming languages supported by Daytona
**Enum Members**:
- `PYTHON` ("python")
- `TYPESCRIPT` ("typescript")
- `JAVASCRIPT` ("javascript")
## DaytonaConfig
```python
class DaytonaConfig(BaseModel)
```
Configuration options for initializing the Daytona client.
**Attributes**:
- `api_key` _str | None_ - API key for authentication with the Daytona API. If not set, it must be provided
via the environment variable `DAYTONA_API_KEY`, or a JWT token must be provided instead.
- `jwt_token` _str | None_ - JWT token for authentication with the Daytona API. If not set, it must be provided
via the environment variable `DAYTONA_JWT_TOKEN`, or an API key must be provided instead.
- `organization_id` _str | None_ - Organization ID used for JWT-based authentication. Required if a JWT token
is provided, and must be set either here or in the environment variable `DAYTONA_ORGANIZATION_ID`.
- `api_url` _str | None_ - URL of the Daytona API. Defaults to `'https://app.daytona.io/api'` if not set
here or in the environment variable `DAYTONA_API_URL`.
- `server_url` _str | None_ - Deprecated. Use `api_url` instead. This property will be removed
in a future version.
- `target` _str | None_ - Target runner location for the Sandbox. Default region for the organization is used
if not set here or in the environment variable `DAYTONA_TARGET`.
- `_experimental` _dict[str, any] | None_ - Configuration for experimental features.
**Example**:
```python
config = DaytonaConfig(api_key="your-api-key")
```
```python
config = DaytonaConfig(jwt_token="your-jwt-token", organization_id="your-organization-id")
```
## CreateSandboxBaseParams
```python
class CreateSandboxBaseParams(BaseModel)
```
Base parameters for creating a new Sandbox.
**Attributes**:
- `name` _str | None_ - Name of the Sandbox.
- `language` _CodeLanguage | CodeLanguageLiteral | None_ - Programming language for the Sandbox.
Defaults to "python".
- `os_user` _str | None_ - OS user for the Sandbox.
- `env_vars` _dict[str, str] | None_ - Environment variables to set in the Sandbox.
- `labels` _dict[str, str] | None_ - Custom labels for the Sandbox.
- `public` _bool | None_ - Whether the Sandbox should be public.
- `timeout` _float | None_ - Timeout in seconds for Sandbox to be created and started.
- `auto_stop_interval` _int | None_ - Interval in minutes after which Sandbox will
automatically stop if no Sandbox event occurs during that time. Default is 15 minutes.
0 means no auto-stop.
- `auto_archive_interval` _int | None_ - Interval in minutes after which a continuously stopped Sandbox will
automatically archive. Default is 7 days.
0 means the maximum interval will be used.
- `auto_delete_interval` _int | None_ - Interval in minutes after which a continuously stopped Sandbox will
automatically be deleted. By default, auto-delete is disabled.
Negative value means disabled, 0 means delete immediately upon stopping.
- `volumes` _list[VolumeMount] | None_ - List of volumes mounts to attach to the Sandbox.
- `network_block_all` _bool | None_ - Whether to block all network access for the Sandbox.
- `network_allow_list` _str | None_ - Comma-separated list of allowed CIDR network addresses for the Sandbox.
- `ephemeral` _bool | None_ - Whether the Sandbox should be ephemeral.
If True, auto_delete_interval will be set to 0.
## CreateSandboxFromImageParams
```python
class CreateSandboxFromImageParams(CreateSandboxBaseParams)
```
Parameters for creating a new Sandbox from an image.
**Attributes**:
- `image` _str | Image_ - Custom Docker image to use for the Sandbox. If an Image object is provided,
the image will be dynamically built.
- `resources` _Resources | None_ - Resource configuration for the Sandbox. If not provided, sandbox will
have default resources.
## CreateSandboxFromSnapshotParams
```python
class CreateSandboxFromSnapshotParams(CreateSandboxBaseParams)
```
Parameters for creating a new Sandbox from a snapshot.
**Attributes**:
- `snapshot` _str | None_ - Name of the snapshot to use for the Sandbox.
## FileSystem
```python
class FileSystem()
```
Provides file system operations within a Sandbox.
This class implements a high-level interface to file system operations that can
be performed within a Daytona Sandbox.
#### FileSystem.\_\_init\_\_
```python
def __init__(api_client: FileSystemApi)
```
Initializes a new FileSystem instance.
**Arguments**:
- `api_client` _FileSystemApi_ - API client for Sandbox file system operations.
#### FileSystem.create\_folder
```python
@intercept_errors(message_prefix="Failed to create folder: ")
@with_instrumentation()
def create_folder(path: str, mode: str) -> None
```
Creates a new directory in the Sandbox at the specified path with the given
permissions.
**Arguments**:
- `path` _str_ - Path where the folder should be created. Relative paths are resolved based
on the sandbox working directory.
- `mode` _str_ - Folder permissions in octal format (e.g., "755" for rwxr-xr-x).
**Example**:
```python
# Create a directory with standard permissions
sandbox.fs.create_folder("workspace/data", "755")
# Create a private directory
sandbox.fs.create_folder("workspace/secrets", "700")
```
#### FileSystem.delete\_file
```python
@intercept_errors(message_prefix="Failed to delete file: ")
@with_instrumentation()
def delete_file(path: str, recursive: bool = False) -> None
```
Deletes a file from the Sandbox.
**Arguments**:
- `path` _str_ - Path to the file to delete. Relative paths are resolved based on the sandbox working directory.
- `recursive` _bool_ - If the file is a directory, this must be true to delete it.
**Example**:
```python
# Delete a file
sandbox.fs.delete_file("workspace/data/old_file.txt")
```
#### FileSystem.download\_file
```python
@overload
def download_file(remote_path: str, timeout: int = 30 * 60) -> bytes
```
Downloads a file from the Sandbox. Returns the file contents as a bytes object.
This method is useful when you want to load the file into memory without saving it to disk.
It can only be used for smaller files.
**Arguments**:
- `remote_path` _str_ - Path to the file in the Sandbox. Relative paths are resolved based
on the sandbox working directory.
- `timeout` _int_ - Timeout for the download operation in seconds. 0 means no timeout. Default is 30 minutes.
**Returns**:
- `bytes` - The file contents as a bytes object.
**Example**:
```python
# Download and save a file locally
content = sandbox.fs.download_file("workspace/data/file.txt")
with open("local_copy.txt", "wb") as f:
f.write(content)
# Download and process text content
content = sandbox.fs.download_file("workspace/data/config.json")
config = json.loads(content.decode('utf-8'))
```
#### FileSystem.download\_file
```python
@overload
def download_file(remote_path: str,
local_path: str,
timeout: int = 30 * 60) -> None
```
Downloads a file from the Sandbox and saves it to a local file using stream.
This method is useful when you want to download larger files that may not fit into memory.
**Arguments**:
- `remote_path` _str_ - Path to the file in the Sandbox. Relative paths are resolved based
on the sandbox working directory.
- `local_path` _str_ - Path to save the file locally.
- `timeout` _int_ - Timeout for the download operation in seconds. 0 means no timeout. Default is 30 minutes.
**Example**:
```python
local_path = "local_copy.txt"
sandbox.fs.download_file("tmp/large_file.txt", local_path)
size_mb = os.path.getsize(local_path) / 1024 / 1024
print(f"Size of the downloaded file {local_path}: {size_mb} MB")
```
#### FileSystem.download\_files
```python
@intercept_errors(message_prefix="Failed to download files: ")
@with_instrumentation()
def download_files(files: list[FileDownloadRequest],
timeout: int = 30 * 60) -> list[FileDownloadResponse]
```
Downloads multiple files from the Sandbox. If the files already exist locally, they will be overwritten.
**Arguments**:
- `files` _list[FileDownloadRequest]_ - List of files to download.
- `timeout` _int_ - Timeout for the download operation in seconds. 0 means no timeout. Default is 30 minutes.
**Returns**:
- `list[FileDownloadResponse]` - List of download results.
**Raises**:
- `Exception` - Only if the request itself fails (network issues, invalid request/response, etc.). Individual
file download errors are returned in the `FileDownloadResponse.error` field.
**Example**:
```python
# Download multiple files
results = sandbox.fs.download_files([
FileDownloadRequest(source="tmp/data.json"),
FileDownloadRequest(source="tmp/config.json", destination="local_config.json")
])
for result in results:
if result.error:
print(f"Error downloading {result.source}: {result.error}")
elif result.result:
print(f"Downloaded {result.source} to {result.result}")
```
#### FileSystem.find\_files
```python
@intercept_errors(message_prefix="Failed to find files: ")
@with_instrumentation()
def find_files(path: str, pattern: str) -> list[Match]
```
Searches for files containing a pattern, similar to
the grep command.
**Arguments**:
- `path` _str_ - Path to the file or directory to search. If the path is a directory,
the search will be performed recursively. Relative paths are resolved based
on the sandbox working directory.
- `pattern` _str_ - Search pattern to match against file contents.
**Returns**:
- `list[Match]` - List of matches found in files. Each Match object includes:
- file: Path to the file containing the match
- line: The line number where the match was found
- content: The matching line content
**Example**:
```python
# Search for TODOs in Python files
matches = sandbox.fs.find_files("workspace/src", "TODO:")
for match in matches:
print(f"{match.file}:{match.line}: {match.content.strip()}")
```
#### FileSystem.get\_file\_info
```python
@intercept_errors(message_prefix="Failed to get file info: ")
@with_instrumentation()
def get_file_info(path: str) -> FileInfo
```
Gets detailed information about a file or directory, including its
size, permissions, and timestamps.
**Arguments**:
- `path` _str_ - Path to the file or directory. Relative paths are resolved based
on the sandbox working directory.
**Returns**:
- `FileInfo` - Detailed file information including:
- name: File name
- is_dir: Whether the path is a directory
- size: File size in bytes
- mode: File permissions
- mod_time: Last modification timestamp
- permissions: File permissions in octal format
- owner: File owner
- group: File group
**Example**:
```python
# Get file metadata
info = sandbox.fs.get_file_info("workspace/data/file.txt")
print(f"Size: {info.size} bytes")
print(f"Modified: {info.mod_time}")
print(f"Mode: {info.mode}")
# Check if path is a directory
info = sandbox.fs.get_file_info("workspace/data")
if info.is_dir:
print("Path is a directory")
```
#### FileSystem.list\_files
```python
@intercept_errors(message_prefix="Failed to list files: ")
@with_instrumentation()
def list_files(path: str) -> list[FileInfo]
```
Lists files and directories in a given path and returns their information, similar to the ls -l command.
**Arguments**:
- `path` _str_ - Path to the directory to list contents from. Relative paths are resolved
based on the sandbox working directory.
**Returns**:
- `list[FileInfo]` - List of file and directory information. Each FileInfo
object includes the same fields as described in get_file_info().
**Example**:
```python
# List directory contents
files = sandbox.fs.list_files("workspace/data")
# Print files and their sizes
for file in files:
if not file.is_dir:
print(f"{file.name}: {file.size} bytes")
# List only directories
dirs = [f for f in files if f.is_dir]
print("Subdirectories:", ", ".join(d.name for d in dirs))
```
#### FileSystem.move\_files
```python
@intercept_errors(message_prefix="Failed to move files: ")
@with_instrumentation()
def move_files(source: str, destination: str) -> None
```
Moves or renames a file or directory. The parent directory of the destination must exist.
**Arguments**:
- `source` _str_ - Path to the source file or directory. Relative paths are resolved
based on the sandbox working directory.
- `destination` _str_ - Path to the destination. Relative paths are resolved based on
the sandbox working directory.
**Example**:
```python
# Rename a file
sandbox.fs.move_files(
"workspace/data/old_name.txt",
"workspace/data/new_name.txt"
)
# Move a file to a different directory
sandbox.fs.move_files(
"workspace/data/file.txt",
"workspace/archive/file.txt"
)
# Move a directory
sandbox.fs.move_files(
"workspace/old_dir",
"workspace/new_dir"
)
```
#### FileSystem.replace\_in\_files
```python
@intercept_errors(message_prefix="Failed to replace in files: ")
@with_instrumentation()
def replace_in_files(files: list[str], pattern: str,
new_value: str) -> list[ReplaceResult]
```
Performs search and replace operations across multiple files.
**Arguments**:
- `files` _list[str]_ - List of file paths to perform replacements in. Relative paths are
resolved based on the sandbox working directory.
- `pattern` _str_ - Pattern to search for.
- `new_value` _str_ - Text to replace matches with.
**Returns**:
- `list[ReplaceResult]` - List of results indicating replacements made in
each file. Each ReplaceResult includes:
- file: Path to the modified file
- success: Whether the operation was successful
- error: Error message if the operation failed
**Example**:
```python
# Replace in specific files
results = sandbox.fs.replace_in_files(
files=["workspace/src/file1.py", "workspace/src/file2.py"],
pattern="old_function",
new_value="new_function"
)
# Print results
for result in results:
if result.success:
print(f"{result.file}: {result.success}")
else:
print(f"{result.file}: {result.error}")
```
#### FileSystem.search\_files
```python
@intercept_errors(message_prefix="Failed to search files: ")
@with_instrumentation()
def search_files(path: str, pattern: str) -> SearchFilesResponse
```
Searches for files and directories whose names match the
specified pattern. The pattern can be a simple string or a glob pattern.
**Arguments**:
- `path` _str_ - Path to the root directory to start search from. Relative paths are resolved
based on the sandbox working directory.
- `pattern` _str_ - Pattern to match against file names. Supports glob
patterns (e.g., "*.py" for Python files).
**Returns**:
- `SearchFilesResponse` - Search results containing:
- files: List of matching file and directory paths
**Example**:
```python
# Find all Python files
result = sandbox.fs.search_files("workspace", "*.py")
for file in result.files:
print(file)
# Find files with specific prefix
result = sandbox.fs.search_files("workspace/data", "test_*")
print(f"Found {len(result.files)} test files")
```
#### FileSystem.set\_file\_permissions
```python
@intercept_errors(message_prefix="Failed to set file permissions: ")
@with_instrumentation()
def set_file_permissions(path: str,
mode: str | None = None,
owner: str | None = None,
group: str | None = None) -> None
```
Sets permissions and ownership for a file or directory. Any of the parameters can be None
to leave that attribute unchanged.
**Arguments**:
- `path` _str_ - Path to the file or directory. Relative paths are resolved based on
the sandbox working directory.
- `mode` _str | None_ - File mode/permissions in octal format
(e.g., "644" for rw-r--r--).
- `owner` _str | None_ - User owner of the file.
- `group` _str | None_ - Group owner of the file.
**Example**:
```python
# Make a file executable
sandbox.fs.set_file_permissions(
path="workspace/scripts/run.sh",
mode="755" # rwxr-xr-x
)
# Change file owner
sandbox.fs.set_file_permissions(
path="workspace/data/file.txt",
owner="daytona",
group="daytona"
)
```
#### FileSystem.upload\_file
```python
@overload
def upload_file(file: bytes, remote_path: str, timeout: int = 30 * 60) -> None
```
Uploads a file to the specified path in the Sandbox. If a file already exists at
the destination path, it will be overwritten. This method is useful when you want to upload
small files that fit into memory.
**Arguments**:
- `file` _bytes_ - File contents as a bytes object.
- `remote_path` _str_ - Path to the destination file. Relative paths are resolved based on
the sandbox working directory.
- `timeout` _int_ - Timeout for the upload operation in seconds. 0 means no timeout. Default is 30 minutes.
**Example**:
```python
# Upload a text file
content = b"Hello, World!"
sandbox.fs.upload_file(content, "tmp/hello.txt")
# Upload a local file
with open("local_file.txt", "rb") as f:
content = f.read()
sandbox.fs.upload_file(content, "tmp/file.txt")
# Upload binary data
import json
data = {"key": "value"}
content = json.dumps(data).encode('utf-8')
sandbox.fs.upload_file(content, "tmp/config.json")
```
#### FileSystem.upload\_file
```python
@overload
def upload_file(local_path: str,
remote_path: str,
timeout: int = 30 * 60) -> None
```
Uploads a file from the local file system to the specified path in the Sandbox.
If a file already exists at the destination path, it will be overwritten. This method uses
streaming to upload the file, so it is useful when you want to upload larger files that may
not fit into memory.
**Arguments**:
- `local_path` _str_ - Path to the local file to upload.
- `remote_path` _str_ - Path to the destination file in the Sandbox. Relative paths are
resolved based on the sandbox working directory.
- `timeout` _int_ - Timeout for the upload operation in seconds. 0 means no timeout. Default is 30 minutes.
**Example**:
```python
sandbox.fs.upload_file("local_file.txt", "tmp/large_file.txt")
```
#### FileSystem.upload\_files
```python
@intercept_errors(message_prefix="Failed to upload files: ")
@with_instrumentation()
def upload_files(files: list[FileUpload], timeout: int = 30 * 60) -> None
```
Uploads multiple files to the Sandbox. If files already exist at the destination paths,
they will be overwritten.
**Arguments**:
- `files` _list[FileUpload]_ - List of files to upload.
- `timeout` _int_ - Timeout for the upload operation in seconds. 0 means no timeout. Default is 30 minutes.
**Example**:
```python
# Upload multiple text files
files = [
FileUpload(
source=b"Content of file 1",
destination="/tmp/file1.txt"
),
FileUpload(
source="workspace/data/file2.txt",
destination="/tmp/file2.txt"
),
FileUpload(
source=b'{"key": "value"}',
destination="/tmp/config.json"
)
]
sandbox.fs.upload_files(files)
```
## FileUpload
```python
@dataclass
class FileUpload()
```
Represents a file to be uploaded to the Sandbox.
**Attributes**:
- `source` _bytes | str_ - File contents as a bytes object or a local file path. If a bytes object is provided,
make sure it fits into memory, otherwise use the local file path which content will be streamed to the Sandbox.
- `destination` _str_ - Absolute destination path in the Sandbox. Relative paths are resolved based on
the sandbox working directory.
## FileDownloadRequest
```python
@dataclass
class FileDownloadRequest()
```
Represents a request to download a single file from the Sandbox.
**Attributes**:
- `source` _str_ - Source path in the Sandbox. Relative paths are resolved based on the user's
root directory.
- `destination` _str | None_ - Destination path in the local filesystem where the file content will be
streamed to. If not provided, the file will be downloaded in the bytes buffer
(might cause memory issues if the file is large).
## FileDownloadResponse
```python
@dataclass
class FileDownloadResponse()
```
Represents the response to a single file download request.
**Attributes**:
- `source` _str_ - The original source path requested for download.
- `result` _str | bytes | None_ - The download result - file path (if destination provided in the request)
or bytes content (if no destination in the request), None if failed or no data received.
- `error` _str | None_ - Error message if the download failed, None if successful.
## Git
```python
class Git()
```
Provides Git operations within a Sandbox.
**Example**:
```python
# Clone a repository
sandbox.git.clone(
url="https://github.com/user/repo.git",
path="workspace/repo"
)
# Check repository status
status = sandbox.git.status("workspace/repo")
print(f"Modified files: {status.modified}")
# Stage and commit changes
sandbox.git.add("workspace/repo", ["file.txt"])
sandbox.git.commit(
path="workspace/repo",
message="Update file",
author="John Doe",
email="john@example.com"
)
```
#### Git.\_\_init\_\_
```python
def __init__(api_client: GitApi)
```
Initializes a new Git handler instance.
**Arguments**:
- `api_client` _GitApi_ - API client for Sandbox Git operations.
#### Git.add
```python
@intercept_errors(message_prefix="Failed to add files: ")
@with_instrumentation()
def add(path: str, files: list[str]) -> None
```
Stages the specified files for the next commit, similar to
running 'git add' on the command line.
**Arguments**:
- `path` _str_ - Path to the Git repository root. Relative paths are resolved based on
the sandbox working directory.
- `files` _list[str]_ - List of file paths or directories to stage, relative to the repository root.
**Example**:
```python
# Stage a single file
sandbox.git.add("workspace/repo", ["file.txt"])
# Stage multiple files
sandbox.git.add("workspace/repo", [
"src/main.py",
"tests/test_main.py",
"README.md"
])
```
#### Git.branches
```python
@intercept_errors(message_prefix="Failed to list branches: ")
@with_instrumentation()
def branches(path: str) -> ListBranchResponse
```
Lists branches in the repository.
**Arguments**:
- `path` _str_ - Path to the Git repository root. Relative paths are resolved based on
the sandbox working directory.
**Returns**:
- `ListBranchResponse` - List of branches in the repository.
**Example**:
```python
response = sandbox.git.branches("workspace/repo")
print(f"Branches: {response.branches}")
```
#### Git.clone
```python
@intercept_errors(message_prefix="Failed to clone repository: ")
@with_instrumentation()
def clone(url: str,
path: str,
branch: str | None = None,
commit_id: str | None = None,
username: str | None = None,
password: str | None = None) -> None
```
Clones a Git repository into the specified path. It supports
cloning specific branches or commits, and can authenticate with the remote
repository if credentials are provided.
**Arguments**:
- `url` _str_ - Repository URL to clone from.
- `path` _str_ - Path where the repository should be cloned. Relative paths are resolved
based on the sandbox working directory.
- `branch` _str | None_ - Specific branch to clone. If not specified,
clones the default branch.
- `commit_id` _str | None_ - Specific commit to clone. If specified,
the repository will be left in a detached HEAD state at this commit.
- `username` _str | None_ - Git username for authentication.
- `password` _str | None_ - Git password or token for authentication.
**Example**:
```python
# Clone the default branch
sandbox.git.clone(
url="https://github.com/user/repo.git",
path="workspace/repo"
)
# Clone a specific branch with authentication
sandbox.git.clone(
url="https://github.com/user/private-repo.git",
path="workspace/private",
branch="develop",
username="user",
password="token"
)
# Clone a specific commit
sandbox.git.clone(
url="https://github.com/user/repo.git",
path="workspace/repo-old",
commit_id="abc123"
)
```
#### Git.commit
```python
@intercept_errors(message_prefix="Failed to commit changes: ")
@with_instrumentation()
def commit(path: str,
message: str,
author: str,
email: str,
allow_empty: bool = False) -> GitCommitResponse
```
Creates a new commit with the staged changes. Make sure to stage
changes using the add() method before committing.
**Arguments**:
- `path` _str_ - Path to the Git repository root. Relative paths are resolved based on
the sandbox working directory.
- `message` _str_ - Commit message describing the changes.
- `author` _str_ - Name of the commit author.
- `email` _str_ - Email address of the commit author.
- `allow_empty` _bool, optional_ - Allow creating an empty commit when no changes are staged. Defaults to False.
**Example**:
```python
# Stage and commit changes
sandbox.git.add("workspace/repo", ["README.md"])
sandbox.git.commit(
path="workspace/repo",
message="Update documentation",
author="John Doe",
email="john@example.com",
allow_empty=True
)
```
#### Git.push
```python
@intercept_errors(message_prefix="Failed to push changes: ")
@with_instrumentation()
def push(path: str,
username: str | None = None,
password: str | None = None) -> None
```
Pushes all local commits on the current branch to the remote
repository. If the remote repository requires authentication, provide
username and password/token.
**Arguments**:
- `path` _str_ - Path to the Git repository root. Relative paths are resolved based on
the sandbox working directory.
- `username` _str | None_ - Git username for authentication.
- `password` _str | None_ - Git password or token for authentication.
**Example**:
```python
# Push without authentication (for public repos or SSH)
sandbox.git.push("workspace/repo")
# Push with authentication
sandbox.git.push(
path="workspace/repo",
username="user",
password="github_token"
)
```
#### Git.pull
```python
@intercept_errors(message_prefix="Failed to pull changes: ")
@with_instrumentation()
def pull(path: str,
username: str | None = None,
password: str | None = None) -> None
```
Pulls changes from the remote repository. If the remote repository requires authentication,
provide username and password/token.
**Arguments**:
- `path` _str_ - Path to the Git repository root. Relative paths are resolved based on
the sandbox working directory.
- `username` _str | None_ - Git username for authentication.
- `password` _str | None_ - Git password or token for authentication.
**Example**:
```python
# Pull without authentication
sandbox.git.pull("workspace/repo")
# Pull with authentication
sandbox.git.pull(
path="workspace/repo",
username="user",
password="github_token"
)
```
#### Git.status
```python
@intercept_errors(message_prefix="Failed to get status: ")
@with_instrumentation()
def status(path: str) -> GitStatus
```
Gets the current Git repository status.
**Arguments**:
- `path` _str_ - Path to the Git repository root. Relative paths are resolved based on
the sandbox working directory.
**Returns**:
- `GitStatus` - Repository status information including:
- current_branch: Current branch name
- file_status: List of file statuses
- ahead: Number of local commits not pushed to remote
- behind: Number of remote commits not pulled locally
- branch_published: Whether the branch has been published to the remote repository
**Example**:
```python
status = sandbox.git.status("workspace/repo")
print(f"On branch: {status.current_branch}")
print(f"Commits ahead: {status.ahead}")
print(f"Commits behind: {status.behind}")
```
#### Git.checkout\_branch
```python
@intercept_errors(message_prefix="Failed to checkout branch: ")
@with_instrumentation()
def checkout_branch(path: str, branch: str) -> None
```
Checkout branch in the repository.
**Arguments**:
- `path` _str_ - Path to the Git repository root. Relative paths are resolved based on
the sandbox working directory.
- `branch` _str_ - Name of the branch to checkout
**Example**:
```python
# Checkout a branch
sandbox.git.checkout_branch("workspace/repo", "feature-branch")
```
#### Git.create\_branch
```python
@intercept_errors(message_prefix="Failed to create branch: ")
@with_instrumentation()
def create_branch(path: str, name: str) -> None
```
Create branch in the repository.
**Arguments**:
- `path` _str_ - Path to the Git repository root. Relative paths are resolved based on
the sandbox working directory.
- `name` _str_ - Name of the new branch to create
**Example**:
```python
# Create a new branch
sandbox.git.create_branch("workspace/repo", "new-feature")
```
#### Git.delete\_branch
```python
@intercept_errors(message_prefix="Failed to delete branch: ")
@with_instrumentation()
def delete_branch(path: str, name: str) -> None
```
Delete branch in the repository.
**Arguments**:
- `path` _str_ - Path to the Git repository root. Relative paths are resolved based on
the sandbox working directory.
- `name` _str_ - Name of the branch to delete
**Example**:
```python
# Delete a branch
sandbox.git.delete_branch("workspace/repo", "old-feature")
```
## GitCommitResponse
```python
class GitCommitResponse()
```
Response from the git commit.
**Attributes**:
- `sha` _str_ - The SHA of the commit
## LspServer
```python
class LspServer()
```
Provides Language Server Protocol functionality for code intelligence to provide
IDE-like features such as code completion, symbol search, and more.
#### LspServer.\_\_init\_\_
```python
def __init__(language_id: LspLanguageId | LspLanguageIdLiteral,
path_to_project: str, api_client: LspApi)
```
Initializes a new LSP server instance.
**Arguments**:
- `language_id` _LspLanguageId | LspLanguageIdLiteral_ - The language server type
(e.g., LspLanguageId.TYPESCRIPT).
- `path_to_project` _str_ - Absolute path to the project root directory.
- `api_client` _LspApi_ - API client for Sandbox operations.
#### LspServer.start
```python
@intercept_errors(message_prefix="Failed to start LSP server: ")
@with_instrumentation()
def start() -> None
```
Starts the language server.
This method must be called before using any other LSP functionality.
It initializes the language server for the specified language and project.
**Example**:
```python
lsp = sandbox.create_lsp_server("typescript", "workspace/project")
lsp.start() # Initialize the server
# Now ready for LSP operations
```
#### LspServer.stop
```python
@intercept_errors(message_prefix="Failed to stop LSP server: ")
@with_instrumentation()
def stop() -> None
```
Stops the language server.
This method should be called when the LSP server is no longer needed to
free up system resources.
**Example**:
```python
# When done with LSP features
lsp.stop() # Clean up resources
```
#### LspServer.did\_open
```python
@intercept_errors(message_prefix="Failed to open file: ")
@with_instrumentation()
def did_open(path: str) -> None
```
Notifies the language server that a file has been opened.
This method should be called when a file is opened in the editor to enable
language features like diagnostics and completions for that file. The server
will begin tracking the file's contents and providing language features.
**Arguments**:
- `path` _str_ - Path to the opened file. Relative paths are resolved based on the project path
set in the LSP server constructor.
**Example**:
```python
# When opening a file for editing
lsp.did_open("workspace/project/src/index.ts")
# Now can get completions, symbols, etc. for this file
```
#### LspServer.did\_close
```python
@intercept_errors(message_prefix="Failed to close file: ")
@with_instrumentation()
def did_close(path: str) -> None
```
Notify the language server that a file has been closed.
This method should be called when a file is closed in the editor to allow
the language server to clean up any resources associated with that file.
**Arguments**:
- `path` _str_ - Path to the closed file. Relative paths are resolved based on the project path
set in the LSP server constructor.
**Example**:
```python
# When done editing a file
lsp.did_close("workspace/project/src/index.ts")
```
#### LspServer.document\_symbols
```python
@intercept_errors(message_prefix="Failed to get symbols from document: ")
@with_instrumentation()
def document_symbols(path: str) -> list[LspSymbol]
```
Gets symbol information (functions, classes, variables, etc.) from a document.
**Arguments**:
- `path` _str_ - Path to the file to get symbols from. Relative paths are resolved based on the project path
set in the LSP server constructor.
**Returns**:
- `list[LspSymbol]` - List of symbols in the document. Each symbol includes:
- name: The symbol's name
- kind: The symbol's kind (function, class, variable, etc.)
- location: The location of the symbol in the file
**Example**:
```python
# Get all symbols in a file
symbols = lsp.document_symbols("workspace/project/src/index.ts")
for symbol in symbols:
print(f"{symbol.kind} {symbol.name}: {symbol.location}")
```
#### LspServer.workspace\_symbols
```python
@deprecated(
reason=
"Method is deprecated. Use `sandbox_symbols` instead. This method will be removed in a future version."
)
@with_instrumentation()
def workspace_symbols(query: str) -> list[LspSymbol]
```
Searches for symbols matching the query string across all files
in the Sandbox.
**Arguments**:
- `query` _str_ - Search query to match against symbol names.
**Returns**:
- `list[LspSymbol]` - List of matching symbols from all files.
#### LspServer.sandbox\_symbols
```python
@intercept_errors(message_prefix="Failed to get symbols from sandbox: ")
@with_instrumentation()
def sandbox_symbols(query: str) -> list[LspSymbol]
```
Searches for symbols matching the query string across all files
in the Sandbox.
**Arguments**:
- `query` _str_ - Search query to match against symbol names.
**Returns**:
- `list[LspSymbol]` - List of matching symbols from all files. Each symbol
includes:
- name: The symbol's name
- kind: The symbol's kind (function, class, variable, etc.)
- location: The location of the symbol in the file
**Example**:
```python
# Search for all symbols containing "User"
symbols = lsp.sandbox_symbols("User")
for symbol in symbols:
print(f"{symbol.name} in {symbol.location}")
```
#### LspServer.completions
```python
@intercept_errors(message_prefix="Failed to get completions: ")
@with_instrumentation()
def completions(path: str, position: LspCompletionPosition) -> CompletionList
```
Gets completion suggestions at a position in a file.
**Arguments**:
- `path` _str_ - Path to the file. Relative paths are resolved based on the project path
set in the LSP server constructor.
- `position` _LspCompletionPosition_ - Cursor position to get completions for.
**Returns**:
- `CompletionList` - List of completion suggestions. The list includes:
- isIncomplete: Whether more items might be available
- items: List of completion items, each containing:
- label: The text to insert
- kind: The kind of completion
- detail: Additional details about the item
- documentation: Documentation for the item
- sortText: Text used to sort the item in the list
- filterText: Text used to filter the item
- insertText: The actual text to insert (if different from label)
**Example**:
```python
# Get completions at a specific position
pos = LspCompletionPosition(line=10, character=15)
completions = lsp.completions("workspace/project/src/index.ts", pos)
for item in completions.items:
print(f"{item.label} ({item.kind}): {item.detail}")
```
## LspLanguageId
```python
class LspLanguageId(str, Enum)
```
Language IDs for Language Server Protocol (LSP).
**Enum Members**:
- `PYTHON` ("python")
- `TYPESCRIPT` ("typescript")
- `JAVASCRIPT` ("javascript")
## LspCompletionPosition
```python
@dataclass
class LspCompletionPosition()
```
Represents a zero-based completion position in a text document,
specified by line number and character offset.
**Attributes**:
- `line` _int_ - Zero-based line number in the document.
- `character` _int_ - Zero-based character offset on the line.
## ObjectStorage
```python
class ObjectStorage()
```
ObjectStorage class for interacting with object storage services.
**Attributes**:
- `endpoint_url` _str_ - The endpoint URL for the object storage service.
- `aws_access_key_id` _str_ - The access key ID for the object storage service.
- `aws_secret_access_key` _str_ - The secret access key for the object storage service.
- `aws_session_token` _str_ - The session token for the object storage service. Used for temporary credentials.
- `bucket_name` _str_ - The name of the bucket to use. Defaults to "daytona-volume-builds".
#### ObjectStorage.upload
```python
@with_instrumentation()
def upload(path: str,
organization_id: str,
archive_base_path: str | None = None) -> str
```
Uploads a file to the object storage service.
**Arguments**:
- `path` _str_ - The path to the file to upload.
- `organization_id` _str_ - The organization ID to use.
- `archive_base_path` _str_ - The base path to use for the archive.
**Returns**:
- `str` - The hash of the uploaded file.
## Process
```python
class Process()
```
Handles process and code execution within a Sandbox.
#### Process.\_\_init\_\_
```python
def __init__(code_toolbox: SandboxCodeToolbox, api_client: ProcessApi)
```
Initialize a new Process instance.
**Arguments**:
- `code_toolbox` _SandboxCodeToolbox_ - Language-specific code execution toolbox.
- `api_client` _ProcessApi_ - API client for process operations.
#### Process.exec
```python
@intercept_errors(message_prefix="Failed to execute command: ")
@with_instrumentation()
def exec(command: str,
cwd: str | None = None,
env: dict[str, str] | None = None,
timeout: int | None = None) -> ExecuteResponse
```
Execute a shell command in the Sandbox.
**Arguments**:
- `command` _str_ - Shell command to execute.
- `cwd` _str | None_ - Working directory for command execution. If not
specified, uses the sandbox working directory.
- `env` _dict[str, str] | None_ - Environment variables to set for the command.
- `timeout` _int | None_ - Maximum time in seconds to wait for the command
to complete. 0 means wait indefinitely.
**Returns**:
- `ExecuteResponse` - Command execution results containing:
- exit_code: The command's exit status
- result: Standard output from the command
- artifacts: ExecutionArtifacts object containing `stdout` (same as result)
and `charts` (matplotlib charts metadata)
**Example**:
```python
# Simple command
response = sandbox.process.exec("echo 'Hello'")
print(response.artifacts.stdout) # Prints: Hello
# Command with working directory
result = sandbox.process.exec("ls", cwd="workspace/src")
# Command with timeout
result = sandbox.process.exec("sleep 10", timeout=5)
```
#### Process.code\_run
```python
@with_instrumentation()
def code_run(code: str,
params: CodeRunParams | None = None,
timeout: int | None = None) -> ExecuteResponse
```
Executes code in the Sandbox using the appropriate language runtime.
**Arguments**:
- `code` _str_ - Code to execute.
- `params` _CodeRunParams | None_ - Parameters for code execution.
- `timeout` _int | None_ - Maximum time in seconds to wait for the code
to complete. 0 means wait indefinitely.
**Returns**:
- `ExecuteResponse` - Code execution result containing:
- exit_code: The execution's exit status
- result: Standard output from the code
- artifacts: ExecutionArtifacts object containing `stdout` (same as result)
and `charts` (matplotlib charts metadata)
**Example**:
```python
# Run Python code
response = sandbox.process.code_run('''
x = 10
y = 20
print(f"Sum: {x + y}")
''')
print(response.artifacts.stdout) # Prints: Sum: 30
```
Matplotlib charts are automatically detected and returned in the `charts` field
of the `ExecutionArtifacts` object.
```python
code = '''
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 10, 30)
y = np.sin(x)
plt.figure(figsize=(8, 5))
plt.plot(x, y, 'b-', linewidth=2)
plt.title('Line Chart')
plt.xlabel('X-axis (seconds)')
plt.ylabel('Y-axis (amplitude)')
plt.grid(True)
plt.show()
'''
response = sandbox.process.code_run(code)
chart = response.artifacts.charts[0]
print(f"Type: {chart.type}")
print(f"Title: {chart.title}")
if chart.type == ChartType.LINE and isinstance(chart, LineChart):
print(f"X Label: {chart.x_label}")
print(f"Y Label: {chart.y_label}")
print(f"X Ticks: {chart.x_ticks}")
print(f"X Tick Labels: {chart.x_tick_labels}")
print(f"X Scale: {chart.x_scale}")
print(f"Y Ticks: {chart.y_ticks}")
print(f"Y Tick Labels: {chart.y_tick_labels}")
print(f"Y Scale: {chart.y_scale}")
print("Elements:")
for element in chart.elements:
print(f"Label: {element.label}")
print(f"Points: {element.points}")
```
#### Process.create\_session
```python
@intercept_errors(message_prefix="Failed to create session: ")
@with_instrumentation()
def create_session(session_id: str) -> None
```
Creates a new long-running background session in the Sandbox.
Sessions are background processes that maintain state between commands, making them ideal for
scenarios requiring multiple related commands or persistent environment setup. You can run
long-running commands and monitor process status.
**Arguments**:
- `session_id` _str_ - Unique identifier for the new session.
**Example**:
```python
# Create a new session
session_id = "my-session"
sandbox.process.create_session(session_id)
session = sandbox.process.get_session(session_id)
# Do work...
sandbox.process.delete_session(session_id)
```
#### Process.get\_session
```python
@intercept_errors(message_prefix="Failed to get session: ")
def get_session(session_id: str) -> Session
```
Gets a session in the Sandbox.
**Arguments**:
- `session_id` _str_ - Unique identifier of the session to retrieve.
**Returns**:
- `Session` - Session information including:
- session_id: The session's unique identifier
- commands: List of commands executed in the session
**Example**:
```python
session = sandbox.process.get_session("my-session")
for cmd in session.commands:
print(f"Command: {cmd.command}")
```
#### Process.get\_entrypoint\_session
```python
@intercept_errors(message_prefix="Failed to get sandbox entrypoint session: ")
def get_entrypoint_session() -> Session
```
Gets the sandbox entrypoint session.
**Returns**:
- `Session` - Entrypoint session information including:
- session_id: The entrypoint session's unique identifier
- commands: List of commands executed in the entrypoint session
**Example**:
```python
session = sandbox.process.get_entrypoint_session()
for cmd in session.commands:
print(f"Command: {cmd.command}")
```
#### Process.get\_session\_command
```python
@intercept_errors(message_prefix="Failed to get session command: ")
@with_instrumentation()
def get_session_command(session_id: str, command_id: str) -> Command
```
Gets information about a specific command executed in a session.
**Arguments**:
- `session_id` _str_ - Unique identifier of the session.
- `command_id` _str_ - Unique identifier of the command.
**Returns**:
- `Command` - Command information including:
- id: The command's unique identifier
- command: The executed command string
- exit_code: Command's exit status (if completed)
**Example**:
```python
cmd = sandbox.process.get_session_command("my-session", "cmd-123")
if cmd.exit_code == 0:
print(f"Command {cmd.command} completed successfully")
```
#### Process.execute\_session\_command
```python
@intercept_errors(message_prefix="Failed to execute session command: ")
@with_instrumentation()
def execute_session_command(
session_id: str,
req: SessionExecuteRequest,
timeout: int | None = None) -> SessionExecuteResponse
```
Executes a command in the session.
**Arguments**:
- `session_id` _str_ - Unique identifier of the session to use.
- `req` _SessionExecuteRequest_ - Command execution request containing:
- command: The command to execute
- run_async: Whether to execute asynchronously
**Returns**:
- `SessionExecuteResponse` - Command execution results containing:
- cmd_id: Unique identifier for the executed command
- output: Combined command output (stdout and stderr) (if synchronous execution)
- stdout: Standard output from the command
- stderr: Standard error from the command
- exit_code: Command exit status (if synchronous execution)
**Example**:
```python
# Execute commands in sequence, maintaining state
session_id = "my-session"
# Change directory
req = SessionExecuteRequest(command="cd /workspace")
sandbox.process.execute_session_command(session_id, req)
# Create a file
req = SessionExecuteRequest(command="echo 'Hello' > test.txt")
sandbox.process.execute_session_command(session_id, req)
# Read the file
req = SessionExecuteRequest(command="cat test.txt")
result = sandbox.process.execute_session_command(session_id, req)
print(f"Command stdout: {result.stdout}")
print(f"Command stderr: {result.stderr}")
```
#### Process.get\_session\_command\_logs
```python
@intercept_errors(message_prefix="Failed to get session command logs: ")
@with_instrumentation()
def get_session_command_logs(session_id: str,
command_id: str) -> SessionCommandLogsResponse
```
Get the logs for a command executed in a session.
**Arguments**:
- `session_id` _str_ - Unique identifier of the session.
- `command_id` _str_ - Unique identifier of the command.
**Returns**:
- `SessionCommandLogsResponse` - Command logs including:
- output: Combined command output (stdout and stderr)
- stdout: Standard output from the command
- stderr: Standard error from the command
**Example**:
```python
logs = sandbox.process.get_session_command_logs(
"my-session",
"cmd-123"
)
print(f"Command stdout: {logs.stdout}")
print(f"Command stderr: {logs.stderr}")
```
#### Process.get\_session\_command\_logs\_async
```python
@intercept_errors(message_prefix="Failed to get session command logs: ")
async def get_session_command_logs_async(
session_id: str, command_id: str, on_stdout: OutputHandler[str],
on_stderr: OutputHandler[str]) -> None
```
Asynchronously retrieves and processes the logs for a command executed in a session as they become available.
Accepts both sync and async callbacks. Async callbacks are awaited.
Blocking synchronous operations inside callbacks may cause WebSocket
disconnections — use async callbacks and async libraries to avoid this.
**Arguments**:
- `session_id` _str_ - Unique identifier of the session.
- `command_id` _str_ - Unique identifier of the command.
- `on_stdout` _OutputHandler[str]_ - Callback function to handle stdout log chunks as they arrive.
- `on_stderr` _OutputHandler[str]_ - Callback function to handle stderr log chunks as they arrive.
**Example**:
```python
await sandbox.process.get_session_command_logs_async(
"my-session",
"cmd-123",
lambda log: print(f"[STDOUT]: {log}"),
lambda log: print(f"[STDERR]: {log}"),
)
```
#### Process.get\_entrypoint\_logs
```python
@intercept_errors(message_prefix="Failed to get entrypoint logs: ")
@with_instrumentation()
def get_entrypoint_logs() -> SessionCommandLogsResponse
```
Get the logs for the entrypoint session.
**Returns**:
- `SessionCommandLogsResponse` - Command logs including:
- output: Combined command output (stdout and stderr)
- stdout: Standard output from the command
- stderr: Standard error from the command
**Example**:
```python
logs = sandbox.process.get_entrypoint_logs()
print(f"Command stdout: {logs.stdout}")
print(f"Command stderr: {logs.stderr}")
```
#### Process.get\_entrypoint\_logs\_async
```python
@intercept_errors(message_prefix="Failed to get entrypoint logs: ")
async def get_entrypoint_logs_async(on_stdout: OutputHandler[str],
on_stderr: OutputHandler[str]) -> None
```
Asynchronously retrieves and processes the logs for the entrypoint session as they become available.
**Arguments**:
on_stdout OutputHandler[str]: Callback function to handle stdout log chunks as they arrive.
on_stderr OutputHandler[str]: Callback function to handle stderr log chunks as they arrive.
**Example**:
```python
await sandbox.process.get_entrypoint_logs_async(
lambda log: print(f"[STDOUT]: {log}"),
lambda log: print(f"[STDERR]: {log}"),
)
```
#### Process.send\_session\_command\_input
```python
@intercept_errors(message_prefix="Failed to send session command input: ")
def send_session_command_input(session_id: str, command_id: str,
data: str) -> None
```
Sends input data to a command executed in a session.
**Arguments**:
- `session_id` _str_ - Unique identifier of the session.
- `command_id` _str_ - Unique identifier of the command.
- `data` _str_ - Input data to send.
#### Process.list\_sessions
```python
@intercept_errors(message_prefix="Failed to list sessions: ")
@with_instrumentation()
def list_sessions() -> list[Session]
```
Lists all sessions in the Sandbox.
**Returns**:
- `list[Session]` - List of all sessions in the Sandbox.
**Example**:
```python
sessions = sandbox.process.list_sessions()
for session in sessions:
print(f"Session {session.session_id}:")
print(f" Commands: {len(session.commands)}")
```
#### Process.delete\_session
```python
@intercept_errors(message_prefix="Failed to delete session: ")
@with_instrumentation()
def delete_session(session_id: str) -> None
```
Terminates and removes a session from the Sandbox, cleaning up any resources
associated with it.
**Arguments**:
- `session_id` _str_ - Unique identifier of the session to delete.
**Example**:
```python
# Create and use a session
sandbox.process.create_session("temp-session")
# ... use the session ...
# Clean up when done
sandbox.process.delete_session("temp-session")
```
#### Process.create\_pty\_session
```python
@intercept_errors(message_prefix="Failed to create PTY session: ")
@with_instrumentation()
def create_pty_session(id: str,
cwd: str | None = None,
envs: dict[str, str] | None = None,
pty_size: PtySize | None = None) -> PtyHandle
```
Creates a new PTY (pseudo-terminal) session in the Sandbox.
Creates an interactive terminal session that can execute commands and handle user input.
The PTY session behaves like a real terminal, supporting features like command history.
**Arguments**:
- `id` - Unique identifier for the PTY session. Must be unique within the Sandbox.
- `cwd` - Working directory for the PTY session. Defaults to the sandbox's working directory.
- `env` - Environment variables to set in the PTY session. These will be merged with
the Sandbox's default environment variables.
- `pty_size` - Terminal size configuration. Defaults to 80x24 if not specified.
**Returns**:
- `PtyHandle` - Handle for managing the created PTY session. Use this to send input,
receive output, resize the terminal, and manage the session lifecycle.
**Raises**:
- `DaytonaError` - If the PTY session creation fails or the session ID is already in use.
#### Process.connect\_pty\_session
```python
@intercept_errors(message_prefix="Failed to connect PTY session: ")
@with_instrumentation()
def connect_pty_session(session_id: str) -> PtyHandle
```
Connects to an existing PTY session in the Sandbox.
Establishes a WebSocket connection to an existing PTY session, allowing you to
interact with a previously created terminal session.
**Arguments**:
- `session_id` - Unique identifier of the PTY session to connect to.
**Returns**:
- `PtyHandle` - Handle for managing the connected PTY session.
**Raises**:
- `DaytonaError` - If the PTY session doesn't exist or connection fails.
#### Process.list\_pty\_sessions
```python
@intercept_errors(message_prefix="Failed to list PTY sessions: ")
@with_instrumentation()
def list_pty_sessions() -> list[PtySessionInfo]
```
Lists all PTY sessions in the Sandbox.
Retrieves information about all PTY sessions in this Sandbox.
**Returns**:
- `list[PtySessionInfo]` - List of PTY session information objects containing
details about each session's state, creation time, and configuration.
**Example**:
```python
# List all PTY sessions
sessions = sandbox.process.list_pty_sessions()
for session in sessions:
print(f"Session ID: {session.id}")
print(f"Active: {session.active}")
print(f"Created: {session.created_at}")
```
#### Process.get\_pty\_session\_info
```python
@intercept_errors(message_prefix="Failed to get PTY session info: ")
@with_instrumentation()
def get_pty_session_info(session_id: str) -> PtySessionInfo
```
Gets detailed information about a specific PTY session.
Retrieves comprehensive information about a PTY session including its current state,
configuration, and metadata.
**Arguments**:
- `session_id` - Unique identifier of the PTY session to retrieve information for.
**Returns**:
- `PtySessionInfo` - Detailed information about the PTY session including ID, state,
creation time, working directory, environment variables, and more.
**Raises**:
- `DaytonaError` - If the PTY session doesn't exist.
**Example**:
```python
# Get details about a specific PTY session
session_info = sandbox.process.get_pty_session_info("my-session")
print(f"Session ID: {session_info.id}")
print(f"Active: {session_info.active}")
print(f"Working Directory: {session_info.cwd}")
print(f"Terminal Size: {session_info.cols}x{session_info.rows}")
```
#### Process.kill\_pty\_session
```python
@intercept_errors(message_prefix="Failed to kill PTY session: ")
@with_instrumentation()
def kill_pty_session(session_id: str) -> None
```
Kills a PTY session and terminates its associated process.
Forcefully terminates the PTY session and cleans up all associated resources.
This will close any active connections and kill the underlying shell process.
This operation is irreversible. Any unsaved work in the terminal session will be lost.
**Arguments**:
- `session_id` - Unique identifier of the PTY session to kill.
**Raises**:
- `DaytonaError` - If the PTY session doesn't exist or cannot be killed.
**Example**:
```python
# Kill a specific PTY session
sandbox.process.kill_pty_session("my-session")
# Verify the session no longer exists
pty_sessions = sandbox.process.list_pty_sessions()
for pty_session in pty_sessions:
print(f"PTY session: {pty_session.id}")
```
#### Process.resize\_pty\_session
```python
@intercept_errors(message_prefix="Failed to resize PTY session: ")
@with_instrumentation()
def resize_pty_session(session_id: str, pty_size: PtySize) -> PtySessionInfo
```
Resizes a PTY session's terminal dimensions.
Changes the terminal size of an active PTY session. This is useful when the
client terminal is resized or when you need to adjust the display for different
output requirements.
**Arguments**:
- `session_id` - Unique identifier of the PTY session to resize.
- `pty_size` - New terminal dimensions containing the desired columns and rows.
**Returns**:
- `PtySessionInfo` - Updated session information reflecting the new terminal size.
**Raises**:
- `DaytonaError` - If the PTY session doesn't exist or resize operation fails.
**Example**:
```python
from daytona.common.pty import PtySize
# Resize a PTY session to a larger terminal
new_size = PtySize(rows=40, cols=150)
updated_info = sandbox.process.resize_pty_session("my-session", new_size)
print(f"Terminal resized to {updated_info.cols}x{updated_info.rows}")
# You can also use the PtyHandle's resize method
pty_handle.resize(new_size)
```
## CodeRunParams
```python
@dataclass
class CodeRunParams()
```
Parameters for code execution.
**Attributes**:
- `argv` _list[str] | None_ - Command line arguments
- `env` _dict[str, str] | None_ - Environment variables
## SessionExecuteRequest
```python
class SessionExecuteRequest(ApiSessionExecuteRequest,
AsyncApiSessionExecuteRequest)
```
Contains the request for executing a command in a session.
**Attributes**:
- `command` _str_ - The command to execute.
- `run_async` _bool | None_ - Whether to execute the command asynchronously.
- `var_async` _bool | None_ - Deprecated. Use `run_async` instead.
- `suppress_input_echo` _bool | None_ - Whether to suppress input echo. Default is `False`.
## ExecutionArtifacts
```python
@dataclass
class ExecutionArtifacts()
```
Artifacts from the command execution.
**Attributes**:
- `stdout` _str_ - Standard output from the command, same as `result` in `ExecuteResponse`
- `charts` _list[Chart] | None_ - List of chart metadata from matplotlib
## ExecuteResponse
```python
class ExecuteResponse(BaseModel)
```
Response from the command execution.
**Attributes**:
- `exit_code` _int_ - The exit code from the command execution
- `result` _str_ - The output from the command execution
- `artifacts` _ExecutionArtifacts | None_ - Artifacts from the command execution
## SessionExecuteResponse
```python
class SessionExecuteResponse(ApiSessionExecuteResponse)
```
Response from the session command execution.
**Attributes**:
- `cmd_id` _str_ - The ID of the executed command
- `stdout` _str | None_ - The stdout from the command execution
- `stderr` _str | None_ - The stderr from the command execution
- `output` _str_ - The output from the command execution
- `exit_code` _int_ - The exit code from the command execution
## SessionCommandLogsResponse
```python
@dataclass
class SessionCommandLogsResponse()
```
Response from the command logs.
**Attributes**:
- `output` _str | None_ - The combined output from the command
- `stdout` _str | None_ - The stdout from the command
- `stderr` _str | None_ - The stderr from the command
#### parse\_session\_command\_logs
```python
def parse_session_command_logs(data: bytes) -> SessionCommandLogsResponse
```
Parse combined stdout/stderr output into separate streams.
**Arguments**:
- `data` - Combined log bytes with STDOUT_PREFIX and STDERR_PREFIX markers
**Returns**:
SessionCommandLogsResponse with separated stdout and stderr
#### demux\_log
```python
def demux_log(data: bytes) -> tuple[bytes, bytes]
```
Demultiplex combined stdout/stderr log data.
**Arguments**:
- `data` - Combined log bytes with STDOUT_PREFIX and STDERR_PREFIX markers
**Returns**:
Tuple of (stdout_bytes, stderr_bytes)
##### OutputHandler
```python
OutputHandler = Union[
Callable[[T], None],
Callable[[T], Awaitable[None]],
]
```
Callback type that accepts both sync and async handlers.
Blocking synchronous operations inside handlers may cause WebSocket disconnections.
## Sandbox
```python
class Sandbox(SandboxDto)
```
Represents a Daytona Sandbox.
**Attributes**:
- `fs` _FileSystem_ - File system operations interface.
- `git` _Git_ - Git operations interface.
- `process` _Process_ - Process execution interface.
- `computer_use` _ComputerUse_ - Computer use operations interface for desktop automation.
- `code_interpreter` _CodeInterpreter_ - Stateful interpreter interface for executing code.
Currently supports only Python. For other languages, use the `process.code_run` interface.
- `id` _str_ - Unique identifier for the Sandbox.
- `name` _str_ - Name of the Sandbox.
- `organization_id` _str_ - Organization ID of the Sandbox.
- `snapshot` _str_ - Daytona snapshot used to create the Sandbox.
- `user` _str_ - OS user running in the Sandbox.
- `env` _dict[str, str]_ - Environment variables set in the Sandbox.
- `labels` _dict[str, str]_ - Custom labels attached to the Sandbox.
- `public` _bool_ - Whether the Sandbox is publicly accessible.
- `target` _str_ - Target location of the runner where the Sandbox runs.
- `cpu` _int_ - Number of CPUs allocated to the Sandbox.
- `gpu` _int_ - Number of GPUs allocated to the Sandbox.
- `memory` _int_ - Amount of memory allocated to the Sandbox in GiB.
- `disk` _int_ - Amount of disk space allocated to the Sandbox in GiB.
- `state` _SandboxState_ - Current state of the Sandbox (e.g., "started", "stopped").
- `error_reason` _str_ - Error message if Sandbox is in error state.
- `recoverable` _bool_ - Whether the Sandbox error is recoverable.
- `backup_state` _SandboxBackupStateEnum_ - Current state of Sandbox backup.
- `backup_created_at` _str_ - When the backup was created.
- `auto_stop_interval` _int_ - Auto-stop interval in minutes.
- `auto_archive_interval` _int_ - Auto-archive interval in minutes.
- `auto_delete_interval` _int_ - Auto-delete interval in minutes.
- `volumes` _list[str]_ - Volumes attached to the Sandbox.
- `build_info` _str_ - Build information for the Sandbox if it was created from dynamic build.
- `created_at` _str_ - When the Sandbox was created.
- `updated_at` _str_ - When the Sandbox was last updated.
- `network_block_all` _bool_ - Whether to block all network access for the Sandbox.
- `network_allow_list` _str_ - Comma-separated list of allowed CIDR network addresses for the Sandbox.
#### Sandbox.\_\_init\_\_
```python
def __init__(sandbox_dto: SandboxDto, toolbox_api: ApiClient,
sandbox_api: SandboxApi, code_toolbox: SandboxCodeToolbox)
```
Initialize a new Sandbox instance.
**Arguments**:
- `sandbox_dto` _SandboxDto_ - The sandbox data from the API.
- `toolbox_api` _ApiClient_ - API client for toolbox operations.
- `sandbox_api` _SandboxApi_ - API client for Sandbox operations.
- `code_toolbox` _SandboxCodeToolbox_ - Language-specific toolbox implementation.
#### Sandbox.refresh\_data
```python
@intercept_errors(message_prefix="Failed to refresh sandbox data: ")
@with_instrumentation()
def refresh_data() -> None
```
Refreshes the Sandbox data from the API.
**Example**:
```python
sandbox.refresh_data()
print(f"Sandbox {sandbox.id}:")
print(f"State: {sandbox.state}")
print(f"Resources: {sandbox.cpu} CPU, {sandbox.memory} GiB RAM")
```
#### Sandbox.get\_user\_home\_dir
```python
@intercept_errors(message_prefix="Failed to get user home directory: ")
@with_instrumentation()
def get_user_home_dir() -> str
```
Gets the user's home directory path inside the Sandbox.
**Returns**:
- `str` - The absolute path to the user's home directory inside the Sandbox.
**Example**:
```python
user_home_dir = sandbox.get_user_home_dir()
print(f"Sandbox user home: {user_home_dir}")
```
#### Sandbox.get\_work\_dir
```python
@intercept_errors(message_prefix="Failed to get working directory path: ")
@with_instrumentation()
def get_work_dir() -> str
```
Gets the working directory path inside the Sandbox.
**Returns**:
- `str` - The absolute path to the Sandbox working directory. Uses the WORKDIR specified in
the Dockerfile if present, or falling back to the user's home directory if not.
**Example**:
```python
work_dir = sandbox.get_work_dir()
print(f"Sandbox working directory: {work_dir}")
```
#### Sandbox.create\_lsp\_server
```python
@with_instrumentation()
def create_lsp_server(language_id: LspLanguageId | LspLanguageIdLiteral,
path_to_project: str) -> LspServer
```
Creates a new Language Server Protocol (LSP) server instance.
The LSP server provides language-specific features like code completion,
diagnostics, and more.
**Arguments**:
- `language_id` _LspLanguageId | LspLanguageIdLiteral_ - The language server type (e.g., LspLanguageId.PYTHON).
- `path_to_project` _str_ - Path to the project root directory. Relative paths are resolved
based on the sandbox working directory.
**Returns**:
- `LspServer` - A new LSP server instance configured for the specified language.
**Example**:
```python
lsp = sandbox.create_lsp_server("python", "workspace/project")
```
#### Sandbox.set\_labels
```python
@intercept_errors(message_prefix="Failed to set labels: ")
@with_instrumentation()
def set_labels(labels: dict[str, str]) -> dict[str, str]
```
Sets labels for the Sandbox.
Labels are key-value pairs that can be used to organize and identify Sandboxes.
**Arguments**:
- `labels` _dict[str, str]_ - Dictionary of key-value pairs representing Sandbox labels.
**Returns**:
dict[str, str]: Dictionary containing the updated Sandbox labels.
**Example**:
```python
new_labels = sandbox.set_labels({
"project": "my-project",
"environment": "development",
"team": "backend"
})
print(f"Updated labels: {new_labels}")
```
#### Sandbox.start
```python
@intercept_errors(message_prefix="Failed to start sandbox: ")
@with_timeout()
@with_instrumentation()
def start(timeout: float | None = 60)
```
Starts the Sandbox and waits for it to be ready.
**Arguments**:
- `timeout` _float | None_ - Maximum time to wait in seconds. 0 means no timeout. Default is 60 seconds.
**Raises**:
- `DaytonaError` - If timeout is negative. If sandbox fails to start or times out.
**Example**:
```python
sandbox = daytona.get("my-sandbox-id")
sandbox.start(timeout=40) # Wait up to 40 seconds
print("Sandbox started successfully")
```
#### Sandbox.recover
```python
@intercept_errors(message_prefix="Failed to recover sandbox: ")
@with_timeout()
def recover(timeout: float | None = 60)
```
Recovers the Sandbox from a recoverable error and waits for it to be ready.
**Arguments**:
- `timeout` _float | None_ - Maximum time to wait in seconds. 0 means no timeout. Default is 60 seconds.
**Raises**:
- `DaytonaError` - If timeout is negative. If sandbox fails to recover or times out.
**Example**:
```python
sandbox = daytona.get("my-sandbox-id")
sandbox.recover(timeout=40) # Wait up to 40 seconds
print("Sandbox recovered successfully")
```
#### Sandbox.stop
```python
@intercept_errors(message_prefix="Failed to stop sandbox: ")
@with_timeout()
@with_instrumentation()
def stop(timeout: float | None = 60)
```
Stops the Sandbox and waits for it to be fully stopped.
**Arguments**:
- `timeout` _float | None_ - Maximum time to wait in seconds. 0 means no timeout. Default is 60 seconds.
**Raises**:
- `DaytonaError` - If timeout is negative; If sandbox fails to stop or times out
**Example**:
```python
sandbox = daytona.get("my-sandbox-id")
sandbox.stop()
print("Sandbox stopped successfully")
```
#### Sandbox.delete
```python
@intercept_errors(message_prefix="Failed to remove sandbox: ")
@with_instrumentation()
def delete(timeout: float | None = 60) -> None
```
Deletes the Sandbox.
**Arguments**:
- `timeout` _float | None_ - Timeout (in seconds) for sandbox deletion. 0 means no timeout.
Default is 60 seconds.
#### Sandbox.wait\_for\_sandbox\_start
```python
@intercept_errors(
message_prefix="Failure during waiting for sandbox to start: ")
@with_timeout()
@with_instrumentation()
def wait_for_sandbox_start(timeout: float | None = 60) -> None
```
Waits for the Sandbox to reach the 'started' state. Polls the Sandbox status until it
reaches the 'started' state, encounters an error or times out.
**Arguments**:
- `timeout` _float | None_ - Maximum time to wait in seconds. 0 means no timeout. Default is 60 seconds.
**Raises**:
- `DaytonaError` - If timeout is negative; If Sandbox fails to start or times out
#### Sandbox.wait\_for\_sandbox\_stop
```python
@intercept_errors(
message_prefix="Failure during waiting for sandbox to stop: ")
@with_timeout()
@with_instrumentation()
def wait_for_sandbox_stop(timeout: float | None = 60) -> None
```
Waits for the Sandbox to reach the 'stopped' state. Polls the Sandbox status until it
reaches the 'stopped' state, encounters an error or times out. It will wait up to 60 seconds
for the Sandbox to stop.
Treats destroyed as stopped to cover ephemeral sandboxes that are automatically deleted after stopping.
**Arguments**:
- `timeout` _float | None_ - Maximum time to wait in seconds. 0 means no timeout. Default is 60 seconds.
**Raises**:
- `DaytonaError` - If timeout is negative. If Sandbox fails to stop or times out.
#### Sandbox.set\_autostop\_interval
```python
@intercept_errors(message_prefix="Failed to set auto-stop interval: ")
@with_instrumentation()
def set_autostop_interval(interval: int) -> None
```
Sets the auto-stop interval for the Sandbox.
The Sandbox will automatically stop after being idle (no new events) for the specified interval.
Events include any state changes or interactions with the Sandbox through the SDK.
Interactions using Sandbox Previews are not included.
**Arguments**:
- `interval` _int_ - Number of minutes of inactivity before auto-stopping.
Set to 0 to disable auto-stop. Defaults to 15.
**Raises**:
- `DaytonaError` - If interval is negative
**Example**:
```python
# Auto-stop after 1 hour
sandbox.set_autostop_interval(60)
# Or disable auto-stop
sandbox.set_autostop_interval(0)
```
#### Sandbox.set\_auto\_archive\_interval
```python
@intercept_errors(message_prefix="Failed to set auto-archive interval: ")
@with_instrumentation()
def set_auto_archive_interval(interval: int) -> None
```
Sets the auto-archive interval for the Sandbox.
The Sandbox will automatically archive after being continuously stopped for the specified interval.
**Arguments**:
- `interval` _int_ - Number of minutes after which a continuously stopped Sandbox will be auto-archived.
Set to 0 for the maximum interval. Default is 7 days.
**Raises**:
- `DaytonaError` - If interval is negative
**Example**:
```python
# Auto-archive after 1 hour
sandbox.set_auto_archive_interval(60)
# Or use the maximum interval
sandbox.set_auto_archive_interval(0)
```
#### Sandbox.set\_auto\_delete\_interval
```python
@intercept_errors(message_prefix="Failed to set auto-delete interval: ")
@with_instrumentation()
def set_auto_delete_interval(interval: int) -> None
```
Sets the auto-delete interval for the Sandbox.
The Sandbox will automatically delete after being continuously stopped for the specified interval.
**Arguments**:
- `interval` _int_ - Number of minutes after which a continuously stopped Sandbox will be auto-deleted.
Set to negative value to disable auto-delete. Set to 0 to delete immediately upon stopping.
By default, auto-delete is disabled.
**Example**:
```python
# Auto-delete after 1 hour
sandbox.set_auto_delete_interval(60)
# Or delete immediately upon stopping
sandbox.set_auto_delete_interval(0)
# Or disable auto-delete
sandbox.set_auto_delete_interval(-1)
```
#### Sandbox.get\_preview\_link
```python
@intercept_errors(message_prefix="Failed to get preview link: ")
@with_instrumentation()
def get_preview_link(port: int) -> PortPreviewUrl
```
Retrieves the preview link for the sandbox at the specified port. If the port is closed,
it will be opened automatically. For private sandboxes, a token is included to grant access
to the URL.
**Arguments**:
- `port` _int_ - The port to open the preview link on.
**Returns**:
- `PortPreviewUrl` - The response object for the preview link, which includes the `url`
and the `token` (to access private sandboxes).
**Example**:
```python
preview_link = sandbox.get_preview_link(3000)
print(f"Preview URL: {preview_link.url}")
print(f"Token: {preview_link.token}")
```
#### Sandbox.create\_signed\_preview\_url
```python
@intercept_errors(message_prefix="Failed to create signed preview url: ")
def create_signed_preview_url(
port: int,
expires_in_seconds: int | None = None) -> SignedPortPreviewUrl
```
Creates a signed preview URL for the sandbox at the specified port.
**Arguments**:
- `port` _int_ - The port to open the preview link on.
- `expires_in_seconds` _int | None_ - The number of seconds the signed preview
url will be valid for. Defaults to 60 seconds.
**Returns**:
- `SignedPortPreviewUrl` - The response object for the signed preview url.
#### Sandbox.expire\_signed\_preview\_url
```python
@intercept_errors(message_prefix="Failed to expire signed preview url: ")
def expire_signed_preview_url(port: int, token: str) -> None
```
Expires a signed preview URL for the sandbox at the specified port.
**Arguments**:
- `port` _int_ - The port to expire the signed preview url on.
- `token` _str_ - The token to expire the signed preview url on.
#### Sandbox.archive
```python
@intercept_errors(message_prefix="Failed to archive sandbox: ")
@with_instrumentation()
def archive() -> None
```
Archives the sandbox, making it inactive and preserving its state. When sandboxes are
archived, the entire filesystem state is moved to cost-effective object storage, making it
possible to keep sandboxes available for an extended period. The tradeoff between archived
and stopped states is that starting an archived sandbox takes more time, depending on its size.
Sandbox must be stopped before archiving.
#### Sandbox.resize
```python
@intercept_errors(message_prefix="Failed to resize sandbox: ")
@with_timeout()
@with_instrumentation()
def resize(resources: Resources, timeout: float | None = 60) -> None
```
Resizes the Sandbox resources.
Changes the CPU, memory, or disk allocation for the Sandbox. Hot resize (on running
sandbox) only allows CPU/memory increases. Disk resize requires a stopped sandbox.
**Arguments**:
- `resources` _Resources_ - New resource configuration. Only specified fields will be updated.
- cpu: Number of CPU cores (minimum: 1). For hot resize, can only be increased.
- memory: Memory in GiB (minimum: 1). For hot resize, can only be increased.
- disk: Disk space in GiB (can only be increased, requires stopped sandbox).
- `timeout` _Optional[float]_ - Timeout (in seconds) for the resize operation. 0 means no timeout.
Default is 60 seconds.
**Raises**:
- `DaytonaError` - If hot resize constraints are violated (CPU/memory decrease on running sandbox).
- `DaytonaError` - If disk resize attempted on running sandbox.
- `DaytonaError` - If disk size decrease is attempted.
- `DaytonaError` - If resize operation times out.
- `DaytonaError` - If no resource changes are specified.
**Example**:
```python
# Increase CPU/memory on running sandbox (hot resize)
sandbox.resize(Resources(cpu=4, memory=8))
# Change disk (sandbox must be stopped)
sandbox.stop()
sandbox.resize(Resources(cpu=2, memory=4, disk=30))
```
#### Sandbox.wait\_for\_resize\_complete
```python
@intercept_errors(
message_prefix="Failure during waiting for resize to complete: ")
@with_timeout()
@with_instrumentation()
def wait_for_resize_complete(timeout: float | None = 60) -> None
```
Waits for the Sandbox resize operation to complete. Polls the Sandbox status until
the state is no longer 'resizing'.
**Arguments**:
- `timeout` _Optional[float]_ - Maximum time to wait in seconds. 0 means no timeout. Default is 60 seconds.
**Raises**:
- `DaytonaError` - If timeout is negative. If resize operation times out.
#### Sandbox.create\_ssh\_access
```python
@intercept_errors(message_prefix="Failed to create SSH access: ")
@with_instrumentation()
def create_ssh_access(expires_in_minutes: int | None = None) -> SshAccessDto
```
Creates an SSH access token for the sandbox.
**Arguments**:
- `expires_in_minutes` _int | None_ - The number of minutes the SSH access token will be valid for.
#### Sandbox.revoke\_ssh\_access
```python
@intercept_errors(message_prefix="Failed to revoke SSH access: ")
@with_instrumentation()
def revoke_ssh_access(token: str) -> None
```
Revokes an SSH access token for the sandbox.
**Arguments**:
- `token` _str_ - The token to revoke.
#### Sandbox.validate\_ssh\_access
```python
@intercept_errors(message_prefix="Failed to validate SSH access: ")
@with_instrumentation()
def validate_ssh_access(token: str) -> SshAccessValidationDto
```
Validates an SSH access token for the sandbox.
**Arguments**:
- `token` _str_ - The token to validate.
#### Sandbox.refresh\_activity
```python
@intercept_errors(message_prefix="Failed to refresh sandbox activity: ")
def refresh_activity() -> None
```
Refreshes the sandbox activity to reset the timer for automated lifecycle management actions.
This method updates the sandbox's last activity timestamp without changing its state.
It is useful for keeping long-running sessions alive while there is still user activity.
**Example**:
```python
sandbox.refresh_activity()
```
## PaginatedSandboxes
```python
class PaginatedSandboxes(PaginatedSandboxesDto)
```
Represents a paginated list of Daytona Sandboxes.
**Attributes**:
- `items` _list[Sandbox]_ - List of Sandbox instances in the current page.
- `total` _int_ - Total number of Sandboxes across all pages.
- `page` _int_ - Current page number.
- `total_pages` _int_ - Total number of pages available.
##### items: `list[Sandbox]`
```python
items = None
```
pyright: ignore[reportIncompatibleVariableOverride]
## Resources
```python
@dataclass
class Resources()
```
Resources configuration for Sandbox.
**Attributes**:
- `cpu` _int | None_ - Number of CPU cores to allocate.
- `memory` _int | None_ - Amount of memory in GiB to allocate.
- `disk` _int | None_ - Amount of disk space in GiB to allocate.
- `gpu` _int | None_ - Number of GPUs to allocate.
**Example**:
```python
resources = Resources(
cpu=2,
memory=4, # 4GiB RAM
disk=20, # 20GiB disk
gpu=1
)
params = CreateSandboxFromImageParams(
image=Image.debian_slim("3.12"),
language="python",
resources=resources
)
```
## Snapshot
```python
class Snapshot(SyncSnapshotDto)
```
Represents a Daytona Snapshot which is a pre-configured sandbox.
**Attributes**:
- `id` _str_ - Unique identifier for the Snapshot.
- `organization_id` _str | None_ - Organization ID of the Snapshot.
- `general` _bool_ - Whether the Snapshot is general.
- `name` _str_ - Name of the Snapshot.
- `image_name` _str_ - Name of the Image of the Snapshot.
- `state` _str_ - State of the Snapshot.
- `size` _float | int | None_ - Size of the Snapshot.
- `entrypoint` _list[str] | None_ - Entrypoint of the Snapshot.
- `cpu` _float | int_ - CPU of the Snapshot.
- `gpu` _float | int_ - GPU of the Snapshot.
- `mem` _float | int_ - Memory of the Snapshot in GiB.
- `disk` _float | int_ - Disk of the Snapshot in GiB.
- `error_reason` _str | None_ - Error reason of the Snapshot.
- `created_at` _str_ - Timestamp when the Snapshot was created.
- `updated_at` _str_ - Timestamp when the Snapshot was last updated.
- `last_used_at` _str_ - Timestamp when the Snapshot was last used.
## SnapshotService
```python
class SnapshotService()
```
Service for managing Daytona Snapshots. Can be used to list, get, create and delete Snapshots.
#### SnapshotService.list
```python
@intercept_errors(message_prefix="Failed to list snapshots: ")
@with_instrumentation()
def list(page: int | None = None,
limit: int | None = None) -> PaginatedSnapshots
```
Returns paginated list of Snapshots.
**Arguments**:
- `page` _int | None_ - Page number for pagination (starting from 1).
- `limit` _int | None_ - Maximum number of items per page.
**Returns**:
- `PaginatedSnapshots` - Paginated list of Snapshots.
**Example**:
```python
daytona = Daytona()
result = daytona.snapshot.list(page=2, limit=10)
for snapshot in result.items:
print(f"{snapshot.name} ({snapshot.image_name})")
```
#### SnapshotService.delete
```python
@intercept_errors(message_prefix="Failed to delete snapshot: ")
@with_instrumentation()
def delete(snapshot: Snapshot) -> None
```
Delete a Snapshot.
**Arguments**:
- `snapshot` _Snapshot_ - Snapshot to delete.
**Example**:
```python
daytona = Daytona()
snapshot = daytona.snapshot.get("test-snapshot")
daytona.snapshot.delete(snapshot)
print("Snapshot deleted")
```
#### SnapshotService.get
```python
@intercept_errors(message_prefix="Failed to get snapshot: ")
@with_instrumentation()
def get(name: str) -> Snapshot
```
Get a Snapshot by name.
**Arguments**:
- `name` _str_ - Name of the Snapshot to get.
**Returns**:
- `Snapshot` - The Snapshot object.
**Example**:
```python
daytona = Daytona()
snapshot = daytona.snapshot.get("test-snapshot-name")
print(f"{snapshot.name} ({snapshot.image_name})")
```
#### SnapshotService.create
```python
@intercept_errors(message_prefix="Failed to create snapshot: ")
@with_timeout()
@with_instrumentation()
def create(params: CreateSnapshotParams,
*,
on_logs: Callable[[str], None] | None = None,
timeout: float | None = 0) -> Snapshot
```
Creates and registers a new snapshot from the given Image definition.
**Arguments**:
- `params` _CreateSnapshotParams_ - Parameters for snapshot creation.
- `on_logs` _Callable[[str], None]_ - This callback function handles snapshot creation logs.
- `timeout` _float | None_ - Default is no timeout. Timeout in seconds (0 means no timeout).
**Example**:
```python
image = Image.debianSlim('3.12').pipInstall('numpy')
daytona.snapshot.create(
CreateSnapshotParams(name='my-snapshot', image=image),
on_logs=lambda chunk: print(chunk, end=""),
)
```
#### SnapshotService.activate
```python
@with_instrumentation()
def activate(snapshot: Snapshot) -> Snapshot
```
Activate a snapshot.
**Arguments**:
- `snapshot` _Snapshot_ - The Snapshot instance.
**Returns**:
- `Snapshot` - The activated Snapshot instance.
#### SnapshotService.process\_image\_context
```python
@staticmethod
@with_instrumentation()
def process_image_context(object_storage_api: ObjectStorageApi,
image: Image) -> list[str]
```
Processes the image context by uploading it to object storage.
**Arguments**:
- `image` _Image_ - The Image instance.
**Returns**:
- `list[str]` - List of context hashes stored in object storage.
## PaginatedSnapshots
```python
class PaginatedSnapshots(PaginatedSnapshotsDto)
```
Represents a paginated list of Daytona Snapshots.
**Attributes**:
- `items` _list[Snapshot]_ - List of Snapshot instances in the current page.
- `total` _int_ - Total number of Snapshots across all pages.
- `page` _int_ - Current page number.
- `total_pages` _int_ - Total number of pages available.
## CreateSnapshotParams
```python
class CreateSnapshotParams(BaseModel)
```
Parameters for creating a new snapshot.
**Attributes**:
- `name` _str_ - Name of the snapshot.
- `image` _str | Image_ - Image of the snapshot. If a string is provided,
it should be available on some registry. If an Image instance is provided,
it will be used to create a new image in Daytona.
- `resources` _Resources | None_ - Resources of the snapshot.
- `entrypoint` _list[str] | None_ - Entrypoint of the snapshot.
- `region_id` _str | None_ - ID of the region where the snapshot will be available.
Defaults to organization default region if not specified.
## Volume
```python
class Volume(VolumeDto)
```
Represents a Daytona Volume which is a shared storage volume for Sandboxes.
**Attributes**:
- `id` _str_ - Unique identifier for the Volume.
- `name` _str_ - Name of the Volume.
- `organization_id` _str_ - Organization ID of the Volume.
- `state` _str_ - State of the Volume.
- `created_at` _str_ - Date and time when the Volume was created.
- `updated_at` _str_ - Date and time when the Volume was last updated.
- `last_used_at` _str_ - Date and time when the Volume was last used.
## VolumeService
```python
class VolumeService()
```
Service for managing Daytona Volumes. Can be used to list, get, create and delete Volumes.
#### VolumeService.list
```python
def list() -> list[Volume]
```
List all Volumes.
**Returns**:
- `list[Volume]` - List of all Volumes.
**Example**:
```python
daytona = Daytona()
volumes = daytona.volume.list()
for volume in volumes:
print(f"{volume.name} ({volume.id})")
```
#### VolumeService.get
```python
@with_instrumentation()
def get(name: str, create: bool = False) -> Volume
```
Get a Volume by name.
**Arguments**:
- `name` _str_ - Name of the Volume to get.
- `create` _bool_ - If True, create a new Volume if it doesn't exist.
**Returns**:
- `Volume` - The Volume object.
**Example**:
```python
daytona = Daytona()
volume = daytona.volume.get("test-volume-name", create=True)
print(f"{volume.name} ({volume.id})")
```
#### VolumeService.create
```python
@with_instrumentation()
def create(name: str) -> Volume
```
Create a new Volume.
**Arguments**:
- `name` _str_ - Name of the Volume to create.
**Returns**:
- `Volume` - The Volume object.
**Example**:
```python
daytona = Daytona()
volume = daytona.volume.create("test-volume")
print(f"{volume.name} ({volume.id}); state: {volume.state}")
```
#### VolumeService.delete
```python
@with_instrumentation()
def delete(volume: Volume) -> None
```
Delete a Volume.
**Arguments**:
- `volume` _Volume_ - Volume to delete.
**Example**:
```python
daytona = Daytona()
volume = daytona.volume.get("test-volume")
daytona.volume.delete(volume)
print("Volume deleted")
```
## VolumeMount
```python
class VolumeMount(ApiVolumeMount, AsyncApiVolumeMount)
```
Represents a Volume mount configuration for a Sandbox.
**Attributes**:
- `volume_id` _str_ - ID of the volume to mount.
- `mount_path` _str_ - Path where the volume will be mounted in the sandbox.
- `subpath` _str | None_ - Optional S3 subpath/prefix within the volume to mount.
When specified, only this prefix will be accessible. When omitted,
the entire volume is mounted.
Sandboxes are isolated runtime environments that run on [runners](https://www.daytona.io/docs/en/runners.md) — machines that form Daytona's compute plane.
Runners are organized into **regions**, which are geographic or logical groupings of compute infrastructure. When creating a sandbox, you can target a specific region, and Daytona will schedule your workload on an available runner within that region.
As a result, you're able to:
- Choose specific geographic locations for reduced latency
- Comply with data residency requirements
- Use your own runner machines for custom regions
- Scale compute resources independently within each custom region
Regions are geographic or logical groupings of runners that execute sandbox workloads. The sandbox region is specified by setting the `target` parameter on initialization:
```python
from daytona import Daytona, DaytonaConfig
# Configure Daytona to use the US region
config = DaytonaConfig(
target="us"
)
# Initialize the Daytona client with the specified configuration
daytona = Daytona(config)
```
```typescript
import { Daytona } from '@daytonaio/sdk';
// Configure Daytona to use the EU region
const daytona: Daytona = new Daytona({
target: "eu"
});
```
```go
package main
import (
"github.com/daytonaio/daytona/libs/sdk-go/pkg/daytona"
"github.com/daytonaio/daytona/libs/sdk-go/pkg/types"
)
// Configure Daytona to use the US region
client, _ := daytona.NewClientWithConfig(&types.DaytonaConfig{
Target: "us",
})
```
```ruby
require 'daytona'
# Configure Daytona to use the EU region
config = Daytona::Config.new(
target: "eu"
)
# Initialize the Daytona client with the specified configuration
daytona = Daytona::Daytona.new(config)
```
### Shared regions
Shared regions are managed by Daytona and available to all organizations. These regions provide immediate access to Daytona's infrastructure without any setup required.
Limits are applied to your organization's default region. For access to a different shared region, contact [sales@daytona.io](mailto:sales@daytona.io).
| Region | Target |
| ------------- | -------- |
| United States | **`us`** |
| Europe | **`eu`** |
### Dedicated regions
Dedicated regions are managed by Daytona and provisioned exclusively for individual organizations. These regions deliver dedicated infrastructure with the operational simplicity of a managed service.
:::note
Contact [sales@daytona.io](mailto:sales@daytona.io) to set up a dedicated region for your organization.
:::
### Custom regions
Custom regions are created and managed by your organization, allowing you to use your own runner machines and scale compute resources independently within each region. This provides maximum control over data locality, compliance, and infrastructure configuration.
Additionally, custom regions have no limits applied for concurrent resource usage, giving you full control over capacity and performance.
For more information, see the [runners](https://www.daytona.io/docs/en/runners.md) guide.
## ComputerUse
Initialize a new ComputerUse instance.
### Constructors
#### new ComputerUse()
```ruby
def initialize(sandbox_id:, toolbox_api:, otel_state:)
```
Initialize a new ComputerUse instance.
**Parameters**:
- `sandbox_id` _String_ - The ID of the sandbox
- `toolbox_api` _DaytonaApiClient:ToolboxApi_ - API client for sandbox operations
- `otel_state` _Daytona:OtelState, nil_ -
**Returns**:
- `ComputerUse` - a new instance of ComputerUse
### Methods
#### sandbox_id()
```ruby
def sandbox_id()
```
**Returns**:
- `String` - The ID of the sandbox
#### toolbox_api()
```ruby
def toolbox_api()
```
**Returns**:
- `DaytonaApiClient:ToolboxApi` - API client for sandbox operations
#### mouse()
```ruby
def mouse()
```
**Returns**:
- `Mouse` - Mouse operations interface
#### keyboard()
```ruby
def keyboard()
```
**Returns**:
- `Keyboard` - Keyboard operations interface
#### screenshot()
```ruby
def screenshot()
```
**Returns**:
- `Screenshot` - Screenshot operations interface
#### display()
```ruby
def display()
```
**Returns**:
- `Display` - Display operations interface
#### recording()
```ruby
def recording()
```
**Returns**:
- `Recording` - Screen recording operations interface
#### start()
```ruby
def start()
```
Starts all computer use processes (Xvfb, xfce4, x11vnc, novnc).
**Returns**:
- `DaytonaApiClient:ComputerUseStartResponse` - Computer use start response
**Raises**:
- `Daytona:Sdk:Error` - If the operation fails
**Examples:**
```ruby
result = sandbox.computer_use.start
puts "Computer use processes started: #{result.message}"
```
#### stop()
```ruby
def stop()
```
Stops all computer use processes.
**Returns**:
- `DaytonaApiClient:ComputerUseStopResponse` - Computer use stop response
**Raises**:
- `Daytona:Sdk:Error` - If the operation fails
**Examples:**
```ruby
result = sandbox.computer_use.stop
puts "Computer use processes stopped: #{result.message}"
```
#### status()
```ruby
def status()
```
Gets the status of all computer use processes.
**Returns**:
- `DaytonaApiClient:ComputerUseStatusResponse` - Status information about all VNC desktop processes
**Raises**:
- `Daytona:Sdk:Error` - If the operation fails
**Examples:**
```ruby
response = sandbox.computer_use.get_status
puts "Computer use status: #{response.status}"
```
#### get_process_status()
```ruby
def get_process_status(process_name:)
```
Gets the status of a specific VNC process.
**Parameters**:
- `process_name` _String_ - Name of the process to check
**Returns**:
- `DaytonaApiClient:ProcessStatusResponse` - Status information about the specific process
**Raises**:
- `Daytona:Sdk:Error` - If the operation fails
**Examples:**
```ruby
xvfb_status = sandbox.computer_use.get_process_status("xvfb")
no_vnc_status = sandbox.computer_use.get_process_status("novnc")
```
#### restart_process()
```ruby
def restart_process(process_name:)
```
Restarts a specific VNC process.
**Parameters**:
- `process_name` _String_ - Name of the process to restart
**Returns**:
- `DaytonaApiClient:ProcessRestartResponse` - Process restart response
**Raises**:
- `Daytona:Sdk:Error` - If the operation fails
**Examples:**
```ruby
result = sandbox.computer_use.restart_process("xfce4")
puts "XFCE4 process restarted: #{result.message}"
```
#### get_process_logs()
```ruby
def get_process_logs(process_name:)
```
Gets logs for a specific VNC process.
**Parameters**:
- `process_name` _String_ - Name of the process to get logs for
**Returns**:
- `DaytonaApiClient:ProcessLogsResponse` - Process logs
**Raises**:
- `Daytona:Sdk:Error` - If the operation fails
**Examples:**
```ruby
logs = sandbox.computer_use.get_process_logs("novnc")
puts "NoVNC logs: #{logs}"
```
#### get_process_errors()
```ruby
def get_process_errors(process_name:)
```
Gets error logs for a specific VNC process.
**Parameters**:
- `process_name` _String_ - Name of the process to get error logs for
**Returns**:
- `DaytonaApiClient:ProcessErrorsResponse` - Process error logs
**Raises**:
- `Daytona:Sdk:Error` - If the operation fails
**Examples:**
```ruby
errors = sandbox.computer_use.get_process_errors("x11vnc")
puts "X11VNC errors: #{errors}"
```
## Config
Main class for a new Daytona::Config object.
### Constructors
#### new Config()
```ruby
def initialize(api_key:, jwt_token:, api_url:, organization_id:, target:, _experimental:)
```
Initializes a new Daytona::Config object.
**Parameters**:
- `api_key` _String, nil_ - Daytona API key. Defaults to ENV['DAYTONA_API_KEY'].
- `jwt_token` _String, nil_ - Daytona JWT token. Defaults to ENV['DAYTONA_JWT_TOKEN'].
- `api_url` _String, nil_ - Daytona API URL. Defaults to ENV['DAYTONA_API_URL'] or Daytona::Config::API_URL.
- `organization_id` _String, nil_ - Daytona organization ID. Defaults to ENV['DAYTONA_ORGANIZATION_ID'].
- `target` _String, nil_ - Daytona target. Defaults to ENV['DAYTONA_TARGET'].
- `_experimental` _Hash, nil_ - Experimental configuration options.
**Returns**:
- `Config` - a new instance of Config
### Methods
#### api_key()
```ruby
def api_key()
```
API key for authentication with the Daytona API
**Returns**:
- `String, nil` - Daytona API key
#### api_key=()
```ruby
def api_key=(value)
```
API key for authentication with the Daytona API
**Returns**:
- `String, nil` - Daytona API key
#### jwt_token()
```ruby
def jwt_token()
```
JWT token for authentication with the Daytona API
**Returns**:
- `String, nil` - Daytona JWT token
#### jwt_token=()
```ruby
def jwt_token=(value)
```
JWT token for authentication with the Daytona API
**Returns**:
- `String, nil` - Daytona JWT token
#### api_url()
```ruby
def api_url()
```
URL of the Daytona API
**Returns**:
- `String, nil` - Daytona API URL
#### api_url=()
```ruby
def api_url=(value)
```
URL of the Daytona API
**Returns**:
- `String, nil` - Daytona API URL
#### organization_id()
```ruby
def organization_id()
```
Organization ID for authentication with the Daytona API
**Returns**:
- `String, nil` - Daytona API URL
#### organization_id=()
```ruby
def organization_id=(value)
```
Organization ID for authentication with the Daytona API
**Returns**:
- `String, nil` - Daytona API URL
#### target()
```ruby
def target()
```
Target environment for sandboxes
**Returns**:
- `String, nil` - Daytona target
#### target=()
```ruby
def target=(value)
```
Target environment for sandboxes
**Returns**:
- `String, nil` - Daytona target
#### _experimental()
```ruby
def _experimental()
```
Experimental configuration options
**Returns**:
- `Hash, nil` - Experimental configuration hash
#### _experimental=()
```ruby
def _experimental=(value)
```
Experimental configuration options
**Returns**:
- `Hash, nil` - Experimental configuration hash
## Daytona
Daytona class for Daytona SDK.
### Constructors
#### new Daytona()
```ruby
def initialize(config)
```
**Parameters**:
- `config` _Daytona:Config_ - Configuration options. Defaults to Daytona::Config.new
**Returns**:
- `Daytona` - a new instance of Daytona
### Methods
#### config()
```ruby
def config()
```
**Returns**:
- `Daytona:Config`
#### api_client()
```ruby
def api_client()
```
**Returns**:
- `DaytonaApiClient`
#### sandbox_api()
```ruby
def sandbox_api()
```
**Returns**:
- `DaytonaApiClient:SandboxApi`
#### volume()
```ruby
def volume()
```
**Returns**:
- `Daytona:VolumeService`
#### object_storage_api()
```ruby
def object_storage_api()
```
**Returns**:
- `DaytonaApiClient:ObjectStorageApi`
#### snapshots_api()
```ruby
def snapshots_api()
```
**Returns**:
- `DaytonaApiClient:SnapshotsApi`
#### snapshot()
```ruby
def snapshot()
```
**Returns**:
- `Daytona:SnapshotService`
#### close()
```ruby
def close()
```
Shuts down OTel providers, flushing any pending telemetry data.
**Returns**:
- `void`
#### create()
```ruby
def create(params, on_snapshot_create_logs:)
```
Creates a sandbox with the specified parameters
**Parameters**:
- `params` _Daytona:CreateSandboxFromSnapshotParams, Daytona:CreateSandboxFromImageParams, Nil_ - Sandbox creation parameters
**Returns**:
- `Daytona:Sandbox` - The created sandbox
**Raises**:
- `Daytona:Sdk:Error` - If auto_stop_interval or auto_archive_interval is negative
#### delete()
```ruby
def delete(sandbox)
```
Deletes a Sandbox.
**Parameters**:
- `sandbox` _Daytona:Sandbox_ -
**Returns**:
- `void`
#### get()
```ruby
def get(id)
```
Gets a Sandbox by its ID.
**Parameters**:
- `id` _String_ -
**Returns**:
- `Daytona:Sandbox`
#### list()
```ruby
def list(labels, page:, limit:)
```
Lists Sandboxes filtered by labels.
**Parameters**:
- `labels` _Hash\_ -
- `page` _Integer, Nil_ -
- `limit` _Integer, Nil_ -
**Returns**:
- `Daytona:PaginatedResource`
**Raises**:
- `Daytona:Sdk:Error` -
#### start()
```ruby
def start(sandbox, timeout)
```
Starts a Sandbox and waits for it to be ready.
**Parameters**:
- `sandbox` _Daytona:Sandbox_ -
- `timeout` _Numeric_ - Maximum wait time in seconds (defaults to 60 s).
**Returns**:
- `void`
#### stop()
```ruby
def stop(sandbox, timeout)
```
Stops a Sandbox and waits for it to be stopped.
**Parameters**:
- `sandbox` _Daytona:Sandbox_ -
- `timeout` _Numeric_ - Maximum wait time in seconds (defaults to 60 s).
**Returns**:
- `void`
## FileSystem
Main class for a new FileSystem instance.
### Constructors
#### new FileSystem()
```ruby
def initialize(sandbox_id:, toolbox_api:, otel_state:)
```
Initializes a new FileSystem instance.
**Parameters**:
- `sandbox_id` _String_ - The Sandbox ID
- `toolbox_api` _DaytonaToolboxApiClient:FileSystemApi_ - API client for Sandbox operations
- `otel_state` _Daytona:OtelState, nil_ -
**Returns**:
- `FileSystem` - a new instance of FileSystem
### Methods
#### sandbox_id()
```ruby
def sandbox_id()
```
**Returns**:
- `String` - The Sandbox ID
#### toolbox_api()
```ruby
def toolbox_api()
```
**Returns**:
- `DaytonaToolboxApiClient:FileSystemApi` - API client for Sandbox operations
#### create_folder()
```ruby
def create_folder(path, mode)
```
Creates a new directory in the Sandbox at the specified path with the given
permissions.
**Parameters**:
- `path` _String_ - Path where the folder should be created. Relative paths are resolved based
on the sandbox working directory.
- `mode` _String_ - Folder permissions in octal format (e.g., "755" for rwxr-xr-x).
**Returns**:
- `void`
**Raises**:
- `Daytona:Sdk:Error` - If the operation fails
**Examples:**
```ruby
# Create a directory with standard permissions
sandbox.fs.create_folder("workspace/data", "755")
# Create a private directory
sandbox.fs.create_folder("workspace/secrets", "700")
```
#### delete_file()
```ruby
def delete_file(path, recursive:)
```
Deletes a file from the Sandbox.
**Parameters**:
- `path` _String_ - Path to the file to delete. Relative paths are resolved based on the sandbox working directory.
- `recursive` _Boolean_ - If the file is a directory, this must be true to delete it.
**Returns**:
- `void`
**Raises**:
- `Daytona:Sdk:Error` - If the operation fails
**Examples:**
```ruby
# Delete a file
sandbox.fs.delete_file("workspace/data/old_file.txt")
# Delete a directory recursively
sandbox.fs.delete_file("workspace/old_dir", recursive: true)
```
#### get_file_info()
```ruby
def get_file_info(path)
```
Gets detailed information about a file or directory, including its
size, permissions, and timestamps.
**Parameters**:
- `path` _String_ - Path to the file or directory. Relative paths are resolved based
on the sandbox working directory.
**Returns**:
- `DaytonaApiClient:FileInfo` - Detailed file information
**Raises**:
- `Daytona:Sdk:Error` - If the operation fails
**Examples:**
```ruby
# Get file metadata
info = sandbox.fs.get_file_info("workspace/data/file.txt")
puts "Size: #{info.size} bytes"
puts "Modified: #{info.mod_time}"
puts "Mode: #{info.mode}"
# Check if path is a directory
info = sandbox.fs.get_file_info("workspace/data")
puts "Path is a directory" if info.is_dir
```
#### list_files()
```ruby
def list_files(path)
```
Lists files and directories in a given path and returns their information, similar to the ls -l command.
**Parameters**:
- `path` _String_ - Path to the directory to list contents from. Relative paths are resolved
based on the sandbox working directory.
**Returns**:
- `Array\` - List of file and directory information
**Raises**:
- `Daytona:Sdk:Error` - If the operation fails
**Examples:**
```ruby
# List directory contents
files = sandbox.fs.list_files("workspace/data")
# Print files and their sizes
files.each do |file|
puts "#{file.name}: #{file.size} bytes" unless file.is_dir
end
# List only directories
dirs = files.select(&:is_dir)
puts "Subdirectories: #{dirs.map(&:name).join(', ')}"
```
#### download_file()
```ruby
def download_file(remote_path, local_path)
```
Downloads a file from the Sandbox. Returns the file contents as a string.
This method is useful when you want to load the file into memory without saving it to disk.
It can only be used for smaller files.
**Parameters**:
- `remote_path` _String_ - Path to the file in the Sandbox. Relative paths are resolved based
on the sandbox working directory.
- `local_path` _String, nil_ - Optional path to save the file locally. If provided, the file will be saved to disk.
**Returns**:
- `File, nil` - The file if local_path is nil, otherwise nil
**Raises**:
- `Daytona:Sdk:Error` - If the operation fails
**Examples:**
```ruby
# Download and get file content
content = sandbox.fs.download_file("workspace/data/file.txt")
puts content
# Download and save a file locally
sandbox.fs.download_file("workspace/data/file.txt", "local_copy.txt")
size_mb = File.size("local_copy.txt") / 1024.0 / 1024.0
puts "Size of the downloaded file: #{size_mb} MB"
```
#### upload_file()
```ruby
def upload_file(source, remote_path)
```
Uploads a file to the specified path in the Sandbox. If a file already exists at
the destination path, it will be overwritten.
**Parameters**:
- `source` _String, IO_ - File contents as a string/bytes or a local file path or IO object.
- `remote_path` _String_ - Path to the destination file. Relative paths are resolved based on
the sandbox working directory.
**Returns**:
- `void`
**Raises**:
- `Daytona:Sdk:Error` - If the operation fails
**Examples:**
```ruby
# Upload a text file from string content
content = "Hello, World!"
sandbox.fs.upload_file(content, "tmp/hello.txt")
# Upload a local file
sandbox.fs.upload_file("local_file.txt", "tmp/file.txt")
# Upload binary data
data = { key: "value" }.to_json
sandbox.fs.upload_file(data, "tmp/config.json")
```
#### upload_files()
```ruby
def upload_files(files)
```
Uploads multiple files to the Sandbox. If files already exist at the destination paths,
they will be overwritten.
**Parameters**:
- `files` _Array\_ - List of files to upload.
**Returns**:
- `void`
**Raises**:
- `Daytona:Sdk:Error` - If the operation fails
**Examples:**
```ruby
# Upload multiple files
files = [
FileUpload.new("Content of file 1", "/tmp/file1.txt"),
FileUpload.new("workspace/data/file2.txt", "/tmp/file2.txt"),
FileUpload.new('{"key": "value"}', "/tmp/config.json")
]
sandbox.fs.upload_files(files)
```
#### find_files()
```ruby
def find_files(path, pattern)
```
Searches for files containing a pattern, similar to the grep command.
**Parameters**:
- `path` _String_ - Path to the file or directory to search. If the path is a directory,
the search will be performed recursively. Relative paths are resolved based
on the sandbox working directory.
- `pattern` _String_ - Search pattern to match against file contents.
**Returns**:
- `Array\` - List of matches found in files
**Raises**:
- `Daytona:Sdk:Error` - If the operation fails
**Examples:**
```ruby
# Search for TODOs in Ruby files
matches = sandbox.fs.find_files("workspace/src", "TODO:")
matches.each do |match|
puts "#{match.file}:#{match.line}: #{match.content.strip}"
end
```
#### search_files()
```ruby
def search_files(path, pattern)
```
Searches for files and directories whose names match the specified pattern.
The pattern can be a simple string or a glob pattern.
**Parameters**:
- `path` _String_ - Path to the root directory to start search from. Relative paths are resolved
based on the sandbox working directory.
- `pattern` _String_ - Pattern to match against file names. Supports glob
patterns (e.g., "*.rb" for Ruby files).
**Returns**:
- `DaytonaApiClient:SearchFilesResponse`
**Raises**:
- `Daytona:Sdk:Error` - If the operation fails
**Examples:**
```ruby
# Find all Ruby files
result = sandbox.fs.search_files("workspace", "*.rb")
result.files.each { |file| puts file }
# Find files with specific prefix
result = sandbox.fs.search_files("workspace/data", "test_*")
puts "Found #{result.files.length} test files"
```
#### move_files()
```ruby
def move_files(source, destination)
```
Moves or renames a file or directory. The parent directory of the destination must exist.
**Parameters**:
- `source` _String_ - Path to the source file or directory. Relative paths are resolved
based on the sandbox working directory.
- `destination` _String_ - Path to the destination. Relative paths are resolved based on
the sandbox working directory.
**Returns**:
- `void`
**Raises**:
- `Daytona:Sdk:Error` - If the operation fails
**Examples:**
```ruby
# Rename a file
sandbox.fs.move_files(
"workspace/data/old_name.txt",
"workspace/data/new_name.txt"
)
# Move a file to a different directory
sandbox.fs.move_files(
"workspace/data/file.txt",
"workspace/archive/file.txt"
)
# Move a directory
sandbox.fs.move_files(
"workspace/old_dir",
"workspace/new_dir"
)
```
#### replace_in_files()
```ruby
def replace_in_files(files:, pattern:, new_value:)
```
Performs search and replace operations across multiple files.
**Parameters**:
- `files` _Array\_ - List of file paths to perform replacements in. Relative paths are
resolved based on the sandbox working directory.
- `pattern` _String_ - Pattern to search for.
- `new_value` _String_ - Text to replace matches with.
**Returns**:
- `Array\` - List of results indicating replacements made in each file
**Raises**:
- `Daytona:Sdk:Error` - If the operation fails
**Examples:**
```ruby
# Replace in specific files
results = sandbox.fs.replace_in_files(
files: ["workspace/src/file1.rb", "workspace/src/file2.rb"],
pattern: "old_function",
new_value: "new_function"
)
# Print results
results.each do |result|
if result.success
puts "#{result.file}: #{result.success}"
else
puts "#{result.file}: #{result.error}"
end
end
```
#### set_file_permissions()
```ruby
def set_file_permissions(path:, mode:, owner:, group:)
```
Sets permissions and ownership for a file or directory. Any of the parameters can be nil
to leave that attribute unchanged.
**Parameters**:
- `path` _String_ - Path to the file or directory. Relative paths are resolved based on
the sandbox working directory.
- `mode` _String, nil_ - File mode/permissions in octal format (e.g., "644" for rw-r--r--).
- `owner` _String, nil_ - User owner of the file.
- `group` _String, nil_ - Group owner of the file.
**Returns**:
- `void`
**Raises**:
- `Daytona:Sdk:Error` - If the operation fails
**Examples:**
```ruby
# Make a file executable
sandbox.fs.set_file_permissions(
path: "workspace/scripts/run.sh",
mode: "755" # rwxr-xr-x
)
# Change file owner
sandbox.fs.set_file_permissions(
path: "workspace/data/file.txt",
owner: "daytona",
group: "daytona"
)
```
## Git
Main class for a new Git handler instance.
### Constructors
#### new Git()
```ruby
def initialize(sandbox_id:, toolbox_api:, otel_state:)
```
Initializes a new Git handler instance.
**Parameters**:
- `sandbox_id` _String_ - The Sandbox ID.
- `toolbox_api` _DaytonaToolboxApiClient:GitApi_ - API client for Sandbox operations.
- `otel_state` _Daytona:OtelState, nil_ -
**Returns**:
- `Git` - a new instance of Git
### Methods
#### sandbox_id()
```ruby
def sandbox_id()
```
**Returns**:
- `String` - The Sandbox ID
#### toolbox_api()
```ruby
def toolbox_api()
```
**Returns**:
- `DaytonaToolboxApiClient:GitApi` - API client for Sandbox operations
#### add()
```ruby
def add(path, files)
```
Stages the specified files for the next commit, similar to
running 'git add' on the command line.
**Parameters**:
- `path` _String_ - Path to the Git repository root. Relative paths are resolved based on
the sandbox working directory.
- `files` _Array\_ - List of file paths or directories to stage, relative to the repository root.
**Returns**:
- `void`
**Raises**:
- `Daytona:Sdk:Error` - if adding files fails
**Examples:**
```ruby
# Stage a single file
sandbox.git.add("workspace/repo", ["file.txt"])
# Stage multiple files
sandbox.git.add("workspace/repo", [
"src/main.rb",
"spec/main_spec.rb",
"README.md"
])
```
#### branches()
```ruby
def branches(path)
```
Lists branches in the repository.
**Parameters**:
- `path` _String_ - Path to the Git repository root. Relative paths are resolved based on
the sandbox working directory.
**Returns**:
- `DaytonaApiClient:ListBranchResponse` - List of branches in the repository.
**Raises**:
- `Daytona:Sdk:Error` - if listing branches fails
**Examples:**
```ruby
response = sandbox.git.branches("workspace/repo")
puts "Branches: #{response.branches}"
```
#### clone()
```ruby
def clone(url:, path:, branch:, commit_id:, username:, password:)
```
Clones a Git repository into the specified path. It supports
cloning specific branches or commits, and can authenticate with the remote
repository if credentials are provided.
**Parameters**:
- `url` _String_ - Repository URL to clone from.
- `path` _String_ - Path where the repository should be cloned. Relative paths are resolved
based on the sandbox working directory.
- `branch` _String, nil_ - Specific branch to clone. If not specified,
clones the default branch.
- `commit_id` _String, nil_ - Specific commit to clone. If specified,
the repository will be left in a detached HEAD state at this commit.
- `username` _String, nil_ - Git username for authentication.
- `password` _String, nil_ - Git password or token for authentication.
**Returns**:
- `void`
**Raises**:
- `Daytona:Sdk:Error` - if cloning repository fails
**Examples:**
```ruby
# Clone the default branch
sandbox.git.clone(
url: "https://github.com/user/repo.git",
path: "workspace/repo"
)
# Clone a specific branch with authentication
sandbox.git.clone(
url: "https://github.com/user/private-repo.git",
path: "workspace/private",
branch: "develop",
username: "user",
password: "token"
)
# Clone a specific commit
sandbox.git.clone(
url: "https://github.com/user/repo.git",
path: "workspace/repo-old",
commit_id: "abc123"
)
```
#### commit()
```ruby
def commit(path:, message:, author:, email:, allow_empty:)
```
Creates a new commit with the staged changes. Make sure to stage
changes using the add() method before committing.
**Parameters**:
- `path` _String_ - Path to the Git repository root. Relative paths are resolved based on
the sandbox working directory.
- `message` _String_ - Commit message describing the changes.
- `author` _String_ - Name of the commit author.
- `email` _String_ - Email address of the commit author.
- `allow_empty` _Boolean_ - Allow creating an empty commit when no changes are staged. Defaults to false.
**Returns**:
- `GitCommitResponse` - Response containing the commit SHA.
**Raises**:
- `Daytona:Sdk:Error` - if committing changes fails
**Examples:**
```ruby
# Stage and commit changes
sandbox.git.add("workspace/repo", ["README.md"])
commit_response = sandbox.git.commit(
path: "workspace/repo",
message: "Update documentation",
author: "John Doe",
email: "john@example.com",
allow_empty: true
)
puts "Commit SHA: #{commit_response.sha}"
```
#### push()
```ruby
def push(path:, username:, password:)
```
Pushes all local commits on the current branch to the remote
repository. If the remote repository requires authentication, provide
username and password/token.
**Parameters**:
- `path` _String_ - Path to the Git repository root. Relative paths are resolved based on
the sandbox working directory.
- `username` _String, nil_ - Git username for authentication.
- `password` _String, nil_ - Git password or token for authentication.
**Returns**:
- `void`
**Raises**:
- `Daytona:Sdk:Error` - if pushing changes fails
**Examples:**
```ruby
# Push without authentication (for public repos or SSH)
sandbox.git.push("workspace/repo")
# Push with authentication
sandbox.git.push(
path: "workspace/repo",
username: "user",
password: "github_token"
)
```
#### pull()
```ruby
def pull(path:, username:, password:)
```
Pulls changes from the remote repository. If the remote repository requires authentication,
provide username and password/token.
**Parameters**:
- `path` _String_ - Path to the Git repository root. Relative paths are resolved based on
the sandbox working directory.
- `username` _String, nil_ - Git username for authentication.
- `password` _String, nil_ - Git password or token for authentication.
**Returns**:
- `void`
**Raises**:
- `Daytona:Sdk:Error` - if pulling changes fails
**Examples:**
```ruby
# Pull without authentication
sandbox.git.pull("workspace/repo")
# Pull with authentication
sandbox.git.pull(
path: "workspace/repo",
username: "user",
password: "github_token"
)
```
#### status()
```ruby
def status(path)
```
Gets the current Git repository status.
**Parameters**:
- `path` _String_ - Path to the Git repository root. Relative paths are resolved based on
the sandbox working directory.
**Returns**:
- `DaytonaToolboxApiClient:GitStatus` - Repository status information including:
**Raises**:
- `Daytona:Sdk:Error` - if getting status fails
**Examples:**
```ruby
status = sandbox.git.status("workspace/repo")
puts "On branch: #{status.current_branch}"
puts "Commits ahead: #{status.ahead}"
puts "Commits behind: #{status.behind}"
```
#### checkout_branch()
```ruby
def checkout_branch(path, branch)
```
Checkout branch in the repository.
**Parameters**:
- `path` _String_ - Path to the Git repository root. Relative paths are resolved based on
the sandbox working directory.
- `branch` _String_ - Name of the branch to checkout
**Returns**:
- `void`
**Raises**:
- `Daytona:Sdk:Error` - if checking out branch fails
**Examples:**
```ruby
# Checkout a branch
sandbox.git.checkout_branch("workspace/repo", "feature-branch")
```
#### create_branch()
```ruby
def create_branch(path, name)
```
Create branch in the repository.
**Parameters**:
- `path` _String_ - Path to the Git repository root. Relative paths are resolved based on
the sandbox working directory.
- `name` _String_ - Name of the new branch to create
**Returns**:
- `void`
**Raises**:
- `Daytona:Sdk:Error` - if creating branch fails
**Examples:**
```ruby
# Create a new branch
sandbox.git.create_branch("workspace/repo", "new-feature")
```
#### delete_branch()
```ruby
def delete_branch(path, name)
```
Delete branch in the repository.
**Parameters**:
- `path` _String_ - Path to the Git repository root. Relative paths are resolved based on
the sandbox working directory.
- `name` _String_ - Name of the branch to delete
**Returns**:
- `void`
**Raises**:
- `Daytona:Sdk:Error` - if deleting branch fails
**Examples:**
```ruby
# Delete a branch
sandbox.git.delete_branch("workspace/repo", "old-feature")
```
## Image
Represents an image definition for a Daytona sandbox.
Do not construct this class directly. Instead use one of its static factory methods,
such as `Image.base()`, `Image.debian_slim()`, or `Image.from_dockerfile()`.
### Constructors
#### new Image()
```ruby
def initialize(dockerfile:, context_list:)
```
**Parameters**:
- `dockerfile` _String, nil_ - The Dockerfile content
- `context_list` _Array\_ - List of context files
**Returns**:
- `Image` - a new instance of Image
### Methods
#### dockerfile()
```ruby
def dockerfile()
```
**Returns**:
- `String, nil` - The generated Dockerfile for the image
#### context_list()
```ruby
def context_list()
```
**Returns**:
- `Array\` - List of context files for the image
#### pip_install()
```ruby
def pip_install(*packages, find_links:, index_url:, extra_index_urls:, pre:, extra_options:)
```
Adds commands to install packages using pip
**Parameters**:
- `packages` _Array\_ - The packages to install
- `find_links` _Array\, nil_ - The find-links to use
- `index_url` _String, nil_ - The index URL to use
- `extra_index_urls` _Array\, nil_ - The extra index URLs to use
- `pre` _Boolean_ - Whether to install pre-release packages
- `extra_options` _String_ - Additional options to pass to pip
**Returns**:
- `Image` - The image with the pip install commands added
**Examples:**
```ruby
image = Image.debian_slim("3.12").pip_install("requests", "pandas")
```
#### pip_install_from_requirements()
```ruby
def pip_install_from_requirements(requirements_txt, find_links:, index_url:, extra_index_urls:, pre:, extra_options:)
```
Installs dependencies from a requirements.txt file
**Parameters**:
- `requirements_txt` _String_ - The path to the requirements.txt file
- `find_links` _Array\, nil_ - The find-links to use
- `index_url` _String, nil_ - The index URL to use
- `extra_index_urls` _Array\, nil_ - The extra index URLs to use
- `pre` _Boolean_ - Whether to install pre-release packages
- `extra_options` _String_ - Additional options to pass to pip
**Returns**:
- `Image` - The image with the pip install commands added
**Raises**:
- `Sdk:Error` - If the requirements file does not exist
**Examples:**
```ruby
image = Image.debian_slim("3.12").pip_install_from_requirements("requirements.txt")
```
#### pip_install_from_pyproject()
```ruby
def pip_install_from_pyproject(pyproject_toml, optional_dependencies:, find_links:, index_url:, extra_index_url:, pre:, extra_options:)
```
Installs dependencies from a pyproject.toml file
**Parameters**:
- `pyproject_toml` _String_ - The path to the pyproject.toml file
- `optional_dependencies` _Array\_ - The optional dependencies to install
- `find_links` _String, nil_ - The find-links to use
- `index_url` _String, nil_ - The index URL to use
- `extra_index_url` _String, nil_ - The extra index URL to use
- `pre` _Boolean_ - Whether to install pre-release packages
- `extra_options` _String_ - Additional options to pass to pip
**Returns**:
- `Image` - The image with the pip install commands added
**Raises**:
- `Sdk:Error` - If pyproject.toml parsing is not supported
**Examples:**
```ruby
image = Image.debian_slim("3.12").pip_install_from_pyproject("pyproject.toml", optional_dependencies: ["dev"])
```
#### add_local_file()
```ruby
def add_local_file(local_path, remote_path)
```
Adds a local file to the image
**Parameters**:
- `local_path` _String_ - The path to the local file
- `remote_path` _String_ - The path to the file in the image
**Returns**:
- `Image` - The image with the local file added
**Examples:**
```ruby
image = Image.debian_slim("3.12").add_local_file("package.json", "/home/daytona/package.json")
```
#### add_local_dir()
```ruby
def add_local_dir(local_path, remote_path)
```
Adds a local directory to the image
**Parameters**:
- `local_path` _String_ - The path to the local directory
- `remote_path` _String_ - The path to the directory in the image
**Returns**:
- `Image` - The image with the local directory added
**Examples:**
```ruby
image = Image.debian_slim("3.12").add_local_dir("src", "/home/daytona/src")
```
#### run_commands()
```ruby
def run_commands(*commands)
```
Runs commands in the image
**Parameters**:
- `commands` _Array\_ - The commands to run
**Returns**:
- `Image` - The image with the commands added
**Examples:**
```ruby
image = Image.debian_slim("3.12").run_commands('echo "Hello, world!"', 'echo "Hello again!"')
```
#### env()
```ruby
def env(env_vars)
```
Sets environment variables in the image
**Parameters**:
- `env_vars` _Hash\_ - The environment variables to set
**Returns**:
- `Image` - The image with the environment variables added
**Raises**:
- `Sdk:Error` -
**Examples:**
```ruby
image = Image.debian_slim("3.12").env({"PROJECT_ROOT" => "/home/daytona"})
```
#### workdir()
```ruby
def workdir(path)
```
Sets the working directory in the image
**Parameters**:
- `path` _String_ - The path to the working directory
**Returns**:
- `Image` - The image with the working directory added
**Examples:**
```ruby
image = Image.debian_slim("3.12").workdir("/home/daytona")
```
#### entrypoint()
```ruby
def entrypoint(entrypoint_commands)
```
Sets the entrypoint for the image
**Parameters**:
- `entrypoint_commands` _Array\_ - The commands to set as the entrypoint
**Returns**:
- `Image` - The image with the entrypoint added
**Examples:**
```ruby
image = Image.debian_slim("3.12").entrypoint(["/bin/bash"])
```
#### cmd()
```ruby
def cmd(cmd)
```
Sets the default command for the image
**Parameters**:
- `cmd` _Array\_ - The commands to set as the default command
**Returns**:
- `Image` - The image with the default command added
**Examples:**
```ruby
image = Image.debian_slim("3.12").cmd(["/bin/bash"])
```
#### dockerfile_commands()
```ruby
def dockerfile_commands(dockerfile_commands, context_dir:)
```
Adds arbitrary Dockerfile-like commands to the image
**Parameters**:
- `dockerfile_commands` _Array\_ - The commands to add to the Dockerfile
- `context_dir` _String, nil_ - The path to the context directory
**Returns**:
- `Image` - The image with the Dockerfile commands added
**Examples:**
```ruby
image = Image.debian_slim("3.12").dockerfile_commands(["RUN echo 'Hello, world!'"])
```
The Daytona Ruby SDK provides a robust interface for programmatically interacting with Daytona Sandboxes.
## Installation
Install the Daytona Ruby SDK using Bundler by adding it to your Gemfile:
```ruby
gem 'daytona'
```
Then run:
```bash
bundle install
```
Or install it directly:
```bash
gem install daytona
```
## Getting Started
Here's a simple example to help you get started with the Daytona Ruby SDK:
```ruby
require 'daytona'
# Initialize the SDK (uses environment variables by default)
daytona = Daytona::Daytona.new
# Create a new sandbox
sandbox = daytona.create
# Execute a command
response = sandbox.process.exec(command: "echo 'Hello, World!'")
puts response.result
# Clean up
daytona.delete(sandbox)
```
## Configuration
The SDK can be configured using environment variables or by passing options to the constructor:
```ruby
require 'daytona'
# Using environment variables (DAYTONA_API_KEY, DAYTONA_API_URL, DAYTONA_TARGET)
daytona = Daytona::Daytona.new
# Using explicit configuration
config = Daytona::Config.new(
api_key: 'your-api-key',
api_url: 'https://app.daytona.io/api',
target: 'us'
)
daytona = Daytona::Daytona.new(config)
```
## Environment Variables
The SDK supports the following environment variables:
| Variable | Description |
|----------|-------------|
| `DAYTONA_API_KEY` | API key for authentication |
| `DAYTONA_API_URL` | URL of the Daytona API (defaults to `https://app.daytona.io/api`) |
| `DAYTONA_TARGET` | Target location for Sandboxes |
| `DAYTONA_JWT_TOKEN` | JWT token for authentication (alternative to API key) |
| `DAYTONA_ORGANIZATION_ID` | Organization ID (required when using JWT token) |
## LspServer
LspServer class for Daytona SDK.
### Constructors
#### new LspServer()
```ruby
def initialize(language_id:, path_to_project:, toolbox_api:, sandbox_id:, otel_state:)
```
**Parameters**:
- `language_id` _Symbol_ -
- `path_to_project` _String_ -
- `toolbox_api` _DaytonaToolboxApiClient:LspApi_ -
- `sandbox_id` _String_ -
- `otel_state` _Daytona:OtelState, nil_ -
**Returns**:
- `LspServer` - a new instance of LspServer
### Methods
#### language_id()
```ruby
def language_id()
```
**Returns**:
- `Symbol`
#### path_to_project()
```ruby
def path_to_project()
```
**Returns**:
- `String`
#### toolbox_api()
```ruby
def toolbox_api()
```
**Returns**:
- `DaytonaToolboxApiClient:LspApi`
#### sandbox_id()
```ruby
def sandbox_id()
```
**Returns**:
- `String`
#### completions()
```ruby
def completions(path:, position:)
```
Gets completion suggestions at a position in a file
**Parameters**:
- `path` _String_ -
- `position` _Daytona:LspServer:Position_ -
**Returns**:
- `DaytonaApiClient:CompletionList`
#### did_close()
```ruby
def did_close(path)
```
Notify the language server that a file has been closed.
This method should be called when a file is closed in the editor to allow
the language server to clean up any resources associated with that file.
**Parameters**:
- `path` _String_ -
**Returns**:
- `void`
#### did_open()
```ruby
def did_open(path)
```
Notifies the language server that a file has been opened.
This method should be called when a file is opened in the editor to enable
language features like diagnostics and completions for that file. The server
will begin tracking the file's contents and providing language features.
**Parameters**:
- `path` _String_ -
**Returns**:
- `void`
#### document_symbols()
```ruby
def document_symbols(path)
```
Gets symbol information (functions, classes, variables, etc.) from a document.
**Parameters**:
- `path` _String_ -
**Returns**:
- `Array\, nil_ - Environment variables to set for the command
- `timeout` _Integer, nil_ - Maximum time in seconds to wait for the command to complete. 0 means wait indefinitely
**Returns**:
- `ExecuteResponse` - Command execution results containing exit_code, result, and artifacts
**Examples:**
```ruby
# Simple command
response = sandbox.process.exec("echo 'Hello'")
puts response.artifacts.stdout
=> "Hello\n"
# Command with working directory
result = sandbox.process.exec("ls", cwd: "workspace/src")
# Command with timeout
result = sandbox.process.exec("sleep 10", timeout: 5)
```
#### code_run()
```ruby
def code_run(code:, params:, timeout:)
```
Execute code in the Sandbox using the appropriate language runtime
**Parameters**:
- `code` _String_ - Code to execute
- `params` _CodeRunParams, nil_ - Parameters for code execution
- `timeout` _Integer, nil_ - Maximum time in seconds to wait for the code to complete. 0 means wait indefinitely
**Returns**:
- `ExecuteResponse` - Code execution result containing exit_code, result, and artifacts
**Examples:**
```ruby
# Run Python code
response = sandbox.process.code_run(<<~CODE)
x = 10
y = 20
print(f"Sum: {x + y}")
CODE
puts response.artifacts.stdout # Prints: Sum: 30
```
#### create_session()
```ruby
def create_session(session_id)
```
Creates a new long-running background session in the Sandbox
Sessions are background processes that maintain state between commands, making them ideal for
scenarios requiring multiple related commands or persistent environment setup.
**Parameters**:
- `session_id` _String_ - Unique identifier for the new session
**Returns**:
- `void`
**Examples:**
```ruby
# Create a new session
session_id = "my-session"
sandbox.process.create_session(session_id)
session = sandbox.process.get_session(session_id)
# Do work...
sandbox.process.delete_session(session_id)
```
#### get_session()
```ruby
def get_session(session_id)
```
Gets a session in the Sandbox
**Parameters**:
- `session_id` _String_ - Unique identifier of the session to retrieve
**Returns**:
- `DaytonaApiClient:Session` - Session information including session_id and commands
**Examples:**
```ruby
session = sandbox.process.get_session("my-session")
session.commands.each do |cmd|
puts "Command: #{cmd.command}"
end
```
#### get_entrypoint_session()
```ruby
def get_entrypoint_session()
```
Gets the Sandbox entrypoint session
**Returns**:
- `DaytonaApiClient:Session` - Entrypoint session information including session_id and commands
**Examples:**
```ruby
session = sandbox.process.get_entrypoint_session()
session.commands.each do |cmd|
puts "Command: #{cmd.command}"
end
```
#### get_session_command()
```ruby
def get_session_command(session_id:, command_id:)
```
Gets information about a specific command executed in a session
**Parameters**:
- `session_id` _String_ - Unique identifier of the session
- `command_id` _String_ - Unique identifier of the command
**Returns**:
- `DaytonaApiClient:Command` - Command information including id, command, and exit_code
**Examples:**
```ruby
cmd = sandbox.process.get_session_command(session_id: "my-session", command_id: "cmd-123")
if cmd.exit_code == 0
puts "Command #{cmd.command} completed successfully"
end
```
#### execute_session_command()
```ruby
def execute_session_command(session_id:, req:)
```
Executes a command in the session
**Parameters**:
- `session_id` _String_ - Unique identifier of the session to use
- `req` _Daytona:SessionExecuteRequest_ - Command execution request containing command and run_async
**Returns**:
- `Daytona:SessionExecuteResponse` - Command execution results containing cmd_id, output, stdout, stderr, and exit_code
**Examples:**
```ruby
# Execute commands in sequence, maintaining state
session_id = "my-session"
# Change directory
req = Daytona::SessionExecuteRequest.new(command: "cd /workspace")
sandbox.process.execute_session_command(session_id:, req:)
# Create a file
req = Daytona::SessionExecuteRequest.new(command: "echo 'Hello' > test.txt")
sandbox.process.execute_session_command(session_id:, req:)
# Read the file
req = Daytona::SessionExecuteRequest.new(command: "cat test.txt")
result = sandbox.process.execute_session_command(session_id:, req:)
puts "Command stdout: #{result.stdout}"
puts "Command stderr: #{result.stderr}"
```
#### get_session_command_logs()
```ruby
def get_session_command_logs(session_id:, command_id:)
```
Get the logs for a command executed in a session
**Parameters**:
- `session_id` _String_ - Unique identifier of the session
- `command_id` _String_ - Unique identifier of the command
**Returns**:
- `Daytona:SessionCommandLogsResponse` - Command logs including output, stdout, and stderr
**Examples:**
```ruby
logs = sandbox.process.get_session_command_logs(session_id: "my-session", command_id: "cmd-123")
puts "Command stdout: #{logs.stdout}"
puts "Command stderr: #{logs.stderr}"
```
#### get_session_command_logs_async()
```ruby
def get_session_command_logs_async(session_id:, command_id:, on_stdout:, on_stderr:)
```
Asynchronously retrieves and processes the logs for a command executed in a session as they become available
**Parameters**:
- `session_id` _String_ - Unique identifier of the session
- `command_id` _String_ - Unique identifier of the command
- `on_stdout` _Proc_ - Callback function to handle stdout log chunks as they arrive
- `on_stderr` _Proc_ - Callback function to handle stderr log chunks as they arrive
**Returns**:
- `WebSocket:Client:Simple:Client`
**Examples:**
```ruby
sandbox.process.get_session_command_logs_async(
session_id: "my-session",
command_id: "cmd-123",
on_stdout: ->(log) { puts "[STDOUT]: #{log}" },
on_stderr: ->(log) { puts "[STDERR]: #{log}" }
)
```
#### get_entrypoint_logs()
```ruby
def get_entrypoint_logs()
```
Get the sandbox entrypoint logs
**Returns**:
- `Daytona:SessionCommandLogsResponse` - Entrypoint logs including output, stdout, and stderr
**Examples:**
```ruby
logs = sandbox.process.get_entrypoint_logs()
puts "Command stdout: #{logs.stdout}"
puts "Command stderr: #{logs.stderr}"
```
#### get_entrypoint_logs_async()
```ruby
def get_entrypoint_logs_async(on_stdout:, on_stderr:)
```
Asynchronously retrieves and processes the sandbox entrypoint logs as they become available
**Parameters**:
- `on_stdout` _Proc_ - Callback function to handle stdout log chunks as they arrive
- `on_stderr` _Proc_ - Callback function to handle stderr log chunks as they arrive
**Returns**:
- `WebSocket:Client:Simple:Client`
**Examples:**
```ruby
sandbox.process.get_entrypoint_logs_async(
on_stdout: ->(log) { puts "[STDOUT]: #{log}" },
on_stderr: ->(log) { puts "[STDERR]: #{log}" }
)
```
#### send_session_command_input()
```ruby
def send_session_command_input(session_id:, command_id:, data:)
```
Sends input data to a command executed in a session
This method allows you to send input to an interactive command running in a session,
such as responding to prompts or providing data to stdin.
**Parameters**:
- `session_id` _String_ - Unique identifier of the session
- `command_id` _String_ - Unique identifier of the command
- `data` _String_ - Input data to send to the command
**Returns**:
- `void`
#### list_sessions()
```ruby
def list_sessions()
```
**Returns**:
- `Array\` - List of all sessions in the Sandbox
**Examples:**
```ruby
sessions = sandbox.process.list_sessions
sessions.each do |session|
puts "Session #{session.session_id}:"
puts " Commands: #{session.commands.length}"
end
```
#### delete_session()
```ruby
def delete_session(session_id)
```
Terminates and removes a session from the Sandbox, cleaning up any resources associated with it
**Parameters**:
- `session_id` _String_ - Unique identifier of the session to delete
**Examples:**
```ruby
# Create and use a session
sandbox.process.create_session("temp-session")
# ... use the session ...
# Clean up when done
sandbox.process.delete_session("temp-session")
```
#### create_pty_session()
```ruby
def create_pty_session(id:, cwd:, envs:, pty_size:)
```
Creates a new PTY (pseudo-terminal) session in the Sandbox.
Creates an interactive terminal session that can execute commands and handle user input.
The PTY session behaves like a real terminal, supporting features like command history.
**Parameters**:
- `id` _String_ - Unique identifier for the PTY session. Must be unique within the Sandbox.
- `cwd` _String, nil_ - Working directory for the PTY session. Defaults to the sandbox's working directory.
- `envs` _Hash\, nil_ - Environment variables to set in the PTY session. These will be merged with
the Sandbox's default environment variables.
- `pty_size` _PtySize, nil_ - Terminal size configuration. Defaults to 80x24 if not specified.
**Returns**:
- `PtyHandle` - Handle for managing the created PTY session. Use this to send input,
receive output, resize the terminal, and manage the session lifecycle.
**Raises**:
- `Daytona:Sdk:Error` - If the PTY session creation fails or the session ID is already in use.
**Examples:**
```ruby
# Create a basic PTY session
pty_handle = sandbox.process.create_pty_session(id: "my-pty")
# Create a PTY session with specific size and environment
pty_size = Daytona::PtySize.new(rows: 30, cols: 120)
pty_handle = sandbox.process.create_pty_session(
id: "my-pty",
cwd: "/workspace",
envs: {"NODE_ENV" => "development"},
pty_size: pty_size
)
# Use the PTY session
pty_handle.wait_for_connection
pty_handle.send_input("ls -la\n")
result = pty_handle.wait
pty_handle.disconnect
```
#### connect_pty_session()
```ruby
def connect_pty_session(session_id)
```
Connects to an existing PTY session in the Sandbox.
Establishes a WebSocket connection to an existing PTY session, allowing you to
interact with a previously created terminal session.
**Parameters**:
- `session_id` _String_ - Unique identifier of the PTY session to connect to.
**Returns**:
- `PtyHandle` - Handle for managing the connected PTY session.
**Raises**:
- `Daytona:Sdk:Error` - If the PTY session doesn't exist or connection fails.
**Examples:**
```ruby
# Connect to an existing PTY session
pty_handle = sandbox.process.connect_pty_session("my-pty-session")
pty_handle.wait_for_connection
pty_handle.send_input("echo 'Hello World'\n")
result = pty_handle.wait
pty_handle.disconnect
```
#### resize_pty_session()
```ruby
def resize_pty_session(session_id, pty_size)
```
Resizes a PTY session to the specified dimensions
**Parameters**:
- `session_id` _String_ - Unique identifier of the PTY session
- `pty_size` _PtySize_ - New terminal size
**Returns**:
- `DaytonaApiClient:PtySessionInfo` - Updated PTY session information
**Examples:**
```ruby
pty_size = Daytona::PtySize.new(rows: 30, cols: 120)
session_info = sandbox.process.resize_pty_session("my-pty", pty_size)
puts "PTY resized to #{session_info.cols}x#{session_info.rows}"
```
#### delete_pty_session()
```ruby
def delete_pty_session(session_id)
```
Deletes a PTY session, terminating the associated process
**Parameters**:
- `session_id` _String_ - Unique identifier of the PTY session to delete
**Returns**:
- `void`
**Examples:**
```ruby
sandbox.process.delete_pty_session("my-pty")
```
#### list_pty_sessions()
```ruby
def list_pty_sessions()
```
Lists all PTY sessions in the Sandbox
**Returns**:
- `Array\` - List of PTY session information
**Examples:**
```ruby
sessions = sandbox.process.list_pty_sessions
sessions.each do |session|
puts "PTY Session #{session.id}: #{session.cols}x#{session.rows}"
end
```
#### get_pty_session_info()
```ruby
def get_pty_session_info(session_id)
```
Gets detailed information about a specific PTY session
Retrieves comprehensive information about a PTY session including its current state,
configuration, and metadata.
**Parameters**:
- `session_id` _String_ - Unique identifier of the PTY session to retrieve information for
**Returns**:
- `DaytonaApiClient:PtySessionInfo` - Detailed information about the PTY session including ID, state,
creation time, working directory, environment variables, and more
**Examples:**
```ruby
# Get details about a specific PTY session
session_info = sandbox.process.get_pty_session_info("my-session")
puts "Session ID: #{session_info.id}"
puts "Active: #{session_info.active}"
puts "Working Directory: #{session_info.cwd}"
puts "Terminal Size: #{session_info.cols}x#{session_info.rows}"
```
## Sandbox
Sandbox class for Daytona SDK.
### Constructors
#### new Sandbox()
```ruby
def initialize(code_toolbox:, sandbox_dto:, config:, sandbox_api:, otel_state:)
```
**Returns**:
- `Sandbox` - a new instance of Sandbox
### Methods
#### id()
```ruby
def id()
```
**Returns**:
- `String` - The ID of the sandbox
#### organization_id()
```ruby
def organization_id()
```
**Returns**:
- `String` - The organization ID of the sandbox
#### snapshot()
```ruby
def snapshot()
```
**Returns**:
- `String` - The snapshot used for the sandbox
#### user()
```ruby
def user()
```
**Returns**:
- `String` - The user associated with the project
#### env()
```ruby
def env()
```
**Returns**:
- `Hash\` - Environment variables for the sandbox
#### labels()
```ruby
def labels()
```
**Returns**:
- `Hash\` - Labels for the sandbox
#### public()
```ruby
def public()
```
**Returns**:
- `Boolean` - Whether the sandbox http preview is public
#### network_block_all()
```ruby
def network_block_all()
```
**Returns**:
- `Boolean` - Whether to block all network access for the sandbox
#### network_allow_list()
```ruby
def network_allow_list()
```
**Returns**:
- `String` - Comma-separated list of allowed CIDR network addresses for the sandbox
#### target()
```ruby
def target()
```
**Returns**:
- `String` - The target environment for the sandbox
#### cpu()
```ruby
def cpu()
```
**Returns**:
- `Float` - The CPU quota for the sandbox
#### gpu()
```ruby
def gpu()
```
**Returns**:
- `Float` - The GPU quota for the sandbox
#### memory()
```ruby
def memory()
```
**Returns**:
- `Float` - The memory quota for the sandbox
#### disk()
```ruby
def disk()
```
**Returns**:
- `Float` - The disk quota for the sandbox
#### state()
```ruby
def state()
```
**Returns**:
- `DaytonaApiClient:SandboxState` - The state of the sandbox
#### desired_state()
```ruby
def desired_state()
```
**Returns**:
- `DaytonaApiClient:SandboxDesiredState` - The desired state of the sandbox
#### error_reason()
```ruby
def error_reason()
```
**Returns**:
- `String` - The error reason of the sandbox
#### backup_state()
```ruby
def backup_state()
```
**Returns**:
- `String` - The state of the backup
#### backup_created_at()
```ruby
def backup_created_at()
```
**Returns**:
- `String` - The creation timestamp of the last backup
#### auto_stop_interval()
```ruby
def auto_stop_interval()
```
**Returns**:
- `Float` - Auto-stop interval in minutes (0 means disabled)
#### auto_archive_interval()
```ruby
def auto_archive_interval()
```
**Returns**:
- `Float` - Auto-archive interval in minutes
#### auto_delete_interval()
```ruby
def auto_delete_interval()
```
(negative value means disabled, 0 means delete immediately upon stopping)
**Returns**:
- `Float` - Auto-delete interval in minutes
#### volumes()
```ruby
def volumes()
```
**Returns**:
- `Array\` - Array of volumes attached to the sandbox
#### build_info()
```ruby
def build_info()
```
**Returns**:
- `DaytonaApiClient:BuildInfo` - Build information for the sandbox
#### created_at()
```ruby
def created_at()
```
**Returns**:
- `String` - The creation timestamp of the sandbox
#### updated_at()
```ruby
def updated_at()
```
**Returns**:
- `String` - The last update timestamp of the sandbox
#### daemon_version()
```ruby
def daemon_version()
```
**Returns**:
- `String` - The version of the daemon running in the sandbox
#### code_toolbox()
```ruby
def code_toolbox()
```
**Returns**:
- `Daytona:SandboxPythonCodeToolbox, Daytona:SandboxTsCodeToolbox`
#### config()
```ruby
def config()
```
**Returns**:
- `Daytona:Config`
#### sandbox_api()
```ruby
def sandbox_api()
```
**Returns**:
- `DaytonaApiClient:SandboxApi`
#### process()
```ruby
def process()
```
**Returns**:
- `Daytona:Process`
#### fs()
```ruby
def fs()
```
**Returns**:
- `Daytona:FileSystem`
#### git()
```ruby
def git()
```
**Returns**:
- `Daytona:Git`
#### computer_use()
```ruby
def computer_use()
```
**Returns**:
- `Daytona:ComputerUse`
#### code_interpreter()
```ruby
def code_interpreter()
```
**Returns**:
- `Daytona:CodeInterpreter`
#### archive()
```ruby
def archive()
```
Archives the sandbox, making it inactive and preserving its state. When sandboxes are
archived, the entire filesystem state is moved to cost-effective object storage, making it
possible to keep sandboxes available for an extended period. The tradeoff between archived
and stopped states is that starting an archived sandbox takes more time, depending on its size.
Sandbox must be stopped before archiving.
**Returns**:
- `void`
#### auto_archive_interval=()
```ruby
def auto_archive_interval=(interval)
```
Sets the auto-archive interval for the Sandbox.
The Sandbox will automatically archive after being continuously stopped for the specified interval.
**Parameters**:
- `interval` _Integer_ -
**Returns**:
- `Integer`
**Raises**:
- `Daytona:Sdk:Error` -
#### auto_delete_interval=()
```ruby
def auto_delete_interval=(interval)
```
Sets the auto-delete interval for the Sandbox.
The Sandbox will automatically delete after being continuously stopped for the specified interval.
**Parameters**:
- `interval` _Integer_ -
**Returns**:
- `Integer`
**Raises**:
- `Daytona:Sdk:Error` -
#### auto_stop_interval=()
```ruby
def auto_stop_interval=(interval)
```
Sets the auto-stop interval for the Sandbox.
The Sandbox will automatically stop after being idle (no new events) for the specified interval.
Events include any state changes or interactions with the Sandbox through the SDK.
Interactions using Sandbox Previews are not included.
**Parameters**:
- `interval` _Integer_ -
**Returns**:
- `Integer`
**Raises**:
- `Daytona:Sdk:Error` -
#### create_ssh_access()
```ruby
def create_ssh_access(expires_in_minutes)
```
Creates an SSH access token for the sandbox.
**Parameters**:
- `expires_in_minutes` _Integer_ - TThe number of minutes the SSH access token will be valid for
**Returns**:
- `DaytonaApiClient:SshAccessDto`
#### delete()
```ruby
def delete()
```
**Returns**:
- `void`
#### get_user_home_dir()
```ruby
def get_user_home_dir()
```
Gets the user's home directory path for the logged in user inside the Sandbox.
**Returns**:
- `String` - The absolute path to the Sandbox user's home directory for the logged in user
**Examples:**
```ruby
user_home_dir = sandbox.get_user_home_dir
puts "Sandbox user home: #{user_home_dir}"
```
#### get_work_dir()
```ruby
def get_work_dir()
```
Gets the working directory path inside the Sandbox.
**Returns**:
- `String` - The absolute path to the Sandbox working directory. Uses the WORKDIR specified
in the Dockerfile if present, or falling back to the user's home directory if not.
**Examples:**
```ruby
work_dir = sandbox.get_work_dir
puts "Sandbox working directory: #{work_dir}"
```
#### labels=()
```ruby
def labels=(labels)
```
Sets labels for the Sandbox.
**Parameters**:
- `labels` _Hash\_ -
**Returns**:
- `Hash\`
#### preview_url()
```ruby
def preview_url(port)
```
Retrieves the preview link for the sandbox at the specified port. If the port is closed,
it will be opened automatically. For private sandboxes, a token is included to grant access
to the URL.
**Parameters**:
- `port` _Integer_ -
**Returns**:
- `DaytonaApiClient:PortPreviewUrl`
#### create_signed_preview_url()
```ruby
def create_signed_preview_url(port, expires_in_seconds)
```
Creates a signed preview URL for the sandbox at the specified port.
**Parameters**:
- `port` _Integer_ - The port to open the preview link on
- `expires_in_seconds` _Integer, nil_ - The number of seconds the signed preview URL
will be valid for. Defaults to 60 seconds.
**Returns**:
- `DaytonaApiClient:SignedPortPreviewUrl` - The signed preview URL response object
**Examples:**
```ruby
signed_url = sandbox.create_signed_preview_url(3000, 120)
puts "Signed URL: #{signed_url.url}"
puts "Token: #{signed_url.token}"
```
#### expire_signed_preview_url()
```ruby
def expire_signed_preview_url(port, token)
```
Expires a signed preview URL for the sandbox at the specified port.
**Parameters**:
- `port` _Integer_ - The port to expire the signed preview URL on
- `token` _String_ - The token to expire
**Returns**:
- `void`
**Examples:**
```ruby
sandbox.expire_signed_preview_url(3000, "token-value")
```
#### refresh()
```ruby
def refresh()
```
Refresh the Sandbox data from the API.
**Returns**:
- `void`
#### refresh_activity()
```ruby
def refresh_activity()
```
Refreshes the sandbox activity to reset the timer for automated lifecycle management actions.
This method updates the sandbox's last activity timestamp without changing its state.
It is useful for keeping long-running sessions alive while there is still user activity.
**Returns**:
- `void`
**Examples:**
```ruby
sandbox.refresh_activity
```
#### revoke_ssh_access()
```ruby
def revoke_ssh_access(token)
```
Revokes an SSH access token for the sandbox.
**Parameters**:
- `token` _String_ -
**Returns**:
- `void`
#### start()
```ruby
def start(timeout)
```
Starts the Sandbox and waits for it to be ready.
**Parameters**:
- `timeout` _Numeric_ - Maximum wait time in seconds (defaults to 60 s).
**Returns**:
- `void`
#### recover()
```ruby
def recover(timeout)
```
Recovers the Sandbox from a recoverable error and waits for it to be ready.
**Parameters**:
- `timeout` _Numeric_ - Maximum wait time in seconds (defaults to 60 s).
**Returns**:
- `void`
**Examples:**
```ruby
sandbox = daytona.get('my-sandbox-id')
sandbox.recover(timeout: 40) # Wait up to 40 seconds
puts 'Sandbox recovered successfully'
```
#### stop()
```ruby
def stop(timeout)
```
Stops the Sandbox and waits for it to be stopped.
**Parameters**:
- `timeout` _Numeric_ - Maximum wait time in seconds (defaults to 60 s).
**Returns**:
- `void`
#### resize()
```ruby
def resize(resources, timeout)
```
Resizes the Sandbox resources.
Changes the CPU, memory, or disk allocation for the Sandbox. Resizing a started
sandbox allows increasing CPU and memory. To resize disk or decrease resources,
the sandbox must be stopped first.
**Parameters**:
- `resources` _Daytona:Resources_ - New resource configuration
- `timeout` _Numeric_ - Maximum wait time in seconds (defaults to 60 s)
**Returns**:
- `void`
**Raises**:
- `Sdk:Error` -
**Examples:**
```ruby
sandbox.resize(Daytona::Resources.new(cpu: 4, memory: 8))
```
```ruby
sandbox.stop
sandbox.resize(Daytona::Resources.new(cpu: 2, memory: 4, disk: 30))
```
#### wait_for_resize_complete()
```ruby
def wait_for_resize_complete(_timeout)
```
Waits for the Sandbox resize operation to complete.
Polls the Sandbox status until the state is no longer 'resizing'.
**Parameters**:
- `timeout` _Numeric_ - Maximum wait time in seconds (defaults to 60 s)
**Returns**:
- `void`
#### create_lsp_server()
```ruby
def create_lsp_server(language_id:, path_to_project:)
```
Creates a new Language Server Protocol (LSP) server instance.
The LSP server provides language-specific features like code completion,
diagnostics, and more.
**Parameters**:
- `language_id` _Symbol_ - The language server type (e.g., Daytona::LspServer::Language::PYTHON)
- `path_to_project` _String_ - Path to the project root directory. Relative paths are resolved
based on the sandbox working directory.
**Returns**:
- `Daytona:LspServer`
#### validate_ssh_access()
```ruby
def validate_ssh_access(token)
```
Validates an SSH access token for the sandbox.
**Parameters**:
- `token` _String_ -
**Returns**:
- `DaytonaApiClient:SshAccessValidationDto`
#### wait_for_sandbox_start()
```ruby
def wait_for_sandbox_start(_timeout)
```
Waits for the Sandbox to reach the 'started' state. Polls the Sandbox status until it
reaches the 'started' state or encounters an error.
**Parameters**:
- `timeout` _Numeric_ - Maximum wait time in seconds (defaults to 60 s).
**Returns**:
- `void`
#### wait_for_sandbox_stop()
```ruby
def wait_for_sandbox_stop(_timeout)
```
Waits for the Sandbox to reach the 'stopped' state. Polls the Sandbox status until it
reaches the 'stopped' state or encounters an error.
Treats destroyed as stopped to cover ephemeral sandboxes that are automatically deleted after stopping.
**Parameters**:
- `timeout` _Numeric_ - Maximum wait time in seconds (defaults to 60 s).
**Returns**:
- `void`
## SnapshotService
SnapshotService class for Daytona SDK.
### Constructors
#### new SnapshotService()
```ruby
def initialize(snapshots_api:, object_storage_api:, default_region_id:, otel_state:)
```
**Parameters**:
- `snapshots_api` _DaytonaApiClient:SnapshotsApi_ - The snapshots API client
- `object_storage_api` _DaytonaApiClient:ObjectStorageApi_ - The object storage API client
- `default_region_id` _String, nil_ - Default region ID for snapshot creation
- `otel_state` _Daytona:OtelState, nil_ -
**Returns**:
- `SnapshotService` - a new instance of SnapshotService
### Methods
#### list()
```ruby
def list(page:, limit:)
```
List all Snapshots.
**Parameters**:
- `page` _Integer, Nil_ -
- `limit` _Integer, Nil_ -
**Returns**:
- `Daytona:PaginatedResource` - Paginated list of all Snapshots
**Raises**:
- `Daytona:Sdk:Error` -
**Examples:**
```ruby
daytona = Daytona::Daytona.new
response = daytona.snapshot.list(page: 1, limit: 10)
snapshots.items.each { |snapshot| puts "#{snapshot.name} (#{snapshot.image_name})" }
```
#### delete()
```ruby
def delete(snapshot)
```
Delete a Snapshot.
**Parameters**:
- `snapshot` _Daytona:Snapshot_ - Snapshot to delete
**Returns**:
- `void`
**Examples:**
```ruby
daytona = Daytona::Daytona.new
snapshot = daytona.snapshot.get("demo")
daytona.snapshot.delete(snapshot)
puts "Snapshot deleted"
```
#### get()
```ruby
def get(name)
```
Get a Snapshot by name.
**Parameters**:
- `name` _String_ - Name of the Snapshot to get
**Returns**:
- `Daytona:Snapshot` - The Snapshot object
**Examples:**
```ruby
daytona = Daytona::Daytona.new
snapshot = daytona.snapshot.get("demo")
puts "#{snapshot.name} (#{snapshot.image_name})"
```
#### create()
```ruby
def create(params, on_logs:)
```
Creates and registers a new snapshot from the given Image definition.
**Parameters**:
- `params` _Daytona:CreateSnapshotParams_ - Parameters for snapshot creation
- `on_logs` _Proc, Nil_ - Callback proc handling snapshot creation logs
**Returns**:
- `Daytona:Snapshot` - The created snapshot
**Examples:**
```ruby
image = Image.debianSlim('3.12').pipInstall('numpy')
params = CreateSnapshotParams.new(name: 'my-snapshot', image: image)
snapshot = daytona.snapshot.create(params) do |chunk|
print chunk
end
```
#### activate()
```ruby
def activate(snapshot)
```
Activate a snapshot
**Parameters**:
- `snapshot` _Daytona:Snapshot_ - The snapshot instance
**Returns**:
- `Daytona:Snapshot`
## VolumeService
Service for managing Daytona Volumes. Can be used to list, get, create and delete Volumes.
### Constructors
#### new VolumeService()
```ruby
def initialize(volumes_api, otel_state:)
```
Service for managing Daytona Volumes. Can be used to list, get, create and delete Volumes.
**Parameters**:
- `volumes_api` _DaytonaApiClient:VolumesApi_ -
- `otel_state` _Daytona:OtelState, nil_ -
**Returns**:
- `VolumeService` - a new instance of VolumeService
### Methods
#### create()
```ruby
def create(name)
```
Create new Volume.
**Parameters**:
- `name` _String_ -
**Returns**:
- `Daytona:Volume`
#### delete()
```ruby
def delete(volume)
```
Delete a Volume.
**Parameters**:
- `volume` _Daytona:Volume_ -
**Returns**:
- `void`
#### get()
```ruby
def get(name, create:)
```
Get a Volume by name.
**Parameters**:
- `name` _String_ -
- `create` _Boolean_ -
**Returns**:
- `Daytona:Volume`
#### list()
```ruby
def list()
```
List all Volumes.
**Returns**:
- `Array\`
## Volume
Initialize volume from DTO
### Constructors
#### new Volume()
```ruby
def initialize(volume_dto)
```
Initialize volume from DTO
**Parameters**:
- `volume_dto` _DaytonaApiClient:SandboxVolume_ -
**Returns**:
- `Volume` - a new instance of Volume
### Methods
#### id()
```ruby
def id()
```
**Returns**:
- `String`
#### name()
```ruby
def name()
```
**Returns**:
- `String`
#### organization_id()
```ruby
def organization_id()
```
**Returns**:
- `String`
#### state()
```ruby
def state()
```
**Returns**:
- `String`
#### created_at()
```ruby
def created_at()
```
**Returns**:
- `String`
#### updated_at()
```ruby
def updated_at()
```
**Returns**:
- `String`
#### last_used_at()
```ruby
def last_used_at()
```
**Returns**:
- `String`
#### error_reason()
```ruby
def error_reason()
```
**Returns**:
- `String, nil`
Runners are machines that power Daytona's compute plane, providing the underlying infrastructure for running sandbox workloads. Each runner is responsible for:
- **Workload execution**: running sandbox workloads
- **Resource management**: allocating and monitoring CPU, memory, and disk resources
- **Health reporting**: continuously reporting metrics and health status to the Daytona control plane
- **Network connectivity**: managing networking, proxy connections, and SSH access for sandboxes
Runners in [shared](https://www.daytona.io/docs/en/regions.md#shared-regions) and [dedicated](https://www.daytona.io/docs/en/regions.md#dedicated-regions) regions are fully managed by Daytona — from provisioning and maintenance to monitoring and scaling. For custom regions, you bring your own runner machines and are responsible for their management and operation.
:::caution
Custom runners are currently an experimental feature and may change in future releases.
To request access, please contact [support@daytona.io](mailto:support@daytona.io).
:::
## Custom regions
Custom regions are created and managed by your organization, allowing you to use your own runner machines and scale compute resources independently within each region. This provides maximum control over data locality, compliance, and infrastructure configuration.
Additionally, custom regions have no limits applied for concurrent resource usage, giving you full control over capacity and performance.
### Custom region configuration
**name** (required)
- A unique identifier for your region
- Must contain only letters, numbers, underscores, periods, and hyphens
- Used for targeting this region when creating a sandbox
**proxyUrl** (optional)
- The URL of the proxy service that routes traffic to sandboxes in this region
- Required if the runner machines in this region are deployed in a private network
**sshGatewayUrl** (optional)
- The URL of the SSH gateway that handles SSH connections to sandboxes in this region
- Required if the runner machines in this region are deployed in a private network
**snapshotManagerUrl** (optional)
- The URL of the snapshot manager that handles storage and retrieval of snapshots in this region
- Required if the runner machines in this region are deployed in a private network
### Custom region credentials
When you create a custom region, Daytona will provide credentials for any optional services you configure:
- An API key that should be used by your proxy service to authenticate with Daytona
- An API key that should be used by your SSH gateway service to authenticate with Daytona
- Basic authentication credentials that Daytona uses to access your snapshot manager service
:::note
If needed, these credentials can always be regenerated, but you will need to redeploy the corresponding services with the updated credentials.
:::
## Custom runners
Custom runners are created and managed by your organization, allowing you to use your own runner machines and scale compute resources independently within each custom region.
### Custom runner configuration
**name** (required)
- A unique identifier for the runner
- Must contain only letters, numbers, underscores, periods, and hyphens
- Helps distinguish between multiple runners in the same region
**regionId** (required)
- The ID of the region this runner is assigned to
- Must be a custom region owned by your organization
- All runners in a region share the region's proxy and SSH gateway configuration
### Custom runner token
When you create a custom runner, Daytona will provide you with a **token** that should be used by your runner to authenticate with Daytona.
:::note
Save this token securely. You won't be able to see it again.
:::
### Installing the custom runner
After registering a custom runner and obtaining its secure token, you need to install and configure the Daytona runner application on your infrastructure.
:::note
Detailed installation instructions for the runner application will be provided in a future update. For assistance with runner installation, please contact [support@daytona.io](mailto:support@daytona.io).
:::
Daytona provides **full composable computers** — **sandboxes** — for AI agents. Sandboxes are isolated runtime environments you can manage programmatically to run code. Each sandbox runs in isolation, giving it a dedicated kernel, filesystem, network stack, and allocated vCPU, RAM, and disk. Agents get access to a full composable computer environment where they can install packages, run servers, compile code, and manage processes.
Sandboxes have **1 vCPU**, **1GB RAM**, and **3GiB disk** by default. [Organizations](https://www.daytona.io/docs/en/organizations.md) get a maximum sandbox resource limit of **4 vCPUs**, **8GB RAM**, and **10GB disk**. For more power, see [resources](#resources) or contact [support@daytona.io](mailto:support@daytona.io).
Sandboxes are built from OCI-compliant images. A [snapshot](https://www.daytona.io/docs/en/snapshots.md) captures a fully configured environment: base OS, installed packages, dependencies, and configuration to create new sandboxes.
Each sandbox has its own network stack with per-sandbox firewall rules. By default, sandboxes follow standard network policies, but you can restrict egress to a specific set of allowed destinations or block all outbound traffic entirely. For details on configuring network access, see [network settings](https://www.daytona.io/docs/en/network-limits.md).
For a detailed overview of the Daytona platform, see [architecture](https://www.daytona.io/docs/en/architecture.md).
## Sandbox lifecycle
Throughout its lifecycle, a Daytona Sandbox can have several different states. The diagram below shows the states and possible transitions between them.
## Multiple runtime support
Daytona Sandboxes support Python, TypeScript, and JavaScript programming language runtimes for direct code execution inside the sandbox.
The `language` parameter controls which programming language runtime is used for the sandbox:
- **`python`**
- **`typescript`**
- **`javascript`**
If omitted, the Daytona SDK will default to `python`. To override this, explicitly set the `language` value when creating the sandbox.
:::note
**Sandbox Names**: You can specify a custom name for your sandbox using the `name` parameter. If not provided, the sandbox ID will be used as the name. Sandbox names are reusable - once a sandbox with a specific name is destroyed, that name becomes available for use again.
:::
## Create Sandboxes
Daytona provides methods to create sandboxes using the [Daytona Dashboard ↗](https://app.daytona.io/dashboard/) or programatically using the Daytona [Python](https://www.daytona.io/docs/en/python-sdk/sync/sandbox.md), [TypeScript](https://www.daytona.io/docs/en/typescript-sdk/sandbox.md), [Ruby](https://www.daytona.io/docs/en/ruby-sdk/sandbox.md), [Go](https://www.daytona.io/docs/en/go-sdk/daytona.md#type-sandbox) **SDKs**, [CLI](https://www.daytona.io/docs/en/tools/cli.md#daytona-create), or [API](https://www.daytona.io/docs/en/tools/api.md#daytona/tag/sandbox).
You can specify [programming language runtime](https://www.daytona.io/docs/en/sandboxes.md#multiple-runtime-support), [snapshots](https://www.daytona.io/docs/en/snapshots.md), [resources](https://www.daytona.io/docs/en/sandboxes.md#resources), [regions](https://www.daytona.io/docs/en/regions.md), [environment variables](https://www.daytona.io/docs/en/configuration.md#environment-variables), and [volumes](https://www.daytona.io/docs/en/volumes.md) for each sandbox. Running sandboxes utilize CPU, memory, and disk storage. Every resource is charged per second of usage.
1. Navigate to [Daytona Sandboxes ↗](https://app.daytona.io/dashboard/sandboxes)
2. Click the **Create Sandbox** button
3. Enter the name of the sandbox
4. Select a source for the sandbox:
- [Snapshot](https://www.daytona.io/docs/en/snapshots.md): a pre-configured sandbox template
- **Image**: OCI-compliant container image ([public](https://www.daytona.io/docs/en/snapshots.md#using-public-images), [local](https://www.daytona.io/docs/en/snapshots.md#using-local-images), [private registries](https://www.daytona.io/docs/en/snapshots.md#using-images-from-private-registries)). Images require setting [sandbox resources](https://www.daytona.io/docs/en/sandboxes.md#resources). Default: **1 vCPU**, **1GB RAM**, **3GiB disk**.
5. Select a [region](https://www.daytona.io/docs/en/regions.md): if not specified, your organization's default region will be used
6. Define [sandbox lifecycle management](#automated-lifecycle-management) options or set as an [ephemeral sandbox](#ephemeral-sandboxes)
7. Add environment variables in key-value pairs or import them from a **`.env`** file
8. Add labels in key-value pairs
9. Select network settings:
- **Public HTTP preview**: allow public access to HTTP [preview URLs](https://www.daytona.io/docs/en/preview.md)
- **Block all network access**: block all outbound network access
10. Click the **Create** button to create the sandbox
```python
from daytona import Daytona, CreateSandboxFromSnapshotParams
daytona = Daytona()
# Create a sandbox
sandbox = daytona.create()
# Create a sandbox with python
params = CreateSandboxFromSnapshotParams(language="python")
sandbox = daytona.create(params)
# Create a sandbox with a custom name
params = CreateSandboxFromSnapshotParams(name="my_awesome_sandbox")
sandbox = daytona.create(params)
# Create a sandbox with custom labels
params = CreateSandboxFromSnapshotParams(labels={"LABEL": "label"})
sandbox = daytona.create(params)
```
```typescript
import { Daytona } from '@daytonaio/sdk';
const daytona = new Daytona();
// Create a sandbox
const sandbox = await daytona.create();
// Create a sandbox with typescript
const sandbox = await daytona.create({ language: 'typescript' });
// Create a sandbox with a custom name
const sandbox = await daytona.create({ name: 'my_awesome_sandbox' });
// Create a sandbox with custom labels
const sandbox = await daytona.create({ labels: { LABEL: 'label' } });
```
```ruby
require 'daytona'
daytona = Daytona::Daytona.new
# Create a sandbox
sandbox = daytona.create
# Create a sandbox with python
params = Daytona::CreateSandboxFromSnapshotParams.new(language: Daytona::CodeLanguage::PYTHON)
sandbox = daytona.create(params)
# Create a sandbox with custom labels
params = Daytona::CreateSandboxFromSnapshotParams.new(labels: { 'LABEL' => 'label' })
sandbox = daytona.create(params)
```
```go
// Create a sandbox
params := types.SnapshotParams{
SandboxBaseParams: types.SandboxBaseParams{
Language: types.CodeLanguagePython,
},
}
sandbox, err := client.Create(ctx, params)
```
```bash
daytona create [flags]
```
```bash
curl 'https://app.daytona.io/api/sandbox' \
--request POST \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer YOUR_SECRET_TOKEN' \
--data '{}'
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk.md), [Go SDK](https://www.daytona.io/docs/en/go-sdk.md), [API](https://www.daytona.io/docs/en/tools/api.md#daytona/), and [CLI](https://www.daytona.io/docs/en/tools/cli.md) references:
> [**create (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/daytona.md#daytonacreate)
>
> [**create (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/daytona.md#create)
>
> [**create (Ruby SDK)**](https://www.daytona.io/docs/en/ruby-sdk/daytona.md#create)
>
> [**Create (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#Client.Create)
>
> [**create (CLI)**](https://www.daytona.io/docs/en/tools/cli.md#daytona-create)
>
> [**create (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona/tag/sandbox/POST/sandbox)
### Resources
Sandboxes have **1 vCPU**, **1GB RAM**, and **3GiB disk** by default. Organizations get a maximum sandbox resource limit of **4 vCPUs**, **8GB RAM**, and **10GB disk**.
To set custom sandbox resources (CPU, memory, and disk space), use the `Resources` class:
```python
from daytona import Daytona, Resources, CreateSandboxFromImageParams, Image
daytona = Daytona()
# Create a sandbox with custom resources
resources = Resources(
cpu=2, # 2 CPU cores
memory=4, # 4GB RAM
disk=8, # 8GB disk space
)
params = CreateSandboxFromImageParams(
image=Image.debian_slim("3.12"),
resources=resources
)
sandbox = daytona.create(params)
```
```typescript
import { Daytona, Image } from "@daytonaio/sdk";
async function main() {
const daytona = new Daytona();
// Create a sandbox with custom resources
const sandbox = await daytona.create({
image: Image.debianSlim("3.12"),
resources: {
cpu: 2, // 2 CPU cores
memory: 4, // 4GB RAM
disk: 8, // 8GB disk space
},
});
}
main();
```
```ruby
require 'daytona'
daytona = Daytona::Daytona.new
# Create a sandbox with custom resources
sandbox = daytona.create(
Daytona::CreateSandboxFromImageParams.new(
image: Daytona::Image.debian_slim('3.12'),
resources: Daytona::Resources.new(
cpu: 2, # 2 CPU cores
memory: 4, # 4GB RAM
disk: 8 # 8GB disk space
)
)
)
```
```go
// Create a sandbox with custom resources
sandbox, err := client.Create(ctx, types.ImageParams{
Image: "python:3.11",
Resources: &types.Resources{
CPU: 2, // 2 CPU cores
Memory: 4, // 4GiB RAM
Disk: 8, // 8GiB disk space
},
})
```
```bash
# --memory is in MB; --disk is in GB
daytona create --cpu 2 --memory 4096 --disk 8
```
```bash
curl 'https://app.daytona.io/api/sandbox' \
--request POST \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer YOUR_SECRET_TOKEN' \
--data '{
"cpu": 2,
"memory": 4,
"disk": 8
}'
```
All resource parameters are optional and must be integers. If not specified, Daytona will use the default values listed below.
| **Resource** | **Unit** | **Default** | **Minimum** | **Maximum** |
| ------------ | -------- | ----------- | ----------- | ----------- |
| CPU | vCPU | **`1`** | **`1`** | **`4`** |
| Memory | GiB | **`1`** | **`1`** | **`8`** |
| Disk | GiB | **`3`** | **`1`** | **`10`** |
Maximum values are per-sandbox limits set at the [organization](https://www.daytona.io/docs/en/organizations.md) level. Contact [support@daytona.io](mailto:support@daytona.io) to increase limits.
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk/daytona.md#resources), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk.md), [Go SDK](https://www.daytona.io/docs/en/go-sdk.md), [CLI](https://www.daytona.io/docs/en/tools/cli.md), and [API](https://www.daytona.io/docs/en/tools/api.md) references:
> [**Resources (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/sandbox.md#resources)
>
> [**Resources (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/daytona.md#resources)
>
> [**Resources (Ruby SDK)**](https://www.daytona.io/docs/en/ruby-sdk/daytona.md)
>
> [**Resources (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona/tag/sandbox/POST/sandbox)
>
> [**Resources (CLI)**](https://www.daytona.io/docs/en/tools/cli.md#daytona-create)
### Ephemeral Sandboxes
Ephemeral Sandboxes are automatically deleted once they are stopped. They are useful for short-lived tasks or for testing purposes.
To create an ephemeral Sandbox, set the `ephemeral` parameter to `True` when creating a sandbox:
```python
from daytona import Daytona, CreateSandboxFromSnapshotParams
daytona = Daytona()
# Create an ephemeral sandbox
params = CreateSandboxFromSnapshotParams(
ephemeral=True,
auto_stop_interval=5 # The ephemeral sandbox will be deleted after 5 minutes of inactivity
)
sandbox = daytona.create(params)
```
```typescript
import { Daytona } from '@daytonaio/sdk';
const daytona = new Daytona();
// Create an ephemeral sandbox
const sandbox = await daytona.create({
ephemeral: true,
autoStopInterval: 5 // The ephemeral sandbox will be deleted after 5 minutes of inactivity
});
```
```ruby
require 'daytona'
daytona = Daytona::Daytona.new
# Create an ephemeral Sandbox
params = Daytona::CreateSandboxFromSnapshotParams.new(
ephemeral: true,
auto_stop_interval: 5 # The ephemeral sandbox will be deleted after 5 minutes of inactivity
)
sandbox = daytona.create(params)
```
```go
// Create an ephemeral sandbox
autoStopInterval := 5
params := types.SnapshotParams{
SandboxBaseParams: types.SandboxBaseParams{
Language: types.CodeLanguagePython,
Ephemeral: true,
AutoStopInterval: &autoStopInterval,
},
}
sandbox, err := client.Create(ctx, params)
```
:::note
Setting ["autoDeleteInterval: 0"](#auto-delete-interval) has the same effect as setting "ephemeral" to `true`.
:::
### Network settings (Firewall)
Daytona Sandboxes provide configurable network firewall controls to enhance security and manage connectivity.
By default, network access follows standard security policies, but you can [customize network settings](https://www.daytona.io/docs/en/network-limits.md) when creating a sandbox.
## Start Sandboxes
Daytona provides options to start sandboxes in [Daytona Dashboard ↗](https://app.daytona.io/dashboard/) or programmatically using the [Python SDK](https://www.daytona.io/docs/en/python-sdk.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk.md), [CLI](https://www.daytona.io/docs/en/tools/cli.md), and [API](https://www.daytona.io/docs/en/tools/api.md#daytona/) references.
1. Navigate to [Daytona Sandboxes ↗](https://app.daytona.io/dashboard/sandboxes)
2. Click the start icon (**▶**) next to the sandbox you want to start.
```text
Starting sandbox with ID:
```
```python
sandbox = daytona.create(CreateSandboxFromSnapshotParams(language="python"))
# Start Sandbox
sandbox.start()
```
```typescript
const sandbox = await daytona.create({ language: 'typescript' });
// Start Sandbox
await sandbox.start();
```
```ruby
sandbox = daytona.create(Daytona::CreateSandboxFromSnapshotParams.new(language: Daytona::CodeLanguage::PYTHON))
# Start Sandbox
sandbox.start
```
```go
// Start sandbox
err = sandbox.Start(ctx)
```
```bash
daytona start [SANDBOX_ID] | [SANDBOX_NAME] [flags]
```
```bash
curl 'https://app.daytona.io/api/sandbox/{sandboxIdOrName}/start' \
--request POST \
--header 'Authorization: Bearer YOUR_SECRET_TOKEN'
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk.md), [Go SDK](https://www.daytona.io/docs/en/go-sdk.md), [CLI](https://www.daytona.io/docs/en/tools/cli.md), and [API](https://www.daytona.io/docs/en/tools/api.md#daytona) references:
> [**start (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/sandbox.md#sandboxstart)
>
> [**start (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/sandbox.md#start)
>
> [**start (Ruby SDK)**](https://www.daytona.io/docs/en/ruby-sdk/sandbox.md#start)
>
> [**Start (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#Sandbox.Start)
>
> [**start (CLI)**](https://www.daytona.io/docs/en/tools/cli.md#daytona-start)
>
> [**start (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona/tag/sandbox/POST/sandbox/{sandboxIdOrName}/start)
## List Sandboxes
Daytona provides options to view information about sandboxes in [Daytona Dashboard ↗](https://app.daytona.io/dashboard/) via the [sandbox details page](#sandbox-details-page) or programmatically using the [Python SDK](https://www.daytona.io/docs/en/python-sdk.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk.md), [Go SDK](https://www.daytona.io/docs/en/go-sdk/daytona.md), [CLI](https://www.daytona.io/docs/en/tools/cli.md), and [API](https://www.daytona.io/docs/en/tools/api.md#daytona) references.
```python
# List all sandboxes
result = daytona.list()
# Iterate through results
for sandbox in result.items:
print(f"Sandbox: {sandbox.id} (state: {sandbox.state})")
# List sandboxes with labels filter
result = daytona.list(labels={"env": "dev"})
```
```typescript
// List all sandboxes
const result = await daytona.list();
// Iterate through results
for (const sandbox of result.items) {
console.log(`Sandbox: ${sandbox.id} (state: ${sandbox.state})`);
}
// List sandboxes with labels filter
const filtered = await daytona.list({ 'env': 'dev' });
```
```ruby
# List all sandboxes
result = daytona.list
# Iterate through results
result.items.each do |sandbox|
puts "Sandbox: #{sandbox.id} (state: #{sandbox.state})"
end
# List sandboxes with labels filter
result = daytona.list({ 'env' => 'dev' })
```
```go
// List all sandboxes
result, err := client.List(ctx, nil, nil, nil)
// Iterate through results
for _, sandbox := range result.Items {
fmt.Printf("Sandbox: %s (state: %s)\n", sandbox.Name, sandbox.State)
}
```
```bash
daytona list [flags]
```
```bash
curl 'https://app.daytona.io/api/sandbox' \
--header 'Authorization: Bearer YOUR_SECRET_TOKEN'
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk.md), [Go SDK](https://www.daytona.io/docs/en/go-sdk.md), [CLI](https://www.daytona.io/docs/en/tools/cli.md), and [API](https://www.daytona.io/docs/en/tools/api.md#daytona) references:
> [**list (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/daytona.md#daytonalist)
>
> [**list (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/daytona.md#list)
>
> [**list (Ruby SDK)**](https://www.daytona.io/docs/en/ruby-sdk/daytona.md#list)
>
> [**List (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#Client.List)
>
> [**list (CLI)**](https://www.daytona.io/docs/en/tools/cli.md#daytona-list)
>
> [**list (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona/tag/sandbox/GET/sandbox)
### Sandbox details page
[Daytona Dashboard ↗](https://app.daytona.io/dashboard/) provides a sandbox details page to view detailed information about a sandbox and interact with it directly.
1. Navigate to [Daytona Sandboxes ↗](https://app.daytona.io/dashboard/sandboxes)
2. Click on a sandbox to open its details page
The sandbox details page provides a summary of the sandbox information and actions to perform on the sandbox:
- **Name**: the name of the sandbox
- **UUID**: the unique identifier of the sandbox
- **State**: the sandbox state with a visual indicator
- **Actions**: [start](#start-sandboxes), [stop](#stop-sandboxes), [recover](#recover-sandboxes), [archive](#archive-sandboxes), [delete](#delete-sandboxes), refresh, [SSH access](https://www.daytona.io/docs/en/ssh-access.md), [screen recordings](https://www.daytona.io/docs/en/computer-use.md#screen-recording)
- [**Region**](https://www.daytona.io/docs/en/regions.md): the target region where the sandbox is running
- [**Snapshot**](https://www.daytona.io/docs/en/snapshots.md): the snapshot used to create the sandbox
- [**Resources**](#resources): allocated sandbox CPU, memory, and disk
- [**Lifecycle**](#sandbox-lifecycle): [auto-stop](#auto-stop-interval), [auto-archive](#auto-archive-interval), and [auto-delete](#auto-delete-interval) intervals
- **Labels**: key-value pairs assigned to the sandbox
- **Timestamps**: when the sandbox was created and when the last event occurred
- [**Web terminal**](https://www.daytona.io/docs/en/web-terminal.md): an embedded web terminal session directly in the browser
- [**VNC**](https://www.daytona.io/docs/en/vnc-access.md): a graphical desktop session for sandboxes that have a desktop environment
- [**Logs**](https://www.daytona.io/docs/en/experimental/otel-collection.md): a detailed record of user and system activity for the sandbox
- **Metrics**: sandbox metrics data displayed as charts
- **Traces**: distributed traces and spans collected from the sandbox
- **Spending**: usage and cost over time
## Stop Sandboxes
Daytona provides methods to stop sandboxes in [Daytona Dashboard ↗](https://app.daytona.io/dashboard/) or programmatically using the [Python SDK](https://www.daytona.io/docs/en/python-sdk.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk.md), and [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk.md).
1. Navigate to [Daytona Sandboxes ↗](https://app.daytona.io/dashboard/sandboxes)
2. Click the stop icon (**⏹**) next to the sandbox you want to stop.
```text
Stopping sandbox with ID:
```
Stopped sandboxes maintain filesystem persistence while their memory state is cleared. They incur only disk usage costs and can be started again when needed.
The stopped state should be used when a sandbox is expected to be started again soon. Otherwise, it is recommended to stop and then archive the sandbox to eliminate disk usage costs.
```python
sandbox = daytona.create(CreateSandboxFromSnapshotParams(language="python"))
# Stop sandbox
sandbox.stop()
print(sandbox.id) # 7cd11133-96c1-4cc8-9baa-c757b8f8c916
# The sandbox ID can later be used to get the sandbox and start it
sandbox = daytona.get("7cd11133-96c1-4cc8-9baa-c757b8f8c916")
# Start sandbox
sandbox.start()
```
```typescript
const sandbox = await daytona.create({ language: 'typescript' });
// Stop sandbox
await sandbox.stop();
console.log(sandbox.id) // 7cd11133-96c1-4cc8-9baa-c757b8f8c916
// The sandbox ID can later be used to get the sandbox and start it
const found = await daytona.get('7cd11133-96c1-4cc8-9baa-c757b8f8c916');
// Start sandbox
await found.start();
```
```ruby
sandbox = daytona.create(Daytona::CreateSandboxFromSnapshotParams.new(language: Daytona::CodeLanguage::PYTHON))
# Stop sandbox
sandbox.stop
puts sandbox.id # 7cd11133-96c1-4cc8-9baa-c757b8f8c916
# The sandbox ID can later be used to find the sandbox and start it
sandbox = daytona.get('7cd11133-96c1-4cc8-9baa-c757b8f8c916')
# Start sandbox
sandbox.start
```
```go
// Stop sandbox
err = sandbox.Stop(ctx)
fmt.Println(sandbox.ID) // 7cd11133-96c1-4cc8-9baa-c757b8f8c916
// The sandbox ID can later be used to find the sandbox and start it
sandbox, err = client.Get(ctx, sandbox.ID)
// Start sandbox
err = sandbox.Start(ctx)
```
```bash
daytona stop [SANDBOX_ID] | [SANDBOX_NAME] [flags]
```
```bash
curl 'https://app.daytona.io/api/sandbox/{sandboxIdOrName}/stop' \
--request POST \
--header 'Authorization: Bearer YOUR_SECRET_TOKEN'
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk.md), [Go SDK](https://www.daytona.io/docs/en/go-sdk/daytona.md), [CLI](https://www.daytona.io/docs/en/tools/cli.md), and [API](https://www.daytona.io/docs/en/tools/api.md#daytona) references:
> [**stop (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/sandbox.md#sandboxstop)
>
> [**stop (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/sandbox.md#stop)
>
> [**stop (Ruby SDK)**](https://www.daytona.io/docs/en/ruby-sdk/sandbox.md#stop)
>
> [**Stop (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#Sandbox.Stop)
>
> [**stop (CLI)**](https://www.daytona.io/docs/en/tools/cli.md#daytona-stop)
>
> [**stop (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona/tag/sandbox/POST/sandbox/{sandboxIdOrName}/stop)
## Archive Sandboxes
Daytona provides methods to archive sandboxes in [Daytona Dashboard ↗](https://app.daytona.io/dashboard/) or programmatically using the [Python SDK](https://www.daytona.io/docs/en/python-sdk.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk.md), and [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk.md).
When sandboxes are archived, the entire filesystem state is moved to a cost-effective object storage, making it possible to keep sandboxes available for an extended period.
Starting an archived sandbox takes more time than starting a stopped sandbox, depending on its size.
A sandbox must be stopped before it can be archived and can be started again in the same way as a stopped sandbox.
```python
# Archive Sandbox
sandbox.archive()
```
```typescript
// Archive Sandbox
await sandbox.archive();
```
```ruby
# Archive Sandbox
sandbox.archive
```
```go
// Archive sandbox
err = sandbox.Archive(ctx)
```
```bash
daytona archive [SANDBOX_ID] | [SANDBOX_NAME] [flags]
```
```bash
curl 'https://app.daytona.io/api/sandbox/{sandboxIdOrName}/archive' \
--request POST \
--header 'Authorization: Bearer YOUR_SECRET_TOKEN'
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk/sync/sandbox.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk/sandbox.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk/sandbox.md), [Go SDK](https://www.daytona.io/docs/en/go-sdk.md), [CLI](https://www.daytona.io/docs/en/tools/cli.md), and [API](https://www.daytona.io/docs/en/tools/api.md#daytona/tag/sandbox) references:
> [**archive (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/sandbox.md#sandboxarchive)
>
> [**archive (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/sandbox.md#archive)
>
> [**archive (Ruby SDK)**](https://www.daytona.io/docs/en/ruby-sdk/sandbox.md#archive)
>
> [**Archive (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#Sandbox.Archive)
>
> [**archive (CLI)**](https://www.daytona.io/docs/en/tools/cli.md#daytona-archive)
>
> [**archive (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona/tag/sandbox/POST/sandbox/{sandboxIdOrName}/archive)
## Recover Sandboxes
Daytona provides methods to recover sandboxes in [Daytona Dashboard ↗](https://app.daytona.io/dashboard/) or programmatically using the [Python SDK](https://www.daytona.io/docs/en/python-sdk.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk.md), and [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk.md).
```python
# Recover sandbox
sandbox.recover()
```
```typescript
// Recover sandbox
await sandbox.recover();
```
```ruby
# Recover sandbox
sandbox.recover
```
```bash
curl 'https://app.daytona.io/api/sandbox/{sandboxIdOrName}/recover' \
--request POST \
--header 'Authorization: Bearer YOUR_SECRET_TOKEN'
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk/sync/sandbox.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk/sandbox.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk/sandbox.md), and [API](https://www.daytona.io/docs/en/tools/api.md#daytona/tag/sandbox) references:
> [**recover (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/sandbox.md#sandboxrecover)
>
> [**recover (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/sandbox.md#recover)
>
> [**recover (Ruby SDK)**](https://www.daytona.io/docs/en/ruby-sdk/sandbox.md#recover)
>
> [**recover (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona/tag/sandbox/POST/sandbox/{sandboxIdOrName}/recover)
### Recover from error state
When a sandbox enters an error state, it can sometimes be recovered using the `recover` method, depending on the underlying error reason. The `recoverable` flag indicates whether the error state can be resolved through an automated recovery procedure.
:::note
Recovery actions are not performed automatically because they address errors that require **further user intervention**, such as freeing up storage space.
:::
```python
# Check if the Sandbox is recoverable
if sandbox.recoverable:
sandbox.recover()
print("Sandbox recovered successfully")
```
```typescript
// Check if the Sandbox is recoverable
if (sandbox.recoverable) {
await sandbox.recover();
console.log('Sandbox recovered successfully');
}
```
```ruby
# Check if the Sandbox is in an error state before recovering
if sandbox.state == 'error'
sandbox.recover
puts 'Sandbox recovered successfully'
end
```
```bash
curl 'https://app.daytona.io/api/sandbox/{sandboxIdOrName}/recover' \
--request POST \
--header 'Authorization: Bearer YOUR_SECRET_TOKEN'
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk/sync/sandbox.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk/sandbox.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk/sandbox.md), and [API](https://www.daytona.io/docs/en/tools/api.md#daytona/tag/sandbox) references:
> [**recover (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/sandbox.md#sandboxrecover)
>
> [**recover (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/sandbox.md#recover)
>
> [**recover (Ruby SDK)**](https://www.daytona.io/docs/en/ruby-sdk/sandbox.md#recover)
>
> [**recover (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona/tag/sandbox/POST/sandbox/{sandboxIdOrName}/recover)
## Resize Sandboxes
Daytona provides methods to resize sandbox resources (CPU, memory, and disk) after creation.
Resizing a started sandbox allows you to `increase CPU and memory` without interruption.
To `increase disk capacity` or `decrease CPU and memory`, the sandbox must be stopped first.
```python
from daytona import Daytona, Resources
daytona = Daytona()
sandbox = daytona.create()
# Resize a started sandbox (CPU and memory can be increased)
sandbox.resize(Resources(cpu=2, memory=4))
# Resize a stopped sandbox (CPU, memory, and disk can be changed)
sandbox.stop()
sandbox.resize(Resources(cpu=4, memory=8, disk=20))
sandbox.start()
```
```typescript
import { Daytona } from '@daytonaio/sdk';
const daytona = new Daytona();
const sandbox = await daytona.create();
// Resize a started sandbox (CPU and memory can be increased)
await sandbox.resize({ cpu: 2, memory: 4 });
// Resize a stopped sandbox (CPU, memory, and disk can be changed)
await sandbox.stop();
await sandbox.resize({ cpu: 4, memory: 8, disk: 20 });
await sandbox.start();
```
```ruby
require 'daytona'
daytona = Daytona::Daytona.new
sandbox = daytona.create
# Resize a started sandbox (CPU and memory can be increased)
sandbox.resize(Daytona::Resources.new(cpu: 2, memory: 4))
# Resize a stopped sandbox (CPU, memory, and disk can be changed)
sandbox.stop
sandbox.resize(Daytona::Resources.new(cpu: 4, memory: 8, disk: 20))
sandbox.start
```
```go
// Resize a started sandbox (CPU and memory can be increased)
err := sandbox.Resize(ctx, &types.Resources{CPU: 2, Memory: 4})
// Resize a stopped sandbox (CPU, memory, and disk can be changed)
err = sandbox.Stop(ctx)
err = sandbox.Resize(ctx, &types.Resources{CPU: 4, Memory: 8, Disk: 20})
err = sandbox.Start(ctx)
```
```bash
curl 'https://app.daytona.io/api/sandbox/{sandboxIdOrName}/resize' \
--request POST \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer YOUR_SECRET_TOKEN' \
--data '{
"cpu": 2,
"memory": 4,
"disk": 20
}'
```
:::note
- **started** sandboxes: CPU and memory can only be increased, not decreased. Disk cannot be changed.
- **stopped** sandboxes: CPU, memory, and disk can be changed. Disk can only be increased.
:::
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk/sync/sandbox.md#sandboxresize), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk/sandbox.md#resize), [Go SDK](https://www.daytona.io/docs/en/go-sdk/daytona.md#Sandbox.Resize), and [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk/sandbox.md#resize) references:
> [**resize (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/sandbox.md#sandboxresize)
>
> [**resize (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/sandbox.md#resize)
>
> [**Resize (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#Sandbox.Resize)
>
> [**resize (Ruby SDK)**](https://www.daytona.io/docs/en/ruby-sdk/sandbox.md#resize)
## Delete Sandboxes
Daytona provides methods to delete sandboxes in [Daytona Dashboard ↗](https://app.daytona.io/dashboard/) or programmatically using the [Python SDK](https://www.daytona.io/docs/en/python-sdk.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk.md), and [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk.md).
1. Navigate to [Daytona Sandboxes ↗](https://app.daytona.io/dashboard/sandboxes)
2. Click the **Delete** button next to the sandbox you want to delete.
```text
Deleting sandbox with ID:
```
```python
# Delete sandbox
sandbox.delete()
```
```typescript
// Delete sandbox
await sandbox.delete();
```
```ruby
# Delete sandbox
sandbox.delete
```
```go
// Delete sandbox
err = sandbox.Delete(ctx)
```
```bash
daytona delete [SANDBOX_ID] | [SANDBOX_NAME] [flags]
```
```bash
curl 'https://app.daytona.io/api/sandbox/{sandboxIdOrName}' \
--request DELETE \
--header 'Authorization: Bearer YOUR_SECRET_TOKEN'
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk/sync/sandbox.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk/sandbox.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk/sandbox.md), [Go SDK](https://www.daytona.io/docs/en/go-sdk/daytona.md), [CLI](https://www.daytona.io/docs/en/tools/cli.md), and [API](https://www.daytona.io/docs/en/tools/api.md#daytona/tag/sandbox) references:
> [**delete (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/sandbox.md#sandboxdelete)
>
> [**delete (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/sandbox.md#delete)
>
> [**delete (Ruby SDK)**](https://www.daytona.io/docs/en/ruby-sdk/sandbox.md#delete)
>
> [**Delete (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#Sandbox.Delete)
>
> [**delete (CLI)**](https://www.daytona.io/docs/en/tools/cli.md#daytona-delete)
>
> [**delete (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona/tag/sandbox/DELETE/sandbox/{sandboxIdOrName})
## Automated lifecycle management
Daytona Sandboxes can be automatically stopped, archived, and deleted based on user-defined intervals.
### Auto-stop interval
The auto-stop interval parameter sets the amount of time after which a running sandbox will be automatically stopped.
The auto-stop interval will trigger even if there are internal processes running in the sandbox. The system differentiates between "internal processes" and "active user interaction". Merely having a script or background task running is not sufficient to keep the sandbox alive.
The parameter can either be set to:
- a time interval in minutes
- `0`: disables the auto-stop functionality, allowing the sandbox to run indefinitely
If the parameter is not set, the default interval of `15 minutes` will be used.
```python
sandbox = daytona.create(CreateSandboxFromSnapshotParams(
snapshot="my-snapshot-name",
# Disables the auto-stop feature - default is 15 minutes
auto_stop_interval=0,
))
```
```typescript
const sandbox = await daytona.create({
snapshot: "my-snapshot-name",
// Disables the auto-stop feature - default is 15 minutes
autoStopInterval: 0,
});
```
```ruby
sandbox = daytona.create(
Daytona::CreateSandboxFromSnapshotParams.new(
snapshot: 'my-snapshot-name',
# Disables the auto-stop feature - default is 15 minutes
auto_stop_interval: 0
)
)
```
```go
// Create a sandbox with auto-stop disabled
autoStopInterval := 0
params := types.SnapshotParams{
Snapshot: "my-snapshot-name",
SandboxBaseParams: types.SandboxBaseParams{
AutoStopInterval: &autoStopInterval,
},
}
sandbox, err := client.Create(ctx, params)
```
```bash
curl 'https://app.daytona.io/api/sandbox/{sandboxIdOrName}/autostop/{interval}' \
--request POST \
--header 'Authorization: Bearer YOUR_SECRET_TOKEN'
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk/sync/sandbox.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk/sandbox.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk/sandbox.md), [Go SDK](https://www.daytona.io/docs/en/go-sdk/daytona.md), and [API](https://www.daytona.io/docs/en/tools/api.md#daytona/tag/sandbox) references:
> [**set_autostop_interval (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/sandbox.md#sandboxset_autostop_interval)
>
> [**setAutostopInterval (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/sandbox.md#setautostopinterval)
>
> [**auto_stop_interval (Ruby SDK)**](https://www.daytona.io/docs/en/ruby-sdk/sandbox.md#auto_stop_interval)
>
> [**set_auto_stop_interval (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona/tag/sandbox/POST/sandbox/{sandboxIdOrName}/autostop/1)
#### What resets the timer
The inactivity timer resets only for specific external interactions:
- Accessing [sandbox previews](https://www.daytona.io/docs/en/preview.md) (network requests through preview URLs)
- Active [SSH connections](https://www.daytona.io/docs/en/ssh-access.md)
- [Daytona Toolbox SDK API](https://www.daytona.io/docs/en/tools/api.md#daytona-toolbox) calls
#### What does not reset the timer
The following do not reset the timer:
- SDK calls that are not toolbox actions
- Background scripts (e.g., `npm run dev` run as a fire-and-forget command)
- Long-running tasks without external interaction
- Processes that don't involve active monitoring
If you run a long-running task like LLM inference that takes more than 15 minutes without any external interaction, the sandbox may auto-stop mid-process because the process itself doesn't count as "activity".
### Auto-archive interval
Daytona provides methods to set the auto-archive interval using the [Python SDK](https://www.daytona.io/docs/en/python-sdk.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk.md), and [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk.md).
The auto-archive interval parameter sets the amount of time after which a continuously stopped sandbox will be automatically archived.
The parameter can either be set to:
- a time interval in minutes
- `0`: the maximum interval of `30 days` will be used
If the parameter is not set, the default interval of `7 days` will be used.
```python
sandbox = daytona.create(CreateSandboxFromSnapshotParams(
snapshot="my-snapshot-name",
# Auto-archive after a sandbox has been stopped for 1 hour
auto_archive_interval=60,
))
```
```typescript
const sandbox = await daytona.create({
snapshot: "my-snapshot-name",
// Auto-archive after a sandbox has been stopped for 1 hour
autoArchiveInterval: 60,
});
```
```ruby
sandbox = daytona.create(
Daytona::CreateSandboxFromSnapshotParams.new(
snapshot: 'my-snapshot-name',
# Auto-archive after a sandbox has been stopped for 1 hour
auto_archive_interval: 60
)
)
```
```go
// Create a sandbox with auto-archive after 1 hour
autoArchiveInterval := 60
params := types.SnapshotParams{
Snapshot: "my-snapshot-name",
SandboxBaseParams: types.SandboxBaseParams{
AutoArchiveInterval: &autoArchiveInterval,
},
}
sandbox, err := client.Create(ctx, params)
```
```bash
curl 'https://app.daytona.io/api/sandbox/{sandboxIdOrName}/autoarchive/{interval}' \
--request POST \
--header 'Authorization: Bearer YOUR_SECRET_TOKEN'
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk/sync/sandbox.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk/sandbox.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk/sandbox.md), [Go SDK](https://www.daytona.io/docs/en/go-sdk/daytona.md), and [API](https://www.daytona.io/docs/en/tools/api.md#daytona/tag/sandbox) references:
> [**set_auto_archive_interval (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/sandbox.md#sandboxset_auto_archive_interval)
>
> [**setAutoArchiveInterval (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/sandbox.md#setautoarchiveinterval)
>
> [**auto_archive_interval (Ruby SDK)**](https://www.daytona.io/docs/en/ruby-sdk/sandbox.md#auto_archive_interval)
>
> [**SetAutoArchiveInterval (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#Sandbox.SetAutoArchiveInterval)
>
> [**set_auto_archive_interval (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona/tag/sandbox/POST/sandbox/{sandboxIdOrName}/autoarchive/{interval})
### Auto-delete interval
Daytona provides methods to set the auto-delete interval using the [Python SDK](https://www.daytona.io/docs/en/python-sdk.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk.md), and [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk.md).
The auto-delete interval parameter sets the amount of time after which a continuously stopped sandbox will be automatically deleted. By default, sandboxes will never be automatically deleted.
The parameter can either be set to:
- a time interval in minutes
- `-1`: disables the auto-delete functionality
- `0`: the sandbox will be deleted immediately after stopping
If the parameter is not set, the sandbox will not be deleted automatically.
```python
sandbox = daytona.create(CreateSandboxFromSnapshotParams(
snapshot="my-snapshot-name",
# Auto-delete after a sandbox has been stopped for 1 hour
auto_delete_interval=60,
))
# Delete the sandbox immediately after it has been stopped
sandbox.set_auto_delete_interval(0)
# Disable auto-deletion
sandbox.set_auto_delete_interval(-1)
```
```typescript
const sandbox = await daytona.create({
snapshot: "my-snapshot-name",
// Auto-delete after a sandbox has been stopped for 1 hour
autoDeleteInterval: 60,
});
// Delete the sandbox immediately after it has been stopped
await sandbox.setAutoDeleteInterval(0)
// Disable auto-deletion
await sandbox.setAutoDeleteInterval(-1)
```
```ruby
sandbox = daytona.create(
Daytona::CreateSandboxFromSnapshotParams.new(
snapshot: 'my-snapshot-name',
# Auto-delete after a sandbox has been stopped for 1 hour
auto_delete_interval: 60
)
)
# Delete the sandbox immediately after it has been stopped
sandbox.auto_delete_interval = 0
# Disable auto-deletion
sandbox.auto_delete_interval = -1
```
```go
// Create a sandbox with auto-delete after 1 hour
autoDeleteInterval := 60
params := types.SnapshotParams{
Snapshot: "my-snapshot-name",
SandboxBaseParams: types.SandboxBaseParams{
AutoDeleteInterval: &autoDeleteInterval,
},
}
sandbox, err := client.Create(ctx, params)
// Delete the sandbox immediately after it has been stopped
zeroInterval := 0
err = sandbox.SetAutoDeleteInterval(ctx, &zeroInterval)
// Disable auto-deletion
disableInterval := -1
err = sandbox.SetAutoDeleteInterval(ctx, &disableInterval)
```
```bash
curl 'https://app.daytona.io/api/sandbox/{sandboxIdOrName}/autodelete/{interval}' \
--request POST \
--header 'Authorization: Bearer YOUR_SECRET_TOKEN'
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk/sync/sandbox.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk/sandbox.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk/sandbox.md), [Go SDK](https://www.daytona.io/docs/en/go-sdk/daytona.md), and [API](https://www.daytona.io/docs/en/tools/api.md#daytona/tag/sandbox) references:
> [**set_auto_delete_interval (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/sandbox.md#sandboxset_auto_delete_interval)
>
> [**setAutoDeleteInterval (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/sandbox.md#setautodeleteinterval)
>
> [**auto_delete_interval (Ruby SDK)**](https://www.daytona.io/docs/en/ruby-sdk/sandbox.md#auto_delete_interval)
>
> [**SetAutoDeleteInterval (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#Sandbox.SetAutoDeleteInterval)
>
> [**set_auto_delete_interval (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona/tag/sandbox/POST/sandbox/{sandboxIdOrName}/autodelete/{interval})
### Running indefinitely
Daytona provides methods to run sandboxes indefinitely using the [Python SDK](https://www.daytona.io/docs/en/python-sdk.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk.md), and [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk.md).
By default, Daytona Sandboxes auto-stop after 15 minutes of inactivity. To keep a sandbox running without interruption, set the auto-stop interval to `0` when creating a new sandbox:
```python
sandbox = daytona.create(CreateSandboxFromSnapshotParams(
snapshot="my_awesome_snapshot",
# Disables the auto-stop feature - default is 15 minutes
auto_stop_interval=0,
))
```
```typescript
const sandbox = await daytona.create({
snapshot: "my_awesome_snapshot",
// Disables the auto-stop feature - default is 15 minutes
autoStopInterval: 0,
});
```
```ruby
sandbox = daytona.create(
Daytona::CreateSandboxFromSnapshotParams.new(
snapshot: 'my_awesome_snapshot',
# Disables the auto-stop feature - default is 15 minutes
auto_stop_interval: 0
)
)
```
```go
// Disables the auto-stop feature - default is 15 minutes
autoStopInterval := 0
params := types.SnapshotParams{
Snapshot: "my_awesome_snapshot",
SandboxBaseParams: types.SandboxBaseParams{
AutoStopInterval: &autoStopInterval,
},
}
sandbox, err := client.Create(ctx, params)
```
The security exhibit outlines the technical and organizational security measures Daytona maintains to protect customer data processed through its platform. It covers Daytona's information security program, compliance posture, incident management procedures, and business continuity practices.
:::note
This security exhibit supplements the Daytona [Terms of Service](https://www.daytona.io/terms-of-service) and [Data Processing Agreement](https://www.daytona.io/dpa), collectively the "Agreement", between Daytona Platforms, Inc. ("Daytona") and Customer ("Customer"). In the event of any conflict between this exhibit and the agreement, the agreement shall control.
:::
## Information security program
Daytona maintains a comprehensive information security program designed to protect Customer data processed through its secure runtime platform. The program is aligned with industry-standard frameworks including SOC 2, ISO 27001, and incorporates controls specific to AI agent infrastructure and ephemeral compute environments.
### Security policies
Daytona maintains a suite of information security policies that are reviewed at least annually and updated as needed by the Chief Trust Officer. These policies are approved by executive leadership and are made available to all Daytona personnel. Policies cover, at minimum: acceptable use, access control, data classification, incident response, vulnerability management, change management, and business continuity.
### Security training
All Daytona personnel with access to Customer data or production systems complete mandatory security awareness training during onboarding and annually thereafter. Training covers phishing recognition, secure coding practices, data handling procedures, incident reporting, and compliance obligations. Completion is tracked and verified.
### Personnel security
Background checks are conducted on all Daytona personnel who have access to Customer data or production systems, in accordance with applicable law. All such personnel are bound by confidentiality agreements. Offboarding procedures include timely revocation of all access credentials and return of company assets.
### Access control
Access to Customer data and production systems is governed by the principle of least privilege and role-based access control (RBAC). Access is granted only upon documented business need and approved by management. Access reviews are conducted quarterly. Multi-factor authentication (MFA) is enforced for all Daytona personnel with access to production infrastructure, administrative consoles, and source code repositories.
### Data storage and classification
Daytona classifies data according to sensitivity levels: Public, Internal, Confidential, and Restricted. Customer data is classified as Confidential at minimum. Data retention and destruction follow documented policies. Customer data is stored in the geographic region specified by the Customer's configuration where supported. Daytona does not use Customer Content to train models or improve services.
### Sandbox isolation
Daytona's core architecture isolates each sandbox using container and/or microVM technology, ensuring that one Customer's runtime environment cannot interact with another's. Isolation controls include: dedicated namespaces per sandbox, network segmentation preventing lateral movement between sandboxes, resource quotas (CPU, memory, storage, network bandwidth), read-only root filesystems where applicable, and configurable network allow-lists with network-level firewall rules.
### Ephemeral sandbox supported
Daytona sandboxes can be configured as ephemeral, meaning they are automatically deleted once stopped. When ephemeral mode is enabled, all associated compute, memory, and local storage are reclaimed upon sandbox termination, and any session-scoped credentials or tokens are revoked. This reduces the attack surface by ensuring no persistent runtime state accumulates between sessions. For non-ephemeral sandboxes, Daytona provides configurable auto-stop and auto-delete intervals to manage sandbox lifecycle and minimize exposure of idle environments.
### Encryption
**Encryption Standards**
- **In transit**: TLS 1.2+ for all external and internal communications
- **At rest**: AES-256 or equivalent across all storage systems
- **Key management**: Infrastructure provider KMS with automatic rotation
### Authentication and access
Daytona provides identity and access management through Auth0, supporting authentication via Google and GitHub identity providers. Multi-factor authentication (MFA) is enforced for all Daytona personnel with administrative access. Daytona implements session management controls including configurable session timeouts and token revocation capabilities. Enterprise customers requiring SAML 2.0 or OIDC-based Single Sign-On (SSO) integration should contact Daytona to discuss available options.
### Backup and recovery
Critical Daytona platform data (control plane, configuration, metadata) is backed up regularly with a defined recovery point objective (RPO) and recovery time objective (RTO). Backups are encrypted at rest and stored in a geographically separate location from the primary infrastructure. Backup restoration procedures are tested at least annually.
### Vulnerability management
Daytona performs automated vulnerability scanning of its infrastructure and applications on at least a monthly basis. Identified vulnerabilities are triaged and remediated according to the following target timelines:
| **Severity** | **Target** | **Example** |
| ------------ | ---------- | -------------------------- |
| Critical | 24 hours | RCE, privilege escalation |
| High | 7 days | Auth bypass, data exposure |
| Medium | 30 days | XSS, misconfigurations |
| Low | 90 days | Informational findings |
### Network security
Daytona implements defense-in-depth network security controls including: network segmentation between sandbox traffic, control plane, and management interfaces; firewall rules reviewed at least annually; DDoS mitigation at the infrastructure edge; and intrusion detection and monitoring for anomalous network activity. Sandbox network access can be restricted using configurable allow-lists and network block policies.
### Secure development lifecycle
Daytona follows a secure software development lifecycle (SDLC) that includes: security requirements analysis during design, peer code review for all changes, automated static analysis and dependency scanning in CI/CD, container image scanning that blocks critical and high vulnerabilities, and separation of development, staging, and production environments.
### Change management
All changes to production systems follow a documented change management process that includes: description and risk assessment of the change, peer review and approval, testing in non-production environments, and rollback procedures. Emergency changes follow an expedited process with retroactive documentation and review.
### Third-party risk management
Daytona evaluates the security posture of third-party vendors and sub-processors before engagement and on an ongoing basis. Evaluation criteria include: security certifications, data handling practices, incident response capabilities, and contractual security obligations. Sub-processors are contractually required to maintain security controls substantially similar to those described in this Exhibit and the DPA.
### Patch management
Daytona applies security patches to operating systems, libraries, and application dependencies in accordance with its vulnerability management SLAs. Critical patches are tested and deployed within 24 hours. Automated dependency monitoring tracks new CVEs affecting the Daytona stack.
### Audit logging and monitoring
Daytona maintains comprehensive audit logs of administrative actions, authentication events, access to Customer data, and system-level events. Logs are stored securely, protected against tampering, and retained for a minimum of 12 months. Security events are monitored and alerted upon in real time. Log access is restricted to authorized security personnel.
### Container and runtime security
:::note
Daytona uses Sysbox as its container runtime to provide VM-level isolation without hardware virtualization overhead.
:::
Sysbox enforces Linux user-namespaces on all sandboxes, ensuring that the root user inside a sandbox maps to a fully unprivileged user on the host. Each sandbox receives exclusive user-ID and group-ID mappings, so a process escaping one sandbox has no permissions to access other sandboxes or host resources.
Additional Sysbox security controls include: partial virtualization of procfs and sysfs to hide host information and prevent modification of system-wide kernel settings, immutable initial mounts that prevent sandbox processes from weakening container isolation even with root capabilities, and selective syscall interception that blocks dangerous operations while preserving compatibility with system-level workloads such as Docker-in-Docker.
Container images are built from minimal base images and scanned for vulnerabilities in CI/CD pipelines, and runtime threat detection monitors for anomalous process behavior.
### Penetration testing
Daytona completes penetration testing at least annually, conducted by a recognized independent third party. Testing scope includes the Daytona platform, APIs, sandbox isolation mechanisms, and control plane. A summary of test results and remediation status is available to Customers upon request.
### Vulnerability disclosure program
Daytona welcomes contributions from the security community to identify and responsibly disclose vulnerabilities in its platform. Daytona maintains a public Vulnerability Disclosure Policy with defined scope, exclusions, safe harbor protections, and coordinated disclosure timelines. Rewards ranging from $100 to $1,000 are offered for valid, original findings based on severity, exploitability, and report quality. Reports should be submitted to [security@daytona.io](mailto:security@daytona.io). Full program details are published in Daytona's [Security Policy](https://github.com/daytonaio/daytona/blob/main/SECURITY.md).
## Compliance and certifications
Daytona pursues and maintains industry-recognized compliance certifications to demonstrate its commitment to security and data protection.
| **Framework** | **Status** | **Details** |
| ------------- | ----------- | ---------------------------------------------------------------- |
| SOC 2 Type I | Achieved | Completed; report available under NDA via Trust Center. |
| SOC 2 Type II | In progress | Audit period underway |
| ISO 27001 | In progress | Certification in progress |
| HIPAA BAA | Available | Business Associate Agreements available for qualifying customers |
Copies of current certifications and audit reports are available to Customers upon written request, subject to reasonable confidentiality obligations, consistent with the DPA (Section 10).
## Assessments, audits, and remediation
### Assessment obligations
Daytona shall maintain its security program and submit to independent third-party audits at least annually to verify compliance with this Exhibit and applicable security standards. Daytona will provide copies of audit reports and certifications upon reasonable written request, subject to confidentiality obligations as set forth in the Agreement.
### Remediation
Where assessments or audits identify material deficiencies, Daytona shall prepare a remediation plan and address findings within timeframes consistent with the vulnerability severity levels defined in Section 1.11.
### Secure disposal
Upon termination of the Agreement or at Customer's request, Daytona shall securely delete or return Customer data in accordance with the DPA (Section 8). Deletion is performed using methods that render data unrecoverable, including cryptographic erasure of encrypted storage volumes. Daytona will certify deletion upon request.
## Security incident management
### Incident response procedures
Daytona maintains a documented incident response plan that defines roles, responsibilities, escalation procedures, and communication protocols. The plan is tested at least annually through tabletop exercises. Incidents are classified by severity and handled by a dedicated incident response team.
### Notification
In the event of a Security Incident involving Customer data, Daytona shall notify the affected Customer without undue delay, consistent with the DPA (Section 15). Notification shall include, to the extent known: the nature and scope of the incident, the types of data affected, steps taken to contain and remediate, recommended Customer actions, and a point of contact for further communication. Notification may be delayed at the request of law enforcement or where delay is reasonably necessary to investigate and remediate.
### Incident remediation
Daytona shall cooperate fully to investigate and remedy any harm or potential harm caused by a Security Incident. The Customer shall be informed of the response plan. Any liability arising from a Security Incident shall be subject to the limitation of liability provisions set forth in the Agreement ([Terms of Service](https://www.daytona.io/terms-of-service), section 15), including the aggregate liability cap and exclusion of indirect, incidental, special, consequential, or punitive damages. Each Party is solely responsible for any regulatory fines imposed directly on it by a supervisory authority, subject to the provisions of the [Data Processing Agreement](https://www.daytona.io/dpa) (section 12).
## Business continuity
Daytona maintains a Business Continuity Plan (BCP) and Disaster Recovery Plan (DRP) that are reviewed and tested at least annually. The plans address: critical system recovery priorities and RTOs, data backup and restoration procedures, communication protocols during disruptions, alternative processing capabilities, and lessons-learned reviews following any activation of the BCP/DRP.
## Termination obligations
Upon termination or expiration of the Agreement, Daytona shall: cease all processing of Customer data except as required to complete termination; return or delete Customer data at Customer's election, in accordance with the DPA (Section 8); certify deletion upon written request; and continue to protect any Customer data lawfully retained in accordance with this Exhibit and the Agreement.
## Contact and sub-processors
### Security contacts
| **Team** | **Email** |
| ------------------------- | ------------------------------------------------- |
| Security | [security@daytona.io](mailto:security@daytona.io) |
| Privacy contact | [privacy@daytona.io](mailto:privacy@daytona.io) |
| Trust center | [trust.daytona.io](https://trust.daytona.io) |
| Data Processing Agreement | [daytona.io/dpa](https://www.daytona.io/dpa) |
| General Support | [support@daytona.io](mailto:support@daytona.io) |
### Sub-processors
Daytona maintains and updates a record of sub-processors that process Customer data. The current sub-processor list is published as Exhibit C of Daytona's [Data Processing Agreement](https://www.daytona.io/dpa).
Daytona will notify Customer of any material changes to its sub-processor list. If Customer reasonably objects to the appointment of a new sub-processor based on data protection concerns, the parties will discuss such concerns in good faith. If no resolution is reached, Customer may terminate the Agreement for convenience as its sole and exclusive remedy, consistent with the [Data Processing Agreement](https://www.daytona.io/dpa) (section 14).
Snapshots are sandbox templates created from [Docker](https://www.docker.com/) or [OCI](https://opencontainers.org/) compatible images. Sandboxes can use a [default snapshot](#default-snapshots) or custom snapshots to provide a consistent and reproducible sandbox environments for your dependencies, settings, and resources.
Daytona supports running [Docker](#run-docker-in-a-sandbox) and [Kubernetes](#run-kubernetes-in-a-sandbox) workloads inside sandboxes using snapshots.
## Snapshot lifecycle
Throughout the snapshot lifecycle, a snapshot can have the following states:
| **State** | **Description** |
| ------------------ | ----------------------------------------------- |
| **`pending`** | Snapshot creation requested |
| **`building`** | Snapshot is being built |
| **`pulling`** | Snapshot image is being pulled from a registry |
| **`active`** | Snapshot is ready to use for creating sandboxes |
| **`inactive`** | Snapshot is deactivated |
| **`error`** | Snapshot creation failed |
| **`build_failed`** | Snapshot build process failed |
| **`removing`** | Snapshot is being deleted |
:::note
Inactive snapshots cannot be used to create sandboxes. They must be explicitly [re-activated](#activate-snapshots) before use. When activated, the snapshot returns to `pending` state and is re-processed before becoming `active` again.
:::
## Create Snapshots
Daytona provides methods to create snapshots using the [Daytona Dashboard ↗](https://app.daytona.io/dashboard/snapshots) or programmatically using the Daytona [Python](https://www.daytona.io/docs/en/python-sdk/sync/snapshot.md), [TypeScript](https://www.daytona.io/docs/en/typescript-sdk/snapshot.md), [Ruby](https://www.daytona.io/docs/en/ruby-sdk/snapshot.md), [Go](https://www.daytona.io/docs/en/go-sdk/daytona.md#SnapshotService) **SDKs**, [CLI](https://www.daytona.io/docs/en/tools/cli.md#daytona-snapshot), or [API](https://www.daytona.io/docs/en/tools/api.md#daytona/tag/snapshots).
Snapshots can be created using:
- [public images](#using-public-images)
- [local images](#using-local-images)
- [images from private registries](#using-images-from-private-registries)
- [the declarative builder](#using-the-declarative-builder)
1. Navigate to [Daytona Snapshots ↗](https://app.daytona.io/dashboard/snapshots)
2. Click the **Create Snapshot** button
3. Enter the **snapshot name**, **image** (tag or digest), **entrypoint**, and **resources**
- **Snapshot name**: Identifier used to reference the snapshot in the SDK or CLI.
- **Image**: Base image for the snapshot. Must include either a tag or a digest (e.g., **`ubuntu:22.04`**). The **`latest`** tag is not allowed. Since images tagged `latest` get frequent updates, only specific tags are supported. Same applies to tags such as `lts` or `stable`, and we recommend avoiding those when defining an image to prevent unexpected behavior.
- **Entrypoint** (optional): The entrypoint command for the snapshot. Ensure that the entrypoint is a long-running command. If not provided, or if the snapshot does not have an entrypoint, `sleep infinity` will be used as the default.
- [**Resources**](https://www.daytona.io/docs/en/sandboxes.md#resources) (optional): The resources you want the underlying Sandboxes to have. By default, Daytona Sandboxes use **1 vCPU**, **1GiB memory**, and **3GiB storage**.
```python
image = Image.debian_slim('3.12').pip_install('numpy')
daytona.snapshot.create(
CreateSnapshotParams(name='my-awesome-snapshot', image=image),
on_logs=lambda chunk: print(chunk, end=""),
)
```
```typescript
const image = Image.debianSlim('3.12').pipInstall('numpy');
await daytona.snapshot.create({ name: 'my-awesome-snapshot', image: image }, { onLogs: console.log });
```
```ruby
image = Image.debian_slim('3.12').pip_install('numpy')
params = CreateSnapshotParams.new(name: 'my-awesome-snapshot', image: image)
snapshot = daytona.snapshot.create(params) do |chunk|
print chunk
end
```
```go
// Create from Docker Hub image
snapshot, logChan, err := client.Snapshots.Create(ctx, &types.CreateSnapshotParams{
Name: "my-awesome-snapshot",
Image: "python:3.11-slim",
})
if err != nil {
return err
}
// Stream build logs
for log := range logChan {
fmt.Println(log)
}
// Create with custom image and resources
image := daytona.Base("python:3.11").PipInstall([]string{"numpy"})
snapshot, logChan, err := client.Snapshots.Create(ctx, &types.CreateSnapshotParams{
Name: "my-awesome-snapshot",
Image: image,
Resources: &types.Resources{CPU: 2, Memory: 4096},
})
```
```bash
daytona snapshot create my-awesome-snapshot --image python:3.11-slim --cpu 2 --memory 4
```
```bash
curl https://app.daytona.io/api/snapshots \
--request POST \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer YOUR_SECRET_TOKEN' \
--data '{
"name": "my-awesome-snapshot",
"imageName": "python:3.11-slim",
"cpu": 2,
"memory": 4
}'
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk/sync/snapshot.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk/snapshot.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk/snapshot.md), [Go SDK](https://www.daytona.io/docs/en/go-sdk/daytona.md#SnapshotService.Create), [CLI](https://www.daytona.io/docs/en/tools/cli.md#daytona-snapshot), and [API](https://www.daytona.io/docs/en/tools/api.md#daytona/tag/snapshots) references:
> [**create (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/snapshot.md#snapshotservicecreate)
>
> [**create (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/snapshot.md#create)
>
> [**create (Ruby SDK)**](https://www.daytona.io/docs/en/ruby-sdk/snapshot.md#create)
>
> [**create (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#SnapshotService.Create)
>
> [**create (CLI)**](https://www.daytona.io/docs/en/tools/cli.md#daytona-snapshot-create)
>
> [**create (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona/tag/snapshots/POST/snapshots)
### Using public images
Daytona supports creating snapshots from any publicly accessible image or container registry.
1. Navigate to [Daytona Snapshots ↗](https://app.daytona.io/dashboard/snapshots)
2. Click the **Create Snapshot** button
3. Enter the **snapshot name** and **image** (tag or digest) of any publicly accessible image or container registry
Once the snapshot is pulled, validated, and has an `Active` state, it is ready to be used.
```python
daytona.snapshot.create(
CreateSnapshotParams(name='my-awesome-snapshot', image='python:3.11-slim'),
on_logs=lambda chunk: print(chunk, end=""),
)
```
```typescript
await daytona.snapshot.create({ name: 'my-awesome-snapshot', image: 'python:3.11-slim' }, { onLogs: console.log });
```
```ruby
params = CreateSnapshotParams.new(name: 'my-awesome-snapshot', image: 'python:3.11-slim')
snapshot = daytona.snapshot.create(params) do |chunk|
print chunk
end
```
```go
snapshot, logChan, err := client.Snapshots.Create(ctx, &types.CreateSnapshotParams{
Name: "my-awesome-snapshot",
Image: "python:3.11-slim",
})
if err != nil {
return err
}
// Stream build logs
for log := range logChan {
fmt.Println(log)
}
```
```bash
daytona snapshot create my-awesome-snapshot --image python:3.11-slim
```
```bash
curl https://app.daytona.io/api/snapshots \
--request POST \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer YOUR_SECRET_TOKEN' \
--data '{
"name": "my-awesome-snapshot",
"imageName": "python:3.11-slim"
}'
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk/sync/snapshot.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk/snapshot.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk/snapshot.md), [Go SDK](https://www.daytona.io/docs/en/go-sdk/daytona.md#SnapshotService.Create), [CLI](https://www.daytona.io/docs/en/tools/cli.md#daytona-snapshot), and [API](https://www.daytona.io/docs/en/tools/api.md#daytona/tag/snapshots) references.
> [**create (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/snapshot.md#snapshotservicecreate)
>
> [**create (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/snapshot.md#create)
>
> [**create (Ruby SDK)**](https://www.daytona.io/docs/en/ruby-sdk/snapshot.md#create)
>
> [**create (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#SnapshotService.Create)
>
> [**create (CLI)**](https://www.daytona.io/docs/en/tools/cli.md#daytona-snapshot-create)
>
> [**create (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona/tag/snapshots/POST/snapshots)
### Using local images
Daytona supports creating snapshots from local images or from local Dockerfiles. To create a snapshot from a local image or from a local Dockerfile, use the [Daytona CLI](https://www.daytona.io/docs/en/tools/cli.md#daytona-snapshot).
Daytona expects the local image to be built for AMD64 architecture. Therefore, the `--platform=linux/amd64` flag is required when building the Docker image if your machine is running on a different architecture.
1. Ensure the image and tag you want to use is available
```bash
docker images
```
2. Create a snapshot and push it to Daytona:
```bash
daytona snapshot push custom-alpine:3.21 --name alpine-minimal
```
:::tip
Use the flags `--cpu`, `--memory` and `--disk` to specify the [resources](https://www.daytona.io/docs/en/sandboxes.md#resources) you want the underlying sandboxes to have. Example:
```bash
daytona snapshot push custom-alpine:3.21 --name alpine-minimal --cpu 2 --memory 4 --disk 8
```
:::
Alternatively, use the `--dockerfile` flag under `create` to pass the path to the Dockerfile you want to use and Daytona will build the snapshot for you. The `COPY`/`ADD` commands will be automatically parsed and added to the context. To manually add files to the context, use the `--context` flag.
```bash
daytona snapshot create my-awesome-snapshot --dockerfile ./Dockerfile
```
```text
Building image from /Users/user/docs/Dockerfile
Step 1/5 : FROM alpine:latest
...
⡿ Waiting for the Snapshot to be validated ...
...
✓ Use 'harbor-transient.internal.daytona.app/daytona/trying-daytona:0.0.1' to create a new sandbox using this Snapshot
```
### Using images from private registries
Daytona supports creating snapshots from images from [Docker Hub](#docker-hub), [Google Artifact Registry](#google-artifact-registry), [GitHub Container Registry](#github-container-registry) or other private container registries.
1. Navigate to [Daytona Registries ↗](https://app.daytona.io/dashboard/registries)
2. Click the **Add Registry** button
3. Enter the **registry name**, **registry URL**, **username**, **password**, and **project** (if applicable)
4. After the container registry is successfully created, navigate to [Daytona Snapshots ↗](https://app.daytona.io/dashboard/snapshots)
5. Click the **Create Snapshot** button
6. Enter the **snapshot name** and private **image** (tag or digest). When creating the snapshot, make sure to input the entire private image name, including the registry location and project name (e.g. **`my-private-registry.com//custom-alpine:3.21`**)
Optionally, set the **`CreateSandboxFromSnapshotParams`** field to use the custom snapshot.
#### Docker Hub
Daytona supports creating snapshots from Docker Hub images.
1. Navigate to [Daytona Registries ↗](https://app.daytona.io/dashboard/registries)
2. Click the **Add Registry** button
3. Enter the **registry name**, **registry URL**, **username**, **password**, and **project** (if applicable)
- **Registry URL**: `docker.io`
- **Username**: Docker Hub username (the account with access to the image)
- **Password**: [Docker Hub Personal Access Token](https://docs.docker.com/docker-hub/access-tokens/) (not your account password)
- **Create the Snapshot**: `docker.io//:`
4. After the container registry is successfully created, navigate to [Daytona Snapshots ↗](https://app.daytona.io/dashboard/snapshots)
5. Click the **Create Snapshot** button
6. Enter the **snapshot name** and **image** (tag or digest). When creating the snapshot, input the entire image name, including the registry location and project name (e.g. **`docker.io//:`**)
#### Google Artifact Registry
Daytona supports creating snapshots from images from Google Artifact Registry.
To use an image from Google Artifact Registry, configure the registry using a [service account key](https://cloud.google.com/iam/docs/keys-create-delete) in JSON format.
1. Navigate to [Daytona Registries ↗](https://app.daytona.io/dashboard/registries)
2. Click the **Add Registry** button
3. Enter the **registry name**, **registry URL**, **username**, **password**, and **project** (if applicable)
- **Registry URL**: base URL for your region (e.g., `https://us-central1-docker.pkg.dev` or `https://us-central1-docker.pkg.dev/your-org`).
- **Username**: `_json_key`
- **Password**: Paste the full contents of your Service Account JSON key file
- **Project**: Google Cloud Project ID
- **Create the Snapshot**: `us-central1-docker.pkg.dev///:`
4. After the container registry is successfully created, navigate to [Daytona Snapshots ↗](https://app.daytona.io/dashboard/snapshots)
5. Click the **Create Snapshot** button
6. Enter the **snapshot name** and **image** (tag or digest). When creating the snapshot, make sure to input the entire image name, including the registry location and project name (e.g. **`us-central1-docker.pkg.dev///:`**)
#### GitHub Container Registry (GHCR)
Daytona supports creating snapshots from images from GitHub Container Registry (GHCR).
1. Navigate to [Daytona Registries ↗](https://app.daytona.io/dashboard/registries)
2. Click the **Add Registry** button
3. Enter the **registry name**, **registry URL**, **username**, **password**, and **project** (if applicable)
- **Registry URL**: `ghcr.io`
- **Username**: GitHub username (the account with access to the image)
- **Password**: [GitHub Personal Access Token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token) (not your account password). Personal access token (PAT) requires **`write:packages`**, **`read:packages`**, and **`delete:packages`** scopes.
4. After the container registry is successfully created, navigate to [Daytona Snapshots ↗](https://app.daytona.io/dashboard/snapshots)
5. Click the **Create Snapshot** button
6. Enter the **snapshot name** and **image** (tag or digest). When creating the snapshot, make sure to input the entire image name, including the registry location and project name (e.g. **`ghcr.io//custom-alpine:3.21`**)
#### Amazon Elastic Container Registry (ECR)
Daytona supports creating snapshots from images from Amazon Elastic Container Registry.
1. Navigate to [Daytona Registries ↗](https://app.daytona.io/dashboard/registries)
2. Click the **Add Registry** button
3. Enter the **registry name**, **registry URL**, **username**, **password**, and **project** (if applicable)
- **Registry URL**: `.dkr.ecr..amazonaws.com`
- **Username**: `AWS`
- **Password**: [Authorization token](https://docs.aws.amazon.com/AmazonECR/latest/userguide/registry_auth.html)
4. After the container registry is successfully created, navigate to [Daytona Snapshots ↗](https://app.daytona.io/dashboard/snapshots)
5. Click the **Create Snapshot** button
6. Enter the **snapshot name** and **image** (tag or digest). When creating the snapshot, make sure to input the entire image name, including the registry location and repository name (e.g. **`123456789012.dkr.ecr.us-east-1.amazonaws.com/my-repo/custom-alpine:3.21`**)
:::caution
Amazon ECR authorization tokens expire after **12 hours**. Update the registry password in Daytona each time the token expires. Support for automatic renewal is coming soon.
:::
### Using the declarative builder
[Declarative Builder](https://www.daytona.io/docs/en/declarative-builder.md) provides a powerful, code-first approach to defining dependencies for Daytona Sandboxes. Instead of importing images from a container registry, you can programmatically define them using the Daytona [SDKs](https://www.daytona.io/docs/en/getting-started.md#sdks).
### Resources
Snapshots can be customized with specific resource requirements. By default, Daytona Sandboxes use **1 vCPU**, **1GB RAM**, and **3GiB disk**. For more information, see [sandbox resources](https://www.daytona.io/docs/en/sandboxes.md#resources).
To view your available resources and limits, see [limits](https://www.daytona.io/docs/en/limits.md) or navigate to [Daytona Limits ↗](https://app.daytona.io/dashboard/limits).
Snapshot resources can be customized using the `Resources` class.
```python
from daytona import (
Daytona,
CreateSnapshotParams,
Image,
Resources,
)
daytona = Daytona()
# Create a snapshot with custom resources
daytona.snapshot.create(
CreateSnapshotParams(
name="my-awesome-snapshot",
image=Image.debian_slim("3.12"),
resources=Resources(
cpu=2,
memory=4,
disk=8,
),
),
on_logs=print,
)
```
```typescript
import { Daytona, Image } from '@daytonaio/sdk'
const daytona = new Daytona()
// Create a snapshot with custom resources
await daytona.snapshot.create(
{
name: 'my-awesome-snapshot',
image: Image.debianSlim('3.13'),
resources: {
cpu: 2,
memory: 4,
disk: 8,
},
},
{ onLogs: console.log }
)
```
```ruby
require 'daytona'
daytona = Daytona::Daytona.new
# Create a snapshot with custom resources
daytona.snapshot.create(
Daytona::CreateSnapshotParams.new(
name: 'my-awesome-snapshot',
image: Daytona::Image.debian_slim('3.12'),
resources: Daytona::Resources.new(
cpu: 2,
memory: 4,
disk: 8
)
),
on_logs: proc { |chunk| puts chunk }
)
```
```go
// Create a snapshot with custom resources
image := daytona.Base("python:3.11").PipInstall([]string{"numpy"})
snapshot, logChan, err := client.Snapshots.Create(ctx, &types.CreateSnapshotParams{
Name: "my-awesome-snapshot",
Image: image,
Resources: &types.Resources{CPU: 2, Memory: 4, Disk: 8},
})
if err != nil {
return err
}
// Stream build logs
for log := range logChan {
fmt.Println(log)
}
```
```bash
daytona snapshot create my-awesome-snapshot --image python:3.11-slim --cpu 2 --memory 4 --disk 8
```
```bash
curl https://app.daytona.io/api/snapshots \
--request POST \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer YOUR_SECRET_TOKEN' \
--data '{
"name": "my-awesome-snapshot",
"imageName": "python:3.11-slim",
"cpu": 2,
"memory": 4,
"disk": 8
}'
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk.md), [Go SDK](https://www.daytona.io/docs/en/go-sdk/daytona.md#SnapshotService.Create), [CLI](https://www.daytona.io/docs/en/tools/cli.md#daytona-snapshot-create), and [API](https://www.daytona.io/docs/en/tools/api.md#daytona/tag/snapshots) references:
> [**CreateSnapshotParams (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/snapshot.md#createsnapshotparams)
>
> [**CreateSnapshotParams (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/snapshot.md#createsnapshotparams)
>
> [**CreateSnapshotParams (Ruby SDK)**](https://www.daytona.io/docs/en/ruby-sdk/snapshot.md#create)
>
> [**CreateSnapshotParams (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/types.md#CreateSnapshotParams)
>
> [**create (CLI)**](https://www.daytona.io/docs/en/tools/cli.md#daytona-snapshot-create)
>
> [**create (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona/tag/snapshots/POST/snapshots)
### Regions
When creating a snapshot, you can specify the [region](https://www.daytona.io/docs/en/regions.md) in which it will be available. If not specified, the snapshot will be created in your organization's default region.
When you later create a sandbox from this snapshot, you can use the snapshot's region as the target region for the sandbox.
```python
from daytona import (
Daytona,
CreateSnapshotParams,
Image,
)
daytona = Daytona()
# Create a Snapshot in a specific region
daytona.snapshot.create(
CreateSnapshotParams(
name="my-awesome-snapshot",
image=Image.debian_slim("3.12"),
region_id="us",
),
on_logs=print,
)
```
```typescript
import { Daytona, Image } from "@daytonaio/sdk";
const daytona = new Daytona();
// Create a Snapshot in a specific region
await daytona.snapshot.create(
{
name: "my-awesome-snapshot",
image: Image.debianSlim("3.13"),
regionId: "us",
},
{ onLogs: console.log }
);
```
```ruby
require 'daytona'
daytona = Daytona::Daytona.new
# Create a Snapshot in a specific region
daytona.snapshot.create(
Daytona::CreateSnapshotParams.new(
name: 'my-awesome-snapshot',
image: Daytona::Image.debian_slim('3.12'),
region_id: 'us'
),
on_logs: proc { |chunk| puts chunk }
)
```
```bash
daytona snapshot create my-awesome-snapshot --image python:3.11-slim --region us
```
```bash
curl https://app.daytona.io/api/snapshots \
--request POST \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer YOUR_SECRET_TOKEN' \
--data '{
"name": "my-awesome-snapshot",
"imageName": "python:3.11-slim",
"regionId": "us"
}'
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk/sync/snapshot.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk/snapshot.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk/snapshot.md), [CLI](https://www.daytona.io/docs/en/tools/cli.md#daytona-snapshot-create), and [API](https://www.daytona.io/docs/en/tools/api.md#daytona/tag/snapshots) references:
> [**create (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/snapshot.md#snapshotservicecreate)
>
> [**create (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/snapshot.md#create)
>
> [**create (Ruby SDK)**](https://www.daytona.io/docs/en/ruby-sdk/snapshot.md#create)
>
> [**create (CLI)**](https://www.daytona.io/docs/en/tools/cli.md#daytona-snapshot-create)
>
> [**create (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona/tag/snapshots/POST/snapshots)
## Get a Snapshot by name
Daytona provides an option to get a snapshot by name.
The following snippet returns the snapshot with the specified name:
```python
daytona = Daytona()
snapshot = daytona.snapshot.get("my-awesome-snapshot")
print(f"{snapshot.name} ({snapshot.image_name})")
```
```typescript
const daytona = new Daytona()
const snapshot = await daytona.snapshot.get('my-awesome-snapshot')
console.log(`Snapshot ${snapshot.name} is in state ${snapshot.state}`)
```
```ruby
daytona = Daytona::Daytona.new
snapshot = daytona.snapshot.get('my-awesome-snapshot')
puts "#{snapshot.name} (#{snapshot.image_name})"
```
```go
snapshot, err := client.Snapshots.Get(ctx, "my-awesome-snapshot")
if err != nil {
return err
}
fmt.Printf("%s (%s)\n", snapshot.Name, snapshot.ImageName)
```
```bash
curl https://app.daytona.io/api/snapshots/my-awesome-snapshot \
--header 'Authorization: Bearer YOUR_SECRET_TOKEN'
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk/sync/snapshot.md#snapshotserviceget), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk/snapshot.md#get), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk/snapshot.md#get), [Go SDK](https://www.daytona.io/docs/en/go-sdk/daytona.md#SnapshotService.Get), and [API](https://www.daytona.io/docs/en/tools/api.md#daytona/tag/snapshots) references:
> [**get (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/snapshot.md#snapshotserviceget)
>
> [**get (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/snapshot.md#get)
>
> [**get (Ruby SDK)**](https://www.daytona.io/docs/en/ruby-sdk/snapshot.md#get)
>
> [**get (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#SnapshotService.Get)
>
> [**get (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona/tag/snapshots/GET/snapshots/{snapshotName})
## List Snapshots
Daytona provides options to list snapshots and view their details.
The following snippet lists all snapshots on the first page with a limit of 10 snapshots per page.
```python
daytona = Daytona()
result = daytona.snapshot.list(page=2, limit=10)
for snapshot in result.items:
print(f"{snapshot.name} ({snapshot.image_name})")
```
```typescript
const daytona = new Daytona()
const result = await daytona.snapshot.list(1, 10)
console.log(`Found ${result.total} snapshots`)
result.items.forEach(snapshot =>
console.log(`${snapshot.name} (${snapshot.imageName})`)
)
```
```ruby
daytona = Daytona::Daytona.new
result = daytona.snapshot.list(page: 2, limit: 10)
result.items.each do |snapshot|
puts "#{snapshot.name} (#{snapshot.image_name})"
end
```
```go
// List first page with default limit
result, err := client.Snapshots.List(ctx, nil, nil)
if err != nil {
return err
}
// List with pagination
page, limit := 2, 10
result, err := client.Snapshots.List(ctx, &page, &limit)
fmt.Printf("Page %d of %d, total: %d\n", result.Page, result.TotalPages, result.Total)
```
```bash
# List snapshots with pagination
daytona snapshot list --page 2 --limit 10
```
```bash
curl 'https://app.daytona.io/api/snapshots?page=2&limit=10' \
--header 'Authorization: Bearer YOUR_SECRET_TOKEN'
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk/sync/snapshot.md), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk/snapshot.md), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk/snapshot.md), [Go SDK](https://www.daytona.io/docs/en/go-sdk/daytona.md#SnapshotService.List), [CLI](https://www.daytona.io/docs/en/tools/cli.md#daytona-snapshot-list), and [API](https://www.daytona.io/docs/en/tools/api.md#daytona/tag/snapshots) references.
> [**list (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/snapshot.md#snapshotservicelist)
>
> [**list (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/snapshot.md#list)
>
> [**list (Ruby SDK)**](https://www.daytona.io/docs/en/ruby-sdk/snapshot.md#list)
>
> [**list (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#SnapshotService.List)
>
> [**list (CLI)**](https://www.daytona.io/docs/en/tools/cli.md#daytona-snapshot-list)
>
> [**list (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona/tag/snapshots/GET/snapshots)
## Activate Snapshots
Snapshots automatically become inactive after 2 weeks of not being used. To activate an inactive snapshot:
1. Navigate to [Daytona Snapshots ↗](https://app.daytona.io/dashboard/snapshots)
2. Click the three dots at the end of the row for the snapshot you want to activate
3. Click the **Activate** button
```python
daytona = Daytona()
snapshot = daytona.snapshot.get("my-inactive-snapshot")
activated_snapshot = daytona.snapshot.activate(snapshot)
print(f"Snapshot {activated_snapshot.name} activated")
```
```typescript
const daytona = new Daytona()
const snapshot = await daytona.snapshot.get("my-inactive-snapshot")
const activatedSnapshot = await daytona.snapshot.activate(snapshot)
console.log(`Snapshot ${activatedSnapshot.name} activated`)
```
```ruby
daytona = Daytona::Daytona.new
snapshot = daytona.snapshot.get('my-inactive-snapshot')
activated_snapshot = daytona.snapshot.activate(snapshot)
puts "Snapshot #{activated_snapshot.name} activated"
```
```bash
curl https://app.daytona.io/api/snapshots/my-inactive-snapshot/activate \
--request POST \
--header 'Authorization: Bearer YOUR_SECRET_TOKEN'
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk/sync/snapshot.md#snapshotserviceactivate), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk/snapshot.md#activate), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk/snapshot.md#activate), and [API](https://www.daytona.io/docs/en/tools/api.md#daytona/tag/snapshots) references:
> [**activate (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/snapshot.md#snapshotserviceactivate)
>
> [**activate (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/snapshot.md#activate)
>
> [**activate (Ruby SDK)**](https://www.daytona.io/docs/en/ruby-sdk/snapshot.md#activate)
>
> [**activate (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona/tag/snapshots/POST/snapshots/{snapshotName}/activate)
## Deactivate Snapshots
Daytona provides an option to deactivate snapshots. Deactivated snapshots are not available for new sandboxes.
1. Navigate to [Daytona Snapshots ↗](https://app.daytona.io/dashboard/snapshots)
2. Click the three dots at the end of the row for the snapshot you want to deactivate
3. Click the **Deactivate** button
## Delete Snapshots
Daytona provides options to delete snapshots. Deleted snapshots cannot be recovered.
1. Navigate to [Daytona Snapshots ↗](https://app.daytona.io/dashboard/snapshots)
2. Click the three dots at the end of the row for the snapshot you want to delete
3. Click the **Delete** button
```python
daytona = Daytona()
snapshot = daytona.snapshot.get("my-awesome-snapshot")
daytona.snapshot.delete(snapshot)
print("Snapshot deleted")
```
```typescript
const daytona = new Daytona()
const snapshot = await daytona.snapshot.get("my-awesome-snapshot")
await daytona.snapshot.delete(snapshot)
console.log("Snapshot deleted")
```
```ruby
daytona = Daytona::Daytona.new
snapshot = daytona.snapshot.get('my-awesome-snapshot')
daytona.snapshot.delete(snapshot)
puts 'Snapshot deleted'
```
```go
snapshot, err := client.Snapshots.Get(ctx, "my-awesome-snapshot")
if err != nil {
return err
}
err = client.Snapshots.Delete(ctx, snapshot)
if err != nil {
return err
}
fmt.Println("Snapshot deleted")
```
```bash
daytona snapshot delete my-awesome-snapshot
```
```bash
curl https://app.daytona.io/api/snapshots/my-awesome-snapshot \
--request DELETE \
--header 'Authorization: Bearer YOUR_SECRET_TOKEN'
```
For more information, see the [Python SDK](https://www.daytona.io/docs/en/python-sdk/sync/snapshot.md#snapshotservicedelete), [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk/snapshot.md#delete), [Ruby SDK](https://www.daytona.io/docs/en/ruby-sdk/snapshot.md#delete), [Go SDK](https://www.daytona.io/docs/en/go-sdk/daytona.md#SnapshotService.Delete), [CLI](https://www.daytona.io/docs/en/tools/cli.md#daytona-snapshot-delete), and [API](https://www.daytona.io/docs/en/tools/api.md#daytona/tag/snapshots) references:
> [**delete (Python SDK)**](https://www.daytona.io/docs/en/python-sdk/sync/snapshot.md#snapshotservicedelete)
>
> [**delete (TypeScript SDK)**](https://www.daytona.io/docs/en/typescript-sdk/snapshot.md#delete)
>
> [**delete (Ruby SDK)**](https://www.daytona.io/docs/en/ruby-sdk/snapshot.md#delete)
>
> [**delete (Go SDK)**](https://www.daytona.io/docs/en/go-sdk/daytona.md#SnapshotService.Delete)
>
> [**delete (CLI)**](https://www.daytona.io/docs/en/tools/cli.md#daytona-snapshot-delete)
>
> [**delete (API)**](https://www.daytona.io/docs/en/tools/api.md#daytona/tag/snapshots/DELETE/snapshots/{snapshotName})
## Run Docker in a Sandbox
Daytona Sandboxes can run Docker containers inside them (**Docker-in-Docker**), enabling you to build, test, and deploy containerized applications. This is particularly useful when your projects have dependencies on external services like databases, message queues, or other microservices.
Agents can seamlessly interact with these services since they run within the same sandbox environment, providing better isolation and security compared to external service dependencies. The following use cases are supported:
- Run databases (PostgreSQL, Redis, MySQL) and other services
- Build and test containerized applications
- Deploy microservices and their dependencies
- Create isolated development environments with full container orchestration
:::note
Docker-in-Docker Sandboxes require additional resources due to the Docker daemon overhead. Consider allocating at least 2 vCPU and 4GiB of memory for optimal performance.
:::
### Create a Docker-in-Docker Snapshot
Daytona provides an option to create a snapshot with Docker support using pre-built Docker-in-Docker images as a base or by manually installing Docker in a custom image.
#### Using pre-built images
The following base images are widely used for creating Docker-in-Docker snapshots or can be used as a base for a custom Dockerfile:
- `docker:28.3.3-dind`: official Docker-in-Docker image (Alpine-based, lightweight)
- `docker:28.3.3-dind-rootless`: rootless Docker-in-Docker for enhanced security
- `docker:28.3.2-dind-alpine3.22`: Docker-in-Docker image with Alpine 3.22
#### Using manual installation
Alternatively, install Docker manually in a custom Dockerfile:
```dockerfile
FROM ubuntu:22.04
# Install Docker using the official install script
RUN curl -fsSL https://get.docker.com | VERSION=28.3.3 sh -
```
### Run Docker Compose in a Sandbox
Docker Compose allows you to define and run multi-container applications. With Docker-in-Docker enabled in a Daytona Sandbox, you can use Docker Compose to orchestrate services like databases, caches, and application containers.
First, create a Docker-in-Docker snapshot using the [Daytona Dashboard ↗](https://app.daytona.io/dashboard/snapshots) or [CLI](https://www.daytona.io/docs/en/tools/cli.md#daytona-snapshot-create) with one of the [pre-built images](#using-pre-built-images) (e.g., `docker:28.3.3-dind`). Then use the following snippet to run Docker Compose services inside a sandbox:
```python
from daytona import Daytona, CreateSandboxFromSnapshotParams
# Initialize the Daytona client
daytona = Daytona()
# Create a sandbox from a Docker-in-Docker snapshot
sandbox = daytona.create(CreateSandboxFromSnapshotParams(snapshot='docker-dind'))
# Create a docker-compose.yml file
compose_content = '''
services:
web:
image: nginx:alpine
ports:
- "8080:80"
'''
sandbox.fs.upload_file(compose_content.encode(), 'docker-compose.yml')
# Start Docker Compose services
result = sandbox.process.exec('docker compose -p demo up -d')
print(result.result)
# Check running services
result = sandbox.process.exec('docker compose -p demo ps')
print(result.result)
# Clean up
sandbox.process.exec('docker compose -p demo down')
```
```typescript
import { Daytona } from '@daytonaio/sdk'
// Initialize the Daytona client
const daytona = new Daytona()
// Create a sandbox from a Docker-in-Docker snapshot
const sandbox = await daytona.create({ snapshot: 'docker-dind' })
// Create a docker-compose.yml file
const composeContent = `
services:
web:
image: nginx:alpine
ports:
- "8080:80"
`
await sandbox.fs.uploadFile(Buffer.from(composeContent), 'docker-compose.yml')
// Start Docker Compose services
let result = await sandbox.process.executeCommand('docker compose -p demo up -d')
console.log(result.result)
// Check running services
result = await sandbox.process.executeCommand('docker compose -p demo ps')
console.log(result.result)
// Clean up
await sandbox.process.executeCommand('docker compose -p demo down')
```
```ruby
require 'daytona'
# Initialize the Daytona client
daytona = Daytona::Daytona.new
# Create a sandbox from a Docker-in-Docker snapshot
sandbox = daytona.create(Daytona::CreateSandboxFromSnapshotParams.new(snapshot: 'docker-dind'))
# Create a docker-compose.yml file
compose_content = <<~YAML
services:
web:
image: nginx:alpine
ports:
- "8080:80"
YAML
sandbox.fs.upload_file(compose_content, 'docker-compose.yml')
# Start Docker Compose services
result = sandbox.process.exec(command: 'docker compose -p demo up -d')
puts result.result
# Check running services
result = sandbox.process.exec(command: 'docker compose -p demo ps')
puts result.result
# Clean up
sandbox.process.exec(command: 'docker compose -p demo down')
```
```go
package main
import (
"context"
"fmt"
"github.com/daytonaio/sdk-go/daytona"
"github.com/daytonaio/sdk-go/types"
)
func main() {
ctx := context.Background()
// Initialize the Daytona client
client, _ := daytona.NewDaytona(nil)
// Create a sandbox from a Docker-in-Docker snapshot
sandbox, _ := client.Create(ctx, &types.CreateSandboxFromSnapshotParams{
Snapshot: daytona.Ptr("docker-dind"),
}, nil)
// Create a docker-compose.yml file
composeContent := `
services:
web:
image: nginx:alpine
ports:
- "8080:80"
`
sandbox.Fs.UploadFile(ctx, []byte(composeContent), "docker-compose.yml")
// Start Docker Compose services
result, _ := sandbox.Process.ExecuteCommand(ctx, "docker compose -p demo up -d", nil)
fmt.Println(result.Result)
// Check running services
result, _ = sandbox.Process.ExecuteCommand(ctx, "docker compose -p demo ps", nil)
fmt.Println(result.Result)
// Clean up
sandbox.Process.ExecuteCommand(ctx, "docker compose -p demo down", nil)
}
```
## Run Kubernetes in a Sandbox
Daytona Sandboxes can run a Kubernetes cluster inside the sandbox. Kubernetes runs entirely inside the sandbox and is removed when the sandbox is deleted, keeping environments secure and reproducible.
### Run k3s in a Sandbox
The following snippet installs and starts a k3s cluster inside a sandbox and lists all running pods.
```typescript
import { Daytona } from '@daytonaio/sdk'
import { setTimeout } from 'timers/promises'
// Initialize the Daytona client
const daytona = new Daytona()
// Create the sandbox instance
const sandbox = await daytona.create()
// Run the k3s installation script
const response = await sandbox.process.executeCommand(
'curl -sfL https://get.k3s.io | sh -'
)
// Run k3s
const sessionName = 'k3s-server'
await sandbox.process.createSession(sessionName)
const k3s = await sandbox.process.executeSessionCommand(sessionName, {
command: 'sudo /usr/local/bin/k3s server',
async: true,
})
// Give time to k3s to fully start
await setTimeout(30000)
// Get all pods
const pods = await sandbox.process.executeCommand(
'sudo /usr/local/bin/kubectl get pod -A'
)
console.log(pods.result)
```
## Default Snapshots
When a sandbox is created with no snapshot specified, Daytona uses a default snapshot that includes `python`, `node`, their language servers, and several common pip packages. Daytona provides three default snapshot sizes:
| **Snapshot** | **vCPU** | **Memory** | **Storage** |
| -------------------- | -------- | ---------- | ----------- |
| **`daytona-small`** | 1 | 1GiB | 3GiB |
| **`daytona-medium`** | 2 | 4GiB | 8GiB |
| **`daytona-large`** | 4 | 8GiB | 10GiB |
All default snapshots are based on the `daytonaio/sandbox:` image. For more information, see the [Dockerfile](https://github.com/daytonaio/daytona/blob/main/images/sandbox/Dockerfile).
### Python packages (pip)
- `anthropic` (v0.76.0)
- `beautifulsoup4` (v4.14.3)
- `claude-agent-sdk` (v0.1.22)
- `daytona` (v0.134.0)
- `django` (v6.0.1)
- `flask` (v3.1.2)
- `huggingface-hub` (v0.36.0)
- `instructor` (v1.14.4)
- `keras` (v3.13.0)
- `langchain` (v1.2.7)
- `llama-index` (v0.14.13)
- `matplotlib` (v3.10.8)
- `numpy` (v2.4.1)
- `ollama` (v0.6.1)
- `openai` (v2.15.0)
- `opencv-python` (v4.13.0.90)
- `pandas` (v2.3.3)
- `pillow` (v12.1.0)
- `pydantic-ai` (v1.47.0)
- `requests` (v2.32.5)
- `scikit-learn` (v1.8.0)
- `scipy` (v1.17.0)
- `seaborn` (v0.13.2)
- `sqlalchemy` (v2.0.46)
- `torch` (v2.10.0)
- `transformers` (v4.57.6)
### Node.js packages (npm)
- `@anthropic-ai/claude-code` (v2.1.19)
- `bun` (v1.3.6)
- `openclaw` (v2026.2.1)
- `opencode-ai` (v1.1.35)
- `ts-node` (v10.9.2)
- `typescript` (v5.9.3)
- `typescript-language-server` (v5.1.3)
Daytona provides SSH access to your sandboxes using token-based authentication. This allows you to connect from local terminals, IDEs, and development tools without installing additional software.
## Access from Dashboard
Create an SSH access token directly from the [Daytona Dashboard ↗](https://app.daytona.io/dashboard/sandboxes).
1. Navigate to [Sandboxes ↗](https://app.daytona.io/dashboard/sandboxes)
2. Locate the sandbox you want to create an SSH access token for
3. Click the sandbox options menu (**⋮**)
4. Select **Create SSH Access**
5. Set the expiration time (defaults to 60 minutes)
6. Click **Create**
Daytona generates a token and displays it in the modal. Copy the token and use it to connect to your sandbox.
## Access via CLI
Daytona provides a CLI command to create an SSH access token for a sandbox:
```shell
daytona create
```
When you create a sandbox, Daytona displays the SSH command automatically in the output:
```text
Sandbox '' created successfully
Connect via SSH: daytona ssh
Open the Web Terminal: https://22222-.proxy.daytona.work
```
To SSH into an existing sandbox, use the following command:
```bash
daytona ssh --expires 60
```
## Access via token
You can create SSH access tokens programmatically. The token can then be used to connect manually:
```python
from daytona import Daytona
daytona = Daytona()
sandbox = daytona.get("sandbox-abc123")
# Create SSH access token
ssh_access = sandbox.create_ssh_access(expires_in_minutes=60)
print(f"SSH Token: {ssh_access.token}")
```
```typescript
import { Daytona } from '@daytonaio/sdk'
const daytona = new Daytona()
const sandbox = await daytona.get('sandbox-abc123')
// Create SSH access token
const sshAccess = await sandbox.createSshAccess(60)
console.log(`SSH Token: ${sshAccess.token}`)
```
```ruby
require 'daytona'
daytona = Daytona::Daytona.new
sandbox = daytona.get('sandbox-abc123')
# Create SSH access token
ssh_access = sandbox.create_ssh_access(expires_in_minutes: 60)
puts "SSH Token: #{ssh_access.token}"
```
```bash
curl 'https://app.daytona.io/api/sandbox/{sandboxId}/ssh-access?expiresInMinutes=60' \
--request POST \
--header 'Authorization: Bearer '
```
To connect to your sandbox, use the following command:
```bash
ssh @ssh.app.daytona.io
```
## Connect with VS Code
You can connect VS Code directly to your sandbox using the Remote SSH extension.
1. Install the [Remote Explorer extension ↗](https://marketplace.visualstudio.com/items?itemName=ms-vscode.remote-explorer)
2. Add a new SSH connection
3. When prompted for the SSH connection URL, paste the SSH command from above
For more information, see the [VS Code Remote SSH documentation ↗](https://code.visualstudio.com/docs/remote/ssh).
## Connect with JetBrains IDEs
JetBrains Gateway provides remote development support for connecting to your sandbox.
1. Download [JetBrains Gateway ↗](https://www.jetbrains.com/remote-development/gateway/)
2. Add a new connection
3. When prompted for the SSH connection URL, paste the SSH command from above
4. Select the IDE to install in your sandbox
## Token management
### Expiration
SSH access tokens expire automatically after 60 minutes. You can specify a custom expiration time when creating the token using the `expires_in_minutes` parameter.
### Revoke token
Revoke SSH access tokens before expiry:
```python
# Revoke specific SSH access token for the sandbox
sandbox.revoke_ssh_access(token="specific-token")
```
```typescript
// Revoke specific SSH access token for the sandbox
await sandbox.revokeSshAccess('specific-token')
```
```ruby
# Revoke specific SSH access token for the sandbox
sandbox.revoke_ssh_access(token: 'specific-token')
```
```bash
# Revoke specific SSH access token
curl 'https://app.daytona.io/api/sandbox/{sandboxId}/ssh-access?token=specific-token' \
--request DELETE \
--header 'Authorization: Bearer '
# Revoke all SSH access for the sandbox
curl 'https://app.daytona.io/api/sandbox/{sandboxId}/ssh-access' \
--request DELETE \
--header 'Authorization: Bearer '
```
## Related
- [Web Terminal](https://www.daytona.io/docs/en/web-terminal.md): browser-based terminal access to sandboxes
- [Preview](https://www.daytona.io/docs/en/preview.md): generate preview URLs for accessing sandbox services
The `daytona` command-line tool provides access to Daytona's core features including managing Snapshots and the lifecycle of Daytona Sandboxes. View the installation instructions by clicking [here](https://www.daytona.io/docs/getting-started.md#cli).
This reference lists all commands supported by the `daytona` command-line tool complete with a description of their behaviour, and any supported flags.
You can access this documentation on a per-command basis by appending the `--help`/`-h` flag when invoking `daytona`.
## daytona
Daytona CLI
```shell
daytona [flags]
```
__Flags__
| Long | Short | Description |
| :--- | :---- | :---------- |
| `--help` | | help for daytona |
| `--version` | `-v` | Display the version of Daytona |
## daytona archive
Archive a sandbox
```shell
daytona archive [SANDBOX_ID] | [SANDBOX_NAME] [flags]
```
__Flags__
| Long | Short | Description |
| :--- | :---- | :---------- |
| `--help` | | help for daytona |
## daytona autocomplete
Adds a completion script for your shell environment
```shell
daytona autocomplete [bash|zsh|fish|powershell] [flags]
```
__Flags__
| Long | Short | Description |
| :--- | :---- | :---------- |
| `--help` | | help for daytona |
## daytona create
Create a new sandbox
```shell
daytona create [flags]
```
__Flags__
| Long | Short | Description |
| :--- | :---- | :---------- |
| `--auto-archive` | | Auto-archive interval in minutes (0 means the maximum interval will be used) |
| `--auto-delete` | | Auto-delete interval in minutes (negative value means disabled, 0 means delete immediately upon stopping) |
| `--auto-stop` | | Auto-stop interval in minutes (0 means disabled) |
| `--class` | | Sandbox class type (small, medium, large) |
| `--context` | `-c` | Files or directories to include in the build context (can be specified multiple times) |
| `--cpu` | | CPU cores allocated to the sandbox |
| `--disk` | | Disk space allocated to the sandbox in GB |
| `--dockerfile` | `-f` | Path to Dockerfile for Sandbox snapshot |
| `--env` | `-e` | Environment variables (format: KEY=VALUE) |
| `--gpu` | | GPU units allocated to the sandbox |
| `--label` | `-l` | Labels (format: KEY=VALUE) |
| `--memory` | | Memory allocated to the sandbox in MB |
| `--name` | | Name of the sandbox |
| `--network-allow-list` | | Comma-separated list of allowed CIDR network addresses for the sandbox |
| `--network-block-all` | | Whether to block all network access for the sandbox |
| `--public` | | Make sandbox publicly accessible |
| `--snapshot` | | Snapshot to use for the sandbox |
| `--target` | | Target region (eu, us) |
| `--user` | | User associated with the sandbox |
| `--volume` | `-v` | Volumes to mount (format: VOLUME_NAME:MOUNT_PATH) |
| `--help` | | help for daytona |
## daytona delete
Delete a sandbox
```shell
daytona delete [SANDBOX_ID] | [SANDBOX_NAME] [flags]
```
__Flags__
| Long | Short | Description |
| :--- | :---- | :---------- |
| `--all` | `-a` | Delete all sandboxes |
| `--help` | | help for daytona |
## daytona docs
Opens the Daytona documentation in your default browser.
```shell
daytona docs [flags]
```
__Flags__
| Long | Short | Description |
| :--- | :---- | :---------- |
| `--help` | | help for daytona |
## daytona exec
Execute a command in a sandbox
```shell
daytona exec [SANDBOX_ID | SANDBOX_NAME] -- [COMMAND] [ARGS...] [flags]
```
__Flags__
| Long | Short | Description |
| :--- | :---- | :---------- |
| `--cwd` | | Working directory for command execution |
| `--timeout` | | Command timeout in seconds (0 for no timeout) |
| `--help` | | help for daytona |
## daytona info
Get sandbox info
```shell
daytona info [SANDBOX_ID] | [SANDBOX_NAME] [flags]
```
__Flags__
| Long | Short | Description |
| :--- | :---- | :---------- |
| `--format` | `-f` | Output format. Must be one of (yaml, json) |
| `--help` | | help for daytona |
## daytona list
List sandboxes
```shell
daytona list [flags]
```
__Flags__
| Long | Short | Description |
| :--- | :---- | :---------- |
| `--format` | `-f` | Output format. Must be one of (yaml, json) |
| `--limit` | `-l` | Maximum number of items per page |
| `--page` | `-p` | Page number for pagination (starting from 1) |
| `--help` | | help for daytona |
## daytona login
Log in to Daytona
```shell
daytona login [flags]
```
__Flags__
| Long | Short | Description |
| :--- | :---- | :---------- |
| `--api-key` | | API key to use for authentication |
| `--help` | | help for daytona |
## daytona logout
Logout from Daytona
```shell
daytona logout [flags]
```
__Flags__
| Long | Short | Description |
| :--- | :---- | :---------- |
| `--help` | | help for daytona |
## daytona mcp
Manage Daytona MCP Server
```shell
daytona mcp [flags]
```
__Flags__
| Long | Short | Description |
| :--- | :---- | :---------- |
| `--help` | | help for daytona |
## daytona mcp config
Outputs JSON configuration for Daytona MCP Server
```shell
daytona mcp config [AGENT_NAME] [flags]
```
__Flags__
| Long | Short | Description |
| :--- | :---- | :---------- |
| `--help` | | help for daytona |
## daytona mcp init
Initialize Daytona MCP Server with an agent (currently supported: claude, windsurf, cursor)
```shell
daytona mcp init [AGENT_NAME] [flags]
```
__Flags__
| Long | Short | Description |
| :--- | :---- | :---------- |
| `--help` | | help for daytona |
## daytona mcp start
Start Daytona MCP Server
```shell
daytona mcp start [flags]
```
__Flags__
| Long | Short | Description |
| :--- | :---- | :---------- |
| `--help` | | help for daytona |
## daytona organization
Manage Daytona organizations
```shell
daytona organization [flags]
```
__Flags__
| Long | Short | Description |
| :--- | :---- | :---------- |
| `--help` | | help for daytona |
## daytona organization create
Create a new organization and set it as active
```shell
daytona organization create [ORGANIZATION_NAME] [flags]
```
__Flags__
| Long | Short | Description |
| :--- | :---- | :---------- |
| `--help` | | help for daytona |
## daytona organization delete
Delete an organization
```shell
daytona organization delete [ORGANIZATION] [flags]
```
__Flags__
| Long | Short | Description |
| :--- | :---- | :---------- |
| `--help` | | help for daytona |
## daytona organization list
List all organizations
```shell
daytona organization list [flags]
```
__Flags__
| Long | Short | Description |
| :--- | :---- | :---------- |
| `--format` | `-f` | Output format. Must be one of (yaml, json) |
| `--help` | | help for daytona |
## daytona organization use
Set active organization
```shell
daytona organization use [ORGANIZATION] [flags]
```
__Flags__
| Long | Short | Description |
| :--- | :---- | :---------- |
| `--help` | | help for daytona |
## daytona preview-url
Get signed preview URL for a sandbox port
```shell
daytona preview-url [SANDBOX_ID | SANDBOX_NAME] [flags]
```
__Flags__
| Long | Short | Description |
| :--- | :---- | :---------- |
| `--expires` | | URL expiration time in seconds |
| `--port` | `-p` | Port number to get preview URL for (required) |
| `--help` | | help for daytona |
## daytona snapshot
Manage Daytona snapshots
```shell
daytona snapshot [flags]
```
__Flags__
| Long | Short | Description |
| :--- | :---- | :---------- |
| `--help` | | help for daytona |
## daytona snapshot create
Create a snapshot
```shell
daytona snapshot create [SNAPSHOT] [flags]
```
__Flags__
| Long | Short | Description |
| :--- | :---- | :---------- |
| `--context` | `-c` | Files or directories to include in the build context (can be specified multiple times). If not provided, context will be automatically determined from COPY/ADD commands in the Dockerfile |
| `--cpu` | | CPU cores that will be allocated to the underlying sandboxes (default: 1) |
| `--disk` | | Disk space that will be allocated to the underlying sandboxes in GB (default: 3) |
| `--dockerfile` | `-f` | Path to Dockerfile to build |
| `--entrypoint` | `-e` | The entrypoint command for the snapshot |
| `--image` | `-i` | The image name for the snapshot |
| `--memory` | | Memory that will be allocated to the underlying sandboxes in GB (default: 1) |
| `--region` | | ID of the region where the snapshot will be available (defaults to organization default region) |
| `--help` | | help for daytona |
## daytona snapshot delete
Delete a snapshot
```shell
daytona snapshot delete [SNAPSHOT_ID] [flags]
```
__Flags__
| Long | Short | Description |
| :--- | :---- | :---------- |
| `--all` | `-a` | Delete all snapshots |
| `--help` | | help for daytona |
## daytona snapshot list
List all snapshots
```shell
daytona snapshot list [flags]
```
__Flags__
| Long | Short | Description |
| :--- | :---- | :---------- |
| `--format` | `-f` | Output format. Must be one of (yaml, json) |
| `--limit` | `-l` | Maximum number of items per page |
| `--page` | `-p` | Page number for pagination (starting from 1) |
| `--help` | | help for daytona |
## daytona snapshot push
Push local snapshot
```shell
daytona snapshot push [SNAPSHOT] [flags]
```
__Flags__
| Long | Short | Description |
| :--- | :---- | :---------- |
| `--cpu` | | CPU cores that will be allocated to the underlying sandboxes (default: 1) |
| `--disk` | | Disk space that will be allocated to the underlying sandboxes in GB (default: 3) |
| `--entrypoint` | `-e` | The entrypoint command for the image |
| `--memory` | | Memory that will be allocated to the underlying sandboxes in GB (default: 1) |
| `--name` | `-n` | Specify the Snapshot name |
| `--region` | | ID of the region where the snapshot will be available (defaults to organization default region) |
| `--help` | | help for daytona |
## daytona ssh
SSH into a sandbox
```shell
daytona ssh [SANDBOX_ID] | [SANDBOX_NAME] [flags]
```
__Flags__
| Long | Short | Description |
| :--- | :---- | :---------- |
| `--expires` | | SSH access token expiration time in minutes (defaults to 24 hours) |
| `--help` | | help for daytona |
## daytona start
Start a sandbox
```shell
daytona start [SANDBOX_ID] | [SANDBOX_NAME] [flags]
```
__Flags__
| Long | Short | Description |
| :--- | :---- | :---------- |
| `--help` | | help for daytona |
## daytona stop
Stop a sandbox
```shell
daytona stop [SANDBOX_ID] | [SANDBOX_NAME] [flags]
```
__Flags__
| Long | Short | Description |
| :--- | :---- | :---------- |
| `--help` | | help for daytona |
## daytona version
Print the version number
```shell
daytona version [flags]
```
__Flags__
| Long | Short | Description |
| :--- | :---- | :---------- |
| `--help` | | help for daytona |
## daytona volume
Manage Daytona volumes
```shell
daytona volume [flags]
```
__Flags__
| Long | Short | Description |
| :--- | :---- | :---------- |
| `--help` | | help for daytona |
## daytona volume create
Create a volume
```shell
daytona volume create [NAME] [flags]
```
__Flags__
| Long | Short | Description |
| :--- | :---- | :---------- |
| `--size` | `-s` | Size of the volume in GB |
| `--help` | | help for daytona |
## daytona volume delete
Delete a volume
```shell
daytona volume delete [VOLUME_ID] [flags]
```
__Flags__
| Long | Short | Description |
| :--- | :---- | :---------- |
| `--help` | | help for daytona |
## daytona volume get
Get volume details
```shell
daytona volume get [VOLUME_ID] [flags]
```
__Flags__
| Long | Short | Description |
| :--- | :---- | :---------- |
| `--format` | `-f` | Output format. Must be one of (yaml, json) |
| `--help` | | help for daytona |
## daytona volume list
List all volumes
```shell
daytona volume list [flags]
```
__Flags__
| Long | Short | Description |
| :--- | :---- | :---------- |
| `--format` | `-f` | Output format. Must be one of (yaml, json) |
| `--help` | | help for daytona |
## ChartType
Chart types
**Enum Members**:
- `BAR` ("bar")
- `LINE` ("line")
- `PIE` ("pie")
- `SCATTER` ("scatter")
- `UNKNOWN` ("unknown")
## parseChart()
```ts
function parseChart(data: any): Chart
```
**Parameters**:
- `data` _any_
**Returns**:
- `Chart`
***
## BarChart
```ts
type BarChart = Chart2D & {
elements: BarData[];
type: BAR;
};
```
Represents a bar chart with metadata.
**Type declaration**:
- `elements` _BarData\[\]_ - The bars of the chart
- `type` _BAR_ - The type of chart
## BarData
```ts
type BarData = {
group: string;
label: string;
value: string;
};
```
Represents a bar in a bar chart.
**Type declaration**:
- `group` _string_ - The group of the bar
- `label` _string_ - The label of the bar
- `value` _string_ - The value of the bar
## BoxAndWhiskerChart
```ts
type BoxAndWhiskerChart = Chart2D & {
elements: BoxAndWhiskerData[];
type: BOX_AND_WHISKER;
};
```
Represents a box and whisker chart with metadata.
**Type declaration**:
- `elements` _BoxAndWhiskerData\[\]_ - The box and whiskers of the chart
- `type` _BOX\_AND\_WHISKER_ - The type of chart
## BoxAndWhiskerData
```ts
type BoxAndWhiskerData = {
first_quartile: number;
label: string;
max: number;
median: number;
min: number;
outliers: number[];
};
```
Represents a box and whisker in a box and whisker chart.
**Type declaration**:
- `first\_quartile` _number_ - The first quartile of the box and whisker
- `label` _string_ - The label of the box and whisker
- `max` _number_ - The third quartile of the box and whisker
- `median` _number_ - The median of the box and whisker
- `min` _number_ - The minimum value of the box and whisker
- `outliers` _number\[\]_
## Chart
```ts
type Chart = {
elements: any[];
png: string;
title: string;
type: ChartType;
};
```
Represents a chart with metadata from matplotlib.
**Type declaration**:
- `elements` _any\[\]_ - The elements of the chart
- `png?` _string_ - The PNG representation of the chart encoded in base64
- `title` _string_ - The title of the chart
- `type` _ChartType_ - The type of chart
## Chart2D
```ts
type Chart2D = Chart & {
x_label: string;
y_label: string;
};
```
Represents a 2D chart with metadata.
**Type declaration**:
- `x\_label?` _string_ - The label of the x-axis
- `y\_label?` _string_ - The label of the y-axis
## CompositeChart
```ts
type CompositeChart = Chart & {
elements: Chart[];
type: COMPOSITE_CHART;
};
```
Represents a composite chart with metadata.
**Type declaration**:
- `elements` _Chart\[\]_ - The charts of the composite chart
- `type` _COMPOSITE\_CHART_ - The type of chart
## LineChart
```ts
type LineChart = PointChart & {
type: LINE;
};
```
Represents a line chart with metadata.
**Type declaration**:
- `type` _LINE_ - The type of chart
## PieChart
```ts
type PieChart = Chart & {
elements: PieData[];
type: PIE;
};
```
Represents a pie chart with metadata.
**Type declaration**:
- `elements` _PieData\[\]_ - The pie slices of the chart
- `type` _PIE_ - The type of chart
## PieData
```ts
type PieData = {
angle: number;
label: string;
radius: number;
};
```
Represents a pie slice in a pie chart.
**Type declaration**:
- `angle` _number_ - The angle of the pie slice
- `label` _string_ - The label of the pie slice
- `radius` _number_ - The radius of the pie slice
## PointChart
```ts
type PointChart = Chart2D & {
elements: PointData[];
x_scale: string;
x_tick_labels: string[];
x_ticks: (number | string)[];
y_scale: string;
y_tick_labels: string[];
y_ticks: (number | string)[];
};
```
Represents a point chart with metadata.
**Type declaration**:
- `elements` _PointData\[\]_ - The points of the chart
- `x\_scale` _string_ - The scale of the x-axis
- `x\_tick\_labels` _string\[\]_ - The labels of the x-axis
- `x\_ticks` _\(number \| string\)\[\]_ - The ticks of the x-axis
- `y\_scale` _string_ - The scale of the y-axis
- `y\_tick\_labels` _string\[\]_ - The labels of the y-axis
- `y\_ticks` _\(number \| string\)\[\]_ - The ticks of the y-axis
## PointData
```ts
type PointData = {
label: string;
points: [number | string, number | string][];
};
```
Represents a point in a 2D chart.
**Type declaration**:
- `label` _string_ - The label of the point
- `points` _\[number \| string, number \| string\]\[\]_ - The points of the chart
## ScatterChart
```ts
type ScatterChart = PointChart & {
type: SCATTER;
};
```
Represents a scatter chart with metadata.
**Type declaration**:
- `type` _SCATTER_ - The type of chart
## CodeInterpreter
Handles Python code interpretation and execution within a Sandbox.
Provides methods to execute code (currently only Python) in isolated interpreter contexts,
manage contexts, and stream execution output via callbacks.
For other languages, use the `codeRun` method from the `Process` interface, or execute the appropriate command directly in the sandbox terminal.
### Constructors
#### new CodeInterpreter()
```ts
new CodeInterpreter(
clientConfig: Configuration,
apiClient: InterpreterApi,
getPreviewToken: () => Promise): CodeInterpreter
```
**Parameters**:
- `clientConfig` _Configuration_
- `apiClient` _InterpreterApi_
- `getPreviewToken` _\(\) =\> Promise\_
**Returns**:
- `CodeInterpreter`
### Methods
#### createContext()
```ts
createContext(cwd?: string): Promise
```
Create a new isolated interpreter context.
**Parameters**:
- `cwd?` _string_ - Working directory for the context. Uses sandbox working directory if omitted.
**Returns**:
- `Promise` - The created context.
**Example:**
```ts
const ctx = await sandbox.codeInterpreter.createContext()
await sandbox.codeInterpreter.runCode('x = 10', { context: ctx })
await sandbox.codeInterpreter.deleteContext(ctx.id!)
```
***
#### deleteContext()
```ts
deleteContext(context: InterpreterContext): Promise
```
Delete an interpreter context and shut down its worker process.
**Parameters**:
- `context` _InterpreterContext_ - Context to delete.
**Returns**:
- `Promise`
**Example:**
```ts
const ctx = await sandbox.codeInterpreter.createContext()
// ... use context ...
await sandbox.codeInterpreter.deleteContext(ctx)
```
***
#### listContexts()
```ts
listContexts(): Promise
```
List all user-created interpreter contexts (default context is excluded).
**Returns**:
- `Promise` - List of contexts.
**Example:**
```ts
const contexts = await sandbox.codeInterpreter.listContexts()
for (const ctx of contexts) {
console.log(ctx.id, ctx.language, ctx.cwd)
}
```
***
#### runCode()
```ts
runCode(code: string, options: RunCodeOptions): Promise
```
Run Python code in the sandbox.
**Parameters**:
- `code` _string_ - Code to run.
- `options` _RunCodeOptions = {}_ - Execution options (context, envs, callbacks, timeout).
**Returns**:
- `Promise` - ExecutionResult containing stdout, stderr and optional error info.
**Example:**
```ts
const handleStdout = (msg: OutputMessage) => process.stdout.write(`STDOUT: ${msg.output}`)
const handleStderr = (msg: OutputMessage) => process.stdout.write(`STDERR: ${msg.output}`)
const handleError = (err: ExecutionError) =>
console.error(`ERROR: ${err.name}: ${err.value}\n${err.traceback ?? ''}`)
const code = `
import sys
import time
for i in range(5):
print(i)
time.sleep(1)
sys.stderr.write("Counting done!")
`
const result = await codeInterpreter.runCode(code, {
onStdout: handleStdout,
onStderr: handleStderr,
onError: handleError,
timeout: 10,
})
```
***
## ExecutionError
Represents an error that occurred during code execution.
**Properties**:
- `name` _string_ - Error type/class name (e.g., "ValueError", "SyntaxError").
- `traceback?` _string_ - Full traceback for the error, if available.
- `value` _string_ - Error value/message.
## ExecutionResult
Result of code execution.
**Properties**:
- `error?` _ExecutionError_ - Details about an execution error, if one occurred.
- `stderr` _string_ - Standard error captured during execution.
- `stdout` _string_ - Standard output captured during execution.
## OutputMessage
Represents stdout or stderr output from code execution.
**Properties**:
- `output` _string_ - Output content.
## RunCodeOptions
Options for executing code in the interpreter.
**Properties**:
- `context?` _InterpreterContext_ - Interpreter context to run code in.
- `envs?` _Record\_ - Environment variables for this execution.
- `onError()?` _\(error: ExecutionError\) =\> any_ - Callback for execution errors (e.g., runtime exceptions).
**Parameters**:
- `error` _ExecutionError_
**Returns**:
- `any`
- `onStderr()?` _\(message: OutputMessage\) =\> any_ - Callback for stderr messages.
**Parameters**:
- `message` _OutputMessage_
**Returns**:
- `any`
- `onStdout()?` _\(message: OutputMessage\) =\> any_ - Callback for stdout messages.
**Parameters**:
- `message` _OutputMessage_
**Returns**:
- `any`
- `timeout?` _number_ - Timeout in seconds. Set to 0 for no timeout. Default is 10 minutes.
## ComputerUse
Computer Use functionality for interacting with the desktop environment.
**Properties**:
- `display` _Display_ - Display operations interface
- `keyboard` _Keyboard_ - Keyboard operations interface
- `mouse` _Mouse_ - Mouse operations interface
- `recording` _RecordingService_ - Screen recording operations interface
- `screenshot` _Screenshot_ - Screenshot operations interface
Provides access to mouse, keyboard, screenshot, display, and recording operations
for automating desktop interactions within a sandbox.
### Constructors
#### new ComputerUse()
```ts
new ComputerUse(apiClient: ComputerUseApi): ComputerUse
```
**Parameters**:
- `apiClient` _ComputerUseApi_
**Returns**:
- `ComputerUse`
### Methods
#### getProcessErrors()
```ts
getProcessErrors(processName: string): Promise
```
Gets error logs for a specific VNC process
**Parameters**:
- `processName` _string_ - Name of the process to get error logs for
**Returns**:
- `Promise` - Process error logs
**Example:**
```typescript
const errorsResp = await sandbox.computerUse.getProcessErrors('x11vnc');
console.log('X11VNC errors:', errorsResp.errors);
```
***
#### getProcessLogs()
```ts
getProcessLogs(processName: string): Promise
```
Gets logs for a specific VNC process
**Parameters**:
- `processName` _string_ - Name of the process to get logs for
**Returns**:
- `Promise` - Process logs
**Example:**
```typescript
const logsResp = await sandbox.computerUse.getProcessLogs('novnc');
console.log('NoVNC logs:', logsResp.logs);
```
***
#### getProcessStatus()
```ts
getProcessStatus(processName: string): Promise
```
Gets the status of a specific VNC process
**Parameters**:
- `processName` _string_ - Name of the process to check
**Returns**:
- `Promise` - Status information about the specific process
**Example:**
```typescript
const xvfbStatus = await sandbox.computerUse.getProcessStatus('xvfb');
const noVncStatus = await sandbox.computerUse.getProcessStatus('novnc');
```
***
#### getStatus()
```ts
getStatus(): Promise
```
Gets the status of all computer use processes
**Returns**:
- `Promise` - Status information about all VNC desktop processes
**Example:**
```typescript
const status = await sandbox.computerUse.getStatus();
console.log('Computer use status:', status.status);
```
***
#### restartProcess()
```ts
restartProcess(processName: string): Promise
```
Restarts a specific VNC process
**Parameters**:
- `processName` _string_ - Name of the process to restart
**Returns**:
- `Promise` - Process restart response
**Example:**
```typescript
const result = await sandbox.computerUse.restartProcess('xfce4');
console.log('XFCE4 process restarted:', result.message);
```
***
#### start()
```ts
start(): Promise
```
Starts all computer use processes (Xvfb, xfce4, x11vnc, novnc)
**Returns**:
- `Promise` - Computer use start response
**Example:**
```typescript
const result = await sandbox.computerUse.start();
console.log('Computer use processes started:', result.message);
```
***
#### stop()
```ts
stop(): Promise
```
Stops all computer use processes
**Returns**:
- `Promise` - Computer use stop response
**Example:**
```typescript
const result = await sandbox.computerUse.stop();
console.log('Computer use processes stopped:', result.message);
```
## Display
Display operations for computer use functionality
### Constructors
#### new Display()
```ts
new Display(apiClient: ComputerUseApi): Display
```
**Parameters**:
- `apiClient` _ComputerUseApi_
**Returns**:
- `Display`
### Methods
#### getInfo()
```ts
getInfo(): Promise
```
Gets information about the displays
**Returns**:
- `Promise` - Display information including primary display and all available displays
**Example:**
```typescript
const info = await sandbox.computerUse.display.getInfo();
console.log(`Primary display: ${info.primary_display.width}x${info.primary_display.height}`);
console.log(`Total displays: ${info.total_displays}`);
info.displays.forEach((display, index) => {
console.log(`Display ${index}: ${display.width}x${display.height} at ${display.x},${display.y}`);
});
```
***
#### getWindows()
```ts
getWindows(): Promise
```
Gets the list of open windows
**Returns**:
- `Promise` - List of open windows with their IDs and titles
**Example:**
```typescript
const windows = await sandbox.computerUse.display.getWindows();
console.log(`Found ${windows.count} open windows:`);
windows.windows.forEach(window => {
console.log(`- ${window.title} (ID: ${window.id})`);
});
```
***
## Keyboard
Keyboard operations for computer use functionality
### Constructors
#### new Keyboard()
```ts
new Keyboard(apiClient: ComputerUseApi): Keyboard
```
**Parameters**:
- `apiClient` _ComputerUseApi_
**Returns**:
- `Keyboard`
### Methods
#### hotkey()
```ts
hotkey(keys: string): Promise
```
Presses a hotkey combination
**Parameters**:
- `keys` _string_ - The hotkey combination (e.g., 'ctrl+c', 'alt+tab', 'cmd+shift+t')
**Returns**:
- `Promise`
**Throws**:
If the hotkey operation fails
**Example:**
```typescript
// Copy
try {
await sandbox.computerUse.keyboard.hotkey('ctrl+c');
console.log('Operation success');
} catch (e) {
console.log('Operation failed:', e);
}
// Paste
try {
await sandbox.computerUse.keyboard.hotkey('ctrl+v');
console.log('Operation success');
} catch (e) {
console.log('Operation failed:', e);
}
// Alt+Tab
try {
await sandbox.computerUse.keyboard.hotkey('alt+tab');
console.log('Operation success');
} catch (e) {
console.log('Operation failed:', e);
}
```
***
#### press()
```ts
press(key: string, modifiers?: string[]): Promise
```
Presses a key with optional modifiers
**Parameters**:
- `key` _string_ - The key to press (e.g., 'Enter', 'Escape', 'Tab', 'a', 'A')
- `modifiers?` _string\[\] = \[\]_ - Modifier keys ('ctrl', 'alt', 'meta', 'shift')
**Returns**:
- `Promise`
**Throws**:
If the press operation fails
**Example:**
```typescript
// Press Enter
try {
await sandbox.computerUse.keyboard.press('Return');
console.log('Operation success');
} catch (e) {
console.log('Operation failed:', e);
}
// Press Ctrl+C
try {
await sandbox.computerUse.keyboard.press('c', ['ctrl']);
console.log('Operation success');
} catch (e) {
console.log('Operation failed:', e);
}
// Press Ctrl+Shift+T
try {
await sandbox.computerUse.keyboard.press('t', ['ctrl', 'shift']);
console.log('Operation success');
} catch (e) {
console.log('Operation failed:', e);
}
```
***
#### type()
```ts
type(text: string, delay?: number): Promise
```
Types the specified text
**Parameters**:
- `text` _string_ - The text to type
- `delay?` _number_ - Delay between characters in milliseconds
**Returns**:
- `Promise`
**Throws**:
If the type operation fails
**Example:**
```typescript
try {
await sandbox.computerUse.keyboard.type('Hello, World!');
console.log('Operation success');
} catch (e) {
console.log('Operation failed:', e);
}
// With delay between characters
try {
await sandbox.computerUse.keyboard.type('Slow typing', 100);
console.log('Operation success');
} catch (e) {
console.log('Operation failed:', e);
}
```
***
## Mouse
Mouse operations for computer use functionality
### Constructors
#### new Mouse()
```ts
new Mouse(apiClient: ComputerUseApi): Mouse
```
**Parameters**:
- `apiClient` _ComputerUseApi_
**Returns**:
- `Mouse`
### Methods
#### click()
```ts
click(
x: number,
y: number,
button?: string,
double?: boolean): Promise
```
Clicks the mouse at the specified coordinates
**Parameters**:
- `x` _number_ - The x coordinate to click at
- `y` _number_ - The y coordinate to click at
- `button?` _string = 'left'_ - The mouse button to click ('left', 'right', 'middle')
- `double?` _boolean = false_ - Whether to perform a double-click
**Returns**:
- `Promise` - Click operation result
**Example:**
```typescript
// Single left click
const result = await sandbox.computerUse.mouse.click(100, 200);
// Double click
const doubleClick = await sandbox.computerUse.mouse.click(100, 200, 'left', true);
// Right click
const rightClick = await sandbox.computerUse.mouse.click(100, 200, 'right');
```
***
#### drag()
```ts
drag(
startX: number,
startY: number,
endX: number,
endY: number,
button?: string): Promise
```
Drags the mouse from start coordinates to end coordinates
**Parameters**:
- `startX` _number_ - The starting x coordinate
- `startY` _number_ - The starting y coordinate
- `endX` _number_ - The ending x coordinate
- `endY` _number_ - The ending y coordinate
- `button?` _string = 'left'_ - The mouse button to use for dragging
**Returns**:
- `Promise` - Drag operation result
**Example:**
```typescript
const result = await sandbox.computerUse.mouse.drag(50, 50, 150, 150);
console.log(`Dragged from ${result.from.x},${result.from.y} to ${result.to.x},${result.to.y}`);
```
***
#### getPosition()
```ts
getPosition(): Promise
```
Gets the current mouse cursor position
**Returns**:
- `Promise` - Current mouse position with x and y coordinates
**Example:**
```typescript
const position = await sandbox.computerUse.mouse.getPosition();
console.log(`Mouse is at: ${position.x}, ${position.y}`);
```
***
#### move()
```ts
move(x: number, y: number): Promise
```
Moves the mouse cursor to the specified coordinates
**Parameters**:
- `x` _number_ - The x coordinate to move to
- `y` _number_ - The y coordinate to move to
**Returns**:
- `Promise` - Position after move
**Example:**
```typescript
const result = await sandbox.computerUse.mouse.move(100, 200);
console.log(`Mouse moved to: ${result.x}, ${result.y}`);
```
***
#### scroll()
```ts
scroll(
x: number,
y: number,
direction: "up" | "down",
amount?: number): Promise
```
Scrolls the mouse wheel at the specified coordinates
**Parameters**:
- `x` _number_ - The x coordinate to scroll at
- `y` _number_ - The y coordinate to scroll at
- `direction` _The direction to scroll_ - `"up"` | `"down"`
- `amount?` _number = 1_ - The amount to scroll
**Returns**:
- `Promise` - Whether the scroll operation was successful
**Example:**
```typescript
// Scroll up
const scrollUp = await sandbox.computerUse.mouse.scroll(100, 200, 'up', 3);
// Scroll down
const scrollDown = await sandbox.computerUse.mouse.scroll(100, 200, 'down', 5);
```
***
## RecordingService
Recording operations for computer use functionality.
### Constructors
#### new RecordingService()
```ts
new RecordingService(apiClient: ComputerUseApi): RecordingService
```
**Parameters**:
- `apiClient` _ComputerUseApi_
**Returns**:
- `RecordingService`
### Methods
#### delete()
```ts
delete(id: string): Promise
```
Deletes a recording by ID
**Parameters**:
- `id` _string_ - The ID of the recording to delete
**Returns**:
- `Promise`
**Example:**
```typescript
await sandbox.computerUse.recording.delete(recordingId);
console.log('Recording deleted');
```
***
#### download()
```ts
download(id: string, localPath: string): Promise
```
Downloads a recording file and saves it to a local path
The file is streamed directly to disk without loading the entire content into memory.
**Parameters**:
- `id` _string_ - The ID of the recording to download
- `localPath` _string_ - Path to save the recording file locally
**Returns**:
- `Promise`
**Example:**
```typescript
// Download recording to file
await sandbox.computerUse.recording.download(recordingId, 'local_recording.mp4');
console.log('Recording downloaded');
```
***
#### get()
```ts
get(id: string): Promise
```
Gets details of a specific recording by ID
**Parameters**:
- `id` _string_ - The ID of the recording to retrieve
**Returns**:
- `Promise` - Recording details
**Example:**
```typescript
const recording = await sandbox.computerUse.recording.get(recordingId);
console.log(`Recording: ${recording.fileName}`);
console.log(`Status: ${recording.status}`);
console.log(`Duration: ${recording.durationSeconds} seconds`);
```
***
#### list()
```ts
list(): Promise
```
Lists all recordings (active and completed)
**Returns**:
- `Promise` - List of all recordings
**Example:**
```typescript
const recordings = await sandbox.computerUse.recording.list();
console.log(`Found ${recordings.recordings.length} recordings`);
recordings.recordings.forEach(rec => {
console.log(`- ${rec.fileName}: ${rec.status}`);
});
```
***
#### start()
```ts
start(label?: string): Promise
```
Starts a new screen recording session
**Parameters**:
- `label?` _string_ - Optional custom label for the recording
**Returns**:
- `Promise` - Started recording details
**Example:**
```typescript
// Start a recording with a label
const recording = await sandbox.computerUse.recording.start('my-test-recording');
console.log(`Recording started: ${recording.id}`);
console.log(`File: ${recording.filePath}`);
```
***
#### stop()
```ts
stop(id: string): Promise
```
Stops an active screen recording session
**Parameters**:
- `id` _string_ - The ID of the recording to stop
**Returns**:
- `Promise` - Stopped recording details
**Example:**
```typescript
const result = await sandbox.computerUse.recording.stop(recording.id);
console.log(`Recording stopped: ${result.durationSeconds} seconds`);
console.log(`Saved to: ${result.filePath}`);
```
***
## Screenshot
Screenshot operations for computer use functionality
### Constructors
#### new Screenshot()
```ts
new Screenshot(apiClient: ComputerUseApi): Screenshot
```
**Parameters**:
- `apiClient` _ComputerUseApi_
**Returns**:
- `Screenshot`
### Methods
#### takeCompressed()
```ts
takeCompressed(options?: ScreenshotOptions): Promise
```
Takes a compressed screenshot of the entire screen
**Parameters**:
- `options?` _ScreenshotOptions = {}_ - Compression and display options
**Returns**:
- `Promise` - Compressed screenshot data
**Example:**
```typescript
// Default compression
const screenshot = await sandbox.computerUse.screenshot.takeCompressed();
// High quality JPEG
const jpeg = await sandbox.computerUse.screenshot.takeCompressed({
format: 'jpeg',
quality: 95,
showCursor: true
});
// Scaled down PNG
const scaled = await sandbox.computerUse.screenshot.takeCompressed({
format: 'png',
scale: 0.5
});
```
***
#### takeCompressedRegion()
```ts
takeCompressedRegion(region: ScreenshotRegion, options?: ScreenshotOptions): Promise
```
Takes a compressed screenshot of a specific region
**Parameters**:
- `region` _ScreenshotRegion_ - The region to capture
- `options?` _ScreenshotOptions = {}_ - Compression and display options
**Returns**:
- `Promise` - Compressed screenshot data
**Example:**
```typescript
const region = { x: 0, y: 0, width: 800, height: 600 };
const screenshot = await sandbox.computerUse.screenshot.takeCompressedRegion(region, {
format: 'webp',
quality: 80,
showCursor: true
});
console.log(`Compressed size: ${screenshot.size_bytes} bytes`);
```
***
#### takeFullScreen()
```ts
takeFullScreen(showCursor?: boolean): Promise
```
Takes a screenshot of the entire screen
**Parameters**:
- `showCursor?` _boolean = false_ - Whether to show the cursor in the screenshot
**Returns**:
- `Promise` - Screenshot data with base64 encoded image
**Example:**
```typescript
const screenshot = await sandbox.computerUse.screenshot.takeFullScreen();
console.log(`Screenshot size: ${screenshot.width}x${screenshot.height}`);
// With cursor visible
const withCursor = await sandbox.computerUse.screenshot.takeFullScreen(true);
```
***
#### takeRegion()
```ts
takeRegion(region: ScreenshotRegion, showCursor?: boolean): Promise
```
Takes a screenshot of a specific region
**Parameters**:
- `region` _ScreenshotRegion_ - The region to capture
- `showCursor?` _boolean = false_ - Whether to show the cursor in the screenshot
**Returns**:
- `Promise` - Screenshot data with base64 encoded image
**Example:**
```typescript
const region = { x: 100, y: 100, width: 300, height: 200 };
const screenshot = await sandbox.computerUse.screenshot.takeRegion(region);
console.log(`Captured region: ${screenshot.region.width}x${screenshot.region.height}`);
```
***
## ScreenshotOptions
Interface for screenshot compression options
**Properties**:
- `format?` _string_
- `quality?` _number_
- `scale?` _number_
- `showCursor?` _boolean_
## ScreenshotRegion
Interface for region coordinates used in screenshot operations
**Properties**:
- `height` _number_
- `width` _number_
- `x` _number_
- `y` _number_
## Daytona
Main class for interacting with the Daytona API.
Provides methods for creating, managing, and interacting with Daytona Sandboxes.
Can be initialized either with explicit configuration or using environment variables.
**Properties**:
- `snapshot` _SnapshotService_ - Service for managing Daytona Snapshots
- `volume` _VolumeService_ - Service for managing Daytona Volumes
**Examples:**
```ts
// Using environment variables
// Uses DAYTONA_API_KEY, DAYTONA_API_URL, DAYTONA_TARGET
const daytona = new Daytona();
const sandbox = await daytona.create();
```
```ts
// Using explicit configuration
const config: DaytonaConfig = {
apiKey: "your-api-key",
apiUrl: "https://your-api.com",
target: "us"
};
const daytona = new Daytona(config);
```
```ts
// Disposes daytona and flushes traces when done
await using daytona = new Daytona({
otelEnabled: true,
});
@class
```
### Implements
- `AsyncDisposable`
### Constructors
#### new Daytona()
```ts
new Daytona(config?: DaytonaConfig): Daytona
```
Creates a new Daytona client instance.
**Parameters**:
- `config?` _DaytonaConfig_ - Configuration options
**Returns**:
- `Daytona`
**Throws**:
- `DaytonaError` - When API key is missing
### Methods
#### \[asyncDispose\]()
```ts
asyncDispose: Promise
```
**Returns**:
- `Promise`
##### Implementation of
```ts
AsyncDisposable.[asyncDispose]
```
***
#### create()
##### Call Signature
```ts
create(params?: CreateSandboxFromSnapshotParams, options?: {
timeout: number;
}): Promise
```
Creates Sandboxes from specified or default snapshot. You can specify various parameters,
including language, image, environment variables, and volumes.
**Parameters**:
- `params?` _CreateSandboxFromSnapshotParams_ - Parameters for Sandbox creation from snapshot
- `options?` _Options for the create operation_
- `timeout?` _number_ - Timeout in seconds (0 means no timeout, default is 60)
**Returns**:
- `Promise` - The created Sandbox instance
**Examples:**
```ts
const sandbox = await daytona.create();
```
```ts
// Create a custom sandbox
const params: CreateSandboxFromSnapshotParams = {
language: 'typescript',
snapshot: 'my-snapshot-id',
envVars: {
NODE_ENV: 'development',
DEBUG: 'true'
},
autoStopInterval: 60,
autoArchiveInterval: 60,
autoDeleteInterval: 120
};
const sandbox = await daytona.create(params, { timeout: 100 });
```
##### Call Signature
```ts
create(params?: CreateSandboxFromImageParams, options?: {
onSnapshotCreateLogs: (chunk: string) => void;
timeout: number;
}): Promise
```
Creates Sandboxes from specified image available on some registry or declarative Daytona Image. You can specify various parameters,
including resources, language, image, environment variables, and volumes. Daytona creates snapshot from
provided image and uses it to create Sandbox.
**Parameters**:
- `params?` _CreateSandboxFromImageParams_ - Parameters for Sandbox creation from image
- `options?` _Options for the create operation_
- `onSnapshotCreateLogs?` _\(chunk: string\) =\> void_ - Callback function to handle snapshot creation logs.
- `timeout?` _number_ - Timeout in seconds (0 means no timeout, default is 60)
**Returns**:
- `Promise` - The created Sandbox instance
**Examples:**
```ts
const sandbox = await daytona.create({ image: 'debian:12.9' }, { timeout: 90, onSnapshotCreateLogs: console.log });
```
```ts
// Create a custom sandbox
const image = Image.base('alpine:3.18').pipInstall('numpy');
const params: CreateSandboxFromImageParams = {
language: 'typescript',
image,
envVars: {
NODE_ENV: 'development',
DEBUG: 'true'
},
resources: {
cpu: 2,
memory: 4 // 4GB RAM
},
autoStopInterval: 60,
autoArchiveInterval: 60,
autoDeleteInterval: 120
};
const sandbox = await daytona.create(params, { timeout: 100, onSnapshotCreateLogs: console.log });
```
***
#### delete()
```ts
delete(sandbox: Sandbox, timeout: number): Promise
```
Deletes a Sandbox.
**Parameters**:
- `sandbox` _Sandbox_ - The Sandbox to delete
- `timeout` _number = 60_ - Timeout in seconds (0 means no timeout, default is 60)
**Returns**:
- `Promise`
**Example:**
```ts
const sandbox = await daytona.get('my-sandbox-id');
await daytona.delete(sandbox);
```
***
#### get()
```ts
get(sandboxIdOrName: string): Promise
```
Gets a Sandbox by its ID or name.
**Parameters**:
- `sandboxIdOrName` _string_ - The ID or name of the Sandbox to retrieve
**Returns**:
- `Promise` - The Sandbox
**Example:**
```ts
const sandbox = await daytona.get('my-sandbox-id-or-name');
console.log(`Sandbox state: ${sandbox.state}`);
```
***
#### list()
```ts
list(
labels?: Record,
page?: number,
limit?: number): Promise
```
Returns paginated list of Sandboxes filtered by labels.
**Parameters**:
- `labels?` _Record\_ - Labels to filter Sandboxes
- `page?` _number_ - Page number for pagination (starting from 1)
- `limit?` _number_ - Maximum number of items per page
**Returns**:
- `Promise` - Paginated list of Sandboxes that match the labels.
**Example:**
```ts
const result = await daytona.list({ 'my-label': 'my-value' }, 2, 10);
for (const sandbox of result.items) {
console.log(`${sandbox.id}: ${sandbox.state}`);
}
```
***
#### start()
```ts
start(sandbox: Sandbox, timeout?: number): Promise
```
Starts a Sandbox and waits for it to be ready.
**Parameters**:
- `sandbox` _Sandbox_ - The Sandbox to start
- `timeout?` _number_ - Optional timeout in seconds (0 means no timeout)
**Returns**:
- `Promise`
**Example:**
```ts
const sandbox = await daytona.get('my-sandbox-id');
// Wait up to 60 seconds for the sandbox to start
await daytona.start(sandbox, 60);
```
***
#### stop()
```ts
stop(sandbox: Sandbox): Promise
```
Stops a Sandbox.
**Parameters**:
- `sandbox` _Sandbox_ - The Sandbox to stop
**Returns**:
- `Promise`
**Example:**
```ts
const sandbox = await daytona.get('my-sandbox-id');
await daytona.stop(sandbox);
```
## CodeLanguage
Supported programming languages for code execution
Python is used as the default sandbox language when no language is explicitly specified.
**Enum Members**:
- `JAVASCRIPT` ("javascript")
- `PYTHON` ("python")
- `TYPESCRIPT` ("typescript")
## CreateSandboxBaseParams
Base parameters for creating a new Sandbox.
**Properties**:
- `autoArchiveInterval?` _number_ - Auto-archive interval in minutes (0 means the maximum interval will be used). Default is 7 days.
- `autoDeleteInterval?` _number_ - Auto-delete interval in minutes (negative value means disabled, 0 means delete immediately upon stopping). By default, auto-delete is disabled.
- `autoStopInterval?` _number_ - Auto-stop interval in minutes (0 means disabled). Default is 15 minutes.
- `envVars?` _Record\_ - Optional environment variables to set in the Sandbox
- `ephemeral?` _boolean_ - Whether the Sandbox should be ephemeral. If true, autoDeleteInterval will be set to 0.
- `labels?` _Record\_ - Sandbox labels
- `language?` _string_ - Programming language for direct code execution. Defaults to "python" if not specified.
- `name?` _string_
- `networkAllowList?` _string_ - Comma-separated list of allowed CIDR network addresses for the Sandbox
- `networkBlockAll?` _boolean_ - Whether to block all network access for the Sandbox
- `public?` _boolean_ - Is the Sandbox port preview public
- `user?` _string_ - Optional os user to use for the Sandbox
- `volumes?` _VolumeMount\[\]_ - Optional array of volumes to mount to the Sandbox
## CreateSandboxFromImageParams
Parameters for creating a new Sandbox.
**Properties**:
- `autoArchiveInterval?` _number_
- `autoDeleteInterval?` _number_
- `autoStopInterval?` _number_
- `envVars?` _Record\_
- `ephemeral?` _boolean_
- `image` _string \| Image_ - Custom Docker image to use for the Sandbox. If an Image object is provided,
the image will be dynamically built.
- `labels?` _Record\_
- `language?` _string_
- `name?` _string_
- `networkAllowList?` _string_
- `networkBlockAll?` _boolean_
- `public?` _boolean_
- `resources?` _Resources_ - Resource allocation for the Sandbox. If not provided, sandbox will
have default resources.
- `user?` _string_
- `volumes?` _VolumeMount\[\]_
## CreateSandboxFromSnapshotParams
Parameters for creating a new Sandbox from a snapshot.
**Properties**:
- `autoArchiveInterval?` _number_
- `autoDeleteInterval?` _number_
- `autoStopInterval?` _number_
- `envVars?` _Record\_
- `ephemeral?` _boolean_
- `labels?` _Record\_
- `language?` _string_
- `name?` _string_
- `networkAllowList?` _string_
- `networkBlockAll?` _boolean_
- `public?` _boolean_
- `snapshot?` _string_ - Name of the snapshot to use for the Sandbox.
- `user?` _string_
- `volumes?` _VolumeMount\[\]_
## DaytonaConfig
Configuration options for initializing the Daytona client.
**Properties**:
- `\_experimental?` _Record\_ - Configuration for experimental features
- `apiKey?` _string_ - API key for authentication with the Daytona API
- `apiUrl?` _string_ - URL of the Daytona API. Defaults to 'https://app.daytona.io/api'
if not set here and not set in environment variable DAYTONA_API_URL.
- `jwtToken?` _string_ - JWT token for authentication with the Daytona API. If not set, it must be provided
via the environment variable `DAYTONA_JWT_TOKEN`, or an API key must be provided instead.
- `organizationId?` _string_ - Organization ID used for JWT-based authentication. Required if a JWT token
is provided, and must be set either here or in the environment variable `DAYTONA_ORGANIZATION_ID`.
- ~~`serverUrl?`~~ _string_ - **_Deprecated_** - Use `apiUrl` instead. This property will be removed in future versions.
- `target?` _string_ - Target location for Sandboxes
**Example:**
```ts
const config: DaytonaConfig = {
apiKey: "your-api-key",
apiUrl: "https://your-api.com",
target: "us"
};
const daytona = new Daytona(config);
```
## Resources
Resource allocation for a Sandbox.
**Properties**:
- `cpu?` _number_ - CPU allocation for the Sandbox in cores
- `disk?` _number_ - Disk space allocation for the Sandbox in GiB
- `gpu?` _number_ - GPU allocation for the Sandbox in units
- `memory?` _number_ - Memory allocation for the Sandbox in GiB
**Example:**
```ts
const resources: SandboxResources = {
cpu: 2,
memory: 4, // 4GiB RAM
disk: 20 // 20GiB disk
};
```
## VolumeMount
Represents a volume mount for a Sandbox.
**Properties**:
- `mountPath` _string_ - Path on the Sandbox to mount the Volume
- `subpath?` _string_ - Optional subpath within the volume to mount. When specified, only this S3 prefix will be accessible. When omitted, the entire volume is mounted.
- _Inherited from_: `SandboxVolume.subpath`
- `volumeId` _string_ - ID of the Volume to mount
**Extends:**
- `SandboxVolume`
## DaytonaError
Base error for Daytona SDK.
**Properties**:
- `headers?` _AxiosHeaders_ - Response headers if available
- `statusCode?` _number_ - HTTP status code if available
**Extends:**
- `Error`
### Extended by
- `DaytonaNotFoundError`
- `DaytonaRateLimitError`
- `DaytonaTimeoutError`
### Constructors
#### new DaytonaError()
```ts
new DaytonaError(
message: string,
statusCode?: number,
headers?: AxiosHeaders): DaytonaError
```
**Parameters**:
- `message` _string_
- `statusCode?` _number_
- `headers?` _AxiosHeaders_
**Returns**:
- `DaytonaError`
##### Overrides
```ts
Error.constructor
```
## DaytonaNotFoundError
Base error for Daytona SDK.
**Properties**:
- `headers?` _AxiosHeaders_ - Response headers if available
- _Inherited from_: `DaytonaError.headers`
- `statusCode?` _number_ - HTTP status code if available
- _Inherited from_: `DaytonaError.statusCode`
**Extends:**
- `DaytonaError`
### Constructors
#### new DaytonaNotFoundError()
```ts
new DaytonaNotFoundError(
message: string,
statusCode?: number,
headers?: AxiosHeaders): DaytonaNotFoundError
```
**Parameters**:
- `message` _string_
- `statusCode?` _number_
- `headers?` _AxiosHeaders_
**Returns**:
- `DaytonaNotFoundError`
##### Overrides
`DaytonaError`.`constructor`
## DaytonaRateLimitError
Error thrown when rate limit is exceeded.
**Properties**:
- `headers?` _AxiosHeaders_ - Response headers if available
- _Inherited from_: `DaytonaError.headers`
- `statusCode?` _number_ - HTTP status code if available
- _Inherited from_: `DaytonaError.statusCode`
**Extends:**
- `DaytonaError`
### Constructors
#### new DaytonaRateLimitError()
```ts
new DaytonaRateLimitError(
message: string,
statusCode?: number,
headers?: AxiosHeaders): DaytonaRateLimitError
```
**Parameters**:
- `message` _string_
- `statusCode?` _number_
- `headers?` _AxiosHeaders_
**Returns**:
- `DaytonaRateLimitError`
##### Overrides
`DaytonaError`.`constructor`
## DaytonaTimeoutError
Error thrown when a timeout occurs.
**Properties**:
- `headers?` _AxiosHeaders_ - Response headers if available
- _Inherited from_: `DaytonaError.headers`
- `statusCode?` _number_ - HTTP status code if available
- _Inherited from_: `DaytonaError.statusCode`
**Extends:**
- `DaytonaError`
### Constructors
#### new DaytonaTimeoutError()
```ts
new DaytonaTimeoutError(
message: string,
statusCode?: number,
headers?: AxiosHeaders): DaytonaTimeoutError
```
**Parameters**:
- `message` _string_
- `statusCode?` _number_
- `headers?` _AxiosHeaders_
**Returns**:
- `DaytonaTimeoutError`
##### Overrides
`DaytonaError`.`constructor`
## ExecuteResponse
Response from the command execution.
**Properties**:
- `artifacts?` _ExecutionArtifacts_ - Artifacts from the command execution
- `exitCode` _number_ - The exit code from the command execution
- `result` _string_ - The output from the command execution
## ExecutionArtifacts
Artifacts from the command execution.
**Properties**:
- `charts?` _Chart\[\]_ - List of chart metadata from matplotlib
- `stdout` _string_ - Standard output from the command, same as `result` in `ExecuteResponse`
## FileSystem
Provides file system operations within a Sandbox.
### Constructors
#### new FileSystem()
```ts
new FileSystem(clientConfig: Configuration, apiClient: FileSystemApi): FileSystem
```
**Parameters**:
- `clientConfig` _Configuration_
- `apiClient` _FileSystemApi_
**Returns**:
- `FileSystem`
### Methods
#### createFolder()
```ts
createFolder(path: string, mode: string): Promise
```
Create a new directory in the Sandbox with specified permissions.
**Parameters**:
- `path` _string_ - Path where the directory should be created. Relative paths are resolved based on the sandbox working directory.
- `mode` _string_ - Directory permissions in octal format (e.g. "755")
**Returns**:
- `Promise`
**Example:**
```ts
// Create a directory with standard permissions
await fs.createFolder('app/data', '755');
```
***
#### deleteFile()
```ts
deleteFile(path: string, recursive?: boolean): Promise
```
Deletes a file or directory from the Sandbox.
**Parameters**:
- `path` _string_ - Path to the file or directory to delete. Relative paths are resolved based on the sandbox working directory.
- `recursive?` _boolean_ - If the file is a directory, this must be true to delete it.
**Returns**:
- `Promise`
**Example:**
```ts
// Delete a file
await fs.deleteFile('app/temp.log');
```
***
#### downloadFile()
##### Call Signature
```ts
downloadFile(remotePath: string, timeout?: number): Promise>
```
Downloads a file from the Sandbox. This method loads the entire file into memory, so it is not recommended
for downloading large files.
**Parameters**:
- `remotePath` _string_ - Path to the file to download. Relative paths are resolved based on the sandbox working directory.
- `timeout?` _number_ - Timeout for the download operation in seconds. 0 means no timeout.
Default is 30 minutes.
**Returns**:
- `Promise>` - The file contents as a Buffer.
**Example:**
```ts
// Download and process a file
const fileBuffer = await fs.downloadFile('tmp/data.json');
console.log('File content:', fileBuffer.toString());
```
##### Call Signature
```ts
downloadFile(
remotePath: string,
localPath: string,
timeout?: number): Promise
```
Downloads a file from the Sandbox and saves it to a local file. This method uses streaming to download the file,
so it is recommended for downloading larger files.
**Parameters**:
- `remotePath` _string_ - Path to the file to download in the Sandbox. Relative paths are resolved based on the sandbox working directory.
- `localPath` _string_ - Path to save the downloaded file.
- `timeout?` _number_ - Timeout for the download operation in seconds. 0 means no timeout.
Default is 30 minutes.
**Returns**:
- `Promise`
**Example:**
```ts
// Download and save a file
await fs.downloadFile('tmp/data.json', 'local_file.json');
```
***
#### downloadFiles()
```ts
downloadFiles(files: FileDownloadRequest[], timeoutSec?: number): Promise
```
Downloads multiple files from the Sandbox. If the files already exist locally, they will be overwritten.
**Parameters**:
- `files` _FileDownloadRequest\[\]_ - Array of file download requests.
- `timeoutSec?` _number = ..._ - Timeout for the download operation in seconds. 0 means no timeout.
Default is 30 minutes.
**Returns**:
- `Promise` - Array of download results.
**Throws**:
If the request itself fails (network issues, invalid request/response, etc.). Individual
file download errors are returned in the `FileDownloadResponse.error` field.
**Example:**
```ts
// Download multiple files
const results = await fs.downloadFiles([
{ source: 'tmp/data.json' },
{ source: 'tmp/config.json', destination: 'local_config.json' }
]);
results.forEach(result => {
if (result.error) {
console.error(`Error downloading ${result.source}: ${result.error}`);
} else if (result.result) {
console.log(`Downloaded ${result.source} to ${result.result}`);
}
});
```
***
#### findFiles()
```ts
findFiles(path: string, pattern: string): Promise
```
Searches for text patterns within files in the Sandbox.
**Parameters**:
- `path` _string_ - Directory to search in. Relative paths are resolved based on the sandbox working directory.
- `pattern` _string_ - Search pattern
**Returns**:
- `Promise` - Array of matches with file and line information
**Example:**
```ts
// Find all TODO comments in TypeScript files
const matches = await fs.findFiles('app/src', 'TODO:');
matches.forEach(match => {
console.log(`${match.file}:${match.line}: ${match.content}`);
});
```
***
#### getFileDetails()
```ts
getFileDetails(path: string): Promise
```
Retrieves detailed information about a file or directory.
**Parameters**:
- `path` _string_ - Path to the file or directory. Relative paths are resolved based on the sandbox working directory.
**Returns**:
- `Promise` - Detailed file information including size, permissions, modification time
**Example:**
```ts
// Get file details
const info = await fs.getFileDetails('app/config.json');
console.log(`Size: ${info.size}, Modified: ${info.modTime}`);
```
***
#### listFiles()
```ts
listFiles(path: string): Promise
```
Lists contents of a directory in the Sandbox.
**Parameters**:
- `path` _string_ - Directory path to list. Relative paths are resolved based on the sandbox working directory.
**Returns**:
- `Promise` - Array of file and directory information
**Example:**
```ts
// List directory contents
const files = await fs.listFiles('app/src');
files.forEach(file => {
console.log(`${file.name} (${file.size} bytes)`);
});
```
***
#### moveFiles()
```ts
moveFiles(source: string, destination: string): Promise
```
Moves or renames a file or directory.
**Parameters**:
- `source` _string_ - Source path. Relative paths are resolved based on the sandbox working directory.
- `destination` _string_ - Destination path. Relative paths are resolved based on the sandbox working directory.
**Returns**:
- `Promise`
**Example:**
```ts
// Move a file to a new location
await fs.moveFiles('app/temp/data.json', 'app/data/data.json');
```
***
#### replaceInFiles()
```ts
replaceInFiles(
files: string[],
pattern: string,
newValue: string): Promise
```
Replaces text content in multiple files.
**Parameters**:
- `files` _string\[\]_ - Array of file paths to process. Relative paths are resolved based on the sandbox working directory.
- `pattern` _string_ - Pattern to replace
- `newValue` _string_ - Replacement text
**Returns**:
- `Promise` - Results of the replace operation for each file
**Example:**
```ts
// Update version number across multiple files
const results = await fs.replaceInFiles(
['app/package.json', 'app/version.ts'],
'"version": "1.0.0"',
'"version": "1.1.0"'
);
```
***
#### searchFiles()
```ts
searchFiles(path: string, pattern: string): Promise
```
Searches for files and directories by name pattern in the Sandbox.
**Parameters**:
- `path` _string_ - Directory to search in. Relative paths are resolved based on the sandbox working directory.
- `pattern` _string_ - File name pattern (supports globs)
**Returns**:
- `Promise` - Search results with matching files
**Example:**
```ts
// Find all TypeScript files
const result = await fs.searchFiles('app', '*.ts');
result.files.forEach(file => console.log(file));
```
***
#### setFilePermissions()
```ts
setFilePermissions(path: string, permissions: FilePermissionsParams): Promise
```
Sets permissions and ownership for a file or directory.
**Parameters**:
- `path` _string_ - Path to the file or directory. Relative paths are resolved based on the sandbox working directory.
- `permissions` _FilePermissionsParams_ - Permission settings
**Returns**:
- `Promise`
**Example:**
```ts
// Set file permissions and ownership
await fs.setFilePermissions('app/script.sh', {
owner: 'daytona',
group: 'users',
mode: '755' // Execute permission for shell script
});
```
***
#### uploadFile()
##### Call Signature
```ts
uploadFile(
file: Buffer,
remotePath: string,
timeout?: number): Promise
```
Uploads a file to the Sandbox. This method loads the entire file into memory, so it is not recommended
for uploading large files.
**Parameters**:
- `file` _Buffer_ - Buffer of the file to upload.
- `remotePath` _string_ - Destination path in the Sandbox. Relative paths are resolved based on the sandbox working directory.
- `timeout?` _number_ - Timeout for the upload operation in seconds. 0 means no timeout.
Default is 30 minutes.
**Returns**:
- `Promise`
**Example:**
```ts
// Upload a configuration file
await fs.uploadFile(Buffer.from('{"setting": "value"}'), 'tmp/config.json');
```
##### Call Signature
```ts
uploadFile(
localPath: string,
remotePath: string,
timeout?: number): Promise
```
Uploads a file from the local file system to the Sandbox. This method uses streaming to upload the file,
so it is recommended for uploading larger files.
**Parameters**:
- `localPath` _string_ - Path to the local file to upload.
- `remotePath` _string_ - Destination path in the Sandbox. Relative paths are resolved based on the sandbox working directory.
- `timeout?` _number_ - Timeout for the upload operation in seconds. 0 means no timeout.
Default is 30 minutes.
**Returns**:
- `Promise`
**Example:**
```ts
// Upload a local file
await fs.uploadFile('local_file.txt', 'tmp/file.txt');
```
***
#### uploadFiles()
```ts
uploadFiles(files: FileUpload[], timeout?: number): Promise
```
Uploads multiple files to the Sandbox. If files already exist at the destination paths,
they will be overwritten.
**Parameters**:
- `files` _FileUpload\[\]_ - Array of files to upload.
- `timeout?` _number = ..._ - Timeout for the upload operation in seconds. 0 means no timeout.
Default is 30 minutes.
**Returns**:
- `Promise`
**Example:**
```ts
// Upload multiple text files
const files = [
{
source: Buffer.from('Content of file 1'),
destination: '/tmp/file1.txt'
},
{
source: 'app/data/file2.txt',
destination: '/tmp/file2.txt'
},
{
source: Buffer.from('{"key": "value"}'),
destination: '/tmp/config.json'
}
];
await fs.uploadFiles(files);
```
***
## DownloadMetadata
Represents metadata for a file download operation.
**Properties**:
- `destination?` _string_ - Destination path in the local filesystem where the file content will be streamed to.
- `error?` _string_ - Error message if the download failed, undefined if successful.
- `result?` _string \| Buffer\ \| Uint8Array\_ - The download result - file path (if destination provided in the request)
or bytes content (if no destination in the request), undefined if failed or no data received.
## FileDownloadRequest
Represents a request to download a single file from the Sandbox.
**Properties**:
- `destination?` _string_ - Destination path in the local filesystem where the file content will be
streamed to. If not provided, the file will be downloaded in the bytes buffer (might cause memory issues if the file is large).
- `source` _string_ - Source path in the Sandbox. Relative paths are resolved based on the user's
root directory.
## FileDownloadResponse
Represents the response to a single file download request.
**Properties**:
- `error?` _string_ - Error message if the download failed, undefined if successful.
- `result?` _string \| Buffer\_ - The download result - file path (if destination provided in the request)
or bytes content (if no destination in the request), undefined if failed or no data received.
- `source` _string_ - The original source path requested for download.
## FilePermissionsParams
Parameters for setting file permissions in the Sandbox.
**Properties**:
- `group?` _string_ - Group owner of the file
- `mode?` _string_ - File mode/permissions in octal format (e.g. "644")
- `owner?` _string_ - User owner of the file
**Example:**
```ts
const permissions: FilePermissionsParams = {
mode: '644',
owner: 'daytona',
group: 'users'
};
```
## FileUpload
Represents a file to be uploaded to the Sandbox.
**Properties**:
- `destination` _string_ - Absolute destination path in the Sandbox. Relative paths are resolved based on the sandbox working directory.
- `source` _string \| Buffer\_ - File to upload. If a Buffer, it is interpreted as the file content which is loaded into memory.
Make sure it fits into memory, otherwise use the local file path which content will be streamed to the Sandbox.
## Git
Provides Git operations within a Sandbox.
### Constructors
#### new Git()
```ts
new Git(apiClient: GitApi): Git
```
**Parameters**:
- `apiClient` _GitApi_
**Returns**:
- `Git`
### Methods
#### add()
```ts
add(path: string, files: string[]): Promise
```
Stages the specified files for the next commit, similar to
running 'git add' on the command line.
**Parameters**:
- `path` _string_ - Path to the Git repository root. Relative paths are resolved based on the sandbox working directory.
- `files` _string\[\]_ - List of file paths or directories to stage, relative to the repository root
**Returns**:
- `Promise`
**Examples:**
```ts
// Stage a single file
await git.add('workspace/repo', ['file.txt']);
```
```ts
// Stage whole repository
await git.add('workspace/repo', ['.']);
```
***
#### branches()
```ts
branches(path: string): Promise
```
List branches in the repository.
**Parameters**:
- `path` _string_ - Path to the Git repository root. Relative paths are resolved based on the sandbox working directory.
**Returns**:
- `Promise` - List of branches in the repository
**Example:**
```ts
const response = await git.branches('workspace/repo');
console.log(`Branches: ${response.branches}`);
```
***
#### checkoutBranch()
```ts
checkoutBranch(path: string, branch: string): Promise
```
Checkout branche in the repository.
**Parameters**:
- `path` _string_ - Path to the Git repository root. Relative paths are resolved based on the sandbox working directory.
- `branch` _string_ - Name of the branch to checkout
**Returns**:
- `Promise`
**Example:**
```ts
await git.checkoutBranch('workspace/repo', 'new-feature');
```
***
#### clone()
```ts
clone(
url: string,
path: string,
branch?: string,
commitId?: string,
username?: string,
password?: string): Promise
```
Clones a Git repository into the specified path. It supports
cloning specific branches or commits, and can authenticate with the remote
repository if credentials are provided.
**Parameters**:
- `url` _string_ - Repository URL to clone from
- `path` _string_ - Path where the repository should be cloned. Relative paths are resolved based on the sandbox working directory.
- `branch?` _string_ - Specific branch to clone. If not specified, clones the default branch
- `commitId?` _string_ - Specific commit to clone. If specified, the repository will be left in a detached HEAD state at this commit
- `username?` _string_ - Git username for authentication
- `password?` _string_ - Git password or token for authentication
**Returns**:
- `Promise`
**Examples:**
```ts
// Clone the default branch
await git.clone(
'https://github.com/user/repo.git',
'workspace/repo'
);
```
```ts
// Clone a specific branch with authentication
await git.clone(
'https://github.com/user/private-repo.git',
'workspace/private',
branch='develop',
username='user',
password='token'
);
```
```ts
// Clone a specific commit
await git.clone(
'https://github.com/user/repo.git',
'workspace/repo-old',
commitId='abc123'
);
```
***
#### commit()
```ts
commit(
path: string,
message: string,
author: string,
email: string,
allowEmpty?: boolean): Promise
```
Commits staged changes.
**Parameters**:
- `path` _string_ - Path to the Git repository root. Relative paths are resolved based on the sandbox working directory.
- `message` _string_ - Commit message describing the changes
- `author` _string_ - Name of the commit author
- `email` _string_ - Email address of the commit author
- `allowEmpty?` _boolean_ - Allow creating an empty commit when no changes are staged
**Returns**:
- `Promise`
**Example:**
```ts
// Stage and commit changes
await git.add('workspace/repo', ['README.md']);
await git.commit(
'workspace/repo',
'Update documentation',
'John Doe',
'john@example.com',
true
);
```
***
#### createBranch()
```ts
createBranch(path: string, name: string): Promise
```
Create branch in the repository.
**Parameters**:
- `path` _string_ - Path to the Git repository root. Relative paths are resolved based on the sandbox working directory.
- `name` _string_ - Name of the new branch to create
**Returns**:
- `Promise`
**Example:**
```ts
await git.createBranch('workspace/repo', 'new-feature');
```
***
#### deleteBranch()
```ts
deleteBranch(path: string, name: string): Promise
```
Delete branche in the repository.
**Parameters**:
- `path` _string_ - Path to the Git repository root. Relative paths are resolved based on the sandbox working directory.
- `name` _string_ - Name of the branch to delete
**Returns**:
- `Promise`
**Example:**
```ts
await git.deleteBranch('workspace/repo', 'new-feature');
```
***
#### pull()
```ts
pull(
path: string,
username?: string,
password?: string): Promise
```
Pulls changes from the remote repository.
**Parameters**:
- `path` _string_ - Path to the Git repository root. Relative paths are resolved based on the sandbox working directory.
- `username?` _string_ - Git username for authentication
- `password?` _string_ - Git password or token for authentication
**Returns**:
- `Promise`
**Examples:**
```ts
// Pull from a public repository
await git.pull('workspace/repo');
```
```ts
// Pull from a private repository
await git.pull(
'workspace/repo',
'user',
'token'
);
```
***
#### push()
```ts
push(
path: string,
username?: string,
password?: string): Promise
```
Push local changes to the remote repository.
**Parameters**:
- `path` _string_ - Path to the Git repository root. Relative paths are resolved based on the sandbox working directory.
- `username?` _string_ - Git username for authentication
- `password?` _string_ - Git password or token for authentication
**Returns**:
- `Promise`
**Examples:**
```ts
// Push to a public repository
await git.push('workspace/repo');
```
```ts
// Push to a private repository
await git.push(
'workspace/repo',
'user',
'token'
);
```
***
#### status()
```ts
status(path: string): Promise
```
Gets the current status of the Git repository.
**Parameters**:
- `path` _string_ - Path to the Git repository root. Relative paths are resolved based on the sandbox working directory.
**Returns**:
- `Promise` - Current repository status including:
- currentBranch: Name of the current branch
- ahead: Number of commits ahead of the remote branch
- behind: Number of commits behind the remote branch
- branchPublished: Whether the branch has been published to the remote repository
- fileStatus: List of file statuses
**Example:**
```ts
const status = await sandbox.git.status('workspace/repo');
console.log(`Current branch: ${status.currentBranch}`);
console.log(`Commits ahead: ${status.ahead}`);
console.log(`Commits behind: ${status.behind}`);
```
***
## GitCommitResponse
Response from the git commit.
**Properties**:
- `sha` _string_ - The SHA of the commit
## Image
Represents an image definition for a Daytona sandbox.
Do not construct this class directly. Instead use one of its static factory methods,
such as `Image.base()`, `Image.debianSlim()` or `Image.fromDockerfile()`.
### Accessors
#### contextList
##### Get Signature
```ts
get contextList(): Context[]
```
###### Returns
`Context`[]
The list of context files to be added to the image.
***
#### dockerfile
##### Get Signature
```ts
get dockerfile(): string
```
**Returns**:
- `string` - The Dockerfile content.
### Methods
#### base()
```ts
static base(image: string): Image
```
Creates an Image from an existing base image.
**Parameters**:
- `image` _string_ - The base image to use.
**Returns**:
- `Image` - The Image instance.
**Example:**
```ts
const image = Image.base('python:3.12-slim-bookworm')
```
***
#### debianSlim()
```ts
static debianSlim(pythonVersion?: "3.9" | "3.10" | "3.11" | "3.12" | "3.13"): Image
```
Creates a Debian slim image based on the official Python Docker image.
**Parameters**:
- `pythonVersion?` _The Python version to use._ - `"3.9"` | `"3.10"` | `"3.11"` | `"3.12"` | `"3.13"`
**Returns**:
- `Image` - The Image instance.
**Example:**
```ts
const image = Image.debianSlim('3.12')
```
***
#### fromDockerfile()
```ts
static fromDockerfile(path: string): Image
```
Creates an Image from an existing Dockerfile.
**Parameters**:
- `path` _string_ - The path to the Dockerfile.
**Returns**:
- `Image` - The Image instance.
**Example:**
```ts
const image = Image.fromDockerfile('Dockerfile')
```
***
#### addLocalDir()
```ts
addLocalDir(localPath: string, remotePath: string): Image
```
Adds a local directory to the image.
**Parameters**:
- `localPath` _string_ - The path to the local directory.
- `remotePath` _string_ - The path of the directory in the image.
**Returns**:
- `Image` - The Image instance.
**Example:**
```ts
const image = Image
.debianSlim('3.12')
.addLocalDir('src', '/home/daytona/src')
```
***
#### addLocalFile()
```ts
addLocalFile(localPath: string, remotePath: string): Image
```
Adds a local file to the image.
**Parameters**:
- `localPath` _string_ - The path to the local file.
- `remotePath` _string_ - The path of the file in the image.
**Returns**:
- `Image` - The Image instance.
**Example:**
```ts
const image = Image
.debianSlim('3.12')
.addLocalFile('requirements.txt', '/home/daytona/requirements.txt')
```
***
#### cmd()
```ts
cmd(cmd: string[]): Image
```
Sets the default command for the image.
**Parameters**:
- `cmd` _string\[\]_ - The command to set as the default command.
**Returns**:
- `Image` - The Image instance.
**Example:**
```ts
const image = Image
.debianSlim('3.12')
.cmd(['/bin/bash'])
```
***
#### dockerfileCommands()
```ts
dockerfileCommands(dockerfileCommands: string[], contextDir?: string): Image
```
Extends an image with arbitrary Dockerfile-like commands.
**Parameters**:
- `dockerfileCommands` _string\[\]_ - The commands to add to the Dockerfile.
- `contextDir?` _string_ - The path to the context directory.
**Returns**:
- `Image` - The Image instance.
**Example:**
```ts
const image = Image
.debianSlim('3.12')
.dockerfileCommands(['RUN echo "Hello, world!"'])
```
***
#### entrypoint()
```ts
entrypoint(entrypointCommands: string[]): Image
```
Sets the entrypoint for the image.
**Parameters**:
- `entrypointCommands` _string\[\]_ - The commands to set as the entrypoint.
**Returns**:
- `Image` - The Image instance.
**Example:**
```ts
const image = Image
.debianSlim('3.12')
.entrypoint(['/bin/bash'])
```
***
#### env()
```ts
env(envVars: Record): Image
```
Sets environment variables in the image.
**Parameters**:
- `envVars` _Record\_ - The environment variables to set.
**Returns**:
- `Image` - The Image instance.
**Example:**
```ts
const image = Image
.debianSlim('3.12')
.env({ FOO: 'bar' })
```
***
#### pipInstall()
```ts
pipInstall(packages: string | string[], options?: PipInstallOptions): Image
```
Adds commands to install packages using pip.
**Parameters**:
- `packages` _The packages to install._ - `string` | `string`[]
- `options?` _PipInstallOptions_ - The options for the pip install command.
**Returns**:
- `Image` - The Image instance.
**Example:**
```ts
const image = Image.debianSlim('3.12').pipInstall('numpy', { findLinks: ['https://pypi.org/simple'] })
```
***
#### pipInstallFromPyproject()
```ts
pipInstallFromPyproject(pyprojectToml: string, options?: PyprojectOptions): Image
```
Installs dependencies from a pyproject.toml file.
**Parameters**:
- `pyprojectToml` _string_ - The path to the pyproject.toml file.
- `options?` _PyprojectOptions_ - The options for the pip install command.
**Returns**:
- `Image` - The Image instance.
**Example:**
```ts
const image = Image.debianSlim('3.12')
image.pipInstallFromPyproject('pyproject.toml', { optionalDependencies: ['dev'] })
```
***
#### pipInstallFromRequirements()
```ts
pipInstallFromRequirements(requirementsTxt: string, options?: PipInstallOptions): Image
```
Installs dependencies from a requirements.txt file.
**Parameters**:
- `requirementsTxt` _string_ - The path to the requirements.txt file.
- `options?` _PipInstallOptions_ - The options for the pip install command.
**Returns**:
- `Image` - The Image instance.
**Example:**
```ts
const image = Image.debianSlim('3.12')
image.pipInstallFromRequirements('requirements.txt', { findLinks: ['https://pypi.org/simple'] })
```
***
#### runCommands()
```ts
runCommands(...commands: (string | string[])[]): Image
```
Runs commands in the image.
**Parameters**:
- `commands` _...\(string \| string\[\]\)\[\]_ - The commands to run.
**Returns**:
- `Image` - The Image instance.
**Example:**
```ts
const image = Image
.debianSlim('3.12')
.runCommands(
'echo "Hello, world!"',
['bash', '-c', 'echo Hello, world, again!']
)
```
***
#### workdir()
```ts
workdir(dirPath: string): Image
```
Sets the working directory in the image.
**Parameters**:
- `dirPath` _string_ - The path to the working directory.
**Returns**:
- `Image` - The Image instance.
**Example:**
```ts
const image = Image
.debianSlim('3.12')
.workdir('/home/daytona')
```
***
## Context
Represents a context file to be added to the image.
**Properties**:
- `archivePath` _string_ - The path inside the archive file in object storage.
- `sourcePath` _string_ - The path to the source file or directory.
## PipInstallOptions
Options for the pip install command.
**Properties**:
- `extraIndexUrls?` _string\[\]_ - The extra index URLs to use for the pip install command.
- `extraOptions?` _string_ - The extra options to use for the pip install command. Given string is passed directly to the pip install command.
- `findLinks?` _string\[\]_ - The find-links to use for the pip install command.
- `indexUrl?` _string_ - The index URL to use for the pip install command.
- `pre?` _boolean_ - Whether to install pre-release versions.
### Extended by
- `PyprojectOptions`
## PyprojectOptions
Options for the pip install command from a pyproject.toml file.
**Properties**:
- `extraIndexUrls?` _string\[\]_ - The extra index URLs to use for the pip install command.
- _Inherited from_: `PipInstallOptions.extraIndexUrls`
- `extraOptions?` _string_ - The extra options to use for the pip install command. Given string is passed directly to the pip install command.
- _Inherited from_: `PipInstallOptions.extraOptions`
- `findLinks?` _string\[\]_ - The find-links to use for the pip install command.
- _Inherited from_: `PipInstallOptions.findLinks`
- `indexUrl?` _string_ - The index URL to use for the pip install command.
- _Inherited from_: `PipInstallOptions.indexUrl`
- `optionalDependencies?` _string\[\]_ - The optional dependencies to install.
- `pre?` _boolean_ - Whether to install pre-release versions.
- _Inherited from_: `PipInstallOptions.pre`
**Extends:**
- `PipInstallOptions`
The Daytona TypeScript SDK provides a powerful interface for programmatically interacting with Daytona Sandboxes.
## Installation
Install the Daytona TypeScript SDK using npm:
```bash
npm install @daytonaio/sdk
```
Or using yarn:
```bash
yarn add @daytonaio/sdk
```
## Getting Started
### Create a Sandbox
Create a Daytona Sandbox to run your code securely in an isolated environment. The following snippet is an example “Hello World” program that runs securely inside a Daytona Sandbox.
```typescript
import { Daytona } from '@daytonaio/sdk'
async function main() {
// Initialize the SDK (uses environment variables by default)
const daytona = new Daytona()
// Create a new sandbox
const sandbox = await daytona.create({
language: 'typescript',
envVars: { NODE_ENV: 'development' },
})
// Execute a command
const response = await sandbox.process.executeCommand('echo "Hello, World!"')
console.log(response.result)
}
main().catch(console.error)
```
## Configuration
The Daytona SDK can be configured using environment variables or by passing options to the constructor:
```typescript
import { Daytona } from '@daytonaio/sdk';
// Using environment variables (DAYTONA_API_KEY, DAYTONA_API_URL, DAYTONA_TARGET)
const daytona = new Daytona();
// Using explicit configuration
const daytona = new Daytona({
apiKey: 'YOUR_API_KEY',
apiUrl: 'https://app.daytona.io/api',
target: 'us'
});
```
For more information on configuring the Daytona SDK, see [configuration](https://www.daytona.io/docs/en/configuration.md).
## Multiple runtime support
Daytona supports multiple programming language runtimes for direct code execution inside the sandbox.
[TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk.md) works across multiple **JavaScript runtimes** including **Node.js**, **browsers**, and **serverless platforms**: Cloudflare Workers, AWS Lambda, Azure Functions, etc.
Using the Daytona SDK in browser-based environments or frameworks like [**Vite**](https://www.daytona.io/docs/en/getting-started.md#daytona-in-vite-projects) and [**Next.js**](https://www.daytona.io/docs/en/getting-started.md#daytona-in-nextjs-projects) requires configuring node polyfills.
### Daytona in Vite projects
When using Daytona SDK in a Vite-based project, configure node polyfills to ensure compatibility.
Add the following configuration to your `vite.config.ts` file in the `plugins` array:
```typescript
import { nodePolyfills } from 'vite-plugin-node-polyfills'
plugins: [
// ... other plugins
nodePolyfills({
globals: { global: true, process: true, Buffer: true },
overrides: {
path: 'path-browserify-win32',
},
}),
],
// ... rest of your config
})
```
### Daytona in Next.js projects
When using Daytona SDK in a Next.js project, configure node polyfills to ensure compatibility with Webpack and Turbopack bundlers.
Add the following configuration to your `next.config.ts` file:
```typescript
import type { NextConfig } from 'next'
import NodePolyfillPlugin from 'node-polyfill-webpack-plugin'
import { env, nodeless } from 'unenv'
const { alias: turbopackAlias } = env(nodeless, {})
const nextConfig: NextConfig = {
// Turbopack
experimental: {
turbo: {
resolveAlias: {
...turbopackAlias,
},
},
},
// Webpack
webpack: (config, { isServer }) => {
if (!isServer) {
config.plugins.push(new NodePolyfillPlugin())
}
return config
},
}
```
## LspServer
Provides Language Server Protocol functionality for code intelligence to provide
IDE-like features such as code completion, symbol search, and more.
### Constructors
#### new LspServer()
```ts
new LspServer(
languageId: LspLanguageId,
pathToProject: string,
apiClient: LspApi): LspServer
```
**Parameters**:
- `languageId` _LspLanguageId_
- `pathToProject` _string_
- `apiClient` _LspApi_
**Returns**:
- `LspServer`
### Methods
#### completions()
```ts
completions(path: string, position: Position): Promise
```
Gets completion suggestions at a position in a file.
**Parameters**:
- `path` _string_ - Path to the file. Relative paths are resolved based on the project path
set in the LSP server constructor.
- `position` _Position_ - The position in the file where completion was requested
**Returns**:
- `Promise` - List of completion suggestions. The list includes:
- isIncomplete: Whether more items might be available
- items: List of completion items, each containing:
- label: The text to insert
- kind: The kind of completion
- detail: Additional details about the item
- documentation: Documentation for the item
- sortText: Text used to sort the item in the list
- filterText: Text used to filter the item
- insertText: The actual text to insert (if different from label)
**Example:**
```ts
// Get completions at a specific position
const completions = await lsp.completions('workspace/project/src/index.ts', {
line: 10,
character: 15
});
completions.items.forEach(item => {
console.log(`${item.label} (${item.kind}): ${item.detail}`);
});
```
***
#### didClose()
```ts
didClose(path: string): Promise
```
Notifies the language server that a file has been closed, should be called when a file is closed
in the editor to allow the language server to clean up any resources associated with that file.
**Parameters**:
- `path` _string_ - Path to the closed file. Relative paths are resolved based on the project path
set in the LSP server constructor.
**Returns**:
- `Promise`
**Example:**
```ts
// When done editing a file
await lsp.didClose('workspace/project/src/index.ts');
```
***
#### didOpen()
```ts
didOpen(path: string): Promise
```
Notifies the language server that a file has been opened, enabling
language features like diagnostics and completions for that file. The server
will begin tracking the file's contents and providing language features.
**Parameters**:
- `path` _string_ - Path to the opened file. Relative paths are resolved based on the sandbox working directory.
**Returns**:
- `Promise`
**Example:**
```ts
// When opening a file for editing
await lsp.didOpen('workspace/project/src/index.ts');
// Now can get completions, symbols, etc. for this file
```
***
#### documentSymbols()
```ts
documentSymbols(path: string): Promise
```
Get symbol information (functions, classes, variables, etc.) from a document.
**Parameters**:
- `path` _string_ - Path to the file to get symbols from. Relative paths are resolved based on the project path
set in the LSP server constructor.
**Returns**:
- `Promise` - List of symbols in the document. Each symbol includes:
- name: The symbol's name
- kind: The symbol's kind (function, class, variable, etc.)
- location: The location of the symbol in the file
**Example:**
```ts
// Get all symbols in a file
const symbols = await lsp.documentSymbols('workspace/project/src/index.ts');
symbols.forEach(symbol => {
console.log(`${symbol.kind} ${symbol.name}: ${symbol.location}`);
});
```
***
#### sandboxSymbols()
```ts
sandboxSymbols(query: string): Promise
```
Searches for symbols matching the query string across the entire Sandbox.
**Parameters**:
- `query` _string_ - Search query to match against symbol names
**Returns**:
- `Promise` - List of matching symbols from all files. Each symbol includes:
- name: The symbol's name
- kind: The symbol's kind (function, class, variable, etc.)
- location: The location of the symbol in the file
**Example:**
```ts
// Search for all symbols containing "User"
const symbols = await lsp.sandboxSymbols('User');
symbols.forEach(symbol => {
console.log(`${symbol.name} (${symbol.kind}) in ${symbol.location}`);
});
```
***
#### start()
```ts
start(): Promise
```
Starts the language server, must be called before using any other LSP functionality.
It initializes the language server for the specified language and project.
**Returns**:
- `Promise