---
title: "Self-host a Cursor Agent SDK agent"
description: "Run a Cursor Agent SDK agent on your own exe.dev VM: a pull request security reviewer under systemd, a private playground, evals, and no public webhook."
url: https://exe.dev/deploy/cursor-agent-sdk
category: "AI agents"
updated: 2026-10-28
---

# Self-host a Cursor Agent SDK agent

Cursor's agents-as-code framework, on a machine you run.

- **Software:** Cursor Agent SDK (https://cursor.com/docs/agent-sdk)
- **Source:** https://www.npmjs.com/package/@grok/agent-sdk
- **License:** Proprietary (Cursor)
- **Time:** 10 minutes
- **Example VM name:** `my-cursor-agent` (yours will differ; on the VM, `hostname` prints it)
- **Machine-readable:** https://exe.dev/deploy/cursor-agent-sdk/manifest.json

## What you get

- The Agent SDK CLI 0.4 on Node.js 24, and Cursor's security-reviewer template in ~/security-reviewer, a git repository that watches GITHUB_REPOS
- The VM signed in to Cursor (`agent-sdk whoami` names the account), with no GitHub token on it
- security-reviewer.service enabled, so it comes back after a reboot, with state in ~/agent-state
- The playground answering at `https://<vm>.exe.xyz:3000/playground`, private to the VM's owner
- Both smoke evals passing with `agent-sdk eval`

Running on the VM:

- **Security reviewer**: Cursor's security-reviewer template, a git repository you edit, data in `~/security-reviewer`
- **agent-sdk serve**: @grok/agent-sdk 0.4 on Node.js 24, the security-reviewer systemd service, port 3000, data in `~/agent-state`
- **Cursor**: Models, plus pull request events and GitHub calls through your Cursor GitHub connection

How it is reached:

- https://my-cursor-agent.exe.xyz:3000/playground (private): the playground, for you and anyone you share the VM with
- ssh my-cursor-agent.exe.xyz (private): the agent's code, evals, and logs

## Deploy with Shelley

Open https://exe.dev/new?prompt=GITHUB_REPOS%3D%3Cfill-this-in%3E%0A%0ASet%20up%20Cursor%20Agent%20SDK%20on%20this%20VM%20by%20following%20the%20exe.dev%20recipe%20at%20https%3A%2F%2Fexe.dev%2Fdeploy%2Fcursor-agent-sdk.md%20from%20top%20to%20bottom.%0A%0AThe%20values%20at%20the%20top%20of%20this%20message%20are%20mine%3A%0A-%20GITHUB_REPOS%3A%20the%20GitHub%20repositories%20to%20review%2C%20as%20owner%2Fname%2C%20comma-separated%2C%20all%20with%20the%20same%20owner%20and%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-agent.%20This%20VM%27s%20name%20is%20the%20output%20of%20%60hostname%60%3A%20use%20it%20wherever%20the%20recipe%20writes%20my-cursor-agent.%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%20Agent%20SDK%20CLI%200.4%20on%20Node.js%2024%2C%20and%20Cursor%27s%20security-reviewer%20template%20in%20~%2Fsecurity-reviewer%2C%20a%20git%20repository%20that%20watches%20GITHUB_REPOS%0A-%20The%20VM%20signed%20in%20to%20Cursor%20%28%60agent-sdk%20whoami%60%20names%20the%20account%29%2C%20with%20no%20GitHub%20token%20on%20it%0A-%20security-reviewer.service%20enabled%2C%20so%20it%20comes%20back%20after%20a%20reboot%2C%20with%20state%20in%20~%2Fagent-state%0A-%20The%20playground%20answering%20at%20%60https%3A%2F%2F%3Cvm%3E.exe.xyz%3A3000%2Fplayground%60%2C%20private%20to%20the%20VM%27s%20owner%0A-%20Both%20smoke%20evals%20passing%20with%20%60agent-sdk%20eval%60%0A%0ARun%20%22Install%20by%20hand%22%20first%2C%20skipping%20VM%20creation%3B%20the%20walkthrough%20is%20for%0Athe%20owner%20afterwards.%20Use%20GITHUB_REPOS%20exactly%20as%20given.%20For%20%22Sign%20in%20to%0ACursor%22%2C%20start%20%60agent-sdk%20login%60%20in%20a%20tmux%20session%2C%20give%20the%20owner%20the%0AURL%20it%20prints%2C%20and%20wait%20until%20%60agent-sdk%20whoami%60%20names%20an%20account%3B%20never%0Aask%20for%2C%20print%2C%20or%20copy%20an%20API%20key.%20Don%27t%20open%2C%20comment%20on%2C%20or%20review%0Apull%20requests%20yourself%2C%20and%20don%27t%20run%20%60agent-sdk%20deploy%60.%20Keep%20port%203000%0Aprivate%3A%20never%20run%20share%20set-public%20or%20share%20port.%20Finish%20with%0Ahttps%3A%2F%2F%3Cvm%3E.exe.xyz%3A3000%2Fplayground%2C%20using%20this%20VM%27s%20name%2C%20and%20point%20the%0Aowner%20to%20%22Review%20a%20pull%20request%22.%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.dev/deploy/cursor-agent-sdk/prompt.txt | ssh exe.dev new --prompt=/dev/stdin
```

Or follow the steps below by hand.

Cursor's [Agent SDK](https://cursor.com/docs/agent-sdk) builds agents as
code: a folder with the prompt in Markdown, tools in TypeScript, channels
that wake the agent on pull requests, Slack messages, or webhooks, and evals
that check it still behaves. It is the framework Cursor
[built its own Bugbot, Security Reviewer, and Rollouts with](https://cursor.com/blog/agent-sdk),
and it ships their review templates. `agent-sdk deploy` runs a project on
Cursor's infrastructure, but the same project also runs as a single Node
process, `agent-sdk serve`, on a machine of your own.

This page makes that machine an exe.dev VM. It runs Cursor's
**security reviewer** template: on every new pull request in the
repositories you pick, it reads the diff and posts one review comment that
lists exploitable bugs, or says the change is clean. The VM stays on, runs
the agent under systemd, keeps its sessions on disk, and serves the
playground privately behind your exe.dev login. Pull request events reach
it through your Cursor GitHub connection, so nothing on the VM is public
and no GitHub token lives there. Its tools run here, next to whatever
private services you give it; Cursor still runs the models.

## Before you start

- A Cursor account with model usage. The reviewer's turns bill like your
  other Cursor agent usage.
- GitHub connected in Cursor for the repositories to review
  ([Cursor dashboard](https://cursor.com/dashboard), Integrations). If
  Bugbot or Cursor's cloud agents already work on a repository, it is
  connected.
- The repositories' names, as `owner/name`. They must share one owner.

## Set it up

Deploy sets it up on a new VM and asks which repositories to watch. It
shows you a Cursor sign-in link: open it on your computer and approve, and
the VM gets a Cursor API key of its own. 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-agent` is taken):

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

### Install Node.js and the CLI

On the VM. The Agent SDK needs Node.js 22.13 or later; install Node.js 24
from NodeSource, and the CLI into `~/.local`, so updates need no sudo:

```bash
curl -fsSL https://deb.nodesource.com/setup_24.x | sudo -E bash -
sudo apt-get install -y nodejs
npm config set prefix ~/.local
npm install --global @grok/agent-sdk@0.4
export PATH="$HOME/.local/bin:$PATH"
agent-sdk --version
```

Expect `0.4.` and a patch version. `~/.local/bin` is already on the PATH
of new shells.

### Create the reviewer

Set `GITHUB_REPOS` to your repositories, then scaffold Cursor's
security-reviewer template and put it under git:

```bash
GITHUB_REPOS=acme/api,acme/web
agent-sdk init ~/security-reviewer --template security-reviewer \
  --var repos="$GITHUB_REPOS" --json < /dev/null | grep '"ok"'
cd ~/security-reviewer
git init -q && git add -A && git commit -qm "security-reviewer from the Agent SDK template"
agent-sdk validate --dir .
```

Expect `"ok": true` and `has no diagnostics`. `bot/lib/repos.ts` now lists
your repositories.

### Sign in to Cursor

```bash
agent-sdk login
```

It prints a `https://cursor.com/loginDeepControl?...` link and waits. Open
the link on your computer, sign in, and approve. The CLI stores the API key
it was given in `~/.config/agent-serve/credentials.json`, mode 600. Check:

```bash
agent-sdk whoami
```

It names your Cursor account.

### Run the evals

The template's two smoke cases send a made-up diff (one with an XSS bug, one
that only touches the README) and check that the reviewer flags the first
and passes the second. Eval sessions skip the GitHub write.

```bash
agent-sdk eval --dir .
```

Expect `2 passed`. These turns use your Cursor usage.

### Start the service

`agent-sdk serve` subscribes to pull request events for the repositories
in `bot/lib/repos.ts` and serves the playground on port 3000. The exe.dev
[HTTPS proxy](/docs/proxy) only lets in people signed in with access to the
VM, so the server admits whoever gets that far (`--allow-anonymous`),
including to the reviewer's GitHub access
(`--allow-anonymous-cursor-github`). `--cursor-scm-proxy` sends GitHub API
calls through Cursor instead of minting a GitHub token on the VM.

```bash
mkdir -p ~/agent-state
sudo tee /etc/systemd/system/security-reviewer.service > /dev/null <<'EOF'
[Unit]
Description=Cursor Agent SDK: security-reviewer
After=network-online.target
Wants=network-online.target

[Service]
User=exedev
WorkingDirectory=/home/exedev/security-reviewer
Environment=AGENT_SERVE_NO_UPDATE_CHECK=1
ExecStart=/home/exedev/.local/bin/agent-sdk serve --dir /home/exedev/security-reviewer --mode single --host 0.0.0.0 --port 3000 --state-root /home/exedev/agent-state --allow-anonymous --allow-anonymous-cursor-github --cursor-scm-proxy
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable --now security-reviewer
sleep 15
journalctl -u security-reviewer -n 20 --no-pager
curl -s -o /dev/null -w '%{http_code}\n' http://localhost:3000/playground
```

The log says `security-reviewer listening` and
`GitHub auth: channel API calls route through https://api.cursor.com/v0/github-proxy`,
and curl prints `200`.

> [!WARNING]
> **Keep port 3000 private.** Anyone who can open the playground can run
> the reviewer with its access to your repositories. Never point
> `share port` at it or make it public.

</details>

## Review a pull request

Open a pull request in one of the watched repositories, or close and reopen
one. Within a minute or two the reviewer posts a review comment headed
**Security review**, with a verdict of CLEAN or a list of findings, each
with a severity, a file and line, and a one-line fix. Drafts are skipped
until they're marked ready for review.

To watch it work, open `https://my-cursor-agent.exe.xyz:3000/playground`
and sign in to exe.dev. **Runs** lists each review session; open one to see
the diff it read, each tool call, and the reply. The **Chat** tab talks to
the same agent, and **Evals** runs the smoke cases from the browser.

From a shell on the VM, the same things:

```bash
agent-sdk session list --url http://127.0.0.1:3000
agent-sdk logs --once --url http://127.0.0.1:3000
```

## Make it yours

The agent is the folder `~/security-reviewer`:

| File | What it does |
| --- | --- |
| `bot/instructions.md` | What counts as a finding, and how to report it |
| `bot/channels/github.ts` | Which events start a review; writes the diff to `pr/diff.patch` first |
| `bot/tools/post_findings.ts` | The one tool the model calls: posts the review comment |
| `bot/agent.ts` | The model, read-only tools (`read`, `grep`), and Cursor's local sandbox |
| `bot/lib/repos.ts` | The watched repositories |
| `evals/review.eval.ts` | The smoke cases |

The loop: change a file, add an eval case for what you want, check, then
restart. On the VM:

```bash
cd ~/security-reviewer
agent-sdk validate --dir . && npm run check && agent-sdk eval --dir .
sudo systemctl restart security-reviewer
git commit -am "Flag missing authz checks on admin routes"
```

To try a change on a real pull request before it goes live, stop the
service, run the development server, and replay the pull request to it.
The replay runs a real review, so it posts a comment: pick a pull request
where that's fine.

```bash
sudo systemctl stop security-reviewer
agent-sdk dev --dir . --port 3000 --host 0.0.0.0 --allow-anonymous --allow-anonymous-cursor-github
# in a second shell:
agent-sdk github replay https://github.com/acme/api/pull/12 --dir .
```

Press Ctrl-C and `sudo systemctl start security-reviewer` when done.

Shelley, the coding agent on every exe.dev VM, can do this loop for you:
open `https://my-cursor-agent.shelley.exe.xyz` and ask it to change the
reviewer. The project's `AGENTS.md` and the SDK's bundled skills
(`agent-sdk skills list`) tell coding agents how. Cursor's other review
templates scaffold the same way: `thermo-review` (bugs and breaking side
effects), `thermo-quality-review` (structure), and `agentic-owners`
(approves what an owners policy allows); see
[the templates](https://cursor.com/docs/agent-sdk/templates/reviews).

To keep the project on GitHub too, give the VM a repository through the
[GitHub integration](/docs/integrations-github) and push to
`https://github.int.exe.xyz/<owner>/<repo>.git`; no token is stored on the
VM.

## Share it

On your computer:

```bash
ssh exe.dev share add my-cursor-agent ann@example.com
```

Ann signs in at the same playground address. Share it only with people
you'd let run the reviewer against your repositories.

## Back up

The project is a git repository; sessions, memory, and eval runs are in
`~/agent-state`. Copy both off the VM now and then. On your computer:

```bash
mkdir -p cursor-agent-backup
rsync -av --exclude node_modules my-cursor-agent.exe.xyz:security-reviewer my-cursor-agent.exe.xyz:agent-state cursor-agent-backup/
```

To restore on a new VM, follow "Install by hand" up to "Sign in to Cursor"
(skip `init`), copy both folders back, run `npm install` in
`~/security-reviewer`, then "Start the service". The Cursor credential isn't
in the backup: sign in again, and revoke the old VM's key in the Cursor
dashboard.

## Update

<details id="update" class="dp-details">
<summary>Update the Agent SDK</summary>

Read the [changelog](https://cursor.com/docs/agent-sdk/changelog) first.
On the VM, update the CLI and the project's copy together, check, and
restart:

```bash
npm install --global @grok/agent-sdk@0.4
cd ~/security-reviewer
npm install @grok/agent-sdk@0.4
agent-sdk validate --dir . && npm run check && agent-sdk eval --dir .
sudo systemctl restart security-reviewer
git commit -am "Update the Agent SDK"
```

For a new minor version, replace `0.4` with it in both commands.

</details>

## Troubleshooting

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

Start with the service log and the project's own checks:

```bash
journalctl -u security-reviewer -n 50 --no-pager
cd ~/security-reviewer && agent-sdk validate --dir . && agent-sdk whoami
```

- **`The Cursor API key was rejected`**, and the service restarts every
  ten seconds: the key was revoked or expired. Run `agent-sdk login` again,
  then `sudo systemctl restart security-reviewer`.
- **`requires a signed-in Cursor account`**: the VM was never signed in.
  Run `agent-sdk login`.
- **No review appears on a new pull request**: check that the repository
  is in `bot/lib/repos.ts`, that GitHub is connected in Cursor for it, and
  that the pull request isn't a draft. `agent-sdk session list --url http://127.0.0.1:3000` shows
  whether a session started; open it in the playground to see where it
  stopped.
- **The first turn reports `[resource_exhausted]`**: the model is out of
  capacity, or GitHub rate-limited the event; wait and reopen the pull
  request.
- **The playground shows no agents**: the service isn't running. See the
  log above.
- **`401` on API calls through the proxy**: the service is missing
  `--allow-anonymous`; compare the `ExecStart` line with the unit above.

Cursor's [troubleshooting page](https://cursor.com/docs/agent-sdk/troubleshooting)
covers more.

</details>

## Frequently asked questions

### What is the Cursor Agent SDK?

Cursor's framework for agents as code, the one behind its own Bugbot, Security Review, and Rollouts. A project is a folder: the prompt in `bot/instructions.md`, tools as TypeScript files, event channels for GitHub, GitLab, Bitbucket, Slack, and webhooks, and evals beside them. It is not the earlier Cursor SDK (`@cursor/sdk`), which drives Cursor's coding agent from your code; the Agent SDK is built on it. The npm package is `@grok/agent-sdk`, formerly `@cursor/bdk`.

### Why self-host instead of running agent-sdk deploy?

`agent-sdk deploy` runs the agent on Cursor's infrastructure, and needs a team with agent hosting turned on. Self-hosting runs the same project as one Node process you control: its tools run on your VM, on your network, so they can reach private services, databases, and [exe.dev integrations](/docs/integrations); you pick the egress, keep sessions on your disk, and can run long or heavy tools without a hosted sandbox's limits. Cursor's docs say to self-host "when you need your own network or process controls".

### What still goes to Cursor?

The model turns: the agent loop runs on the VM, but every model call goes to Cursor and counts against your Cursor plan's usage, under your account's privacy setting. Pull request events and GitHub API calls also go through your Cursor GitHub connection. Diffs the reviewer reads are sent to the model.

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

No. The Agent SDK runs Cursor's agent harness, which only talks to Cursor's backend, and `model` in `bot/agent.ts` takes Cursor model IDs such as `grok-4.5` or `composer-2.5`. Tools you write can still call `https://llm.int.exe.xyz` through the [LLM integration](/docs/integrations-llm), for example for a cheap classification step.

### Do I need a public webhook URL or a GitHub token?

No. With `cursorAccount`, the agent pulls pull request events from Cursor and makes its GitHub calls through Cursor's GitHub proxy (`--cursor-scm-proxy`), using the GitHub connection you already have in Cursor. Nothing on the VM needs to be public, and no GitHub token is minted on it.

### Which Cursor plan do I need?

A Cursor account with model usage: the reviewer's turns are billed like your other agent usage. Cursor's docs don't name a plan for self-hosting, which needs only an API key; Cursor-managed hosting needs a team with agent hosting turned on.

### Can I run more than one agent on the VM?

Yes. Put each project in its own folder under one directory and point `agent-sdk serve --dir` at that directory in multi mode (the default); each agent then gets `/<slug>/playground`. Let only one process run schedules per project.


## Related

- [Host a Claude Agent SDK app in a sandbox VM](https://exe.dev/deploy/claude-agent-sdk.md): Claude Code as a library, with a whole computer to run on.
- [Sandboxes for the OpenAI Agents SDK](https://exe.dev/deploy/openai-agents-sdk.md): The SDK runs the agent loop. Each session's commands run on a VM of its own.
- [Run Claude Code on a remote server](https://exe.dev/deploy/claude-code.md): A computer for Claude. A breather for your laptop.
- [Running Agents](https://exe.dev/deploy/agents.md): Use exe.dev VMs as a sandbox
- [Host OpenClaw](https://exe.dev/deploy/openclaw.md): An AI sidekick with its own computer. Your laptop can take a nap.
- [Run Codex on a remote server](https://exe.dev/deploy/codex.md): A computer for Codex. An early night for your laptop.
