Metadata-Version: 2.4
Name: modal-computer-use
Version: 1.1.0
Summary: Daemon-first Modal-native computer-use primitives for Linux desktops
Project-URL: Homepage, https://github.com/ashtonchew/modal-computer-use
Project-URL: Documentation, https://github.com/ashtonchew/modal-computer-use/blob/main/docs/README.md
Project-URL: Repository, https://github.com/ashtonchew/modal-computer-use
Project-URL: Issues, https://github.com/ashtonchew/modal-computer-use/issues
Project-URL: Changelog, https://github.com/ashtonchew/modal-computer-use/blob/main/CHANGELOG.md
Author: modal-computer-use contributors
License-Expression: MIT
License-File: LICENSE
Requires-Python: >=3.12
Requires-Dist: anyio>=4
Requires-Dist: fastapi>=0.115
Requires-Dist: h2>=4.1
Requires-Dist: httpx[http2]>=0.27
Requires-Dist: hypercorn>=0.17
Requires-Dist: mss>=10.0
Requires-Dist: pillow>=12.3.0
Requires-Dist: pydantic>=2.7
Requires-Dist: python-dotenv>=1.0
Requires-Dist: starlette>=1.0.1
Requires-Dist: uvicorn[standard]>=0.30
Requires-Dist: websockets>=13.0
Requires-Dist: xxhash>=3.6
Provides-Extra: anthropic
Requires-Dist: anthropic>=0.101; extra == 'anthropic'
Provides-Extra: bench-daytona
Requires-Dist: daytona==0.175.0; extra == 'bench-daytona'
Provides-Extra: bench-e2b
Requires-Dist: e2b-desktop==2.4.2; extra == 'bench-e2b'
Provides-Extra: bench-providers
Requires-Dist: daytona==0.175.0; extra == 'bench-providers'
Requires-Dist: e2b-desktop==2.4.2; extra == 'bench-providers'
Requires-Dist: tzafon==2.44.1; extra == 'bench-providers'
Provides-Extra: bench-tzafon
Requires-Dist: tzafon==2.44.1; extra == 'bench-tzafon'
Provides-Extra: dev
Requires-Dist: mypy>=1.10; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
Requires-Dist: pytest>=8.2; extra == 'dev'
Requires-Dist: ruff>=0.6; extra == 'dev'
Provides-Extra: modal
Requires-Dist: modal~=1.5.2; extra == 'modal'
Provides-Extra: openai
Requires-Dist: openai>=2.36; extra == 'openai'
Description-Content-Type: text/markdown

# modal-computer-use

`modal-computer-use` turns a Modal Sandbox into a remotely controllable Linux desktop through a
typed, provider-neutral Python SDK and an in-Sandbox daemon.

This is an independent project using Modal.

## Quick start

Use Python 3.12 or later and `uv`. Install the Modal extra from PyPI:

```bash
uv add "modal-computer-use[modal]"
```

The Modal extra supports the Modal 1.5 line and requires Modal 1.5.2 or later.

Save this as `quickstart.py`:

```python
from modal_computer_use import (
    BrowserConfig,
    ComputerConfig,
    ComputerSandbox,
    ResourceConfig,
)

config = ComputerConfig(
    resources=ResourceConfig(profile="browser"),
    browser=BrowserConfig(kind="chromium"),
)

with ComputerSandbox.create(config=config) as computer:
    computer.browser.open_url("https://example.com")
    computer.mouse.move(320, 240)
    screenshot = computer.screenshots.full()
    screenshot.save("screenshot.png")
    print(screenshot.width, screenshot.height, screenshot.sha256)
```

Run it:

```bash
uv run python quickstart.py
```

When the `with` block ends, the SDK terminates the Sandbox and closes the connection.

## Core API

`ComputerSandbox` is the primary synchronous entry point. `AsyncComputerSandbox` provides native
async Modal creation, attachment, and named acquisition with the same ownership rules; see the
[async owner example](https://github.com/ashtonchew/modal-computer-use/blob/main/examples/async_modal_owner.py).
`AsyncDaemonClient` connects to an existing daemon without blocking the event loop.

| Task | Representative API |
| --- | --- |
| Create or attach | `ComputerSandbox.create()`, `ComputerSandbox.attach()`, `AsyncComputerSandbox.create()`, `AsyncComputerSandbox.attach()` |
| Acquire by name | `ComputerSandbox.attach_or_create(name=...)`, `AsyncComputerSandbox.attach_or_create(name=...)` |
| Input | `computer.mouse.move()`, `computer.keyboard.type()`, `computer.clipboard.get_text()` |
| Observe | `computer.screenshots.full()`, `computer.display.info()`, `computer.windows.list()` |
| Browser and apps | `computer.browser.open_url()`, `computer.apps.launch()` |
| Execute | `computer.actions.run()`, `computer.commands.run()` |
| Files and recordings | `computer.artifacts.download()`, `computer.recordings.start()` |
| Operate | `computer.lifecycle.status()`, `computer.processes.logs(name)` |

Action batches validate the full request before execution. They stop on the first error by default,
can opt into `continue_on_error`, and can capture a trailing screenshot in the same request.

Inside an active `ComputerSandbox`:

```python
batch = computer.actions.run(
    [
        {"type": "move", "x": 320, "y": 240},
        {"type": "click", "x": 320, "y": 240},
    ],
    screenshot_after=True,
)
```

`batch.screenshot` contains the trailing observation when the batch succeeds.

See the [API guide](https://github.com/ashtonchew/modal-computer-use/blob/main/docs/api.md) for
namespace semantics and the generated
[OpenAPI schema](https://github.com/ashtonchew/modal-computer-use/blob/main/docs/openapi.json) for
HTTP request and response shapes.

## How it works

`ComputerSandbox.create()` starts a new Modal Sandbox. If you use it in a `with` block, the SDK
terminates the Sandbox automatically when the block ends. `ComputerSandbox.attach()` connects to an
existing Sandbox. Leaving an attached `with` block closes the SDK connection but keeps the Sandbox
running.

`ComputerSandbox.attach_or_create(name=...)` and its async counterpart acquire a compatible live
Sandbox with that app-scoped name, or create one if it is missing. If the call creates the Sandbox,
leaving the block terminates it. If the Sandbox already existed, leaving the block keeps it running.

A daemon inside the Sandbox executes desktop actions, captures screenshots and recordings, runs
commands, and reads or writes files through `computer.artifacts`.

## Performance

[![Warm-operation p50 latency on July 30, 2026. Modal optimized recorded the lowest p50 in each of six displayed rows; configurations and caller topologies differed.](https://raw.githubusercontent.com/ashtonchew/modal-computer-use/main/docs/assets/warm-operation-p50-2026-07-30.svg)](https://github.com/ashtonchew/modal-computer-use/blob/main/docs/benchmark-results-2026-07-30-warm-paths.md)

The figure shows July 2026 p50 latency for six computer-use cases, based on 30 successful samples
per cell. Lower is better. Note that warm-operation latency starts after the desktop and client
connection are ready.

The [detailed report](https://github.com/ashtonchew/modal-computer-use/blob/main/docs/benchmark-results-2026-07-30-warm-paths.md)
gives p95 results and explains how each path was configured and measured.

## Examples

| Workflow | Example |
| --- | --- |
| Configure and prewarm a browser | [`browser_profile.py`](https://github.com/ashtonchew/modal-computer-use/blob/main/examples/browser_profile.py) |
| Acquire one named desktop from async code | [`async_named_desktop.py`](https://github.com/ashtonchew/modal-computer-use/blob/main/examples/async_named_desktop.py) |
| Attach without taking lifecycle ownership | [`attach_existing_sandbox.py`](https://github.com/ashtonchew/modal-computer-use/blob/main/examples/attach_existing_sandbox.py) |
| Capture and download a recording | [`recording_lifecycle.py`](https://github.com/ashtonchew/modal-computer-use/blob/main/examples/recording_lifecycle.py) |
| Persist artifacts with a Modal Volume | [`volume_artifacts.py`](https://github.com/ashtonchew/modal-computer-use/blob/main/examples/volume_artifacts.py) |
| Hand a desktop to a Modal Function | [`modal_function_session_handoff.py`](https://github.com/ashtonchew/modal-computer-use/blob/main/examples/modal_function_session_handoff.py) |
| Run an application-owned model loop | [OpenAI](https://github.com/ashtonchew/modal-computer-use/blob/main/examples/03_openai_computer_loop.py) · [Anthropic](https://github.com/ashtonchew/modal-computer-use/blob/main/examples/anthropic_message_server.py) |

## Documentation

| Guide | What it covers |
| --- | --- |
| [Documentation map](https://github.com/ashtonchew/modal-computer-use/blob/main/docs/README.md) | Every maintained guide, grouped by task. |
| [Modal deployment](https://github.com/ashtonchew/modal-computer-use/blob/main/docs/modal-deployment.md) | Sandbox lifecycle, readiness, Function handoff, warm capacity, and cleanup. |
| [Modal optimization](https://github.com/ashtonchew/modal-computer-use/blob/main/docs/modal-optimization.md) | Production guidance for caller placement, connection reuse, async orchestration, and per-turn work. |
| [Performance](https://github.com/ashtonchew/modal-computer-use/blob/main/docs/performance.md) and [benchmarking](https://github.com/ashtonchew/modal-computer-use/blob/main/docs/benchmarking.md) | Latency mechanisms, tuning evidence, benchmark commands, and publication rules. |
| [OpenAI adapter](https://github.com/ashtonchew/modal-computer-use/blob/main/docs/openai-adapter.md) and [Anthropic adapter](https://github.com/ashtonchew/modal-computer-use/blob/main/docs/anthropic-adapter.md) | Provider action and screenshot translation for application-owned model loops. |
| [Contributing](https://github.com/ashtonchew/modal-computer-use/blob/main/CONTRIBUTING.md) | Development setup, required checks, and pull request expectations. |

## Local development

See the [local development guide](https://github.com/ashtonchew/modal-computer-use/blob/main/docs/local-development.md)
for daemon startup, mock and X11 backends, synchronous and async clients, authentication, and
repository checks.

## Security

The daemon can control the desktop and access clipboard contents, screenshots, recordings, and
artifacts. Do not expose it without authentication.

See the [security policy](https://github.com/ashtonchew/modal-computer-use/blob/main/SECURITY.md) for
reporting vulnerabilities and the
[runtime security guide](https://github.com/ashtonchew/modal-computer-use/blob/main/docs/security.md)
for deployment guidance.
