Run Cursor Self-Hosted Machines on Daytona
Cursor Cloud Agents
Section titled “Cursor Cloud Agents”Cursor Cloud Agents work asynchronously on repositories. They inspect code, edit files, run commands and tests, and respond to follow-up messages while users track progress in Cursor.
Self-Hosted Machines moves Cloud Agent tool execution to machines you manage. Cursor continues to host the agent control plane and user experience. You control where workers run and which operating system, tools, dependencies, and network access they use. For teams, a Self-Hosted Pool adds shared worker capacity with service-account authentication.
This guide shows how to run Cursor Self-Hosted Machines on Daytona through a Self-Hosted Pool.
How it works
Section titled “How it works”We provide a runnable reference implementation for running Cursor Self-Hosted Pool workers on Daytona. The code lives in python/cursor/self-hosted-machines/.
For example, a daytona-windows pool uses Cursor’s controller to run our spawn-cursor-self-hosted-worker command. The command creates a Daytona sandbox from the configured Windows snapshot. The worker runs inside that sandbox until the request finishes.
The same sequence applies to every sandbox class:
- A user selects a Daytona pool for a Cloud Agent request.
agent worker controllerclaims the request from Cursor.- The controller runs
spawn-cursor-self-hosted-worker. - The spawn helper creates a sandbox from
SNAPSHOT_NAMEand sets the requested repository as the workspaceorigin. - The Cursor worker starts inside the sandbox and connects to Cursor.
- Cursor mints a short-lived GitHub token for the run, and the checkout hook fetches the requested branch into the workspace.
monitor-cursor-self-hosted-workerdeletes the sandbox after the worker exits.
Each claimed request gets one sandbox and one worker process. Follow-up messages can reuse that worker during CURSOR_WORKER_IDLE_RELEASE_TIMEOUT.
If worker startup fails, the spawn helper releases the request and deletes the sandbox.
Set up
Section titled “Set up”The setup combines two parts:
- Cursor provides
agent worker controller, which claims requests from a Self-Hosted Pool. Cursor currently provides this command through the Cursor CLI lab channel. - We provide the snapshot builders, spawn helper, and sandbox monitor in the Daytona guides repository.
Our spawn helper connects to Cursor’s controller through the controller’s --spawn option.
Requirements
Section titled “Requirements”You need:
- A Cursor Enterprise team.
- A Cursor service-account API key.
- A Daytona API key.
- A macOS or Linux host with Python 3.12 or newer.
- Outbound HTTPS access from the controller host.
The controller host remains macOS or Linux for all sandbox classes. A Windows pool runs the worker inside a Windows sandbox.
Get the code
Section titled “Get the code”Clone the Daytona guides repository and install the package:
git clone https://github.com/daytona/guides.gitcd guides/python/cursor/self-hosted-machines
python3.12 -m venv .venvsource .venv/bin/activate
pip install -e .cp .env.example .envThis package installs:
build-cursor-self-hosted-snapshotspawn-cursor-self-hosted-workermonitor-cursor-self-hosted-worker
Install the Cursor controller
Section titled “Install the Cursor controller”Install the Cursor CLI from its lab channel:
curl 'https://cursor.com/install?channel=lab' -fsS | bashexport PATH="$HOME/.local/bin:$PATH"
agent --versionagent worker controller --helpIf the Cursor CLI is already installed, switch it to the lab channel:
agent set-channel labagent updateagent worker controller --help must include the --spawn option.
Configure Cursor
Section titled “Configure Cursor”A Cursor team administrator must configure the team:
- Open Dashboard > Settings > API Keys > Service Accounts.
- Create a service account for the Daytona pool.
- Copy the service-account API key.
- Open Dashboard > Cloud Agents > Self-Hosted.
- Enable Allow Self-Hosted Agents.
- Enable GitHub token minting for self-hosted workers.
- Open Dashboard > Settings > Integrations.
- Connect the Cursor GitHub App at the team level.
- Give the GitHub App access to each repository that the pool will use.
Set the service-account API key as CURSOR_API_KEY. Other Cursor API-key types cannot start pool workers.
The spawn command sets the requested repository as the workspace origin, and the worker starts with agent worker --mint-github-token --on-session-start <checkout hook>. When Cursor claims the worker, it mints a short-lived GitHub token for the run, and the checkout hook fetches the requested ref into the workspace. Do not add a GitHub personal access token to .env.
Build a Daytona snapshot
Section titled “Build a Daytona snapshot”Add both API keys to .env. Leave SNAPSHOT_NAME empty for the first build.
DAYTONA_API_KEY=replace-with-your-daytona-api-keyDAYTONA_TARGET=usSNAPSHOT_NAME=CURSOR_API_KEY=replace-with-your-cursor-service-account-keyChoose the sandbox class for the pool:
| Sandbox class | Guest OS | Default source | Workspace |
|---|---|---|---|
container | Linux | Included Dockerfile | /home/daytona/workspace |
linux-vm | Linux | daytona-vm-medium | /home/daytona/workspace |
windows | Windows | windows-medium | C:\cursor\workspace |
Build the snapshot:
# Linux containerbuild-cursor-self-hosted-snapshot --sandbox-class container --target us
# Linux VMbuild-cursor-self-hosted-snapshot \ --sandbox-class linux-vm \ --target eu-central-1
# Windowsbuild-cursor-self-hosted-snapshot --sandbox-class windows --target usThe target must support the selected sandbox class. VM targets must also contain the required source snapshot.
The builder derives the snapshot name from the build recipe. It reuses an existing snapshot when the recipe is unchanged.
For a VM build, the builder:
- Starts a temporary VM.
- Installs the Cursor worker and required tools.
- Captures a cold snapshot.
- Starts a second VM from that snapshot.
- Confirms that the worker can start.
- Deletes both temporary VMs.
Copy the returned snapshot_name into SNAPSHOT_NAME. Keep DAYTONA_TARGET set to the target that contains the snapshot.
Each active worker uses one Daytona sandbox. Check your organization’s tier limits before you set pool concurrency.
Run the controller
Section titled “Run the controller”Load .env and start the controller:
set -a. ./.envset +a
agent worker controller \ --spawn "$(pwd)/.venv/bin/spawn-cursor-self-hosted-worker" \ --pool daytona-containerThe pool name must match the pool selected in Cursor.
Keep the controller process running. It claims requests from the pool and runs the spawn helper for each request.
One controller process uses one pool, one SNAPSHOT_NAME, and one DAYTONA_TARGET.
Use a separate working directory, .env file, and controller process for each sandbox class. For example:
daytona-containeruses acontainersnapshot.daytona-linux-vmuses alinux-vmsnapshot.daytona-windowsuses awindowssnapshot.
The spawn helper reads the sandbox class from the snapshot metadata. Do not set a separate sandbox-class environment variable.
Open Cursor Agents, create an agent for an HTTPS GitHub repository, and select the Daytona pool.
The Daytona dashboard shows the sandbox while the worker runs. The monitor deletes the sandbox after the worker exits.
Controller settings
Section titled “Controller settings”| Variable | Required | Purpose |
|---|---|---|
DAYTONA_API_KEY | Yes | Creates, finds, and deletes Daytona sandboxes. |
DAYTONA_TARGET | Recommended | Selects the target that contains the snapshot. |
SNAPSHOT_NAME | Yes | Selects the snapshot used for new workers. |
CURSOR_API_KEY | Yes | Authenticates the controller and workers with Cursor. |
CURSOR_WORKER_IDLE_RELEASE_TIMEOUT | No | Keeps a worker available for follow-up messages. Default: 900 seconds. |
MONITOR_POLL_SECONDS | No | Sets the monitor interval. Default: 5 seconds. |
SANDBOX_CREATE_TIMEOUT_SECONDS | No | Sets the Daytona create and delete timeout. Default: 120 seconds. |
SANDBOX_LAUNCH_TIMEOUT_SECONDS | No | Sets the worker startup timeout. Default: 60 seconds. |
Do not set CURSOR_AGENT_WORKER_ID, CURSOR_POOL, or CURSOR_REQUEST_ID. The Cursor controller sets them for each request.
Network and credentials
Section titled “Network and credentials”The controller host needs outbound HTTPS access to:
- Cursor
- The Cursor download service
- The Python package index
- The Daytona API
Each sandbox needs outbound HTTPS access to:
- Cursor
- The requested Git host
- Artifact storage
- Package and tool hosts used by the workload
The sandbox does not need an inbound port. The worker management address, 0.0.0.0:8080, stays inside the sandbox.
The controller holds DAYTONA_API_KEY and CURSOR_API_KEY. The sandbox receives CURSOR_API_KEY, but it never receives DAYTONA_API_KEY.
Code inside the sandbox runs as the same operating-system user as the Cursor worker. Use a dedicated, least-privilege Cursor service account for each customer or trust boundary.
The snapshots contain no API keys. The Windows launcher also deletes its temporary environment file after the worker starts.
Conclusion
Section titled “Conclusion”Running the workers on Daytona gives you:
- A fresh, isolated sandbox for each claimed request.
- Linux container, Linux VM, and Windows VM pools.
- Control over the operating system, tools, dependencies, and network access.
- Consistent worker environments built from reusable snapshots.
- Faster startup because snapshots can include the required tools and dependencies.
- No inbound network requirement for the worker sandboxes.
- Automatic sandbox cleanup after workers exit.
- Visibility into active workers through the Daytona dashboard.