Windows Sandboxes
Daytona provides Windows sandboxes for AI agents that need a Windows operating system. A Windows sandbox is an isolated Windows virtual machine you manage programmatically to run code. Each sandbox runs its own Windows kernel with a dedicated filesystem, network stack, and allocated vCPU, RAM, and disk. Agents and developers can install software, run Windows applications, run commands in the command prompt or PowerShell, and control the desktop through Computer Use.
Windows sandboxes start from a Windows snapshot and keep their filesystem across stop and start. Pause and resume keeps memory and running processes, fork copies a running sandbox into a new one, and memory snapshots capture a running sandbox as a template for new sandboxes.
| Term | Description |
|---|---|
| Sandbox | An isolated Windows environment created on demand to run code. |
| Windows VM | A sandbox that runs as a virtual machine with its own Windows kernel. The hardware enforces the boundary between sandboxes. |
| Sandbox class | The runtime of a sandbox. Windows sandboxes use the Windows class, set by the snapshot. |
| Snapshot | A pre-configured template that new sandboxes start from. |
| Toolbox | The Daytona daemon inside the sandbox that serves file, Git, process, and Computer Use requests. |
| Shell | The program the toolbox runs commands with. The command prompt by default, or PowerShell when configured. |
Use cases
Section titled “Use cases”Windows sandboxes are used when the software, the test, or the task requires Windows.
- Computer-use agents on Windows: an agent operates Windows applications through screenshots, mouse and keyboard input, and the accessibility tree with Computer Use, for tasks that exist only in Windows software.
- Windows-only software: programs, installers, and command-line tools that have no Linux version run in an isolated machine instead of on a shared Windows server.
- Build and test on Windows: code, scripts, and installers are built or tested on a clean Windows machine for each run, so results do not depend on leftover state.
- PowerShell and automation: PowerShell scripts and Windows administration tasks run against a real Windows installation before they reach production machines.
- Evaluation and reinforcement learning (RL): each test case or episode gets an identical Windows machine, started from the base snapshot or from a filesystem snapshot you prepared.
- Long-lived agent sessions: a Windows sandbox pauses when the agent goes idle and resumes with its processes and memory intact.
- Branching from a running state: a Windows sandbox is forked to try several approaches from the same point. Each fork gets its own copy of the filesystem and memory.
Create a Windows sandbox
Section titled “Create a Windows sandbox”Create a Windows sandbox.
- Go to Daytona Sandboxes ↗
- Click
- Select a Windows :
windows-small,windows-medium, orwindows-large - Click
from daytona import Daytona, CreateSandboxFromSnapshotParams
daytona = Daytona()sandbox = daytona.create(CreateSandboxFromSnapshotParams(snapshot="windows-small"))import { Daytona } from '@daytona/sdk'
const daytona = new Daytona()const sandbox = await daytona.create({ snapshot: 'windows-small' })require 'daytona'
daytona = Daytona::Daytona.newsandbox = daytona.create( Daytona::CreateSandboxFromSnapshotParams.new(snapshot: 'windows-small'))package main
import ( "context"
"github.com/daytona/clients/sdk-go/pkg/daytona" "github.com/daytona/clients/sdk-go/pkg/types")
func main() { client, _ := daytona.NewClient() ctx := context.Background() _, _ = client.Create(ctx, types.SnapshotParams{ Snapshot: "windows-small", })}import io.daytona.sdk.Daytona;import io.daytona.sdk.Sandbox;import io.daytona.sdk.model.CreateSandboxFromSnapshotParams;
public class App { public static void main(String[] args) { try (Daytona daytona = new Daytona()) { CreateSandboxFromSnapshotParams params = new CreateSandboxFromSnapshotParams(); params.setSnapshot("windows-small"); Sandbox sandbox = daytona.create(params); } }}daytona create --snapshot windows-smallcurl 'https://app.daytona.io/api/sandbox' \ --request POST \ --header 'Content-Type: application/json' \ --header 'Authorization: Bearer YOUR_API_KEY' \ --data '{ "snapshot": "windows-small"}'To create Windows sandboxes from your own environment, prepare a Windows sandbox and create a filesystem snapshot or a memory snapshot from it.
Desktop
Section titled “Desktop”Windows sandboxes support Computer Use on the Windows desktop: screenshots, mouse and keyboard input, display and window information, the accessibility tree, and screen recordings.
The toolbox runs commands with the Windows command prompt by default. To run commands with another shell, such as Windows PowerShell or PowerShell 7, set the following environment variable in the sandbox. The toolbox looks the value up on the PATH and falls back to the command prompt if it is not found. If the toolbox cannot find the command prompt, it uses Windows PowerShell.
| Environment variable | Value | Shell |
|---|---|---|
DAYTONA_SHELL | cmd.exe | Command prompt (default) |
DAYTONA_SHELL | powershell.exe | Windows PowerShell |
DAYTONA_SHELL | pwsh.exe | PowerShell 7 |
The command prompt rejects command lines longer than 8191 characters. For longer commands, use a session command or PowerShell.
Filesystem persistence
Section titled “Filesystem persistence”Filesystem persistence keeps the contents of a sandbox’s disk: files, installed programs, cloned repositories, and build artifacts. A sandbox with a preserved filesystem starts with its environment intact, with nothing to reinstall or rebuild.
Windows sandboxes preserve their filesystem across stop and start and filesystem snapshots created from a sandbox. An ephemeral sandbox is deleted on stop, so its filesystem is not kept.
from daytona import Daytona, CreateSandboxFromSnapshotParams
daytona = Daytona()sandbox = daytona.create(CreateSandboxFromSnapshotParams(snapshot="windows-small"))
# Write a file to the filesystemsandbox.fs.upload_file(b"done", "setup.txt")
# Stop clears memory and moves the filesystem to nearby storagesandbox.stop()
# Start restores the filesystem and boots the sandboxsandbox.start()content = sandbox.fs.download_file("setup.txt")print(content.decode()) # doneimport { Daytona } from '@daytona/sdk'
const daytona = new Daytona()const sandbox = await daytona.create({ snapshot: 'windows-small' })
// Write a file to the filesystemawait sandbox.fs.uploadFile(Buffer.from('done'), 'setup.txt')
// Stop clears memory and moves the filesystem to nearby storageawait sandbox.stop()
// Start restores the filesystem and boots the sandboxawait sandbox.start()const content = await sandbox.fs.downloadFile('setup.txt')console.log(content.toString()) // donerequire 'daytona'
daytona = Daytona::Daytona.newsandbox = daytona.create(Daytona::CreateSandboxFromSnapshotParams.new(snapshot: 'windows-small'))
# Write a file to the filesystemsandbox.fs.upload_file('done', 'setup.txt')
# Stop clears memory and moves the filesystem to nearby storagesandbox.stop
# Start restores the filesystem and boots the sandboxsandbox.startcontent = sandbox.fs.download_file('setup.txt')puts content # donepackage main
import ( "context" "fmt"
"github.com/daytona/clients/sdk-go/pkg/daytona" "github.com/daytona/clients/sdk-go/pkg/types")
func main() { client, _ := daytona.NewClient() ctx := context.Background() sandbox, err := client.Create(ctx, types.SnapshotParams{Snapshot: "windows-small"}) if err != nil { panic(err) }
// Write a file to the filesystem if err := sandbox.FileSystem.UploadFile(ctx, []byte("done"), "setup.txt"); err != nil { panic(err) }
// Stop clears memory and moves the filesystem to nearby storage if err := sandbox.Stop(ctx); err != nil { panic(err) }
// Start restores the filesystem and boots the sandbox if err := sandbox.Start(ctx); err != nil { panic(err) } content, err := sandbox.FileSystem.DownloadFile(ctx, "setup.txt", nil) if err != nil { panic(err) } fmt.Println(string(content)) // done}import io.daytona.sdk.Daytona;import io.daytona.sdk.Sandbox;import io.daytona.sdk.model.CreateSandboxFromSnapshotParams;
public class App { public static void main(String[] args) { try (Daytona daytona = new Daytona()) { CreateSandboxFromSnapshotParams params = new CreateSandboxFromSnapshotParams(); params.setSnapshot("windows-small"); Sandbox sandbox = daytona.create(params);
// Write a file to the filesystem sandbox.fs.uploadFile("done".getBytes(), "setup.txt");
// Stop clears memory and moves the filesystem to nearby storage sandbox.stop();
// Start restores the filesystem and boots the sandbox sandbox.start(); byte[] content = sandbox.fs.downloadFile("setup.txt"); System.out.println(new String(content)); // done } }}daytona create --snapshot windows-small
# Write a file to the filesystemdaytona exec [SANDBOX_ID] -- cmd /c "echo done> setup.txt"
# Stop clears memory and moves the filesystem to nearby storagedaytona stop [SANDBOX_ID]
# Start restores the filesystem and boots the sandboxdaytona start [SANDBOX_ID]daytona exec [SANDBOX_ID] -- type setup.txtcurl 'https://app.daytona.io/api/sandbox' \ --request POST \ --header 'Content-Type: application/json' \ --header 'Authorization: Bearer YOUR_API_KEY' \ --data '{"snapshot": "windows-small"}'
# Write a file to the filesystemcurl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/files/upload-v2?path=setup.txt' \ --request POST \ --header 'Authorization: Bearer YOUR_API_KEY' \ --form 'file=@setup.txt'
# Stop clears memory and moves the filesystem to nearby storagecurl 'https://app.daytona.io/api/sandbox/{sandboxId}/stop' \ --request POST \ --header 'Authorization: Bearer YOUR_API_KEY'
# Start restores the filesystem and boots the sandboxcurl 'https://app.daytona.io/api/sandbox/{sandboxId}/start' \ --request POST \ --header 'Authorization: Bearer YOUR_API_KEY'
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/files/download?path=setup.txt' \ --header 'Authorization: Bearer YOUR_API_KEY'Memory persistence
Section titled “Memory persistence”Memory persistence keeps the runtime state of a sandbox: running processes, open applications, and everything loaded in RAM. A sandbox with preserved memory continues from the point it was frozen, with processes still running, instead of starting from a clean boot.
Windows sandboxes preserve their memory across pause and resume, memory snapshots created from a sandbox, and forks. Memory state is cleared on every stop.
The following example creates a Windows sandbox. Pause requires a non-ephemeral Windows sandbox in the Started state.
from daytona import Daytona, CreateSandboxFromSnapshotParams, SessionExecuteRequest
daytona = Daytona()sandbox = daytona.create(CreateSandboxFromSnapshotParams(snapshot="windows-small"))
# Start a process that runs in the backgroundsandbox.process.create_session("keepalive")response = sandbox.process.execute_session_command( "keepalive", SessionExecuteRequest(command="ping -n 3600 127.0.0.1", run_async=True),)
# Pause keeps the filesystem and memorysandbox.pause()
# Start resumes every process from the point where the sandbox pausedsandbox.start()command = sandbox.process.get_session_command("keepalive", response.cmd_id)print(command.exit_code) # None: the process is still runningimport { Daytona } from '@daytona/sdk'
const daytona = new Daytona()const sandbox = await daytona.create({ snapshot: 'windows-small' })
// Start a process that runs in the backgroundawait sandbox.process.createSession('keepalive')const response = await sandbox.process.executeSessionCommand('keepalive', { command: 'ping -n 3600 127.0.0.1', runAsync: true,})
// Pause keeps the filesystem and memoryawait sandbox.pause()
// Start resumes every process from the point where the sandbox pausedawait sandbox.start()const command = await sandbox.process.getSessionCommand('keepalive', response.cmdId)console.log(command.exitCode) // undefined: the process is still runningrequire 'daytona'
daytona = Daytona::Daytona.newsandbox = daytona.create(Daytona::CreateSandboxFromSnapshotParams.new(snapshot: 'windows-small'))
# Start a process that runs in the backgroundsandbox.process.create_session('keepalive')response = sandbox.process.execute_session_command( session_id: 'keepalive', req: Daytona::SessionExecuteRequest.new(command: 'ping -n 3600 127.0.0.1', run_async: true))
# Pause keeps the filesystem and memorysandbox.pause
# Start resumes every process from the point where the sandbox pausedsandbox.startcommand = sandbox.process.get_session_command(session_id: 'keepalive', command_id: response.cmd_id)puts command.exit_code.inspect # nil: the process is still runningpackage main
import ( "context" "fmt"
"github.com/daytona/clients/sdk-go/pkg/daytona" "github.com/daytona/clients/sdk-go/pkg/types")
func main() { client, _ := daytona.NewClient() ctx := context.Background() sandbox, err := client.Create(ctx, types.SnapshotParams{Snapshot: "windows-small"}) if err != nil { panic(err) }
// Start a process that runs in the background if err := sandbox.Process.CreateSession(ctx, "keepalive"); err != nil { panic(err) } response, err := sandbox.Process.ExecuteSessionCommand(ctx, "keepalive", "ping -n 3600 127.0.0.1", true, false) if err != nil { panic(err) }
// Pause keeps the filesystem and memory if err := sandbox.Pause(ctx); err != nil { panic(err) }
// Start resumes every process from the point where the sandbox paused if err := sandbox.Start(ctx); err != nil { panic(err) } command, err := sandbox.Process.GetSessionCommand(ctx, "keepalive", response["cmdId"].(string)) if err != nil { panic(err) } fmt.Println(command["exitCode"]) // <nil>: the process is still running}import io.daytona.sdk.Daytona;import io.daytona.sdk.Sandbox;import io.daytona.sdk.model.Command;import io.daytona.sdk.model.CreateSandboxFromSnapshotParams;import io.daytona.sdk.model.SessionExecuteRequest;import io.daytona.sdk.model.SessionExecuteResponse;
public class App { public static void main(String[] args) { try (Daytona daytona = new Daytona()) { CreateSandboxFromSnapshotParams params = new CreateSandboxFromSnapshotParams(); params.setSnapshot("windows-small"); Sandbox sandbox = daytona.create(params);
// Start a process that runs in the background sandbox.process.createSession("keepalive"); SessionExecuteResponse response = sandbox.process.executeSessionCommand( "keepalive", new SessionExecuteRequest("ping -n 3600 127.0.0.1", true) );
// Pause keeps the filesystem and memory sandbox.pause();
// Start resumes every process from the point where the sandbox paused sandbox.start(); Command command = sandbox.process.getSessionCommand("keepalive", response.getCmdId()); System.out.println(command.getExitCode()); // null: the process is still running } }}daytona create --snapshot windows-small
# Pause keeps the filesystem and memorydaytona pause [SANDBOX_ID]
# Start resumes every process from the point where the sandbox pauseddaytona start [SANDBOX_ID]curl 'https://app.daytona.io/api/sandbox' \ --request POST \ --header 'Content-Type: application/json' \ --header 'Authorization: Bearer YOUR_API_KEY' \ --data '{"snapshot": "windows-small"}'
# Start a process that runs in the backgroundcurl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/process/session' \ --request POST \ --header 'Content-Type: application/json' \ --header 'Authorization: Bearer YOUR_API_KEY' \ --data '{"sessionId": "keepalive"}'
curl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/process/session/keepalive/exec' \ --request POST \ --header 'Content-Type: application/json' \ --header 'Authorization: Bearer YOUR_API_KEY' \ --data '{"command": "ping -n 3600 127.0.0.1", "runAsync": true}'
# Pause keeps the filesystem and memorycurl 'https://app.daytona.io/api/sandbox/{sandboxId}/pause' \ --request POST \ --header 'Authorization: Bearer YOUR_API_KEY'
# Start resumes every process from the point where the sandbox pausedcurl 'https://app.daytona.io/api/sandbox/{sandboxId}/start' \ --request POST \ --header 'Authorization: Bearer YOUR_API_KEY'
# The command has no exitCode while the process is still runningcurl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/process/session/keepalive/command/{commandId}' \ --header 'Authorization: Bearer YOUR_API_KEY'Memory snapshot
Section titled “Memory snapshot”A memory snapshot, also called a hot snapshot, saves the filesystem and memory of a started Windows sandbox. A sandbox created from a memory snapshot starts with its processes and open applications already running. Enable the include memory option when you create the snapshot.
A memory snapshot requires a Windows sandbox in the Started state. The SDKs do not expose the include memory option, so use the API.
curl 'https://app.daytona.io/api/sandbox/{sandboxIdOrName}/snapshot' \ --request POST \ --header 'Content-Type: application/json' \ --header 'Authorization: Bearer YOUR_API_KEY' \ --data '{ "name": "my-windows-hot-snapshot", "includeMemory": true}'Filesystem snapshot
Section titled “Filesystem snapshot”A filesystem snapshot, also called a cold snapshot, saves the filesystem of a stopped Windows sandbox. A snapshot without the include memory option is a filesystem snapshot.
A filesystem snapshot requires a Windows sandbox in the Stopped state. An ephemeral sandbox is deleted on stop, so it cannot take a filesystem snapshot.
from daytona import Daytona, CreateSandboxFromSnapshotParams
daytona = Daytona()sandbox = daytona.create(CreateSandboxFromSnapshotParams(snapshot="windows-small"))
# Write a file to the filesystemsandbox.fs.upload_file(b"done", "setup.txt")
# A filesystem snapshot requires a stopped sandboxsandbox.stop()sandbox.create_snapshot("my-windows-snapshot")
# A sandbox created from the snapshot starts with the same filesystemnew_sandbox = daytona.create(CreateSandboxFromSnapshotParams(snapshot="my-windows-snapshot"))content = new_sandbox.fs.download_file("setup.txt")print(content.decode()) # doneimport { Daytona } from '@daytona/sdk'
const daytona = new Daytona()const sandbox = await daytona.create({ snapshot: 'windows-small' })
// Write a file to the filesystemawait sandbox.fs.uploadFile(Buffer.from('done'), 'setup.txt')
// A filesystem snapshot requires a stopped sandboxawait sandbox.stop()await sandbox.createSnapshot('my-windows-snapshot')
// A sandbox created from the snapshot starts with the same filesystemconst newSandbox = await daytona.create({ snapshot: 'my-windows-snapshot' })const content = await newSandbox.fs.downloadFile('setup.txt')console.log(content.toString()) // donerequire 'daytona'
daytona = Daytona::Daytona.newsandbox = daytona.create(Daytona::CreateSandboxFromSnapshotParams.new(snapshot: 'windows-small'))
# Write a file to the filesystemsandbox.fs.upload_file('done', 'setup.txt')
# A filesystem snapshot requires a stopped sandboxsandbox.stopsandbox.create_snapshot(name: 'my-windows-snapshot')
# A sandbox created from the snapshot starts with the same filesystemnew_sandbox = daytona.create(Daytona::CreateSandboxFromSnapshotParams.new(snapshot: 'my-windows-snapshot'))content = new_sandbox.fs.download_file('setup.txt')puts content # donepackage main
import ( "context" "fmt"
"github.com/daytona/clients/sdk-go/pkg/daytona" "github.com/daytona/clients/sdk-go/pkg/types")
func main() { client, _ := daytona.NewClient() ctx := context.Background() sandbox, err := client.Create(ctx, types.SnapshotParams{Snapshot: "windows-small"}) if err != nil { panic(err) }
// Write a file to the filesystem if err := sandbox.FileSystem.UploadFile(ctx, []byte("done"), "setup.txt"); err != nil { panic(err) }
// A filesystem snapshot requires a stopped sandbox if err := sandbox.Stop(ctx); err != nil { panic(err) } if err := sandbox.CreateSnapshot(ctx, "my-windows-snapshot"); err != nil { panic(err) }
// A sandbox created from the snapshot starts with the same filesystem newSandbox, err := client.Create(ctx, types.SnapshotParams{Snapshot: "my-windows-snapshot"}) if err != nil { panic(err) } content, err := newSandbox.FileSystem.DownloadFile(ctx, "setup.txt", nil) if err != nil { panic(err) } fmt.Println(string(content)) // done}import io.daytona.sdk.Daytona;import io.daytona.sdk.Sandbox;import io.daytona.sdk.model.CreateSandboxFromSnapshotParams;
public class App { public static void main(String[] args) { try (Daytona daytona = new Daytona()) { CreateSandboxFromSnapshotParams params = new CreateSandboxFromSnapshotParams(); params.setSnapshot("windows-small"); Sandbox sandbox = daytona.create(params);
// Write a file to the filesystem sandbox.fs.uploadFile("done".getBytes(), "setup.txt");
// A filesystem snapshot requires a stopped sandbox sandbox.stop(); sandbox.createSnapshot("my-windows-snapshot");
// A sandbox created from the snapshot starts with the same filesystem CreateSandboxFromSnapshotParams fromSnapshot = new CreateSandboxFromSnapshotParams(); fromSnapshot.setSnapshot("my-windows-snapshot"); Sandbox newSandbox = daytona.create(fromSnapshot); byte[] content = newSandbox.fs.downloadFile("setup.txt"); System.out.println(new String(content)); // done } }}curl 'https://app.daytona.io/api/sandbox' \ --request POST \ --header 'Content-Type: application/json' \ --header 'Authorization: Bearer YOUR_API_KEY' \ --data '{"snapshot": "windows-small"}'
# Write a file to the filesystemcurl 'https://proxy.app.daytona.io/toolbox/{sandboxId}/files/upload-v2?path=setup.txt' \ --request POST \ --header 'Authorization: Bearer YOUR_API_KEY' \ --form 'file=@setup.txt'
# A filesystem snapshot requires a stopped sandboxcurl 'https://app.daytona.io/api/sandbox/{sandboxId}/stop' \ --request POST \ --header 'Authorization: Bearer YOUR_API_KEY'
curl 'https://app.daytona.io/api/sandbox/{sandboxId}/snapshot' \ --request POST \ --header 'Content-Type: application/json' \ --header 'Authorization: Bearer YOUR_API_KEY' \ --data '{ "name": "my-windows-snapshot", "includeMemory": false}'
# A sandbox created from the snapshot starts with the same filesystemcurl 'https://app.daytona.io/api/sandbox' \ --request POST \ --header 'Content-Type: application/json' \ --header 'Authorization: Bearer YOUR_API_KEY' \ --data '{"snapshot": "my-windows-snapshot"}'
curl 'https://proxy.app.daytona.io/toolbox/{newSandboxId}/files/download?path=setup.txt' \ --header 'Authorization: Bearer YOUR_API_KEY'Lifecycle
Section titled “Lifecycle”Every Windows sandbox moves through a lifecycle. A Windows sandbox can have several different states. Each state reflects the status of your sandbox. A Windows sandbox transitions between states in response to user actions, or automatically when one of its timeouts elapses.
| Feature | Persistent | Ephemeral |
|---|---|---|
| Stop and start | ✓ | ✗ |
| Pause and resume | ✓ | ✗ |
| Fork | ✓ | ✓ |
| Archive | ✗ | ✗ |
| Delete | ✓ | ✓ |
| Filesystem persistence | ✓ | ✗ |
| Memory persistence | ✓ | ✗ |
| Memory snapshot | ✓ | ✓ |
| Filesystem snapshot | ✓ | ✗ |
| Desktop | ✓ Computer Use | ✓ Computer Use |
| State | Description |
|---|---|
| Pulling Snapshot | The sandbox is pulling a snapshot. |
| Creating | The sandbox is being created. |
| Starting | The sandbox is starting. |
| Started | The sandbox is running and accepts requests. |
| Stopping | The sandbox is stopping and does not accept new requests. |
| Stopped | The sandbox is stopped. The filesystem is kept and memory is cleared. |
| Pausing | The sandbox is pausing. |
| Paused | The sandbox is paused with its filesystem and memory preserved. |
| Resuming | The sandbox is resuming from the paused state. |
| Restoring | The sandbox is being restored. |
| Resizing | The sandbox resources are being changed. |
| Snapshotting | The sandbox is creating a memory snapshot or a filesystem snapshot. |
| Forking | The sandbox is being forked. |
| Deleting | The sandbox is being deleted. |
| Deleted | The sandbox is deleted. |
| Error | The sandbox hit an error. A recoverable error can be recovered. |
| Initial state | Target state | Trigger |
|---|---|---|
| Started | Stopping | A stop is requested, or the auto-stop interval elapses. |
| Stopping | Stopped | The shutdown completes. The filesystem is kept and memory is cleared. |
| Stopped | Starting | A start is requested. |
| Started | Pausing | A pause is requested, or the auto-pause interval elapses. |
| Pausing | Paused | The filesystem and memory are preserved. |
| Paused | Resuming | A start is requested on a paused sandbox. |
| Paused | Stopping | A stop is requested on a paused sandbox. |
| Resuming | Started | The sandbox resumes from memory and is running. |
| Started | Snapshotting | A memory snapshot is requested. |
| Stopped | Snapshotting | A filesystem snapshot is requested. |
| Started | Forking | A fork is requested. |
| Started | Deleting | A delete is requested, or an ephemeral sandbox is stopped. |
| Stopped | Deleting | A delete is requested, or the auto-delete interval elapses. |
| Deleting | Deleted | The sandbox is removed and its resources are released. |
Wait for state
Section titled “Wait for state”Wait until a Windows sandbox reaches the started or stopped state. Each method takes a timeout in seconds.
sandbox.wait_for_sandbox_start(timeout=60)sandbox.wait_for_sandbox_stop(timeout=60)await sandbox.waitUntilStarted(60)await sandbox.waitUntilStopped(60)sandbox.wait_for_sandbox_start(60)sandbox.wait_for_sandbox_stop(60)err := sandbox.WaitForStart(ctx, 60*time.Second)err = sandbox.WaitForStop(ctx, 60*time.Second)sandbox.waitUntilStarted(60);sandbox.waitUntilStopped(60);Stop / start
Section titled “Stop / start”Stop a sandbox. The sandbox moves to the stopped state when shutdown completes. While a stop is in progress, the sandbox is in the stopping state and does not accept new requests.
Stopping shuts down the virtual machine while preserving the filesystem. Memory state is cleared. To preserve running process state without consuming CPU, use pause / resume.
Start a sandbox.
- Go to Daytona Sandboxes ↗
- Click the stop icon (⏹) next to the sandbox you want to stop
- Click the start icon next to the sandbox you want to start
sandbox.stop()sandbox.start()await sandbox.stop()await sandbox.start()sandbox.stopsandbox.startsandbox.Stop(ctx)sandbox.Start(ctx)sandbox.stop();sandbox.start();daytona stop [SANDBOX_ID] | [SANDBOX_NAME]daytona start [SANDBOX_ID] | [SANDBOX_NAME]curl 'https://app.daytona.io/api/sandbox/{sandboxIdOrName}/stop' \ --request POST \ --header 'Authorization: Bearer YOUR_API_KEY'
curl 'https://app.daytona.io/api/sandbox/{sandboxIdOrName}/start' \ --request POST \ --header 'Authorization: Bearer YOUR_API_KEY'Pause / resume
Section titled “Pause / resume”Pause and resume a sandbox.
The filesystem and memory state are preserved, and CPU is no longer consumed.
sandbox.pause()
# Resume the paused sandboxsandbox.start()await sandbox.pause()
// Resume the paused sandboxawait sandbox.start()sandbox.pause
# Resume the paused sandboxsandbox.startsandbox.Pause(ctx)
// Resume the paused sandboxsandbox.Start(ctx)sandbox.pause();
// Resume the paused sandboxsandbox.start();daytona pause [SANDBOX_ID] | [SANDBOX_NAME]
# Resume the paused sandboxdaytona start [SANDBOX_ID] | [SANDBOX_NAME]curl 'https://app.daytona.io/api/sandbox/{sandboxIdOrName}/pause' \ --request POST \ --header 'Authorization: Bearer YOUR_API_KEY'
# Resume the paused sandboxcurl 'https://app.daytona.io/api/sandbox/{sandboxIdOrName}/start' \ --request POST \ --header 'Authorization: Bearer YOUR_API_KEY'Fork a sandbox.
Forking creates a duplicate of a Windows sandbox’s filesystem and memory state in a new sandbox. The forked sandbox is fully independent: it can be started, stopped, and deleted without affecting the original.
Daytona tracks the parent-child relationship in a fork tree, so you can trace a fork’s lineage back to the sandbox it was created from. You can fork a fork to build branches. The parent sandbox cannot be deleted while it has active fork children.
- Go to Daytona Sandboxes ↗
- Click the three-dot menu (⋮) next to the started Windows sandbox you want to fork
- Select
forked = sandbox.fork(name="my-forked-sandbox")const forked = await sandbox.fork({ name: 'my-forked-sandbox' })forked = sandbox.fork(name: 'my-forked-sandbox')name := "my-forked-sandbox"forked, err := sandbox.Fork(ctx, &name)if err != nil { return err}Sandbox forked = sandbox.fork("my-forked-sandbox", 60);curl 'https://app.daytona.io/api/sandbox/{sandboxIdOrName}/fork' \ --request POST \ --header 'Content-Type: application/json' \ --header 'Authorization: Bearer YOUR_API_KEY' \ --data '{ "name": "my-forked-sandbox"}'
# List the direct forks of a sandboxcurl 'https://app.daytona.io/api/sandbox/{sandboxIdOrName}/forks' \ --header 'Authorization: Bearer YOUR_API_KEY'
# Get the parent of a forkcurl 'https://app.daytona.io/api/sandbox/{sandboxIdOrName}/parent' \ --header 'Authorization: Bearer YOUR_API_KEY'
# Get the ancestor chain of a forkcurl 'https://app.daytona.io/api/sandbox/{sandboxIdOrName}/ancestors' \ --header 'Authorization: Bearer YOUR_API_KEY'Delete
Section titled “Delete”Delete a sandbox.
- Go to Daytona Sandboxes ↗
- Click next to the sandbox you want to delete
sandbox.delete()
# Block until the sandbox is deletedsandbox.delete(timeout=60, wait=True)await sandbox.delete()
// Block until the sandbox is deletedawait sandbox.delete(60, true)sandbox.delete
# Block until the sandbox is deletedsandbox.delete(60, wait: true)err = sandbox.Delete(ctx)
// Block until the sandbox is deletederr = sandbox.DeleteAndWait(ctx, 60*time.Second)sandbox.delete();
// Block until the sandbox is deletedsandbox.delete(60, true);daytona delete [SANDBOX_ID] | [SANDBOX_NAME]curl 'https://app.daytona.io/api/sandbox/{sandboxIdOrName}' \ --request DELETE \ --header 'Authorization: Bearer YOUR_API_KEY'Timeouts
Section titled “Timeouts”Daytona stops, pauses, or deletes a Windows sandbox when a timeout elapses. Each timeout is set in minutes. Zero disables auto-stop, auto-pause, and wall-clock TTL. Zero does not disable auto-delete: auto-delete set to zero deletes the sandbox as soon as it stops. To disable auto-delete, set it to -1. Windows sandboxes do not support auto-archive.
| Interval | Default | Action |
|---|---|---|
| Auto-stop | Disabled when auto-pause is active | Stops the sandbox after inactivity. |
| Auto-pause | 60 minutes when neither interval is set | Pauses the sandbox after inactivity. |
| Auto-delete | Not set | Deletes a stopped sandbox. |
| Wall-clock TTL | Not set | Deletes the sandbox at a fixed deadline, in any state. |
Auto-pause
Section titled “Auto-pause”The auto-pause interval sets the amount of time after which an idle VM sandbox is automatically paused. Auto-pause applies only to VM sandboxes and is mutually exclusive with the auto-stop interval: at most one of the two intervals may be non-zero. Ephemeral sandboxes cannot have auto-pause enabled.
The interval is set in minutes:
0: disables the auto-pause functionality- if neither auto-pause nor auto-stop is set, non-ephemeral sandbox classes that support pausing default to an auto-pause interval of 60 minutes with auto-stop disabled
The sandbox pauses after no new events occur for the specified interval. Events include sandbox state changes and interactions with the sandbox through the SDK. Interactions through sandbox previews do not reset the timer.
from daytona import CreateSandboxFromSnapshotParams
sandbox = daytona.create(CreateSandboxFromSnapshotParams( snapshot="windows-small", auto_pause_interval=60,))
# Change the interval on an existing sandboxsandbox.set_auto_pause_interval(30)const sandbox = await daytona.create({ snapshot: 'windows-small', autoPauseInterval: 60,})
// Change the interval on an existing sandboxawait sandbox.setAutoPauseInterval(30)sandbox = daytona.create( Daytona::CreateSandboxFromSnapshotParams.new( snapshot: 'windows-small', auto_pause_interval: 60 ))
# Change the interval on an existing sandboxsandbox.auto_pause_interval = 30autoPauseInterval := 60sandbox, err := client.Create(ctx, types.SnapshotParams{ Snapshot: "windows-small", SandboxBaseParams: types.SandboxBaseParams{ AutoPauseInterval: &autoPauseInterval, },})CreateSandboxFromSnapshotParams params = new CreateSandboxFromSnapshotParams();params.setSnapshot("windows-small");params.setAutoPauseInterval(60);Sandbox sandbox = daytona.create(params);
// Change the interval on an existing sandboxsandbox.setAutoPauseInterval(30);Wall-clock TTL
Section titled “Wall-clock TTL”The wall-clock TTL (time-to-live) sets a hard upper bound on how long a sandbox may exist. Unlike the auto-delete interval, which counts time only while the sandbox is stopped, TTL runs as wall-clock time from creation (or from the moment you last set it) and destroys the sandbox in any state: started, stopped, paused, or archived.
Set ttl_minutes when creating a sandbox, or update it later. The value is in minutes:
0: disables the TTL- if not set, the sandbox has no TTL deadline
Calling set_ttl after creation resets the deadline from the current moment. Use wall-clock TTL for agent sessions, CI jobs, and any sandbox that must not outlive a fixed deadline.
sandbox = daytona.create(CreateSandboxFromSnapshotParams( snapshot="windows-small", ttl_minutes=120,))
# Reset the deadline to 60 minutes from nowsandbox.set_ttl(60)const sandbox = await daytona.create({ snapshot: 'windows-small', ttlMinutes: 120,})
// Reset the deadline to 60 minutes from nowawait sandbox.setTtl(60)sandbox = daytona.create( Daytona::CreateSandboxFromSnapshotParams.new( snapshot: 'windows-small', ttl_minutes: 120 ))
# Reset the deadline to 60 minutes from nowsandbox.ttl_minutes = 60ttlMinutes := 120sandbox, err := client.Create(ctx, types.SnapshotParams{ Snapshot: "windows-small", SandboxBaseParams: types.SandboxBaseParams{ TtlMinutes: &ttlMinutes, },})CreateSandboxFromSnapshotParams params = new CreateSandboxFromSnapshotParams();params.setSnapshot("windows-small");params.setTtlMinutes(120);Sandbox sandbox = daytona.create(params);
// Reset the deadline to 60 minutes from nowsandbox.setTtl(60);daytona create --snapshot windows-small --ttl 120curl 'https://app.daytona.io/api/sandbox' \ --request POST \ --header 'Content-Type: application/json' \ --header 'Authorization: Bearer YOUR_API_KEY' \ --data '{ "snapshot": "windows-small", "ttlMinutes": 120}'
# Reset the deadline to 60 minutes from nowcurl 'https://app.daytona.io/api/sandbox/{sandboxIdOrName}/ttl/60' \ --request POST \ --header 'Authorization: Bearer YOUR_API_KEY'