Metadata-Version: 2.5
Name: daytona-use-computer
Version: 0.0.48
Summary: Python SDK for use.computer macOS sandboxes
Project-URL: Homepage, https://use.computer
Project-URL: Documentation, https://api.use.computer/docs
Project-URL: Repository, https://github.com/daytona/use-computer-sdk
Author: use.computer
Keywords: automation,computer-use,macos,sandbox,vnc
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Typing :: Typed
Requires-Python: >=3.10
Requires-Dist: httpx>=0.27
Provides-Extra: agents
Requires-Dist: anthropic>=0.86; extra == 'agents'
Requires-Dist: google-genai>=1; extra == 'agents'
Requires-Dist: litellm>=1; extra == 'agents'
Requires-Dist: openai>=1; extra == 'agents'
Requires-Dist: pillow>=10; extra == 'agents'
Requires-Dist: tinker-cookbook>=0.1.0; (python_full_version >= '3.11') and extra == 'agents'
Requires-Dist: tinker>=0.14.0; (python_full_version >= '3.11') and extra == 'agents'
Description-Content-Type: text/markdown

# use-computer Python SDK (`daytona-use-computer`)

use.computer gives you macOS sandboxes: VMs on dedicated Apple M4 Mac minis that you reserve for 24 hours or more, up to 2 VMs at a time per Mac.

```bash
pip install daytona-use-computer
export USE_COMPUTER_API_KEY=uc_live_...
```

Optional agent integrations are installed explicitly:

```bash
pip install "daytona-use-computer[agents]"        # computer-use agents and provider SDKs
```

Base installs only the SDK client and `httpx`. The `agents` extra installs the agent runtime plus model-provider dependencies (Anthropic, OpenAI, Gemini, LiteLLM).

## Quickstart

Flow: sign up → $100 starter credit → reserve a Mac mini (dashboard, or `client.reserve(hours=24)` in the SDK) → `create()` a macOS sandbox → drive it (mouse, keyboard, screenshot, exec, files, recording, UI tree, VNC) → `delete()`. Reservations cost $1.91/hour per Mac; the starter credit pays for them.

```python
from use_computer import Computer

client = Computer()

# 1. Reserve one M4 Mac Mini for 24 hours
reservation = client.reserve(hours=24, mac_model="m4")

# 2. Launch a macOS sandbox on the reserved Mac
with client.create(reservation_id=reservation.id) as mac:
    # 3. Drive the macOS sandbox
    mac.exec("open -a Safari")
    mac.keyboard.type("hello from use.computer")
    mac.mouse.click(500, 500)
    png = mac.screenshot.take_full_screen()
    print("Sandbox:", mac.sandbox_id)
    # Open this sandbox's viewer from the use.computer dashboard.
```

Never print or share `vnc_url`: it contains your account API key. Open the viewer from the dashboard instead.

The optional `mac_model` picks the Mac: `"m4"` (the default; 10 vCPU and 16 GiB RAM) or `"m4-pro"` (12 or more vCPU and 24 GiB RAM). `reservation.mac_model` reports it.

Each `create()` can set `cpu`, `memory_gib`, and `disk_gib`. Omitted fields use the Mac's warm VM size, which is 5 vCPU and 8 GiB RAM today and starts right away. Any other size boots a new VM, which can take up to 5 minutes, so `create()` waits up to 10 minutes when you set any of them. A Mac runs at most 2 sandboxes at a time, and their sizes must fit in the Mac. The sandbox reports `cpu`, `memory_gib`, `disk_gib`, and `boot` (`"warm"` or `"cold"`):

```python
with client.create(reservation_id=reservation.id, cpu=8, memory_gib=12) as mac:
    print(mac.cpu, mac.memory_gib, mac.boot)
```

If the size does not fit, `create()` raises `SandboxResourcesError`. Its `code` is `invalid_resources`, `resources_exceed_mac`, `sandbox_limit_reached`, or `insufficient_capacity`, and its `message` explains the refusal. `AsyncComputer` accepts the same options. Check `Computer().platforms(reservation_id=...)["macos"]["capacity"]` for the selected reservation's `max` and `used` counts.

The older `vm_layout` reservation option still works but is deprecated; the SDK sends it only when you pass it. `"split"` (the server default) allows two sandboxes, and `"whole"` allows one sandbox at a time.

When `ephemeral` is omitted, the server default is the reservation lifetime. Explicit `ephemeral=True` opts into destruction after 2 idle minutes; call `sandbox.start_keepalive(interval=30)` during long model-think periods. Explicit `ephemeral=False` disables idle destruction. Context managers still delete their sandbox on exit.

This default applies to the source release documented here. Published Python 0.0.46
still defaults to `ephemeral=True`; pass `ephemeral=False` explicitly on that
version. The next tagged release includes the omitted-field default above.

## Computer actions

Coordinates use screenshot pixels. `mouse.click(x, y, button="middle")` selects the
middle button; `click_count=3` sends one native triple-click sequence.
`mouse.down()` / `mouse.up()` hold and release the left button at the current
cursor, with optional `button`, `x`, and `y`. `keyboard.hold("shift", 0.5)` holds
keys for seconds. `mouse.drag(..., path=[{"x": 10, "y": 20}, ...])` preserves all
path points. `mouse.scroll(x, y, scroll_x=40, scroll_y=-80)` sends both pixel
deltas (positive right/down); the direction/amount form remains available.
The async methods have the same arguments.

Provider mappings are recorded in
[`action_manifest.json`](use_computer/agents/action_manifest.json).
Anthropic tool pixels are scaled to sandbox pixels; Gemini uses normalized
0..999 coordinates. Control and Command remain distinct. Invalid actions and
gateway errors are not reported as executed.

Agent logs separate action execution from `settle+screenshot`: the latter
includes a deliberate two-second settle, screenshot requests, and any recovery.
These are not model inference timings or raw screenshot latency.

`exec(command, timeout=120)` uses the gateway's non-login `/bin/zsh -c`;
`exec_ax` uses `/bin/sh` through the desktop server. The timeout is seconds
and is sent to the gateway and used as the HTTP timeout. For a 200-second
command, use `timeout=300`. Results retain separate stdout, stderr, and
`return_code`; a nonzero process exit is not an HTTP transport failure.

## Application automation permissions

macOS asks for consent when a process sends Apple events to another application
through AppleScript or `osascript`. That consent dialog cannot be answered inside
the sandbox. The gateway approves every installed application when creating a
sandbox or restoring a snapshot. After installing another app, call
`sandbox.permissions.allow_automation()` to approve it before scripting it:

```python
# Inside an async macOS sandbox session:
result = await sandbox.exec("brew install --cask firefox")
if result.return_code != 0:
    raise RuntimeError(result.stderr)
approval = await sandbox.permissions.allow_automation(
    bundle_ids=["org.mozilla.firefox"]
)
print(approval.success, approval.targets, approval.changed)

# Alternatively, approve all currently installed applications:
approval = await sandbox.permissions.allow_automation(installed=True)
```

The synchronous `MacOSSandbox` exposes the same method without `await`.
Approvals cover Apple events sent through `osascript`, SSH sessions, `exec`, and
Terminal.

`allow_automation(bundle_ids=None, installed=False)` sends
`POST /v1/sandboxes/{sandboxID}/permissions/automation`. Supply specific
`bundle_ids`, `installed=True` for all installed applications, or both in one
call. Omitted bundle IDs and the default `installed=False` are not sent.
The 200 response is decoded as the exported `AutomationApproval` dataclass:
`success: bool`, `targets: int` (applications considered), and `changed: int`
(approvals added or flipped from denied).

The gateway validates bundle IDs against
`^[A-Za-z0-9][A-Za-z0-9._-]{0,254}$`. Malformed IDs or an empty request receive
HTTP 400 with `{"error": ...}`. The SDK does not validate them locally; it raises
the standard `httpx.HTTPStatusError`, whose `response` retains the status and
error body.

## Runtime Snapshots

macOS snapshots let you seed a VM once, snapshot it, then create new sandboxes from that snapshot version. macOS snapshots preserve disk state, so installed apps, accounts, and seeded files are available immediately:

```python
from use_computer import Computer

client = Computer()

# Configure the macOS desktop by hand over VNC, then snapshot it.
with client.create(type="macos") as mac:
    print("Configure sandbox in the dashboard viewer:", mac.sandbox_id)
    input("Press Enter once the desktop is ready to snapshot...")
    snapshot = mac.snapshot("chrome-seeded-macos")

# New sandboxes boot from that saved disk state, no setup needed.
with client.create(type="macos", snapshot=snapshot.version) as seeded:
    print("Seeded sandbox ready:", seeded.sandbox_id)
```

Use `client.snapshots()` to list saved snapshot versions.

## Examples

| File | What it shows |
| --- | --- |
| [`examples/_1_hello_macos.py`](../examples/python/_1_hello_macos.py) | reserve → create → exec → keyboard → screenshot |
| [`examples/_2_recording.py`](../examples/python/_2_recording.py) | start / stop / download a screen recording |
| [`examples/_3_file_transfer.py`](../examples/python/_3_file_transfer.py) | upload bytes, download a file back |
| [`examples/_4_keepalive.py`](../examples/python/_4_keepalive.py) | heartbeat for ephemeral sessions idle > 2 min |
| [`examples/_5_snapshots.py`](../examples/python/_5_snapshots.py) | snapshot seeded macOS state |

## HTTP API

Every SDK method wraps `https://api.use.computer/v1/...` with `Authorization: Bearer uc_live_...`. Swagger: [api.use.computer/docs](https://api.use.computer/docs). OpenAPI spec: [api.use.computer/openapi.yaml](https://api.use.computer/openapi.yaml).

Gateway URLs, whether passed explicitly or via `USE_COMPUTER_BASE_URL`, must use HTTPS except for loopback HTTP. The SDK does not load `.env` files by default; load one explicitly in your application if needed. Authenticated requests, including keepalive and agent reference screenshots, do not follow redirects.

Lifecycle calls (`reserve`, `create`, and `snapshot`, including restores via `create(snapshot=...)`) send a fresh UUID v4 `Idempotency-Key` per call. Idempotent HTTP methods and keyed lifecycle mutations retry transient failures using the same key and body; unkeyed mutations are not retried. A new lifecycle method invocation is a new intent with a new key.
