Cua Docs

Manage local sandbox lifecycle

Create, reconnect to, list, and clean up local sandboxes with the Sandbox SDK.

These patterns run on your own machine with local=True. Choose a compatible host and runtime before running them. They are operation patterns, not a complete installation tutorial.

For the ownership model, read Sandbox lifecycle. For Fleet, use Create a sandbox pool with Python: releasing a claim and deleting pool capacity are separate operations.

Create and auto-destroy a sandbox#

Use Sandbox.ephemeral for scripts, CI, and one-off tasks.

import asyncio
from cua import Sandbox, Image
 
async def main():
    async with Sandbox.ephemeral(Image.linux(), local=True) as sb:
        result = await sb.shell.run('echo hello')
        print(result.stdout)  # 'hello\n'
    # sandbox deleted here
 
asyncio.run(main())

Sandbox.ephemeral is auto-destroyed when the async with block exits. Its context manager tears the sandbox down automatically.

Create a persistent sandbox#

Use Sandbox.create when the sandbox must outlive the script. Call await sb.disconnect() to drop the connection while the sandbox keeps running.

sb = await Sandbox.create(Image.linux(), name='my-dev-sandbox', local=True)
await sb.shell.run('apt-get install -y vim')
await sb.disconnect()  # sandbox keeps running

Delete the sandbox when you are done with it.

async with Sandbox.connect('my-dev-sandbox', local=True) as sb:
    await sb.destroy()
MethodEffectWhen
await sb.disconnect()keeps runningreconnect later
await sb.destroy()permanently destroyeddone with it
await Sandbox.delete(name)permanently destroyed (by name, no connect)classmethod

Reconnect to a running sandbox#

Use Sandbox.connect to attach to an already-running sandbox.

Sandbox.connect never starts or stops the sandbox. It only manages the network connection.

Reconnect by name.

async with Sandbox.connect('my-dev-sandbox', local=True) as sb:
    result = await sb.shell.run('vim --version')
    print(result.stdout)

Sandbox.connect supports both await and async with. Its context manager calls disconnect() automatically, so the sandbox keeps running after the connection closes.

async with Sandbox.connect('my-sandbox', local=True) as sb:
    await sb.shell.run('echo reconnected')
# connection dropped, sandbox keeps running

List running sandboxes#

List available sandboxes, then filter to local runtimes when needed.

sandboxes = await Sandbox.list(local=True)
for info in sandboxes:
    print(info.name, info.os_type, info.status)

Choose a local runtime#

Pass local=True to use a runtime on your own machine. Cua selects a local runtime from the image type: Docker for Linux containers, QEMU for Linux VMs, Lume for macOS VMs, and QEMU or Hyper-V for Windows VMs. Selection still requires a compatible host and usable image; it is not a boot check. See the runtime support reference before choosing a backend.

# local Docker desktop container
async with Sandbox.ephemeral(
    Image.linux(kind='container'),
    local=True,
) as sb:
    ...