---
title: "Run Cursor cloud agents on your own machine"
description: "Run Cursor Cloud Agents on an always-on exe.dev VM instead of a Mac mini: a My Machines worker under systemd, with your repository and no GitHub token."
url: https://exe-staging.dev/deploy/cursor
category: "AI agents"
updated: 2026-10-30
---

# Run Cursor cloud agents on your own machine

Cursor's cloud agents, running their tools on a VM you own.

- **Software:** Cursor Cloud Agents (https://cursor.com)
- **License:** Proprietary (Cursor)
- **Time:** 10 minutes
- **Example VM name:** `my-cursor` (yours will differ; on the VM, `hostname` prints it)
- **Machine-readable:** https://exe-staging.dev/deploy/cursor/manifest.json

## What you get

- The Cursor CLI in ~/.local/bin, signed in to your Cursor account (`agent about` shows your email)
- GITHUB_REPO cloned into ~/repos through the exe.dev GitHub integration, with origin left at github.com and no GitHub token on the VM
- cursor-worker.service enabled, so the worker reconnects after a crash or a reboot
- `Worker is now running` in the service's log, under this VM's name, with GITHUB_REPO as its repository

Running on the VM:

- **Cursor worker**: `agent worker` from the Cursor CLI, the cursor-worker systemd service, data in `~/.local/share/cursor-agent`
- **Your repository**: Cloned through the exe.dev GitHub integration, with origin left at github.com, data in `~/repos`
- **Cursor**: The agent loop and models, started from cursor.com/agents, the desktop app, Slack, GitHub, or Linear

How it is reached:

- ssh my-cursor.exe.xyz (private): a shell, the worker's log, and the checkouts the agents work in

## Deploy with Shelley

Open https://exe-staging.dev/new?prompt=GITHUB_REPO%3D%3Cfill-this-in%3E%0A%0ASet%20up%20Cursor%20Cloud%20Agents%20on%20this%20VM%20by%20following%20the%20exe.dev%20recipe%20at%20https%3A%2F%2Fexe-staging.dev%2Fdeploy%2Fcursor.md%20from%20top%20to%20bottom.%0A%0AThe%20values%20at%20the%20top%20of%20this%20message%20are%20mine%3A%0A-%20GITHUB_REPO%3A%20the%20GitHub%20repository%20the%20agents%20work%20on%2C%20as%20owner%2Fname%2C%20already%20connected%20to%20Cursor%0AAsk%20me%20for%20any%20that%20still%20say%20%3Cfill-this-in%3E%20before%20you%20need%20them.%0A%0AThe%20recipe%27s%20example%20VM%20name%20is%20my-cursor.%20This%20VM%27s%20name%20is%20the%20output%20of%20%60hostname%60%3A%20use%20it%20wherever%20the%20recipe%20writes%20my-cursor.%20Skip%20the%20step%20that%20creates%20the%20VM%3B%20you%20are%20on%20it.%0A%0AYou%20are%20done%20when%20all%20of%20these%20are%20true.%20Check%20each%20one%20yourself%3A%0A-%20The%20Cursor%20CLI%20in%20~%2F.local%2Fbin%2C%20signed%20in%20to%20your%20Cursor%20account%20%28%60agent%20about%60%20shows%20your%20email%29%0A-%20GITHUB_REPO%20cloned%20into%20~%2Frepos%20through%20the%20exe.dev%20GitHub%20integration%2C%20with%20origin%20left%20at%20github.com%20and%20no%20GitHub%20token%20on%20the%20VM%0A-%20cursor-worker.service%20enabled%2C%20so%20the%20worker%20reconnects%20after%20a%20crash%20or%20a%20reboot%0A-%20%60Worker%20is%20now%20running%60%20in%20the%20service%27s%20log%2C%20under%20this%20VM%27s%20name%2C%20with%20GITHUB_REPO%20as%20its%20repository%0A%0ARun%20%22Install%20by%20hand%22%20first%2C%20skipping%20VM%20creation%3B%20the%20rest%20of%20the%20page%0Ais%20for%20the%20owner%20afterwards.%20Use%20GITHUB_REPO%20exactly%20as%20given.%20Before%0Acloning%2C%20run%20%60git%20ls-remote%20https%3A%2F%2Fgithub.int.exe.xyz%2F%3CGITHUB_REPO%3E.git%60%3B%0Aif%20it%20fails%2C%20give%20the%20owner%20the%20%60integrations%20add%20github%60%20command%20with%0Athis%20VM%27s%20name%20%28or%20%60integrations%20attach%20%3Cname%3E%20vm%3A%3Cvm%3E%60%20if%20they%20already%0Ahave%20an%20integration%20for%20it%29%20and%20wait%20until%20it%20works.%20Set%20git%27s%0Auser.name%20and%20user.email%20to%20the%20owner%27s%3B%20ask%20if%20you%20don%27t%20know%20them.%0AFor%20%22Sign%20in%20to%20Cursor%22%2C%20run%20%60NO_OPEN_BROWSER%3D1%20agent%20login%60%20in%20a%20tmux%0Asession%20named%20cursor-login%2C%20give%20the%20owner%20the%20whole%20link%20from%0A%60tmux%20capture-pane%20-p%20-J%20-t%20cursor-login%60%2C%20and%20wait%20until%20%60agent%20about%60%0Ashows%20their%20email%3B%20if%20the%20link%20stops%20working%2C%20start%20it%20again.%20Never%20ask%0Afor%2C%20print%2C%20or%20copy%20an%20API%20key.%20Don%27t%20start%20Cloud%20Agents%2C%20push%20to%20the%0Arepository%2C%20or%20turn%20on%20the%20live%20workspace%20or%20computer%20use%20unless%20the%0Aowner%20asks.%20Finish%20by%20telling%20the%20owner%20to%20pick%20this%20VM%27s%20name%20under%20My%0AMachines%20at%20https%3A%2F%2Fcursor.com%2Fagents.%0A%0AFinish%20with%20the%20URLs%20I%20should%20open.%0A to create a VM whose agent, Shelley, follows this recipe. From a terminal:

```sh
curl -fsSL https://exe-staging.dev/deploy/cursor/prompt.txt | ssh exe.dev new --prompt=/dev/stdin
```

Or follow the steps below by hand.

Cursor's [Cloud Agents](https://cursor.com/docs/cloud-agent) normally run
in a VM that Cursor starts for each task. With
[My Machines](https://cursor.com/docs/cloud-agent/self-hosted/my-machines),
Cursor still runs the agent loop and the models, but every file edit and
terminal command runs on a machine you choose. A worker process there
holds an outbound HTTPS connection to Cursor and carries out the agent's
tool calls. You start agents the usual way, from cursor.com/agents, the
desktop app, Slack, GitHub, or Linear, and pick your machine.

Plenty of people point this at a Mac mini in a closet. This page uses an
exe.dev VM instead. It is always on, with nothing to buy or keep powered.
The worker only dials out, so nothing on the VM is reachable from the
internet. Whatever the agents install stays installed for the next task.
The repository comes in through the exe.dev
[GitHub integration](/docs/integrations-github), so no GitHub token sits on
the VM. And a Linux worker can open an agent's live workspace in the
Cursor desktop app, which a Mac can't.

## Before you start

- A Cursor plan with Cloud Agents: Premium or higher, Teams, Enterprise,
  or a legacy paid plan. On a team, an admin must turn on **Allow Personal
  Machines** or **Allow Self-Hosted Machines** in the
  [Cloud Agents dashboard](https://cursor.com/dashboard/cloud-agents).
- GitHub connected in Cursor for the repository. If Cloud Agents or
  Bugbot already work on it, it is.
- Your GitHub account linked to exe.dev on the
  [Integrations page](https://exe.dev/integrations).

## Set it up

Deploy sets it up on a new VM and asks for the repository. Shelley gives
you one command to run on your computer, which lets the VM reach the
repository. Then it shows you a Cursor sign-in link: open it on your
computer and approve. To do it yourself:

<details id="create-the-vm" data-manual-setup class="dp-details">
<summary>Install by hand</summary>

### Create the VM

On your computer (pick another name if `my-cursor` is taken):

```bash
ssh exe.dev new --name=my-cursor
```

### Give the VM your repository

On your computer, attach the repository to the VM through the GitHub
integration, with yours in place of `acme/app`:

```bash
ssh exe.dev integrations add github --name app --repository acme/app --attach vm:my-cursor
```

If you already have an integration for the repository, attach that one
instead: `ssh exe.dev integrations attach <name> vm:my-cursor`.

### Install the Cursor CLI

On the VM (`ssh my-cursor.exe.xyz`):

```bash
curl https://cursor.com/install -fsS | bash
export PATH="$HOME/.local/bin:$PATH"
agent --version
```

It prints a version such as `2026.10.22-27dcf5f`. The installer puts
`agent` in `~/.local/bin`, which new shells already have on their PATH.

### Clone the repository

Set `GITHUB_REPO` to yours. The `insteadOf` rule sends git's traffic for
that repository through the integration, while the checkout's `origin`
stays the github.com address Cursor matches tasks against:

```bash
GITHUB_REPO=acme/app
git config --global url."https://github.int.exe.xyz/$GITHUB_REPO.git".insteadOf "https://github.com/$GITHUB_REPO.git"
mkdir -p ~/repos
git clone "https://github.com/$GITHUB_REPO.git" ~/repos/"${GITHUB_REPO#*/}"
git -C ~/repos/"${GITHUB_REPO#*/}" config --get remote.origin.url
```

It prints `https://github.com/acme/app.git`. Agents commit, so give git a
name and an email, yours:

```bash
git config --global user.name "Your Name"
git config --global user.email you@example.com
```

### Sign in to Cursor

```bash
NO_OPEN_BROWSER=1 agent login
```

It prints a `https://cursor.com/loginDeepControl?...` link and waits. Open
the link on your computer, sign in, and approve. Then check:

```bash
agent about
```

`User Email` shows your Cursor account.

### Run the worker

A small script starts the worker named after the VM, with every checkout
in `~/repos` as a place agents can work. systemd runs it, and starts it
again whenever it exits. The unit's `PATH` puts `~/.local/bin` first, so
the agents' commands find tools installed there:

```bash
cat > ~/.local/bin/cursor-worker <<'EOF'
#!/bin/bash
# Runs the Cursor worker, named after this VM, for every git checkout in ~/repos.
set -euo pipefail
dirs=()
for d in "$HOME"/repos/*/; do
  [ -d "$d.git" ] && dirs+=(--worker-dir "${d%/}")
done
if [ ${#dirs[@]} -eq 0 ]; then
  echo "cursor-worker: no git checkouts in ~/repos" >&2
  exit 1
fi
exec "$HOME/.local/bin/agent" worker --name "$(hostname)" "${dirs[@]}" start
EOF
chmod +x ~/.local/bin/cursor-worker

sudo tee /etc/systemd/system/cursor-worker.service > /dev/null <<'EOF'
[Unit]
Description=Cursor Cloud Agents worker (My Machines)
After=network-online.target
Wants=network-online.target

[Service]
User=exedev
WorkingDirectory=/home/exedev
Environment=PATH=/home/exedev/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin
ExecStart=/home/exedev/.local/bin/cursor-worker
Restart=always
RestartSec=15

[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable --now cursor-worker
sleep 10
journalctl -u cursor-worker -n 20 --no-pager
```

The log says `Worker is now running`, then `Name: my-cursor` and the
directory. To check what Cursor sees (your account, the repository the
worker registered, and whether Cursor finds the worker):

```bash
agent worker debug
```

</details>

## Run an agent on the VM

1. Open [cursor.com/agents](https://cursor.com/agents), or Cloud Agents
   in the Cursor desktop app.
2. In the menu that sets where the agent runs, pick **my-cursor** under
   **My Machines**.
3. Send a task in your repository, for example "Run the tests and fix
   the first failure."

The agent's commands run on the VM as `exedev`, in `~/repos/app`. To
watch from a shell on the VM:

```bash
journalctl -u cursor-worker -f
git -C ~/repos/app status
```

The agent's git commands use the VM's own credentials, so its pushes go
through the GitHub integration. They show up as
`exe-dev-github-integration[bot]` unless you turn on `--act-as-user` for
the integration.

### From Slack, GitHub, or Linear

Name the machine with `worker=` (or `machine=`):

- Slack: `@Cursor worker=my-cursor fix the flaky test`
- A GitHub issue or pull request comment:
  `@cursoragent worker=my-cursor fix the flaky test`
- Linear: `worker=my-cursor` in the issue body, then mention `@Cursor` in
  a comment.

Cursor runs the task here only if the machine is yours and a checkout on
it is the task's repository. Otherwise it refuses, rather than running
the task somewhere else.

### Between tasks

The worker doesn't clone, switch branches, or clean up: each agent starts
from the checkout as the last one left it. Before a new task, put it back
on the default branch:

```bash
cd ~/repos/app
git status --short
git switch main && git pull --ff-only
```

## Add another repository

On your computer, give the VM the repository:

```bash
ssh exe.dev integrations add github --name web --repository acme/web --attach vm:my-cursor
```

On the VM, clone it the same way, then restart the worker so it picks up
the new checkout. A restart ends running agents, so do it between tasks:

```bash
GITHUB_REPO=acme/web
git config --global url."https://github.int.exe.xyz/$GITHUB_REPO.git".insteadOf "https://github.com/$GITHUB_REPO.git"
git clone "https://github.com/$GITHUB_REPO.git" ~/repos/"${GITHUB_REPO#*/}"
sudo systemctl restart cursor-worker
```

## Open the live workspace

With the live workspace on, the Cursor desktop app (3.25 or later) can
open an agent's files, changes, terminal, and forwarded ports. Add
`--connect-workspace` to the worker and restart it:

```bash
sed -i 's|agent" worker |agent" worker --connect-workspace |' ~/.local/bin/cursor-worker
sudo systemctl restart cursor-worker
```

When the app first opens an agent, the worker downloads Cursor's signed
server build into `~/.cursor-server` and runs it on 127.0.0.1; no port
opens on the VM.

> [!WARNING]
> Anyone who can open the agent gets a terminal on the VM as `exedev`:
> you, and teammates if a team admin turns on **Allow VM sharing**.

## Let agents use a desktop and a browser

With computer use, agents can take screenshots, click, and type in a
desktop the worker starts on the VM, and drive Chrome in it. Install the
desktop packages and Chrome (about 1.2 GB), then add `--computer-use`:

```bash
sudo apt-get install -y --no-install-recommends \
  dbus-x11 ffmpeg tigervnc-standalone-server \
  x11-utils x11-xserver-utils xdotool xfce4
curl -fsSLo /tmp/chrome.deb https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
sudo apt-get install -y /tmp/chrome.deb
sed -i 's|agent" worker |agent" worker --computer-use |' ~/.local/bin/cursor-worker
sudo systemctl restart cursor-worker
```

To watch the agent's desktop from Cursor, add `--share-desktop` the same
way. See Cursor's
[computer use guide](https://cursor.com/docs/cloud-agent/self-hosted/computer-use)
for the details.

## Back up

Little on the VM is hard to replace. The work that matters is in
`~/repos`, and the agents' branches are on GitHub once pushed: check for
anything unpushed before deleting the VM.

```bash
for d in ~/repos/*/; do git -C "$d" status --short --branch; done
```

The Cursor sign-in isn't worth copying: on a new VM, sign in again and
remove the old machine in the Cursor dashboard.

## Update

<details id="update" class="dp-details">
<summary>Update the Cursor CLI</summary>

On the VM, between tasks:

```bash
agent update
sudo systemctl restart cursor-worker
agent --version
```

</details>

## Troubleshooting

<details id="troubleshooting" class="dp-details">
<summary>Troubleshooting</summary>

Start with the worker's log and Cursor's own checks:

```bash
journalctl -u cursor-worker -n 50 --no-pager
agent worker debug
```

**`Authentication required for worker mode`.** The VM isn't signed in
to Cursor. Run `NO_OPEN_BROWSER=1 agent login` again; the service retries
every 15 seconds and connects on its own once you approve.

**The machine isn't in the picker.** Check that `agent about` shows the
same account as the app, and that the log says `Worker is now running`.
Then check the checkout's origin:

```bash
git -C ~/repos/app config --get remote.origin.url
```

It must be `https://github.com/...`. If it is
`https://github.int.exe.xyz/...`, set it back with
`git remote set-url origin https://github.com/acme/app.git`, add the
`insteadOf` rule from "Clone the repository", and restart the worker.

**`worker=my-cursor is registered on your machine but for a different
repository`.** The VM has no checkout of the repository the task is for.
Add it as in "Add another repository".

**The worker can't reach Cursor.** It needs outbound HTTPS to
`api2.cursor.sh` and `api2direct.cursor.sh`. A VM whose
[egress policy](/docs/internet-access) is `integrations` can't reach
them: `ssh exe.dev egress my-cursor` on your computer shows the policy.

**Clone, fetch, or push fails.** Check that the VM reaches the repository
through the integration:

```bash
git ls-remote https://github.int.exe.xyz/acme/app.git | head -1
```

An error means the integration isn't attached to this VM, or names
another repository. A push refused with a 403 means the integration is
read-only.

**`Please tell me who you are`.** Git has no identity for the agents'
commits. Set `user.name` and `user.email` as in "Clone the repository".

</details>

## Frequently asked questions

### Which Cursor plan do I need?

One that includes Cloud Agents: Premium or higher, Teams, Enterprise, or a legacy paid plan; Free and Plus don't. My Machines, the personal worker on this page, needs no Enterprise plan. On a team, an admin must turn on **Allow Personal Machines** or **Allow Self-Hosted Machines** in the [Cloud Agents dashboard](https://cursor.com/dashboard/cloud-agents). Agents bill like other Cloud Agent usage, at the model's rate.

### Why a VM instead of a Mac mini?

There's nothing to buy, power, or keep online, and the worker only dials out, so the VM needs no open ports. A Linux worker can also open an agent's live workspace (files, terminal, forwarded ports) in the Cursor desktop app, which macOS workers can't. Keep the Mac for iOS builds and for agents that drive macOS apps.

### What runs on the VM, and what goes to Cursor?

Every file edit, terminal command, and local (stdio) MCP server runs on the VM, as `exedev`. Cursor runs the agent loop and the models, so the worker sends it what the agent reads: file contents, terminal output, diffs, and screenshots. Artifacts such as screenshots and videos upload to Cursor's storage. Privacy Mode applies as usual.

### Can the agents use exe.dev's LLM gateway instead of Cursor's models?

No. The agent loop runs on Cursor's servers with Cursor's models, on your Cursor plan. Commands the agents run on the VM can still use the [LLM integration](/docs/integrations-llm), and so can Claude Code, Codex, and Shelley, which come with every VM.

### Why does the checkout's origin still say github.com?

Cursor sends a task to your machine only when a checkout's `origin` names the task's repository. The worker reads `origin` as written and treats hosts it doesn't know as their own servers, like GitHub Enterprise: cloned from `https://github.int.exe.xyz/acme/app.git`, the checkout registers as `github.int.exe.xyz/acme/app` and never matches `acme/app`. Git's `insteadOf` rule keeps `origin` at github.com and sends the traffic through the integration.

### Can several agents run on the VM at once?

Yes: a My Machines worker takes several agents at the same time, and they all work in the same checkouts. For parallel work on one repository, set up a second VM the same way; each VM is its own machine in the picker.

### Can I run a Team Pool on exe.dev VMs instead?

Team Pools (`agent worker --pool`) need a Cursor Enterprise plan and a service account API key. The worker is the same CLI, so a pool worker runs on an exe.dev VM too, but this page covers the personal My Machines worker.


## Related

- [Self-host a Cursor Agent SDK agent](https://exe-staging.dev/deploy/cursor-agent-sdk.md): Cursor's agents-as-code framework, on a machine you run.
- [Run Claude Code on a remote server](https://exe-staging.dev/deploy/claude-code.md): A computer for Claude. A breather for your laptop.
- [Run Codex on a remote server](https://exe-staging.dev/deploy/codex.md): A computer for Codex. An early night for your laptop.
- [Running a self-hosted GitHub Actions Runner](https://exe-staging.dev/deploy/github-actions-runner.md): Log in easily into your CI environment
- [Running Agents](https://exe-staging.dev/deploy/agents.md): Use exe.dev VMs as a sandbox
- [Host OpenClaw](https://exe-staging.dev/deploy/openclaw.md): An AI sidekick with its own computer. Your laptop can take a nap.
